Browse Source

Merge pull request #617 from AppFlowy-IO/feat/add_more_grid_documentation

Nathan.fooo 2 năm trước cách đây
mục cha
commit
c860d1bc0b

+ 23 - 12
frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart

@@ -1,3 +1,4 @@
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
@@ -6,27 +7,32 @@ import 'package:dartz/dartz.dart';
 part 'field_editor_bloc.freezed.dart';
 
 class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
+  final TypeOptionDataController dataController;
+
   FieldEditorBloc({
     required String gridId,
     required String fieldName,
-    required IFieldTypeOptionLoader fieldContextLoader,
-  }) : super(FieldEditorState.initial(gridId, fieldName, fieldContextLoader)) {
+    required IFieldTypeOptionLoader loader,
+  })  : dataController = TypeOptionDataController(gridId: gridId, loader: loader),
+        super(FieldEditorState.initial(gridId, fieldName)) {
     on<FieldEditorEvent>(
       (event, emit) async {
         await event.when(
           initial: () async {
-            final fieldContext = GridFieldContext(gridId: gridId, loader: fieldContextLoader);
-            await fieldContext.loadData().then((result) {
-              result.fold(
-                (l) => emit(state.copyWith(fieldContext: Some(fieldContext), name: fieldContext.field.name)),
-                (r) => null,
-              );
+            dataController.addFieldListener((field) {
+              if (!isClosed) {
+                add(FieldEditorEvent.didReceiveFieldChanged(field));
+              }
             });
+            await dataController.loadData();
           },
           updateName: (name) {
-            state.fieldContext.fold(() => null, (fieldContext) => fieldContext.fieldName = name);
+            dataController.fieldName = name;
             emit(state.copyWith(name: name));
           },
+          didReceiveFieldChanged: (Field field) {
+            emit(state.copyWith(field: Some(field)));
+          },
         );
       },
     );
@@ -42,6 +48,7 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
 class FieldEditorEvent with _$FieldEditorEvent {
   const factory FieldEditorEvent.initial() = _InitialField;
   const factory FieldEditorEvent.updateName(String name) = _UpdateName;
+  const factory FieldEditorEvent.didReceiveFieldChanged(Field field) = _DidReceiveFieldChanged;
 }
 
 @freezed
@@ -50,13 +57,17 @@ class FieldEditorState with _$FieldEditorState {
     required String gridId,
     required String errorText,
     required String name,
-    required Option<GridFieldContext> fieldContext,
+    required Option<Field> field,
   }) = _FieldEditorState;
 
-  factory FieldEditorState.initial(String gridId, String fieldName, IFieldTypeOptionLoader loader) => FieldEditorState(
+  factory FieldEditorState.initial(
+    String gridId,
+    String fieldName,
+  ) =>
+      FieldEditorState(
         gridId: gridId,
-        fieldContext: none(),
         errorText: '',
+        field: none(),
         name: fieldName,
       );
 }

+ 8 - 15
frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart

@@ -1,4 +1,5 @@
 import 'package:dartz/dartz.dart';
+import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@@ -193,14 +194,14 @@ class FieldTypeOptionLoader extends IFieldTypeOptionLoader {
   }
 }
 
-class GridFieldContext {
+class TypeOptionDataController {
   final String gridId;
   final IFieldTypeOptionLoader _loader;
 
   late FieldTypeOptionData _data;
-  ValueNotifier<Field>? _fieldNotifier;
+  final PublishNotifier<Field> _fieldNotifier = PublishNotifier();
 
-  GridFieldContext({
+  TypeOptionDataController({
     required this.gridId,
     required IFieldTypeOptionLoader loader,
   }) : _loader = loader;
@@ -211,13 +212,7 @@ class GridFieldContext {
       (data) {
         data.freeze();
         _data = data;
-
-        if (_fieldNotifier == null) {
-          _fieldNotifier = ValueNotifier(data.field_2);
-        } else {
-          _fieldNotifier?.value = data.field_2;
-        }
-
+        _fieldNotifier.value = data.field_2;
         return left(unit);
       },
       (err) {
@@ -260,9 +255,7 @@ class GridFieldContext {
       }
     });
 
-    if (_data.field_2 != _fieldNotifier?.value) {
-      _fieldNotifier?.value = _data.field_2;
-    }
+    _fieldNotifier.value = _data.field_2;
 
     FieldService.insertField(
       gridId: gridId,
@@ -292,11 +285,11 @@ class GridFieldContext {
       callback(field);
     }
 
-    _fieldNotifier?.addListener(listener);
+    _fieldNotifier.addListener(listener);
     return listener;
   }
 
   void removeFieldListener(void Function() listener) {
-    _fieldNotifier?.removeListener(listener);
+    _fieldNotifier.removeListener(listener);
   }
 }

+ 7 - 7
frontend/app_flowy/lib/workspace/application/grid/field/field_type_option_edit_bloc.dart

@@ -8,17 +8,17 @@ import 'field_service.dart';
 part 'field_type_option_edit_bloc.freezed.dart';
 
 class FieldTypeOptionEditBloc extends Bloc<FieldTypeOptionEditEvent, FieldTypeOptionEditState> {
-  final GridFieldContext _fieldContext;
+  final TypeOptionDataController _dataController;
   void Function()? _fieldListenFn;
 
-  FieldTypeOptionEditBloc(GridFieldContext fieldContext)
-      : _fieldContext = fieldContext,
-        super(FieldTypeOptionEditState.initial(fieldContext)) {
+  FieldTypeOptionEditBloc(TypeOptionDataController dataController)
+      : _dataController = dataController,
+        super(FieldTypeOptionEditState.initial(dataController)) {
     on<FieldTypeOptionEditEvent>(
       (event, emit) async {
         event.when(
           initial: () {
-            _fieldListenFn = fieldContext.addFieldListener((field) {
+            _fieldListenFn = dataController.addFieldListener((field) {
               add(FieldTypeOptionEditEvent.didReceiveFieldUpdated(field));
             });
           },
@@ -33,7 +33,7 @@ class FieldTypeOptionEditBloc extends Bloc<FieldTypeOptionEditEvent, FieldTypeOp
   @override
   Future<void> close() async {
     if (_fieldListenFn != null) {
-      _fieldContext.removeFieldListener(_fieldListenFn!);
+      _dataController.removeFieldListener(_fieldListenFn!);
     }
     return super.close();
   }
@@ -51,7 +51,7 @@ class FieldTypeOptionEditState with _$FieldTypeOptionEditState {
     required Field field,
   }) = _FieldTypeOptionEditState;
 
-  factory FieldTypeOptionEditState.initial(GridFieldContext fieldContext) => FieldTypeOptionEditState(
+  factory FieldTypeOptionEditState.initial(TypeOptionDataController fieldContext) => FieldTypeOptionEditState(
         field: fieldContext.field,
       );
 }

+ 4 - 4
frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart

@@ -13,12 +13,12 @@ class MultiSelectTypeOptionContext extends TypeOptionWidgetContext<MultiSelectTy
 
   MultiSelectTypeOptionContext({
     required MultiSelectTypeOptionWidgetDataParser dataBuilder,
-    required GridFieldContext fieldContext,
+    required TypeOptionDataController dataController,
   })  : service = TypeOptionService(
-          gridId: fieldContext.gridId,
-          fieldId: fieldContext.field.id,
+          gridId: dataController.gridId,
+          fieldId: dataController.field.id,
         ),
-        super(dataParser: dataBuilder, fieldContext: fieldContext);
+        super(dataParser: dataBuilder, dataController: dataController);
 
   @override
   List<SelectOption> Function(SelectOption) get deleteOption {

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart

@@ -13,12 +13,12 @@ class SingleSelectTypeOptionContext extends TypeOptionWidgetContext<SingleSelect
 
   SingleSelectTypeOptionContext({
     required SingleSelectTypeOptionWidgetDataParser dataBuilder,
-    required GridFieldContext fieldContext,
+    required TypeOptionDataController fieldContext,
   })  : service = TypeOptionService(
           gridId: fieldContext.gridId,
           fieldId: fieldContext.field.id,
         ),
-        super(dataParser: dataBuilder, fieldContext: fieldContext);
+        super(dataParser: dataBuilder, dataController: fieldContext);
 
   @override
   List<SelectOption> Function(SelectOption) get deleteOption {

+ 7 - 7
frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart

@@ -39,30 +39,30 @@ abstract class TypeOptionDataParser<T> {
 
 class TypeOptionWidgetContext<T extends GeneratedMessage> {
   T? _typeOptionObject;
-  final GridFieldContext _fieldContext;
+  final TypeOptionDataController _dataController;
   final TypeOptionDataParser<T> dataParser;
 
   TypeOptionWidgetContext({
     required this.dataParser,
-    required GridFieldContext fieldContext,
-  }) : _fieldContext = fieldContext;
+    required TypeOptionDataController dataController,
+  }) : _dataController = dataController;
 
-  String get gridId => _fieldContext.gridId;
+  String get gridId => _dataController.gridId;
 
-  Field get field => _fieldContext.field;
+  Field get field => _dataController.field;
 
   T get typeOption {
     if (_typeOptionObject != null) {
       return _typeOptionObject!;
     }
 
-    final T object = dataParser.fromBuffer(_fieldContext.typeOptionData);
+    final T object = dataParser.fromBuffer(_dataController.typeOptionData);
     _typeOptionObject = object;
     return object;
   }
 
   set typeOption(T typeOption) {
-    _fieldContext.typeOptionData = typeOption.writeToBuffer();
+    _dataController.typeOptionData = typeOption.writeToBuffer();
     _typeOptionObject = typeOption;
   }
 }

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart

@@ -65,7 +65,7 @@ class GridFieldCell extends StatelessWidget {
     FieldEditor(
       gridId: state.gridId,
       fieldName: field.name,
-      contextLoader: FieldTypeOptionLoader(
+      typeOptionLoader: FieldTypeOptionLoader(
         gridId: state.gridId,
         field: field,
       ),

+ 9 - 6
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart

@@ -14,11 +14,11 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
   final String gridId;
   final String fieldName;
 
-  final IFieldTypeOptionLoader contextLoader;
+  final IFieldTypeOptionLoader typeOptionLoader;
   const FieldEditor({
     required this.gridId,
     required this.fieldName,
-    required this.contextLoader,
+    required this.typeOptionLoader,
     Key? key,
   }) : super(key: key);
 
@@ -28,7 +28,7 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
       create: (context) => FieldEditorBloc(
         gridId: gridId,
         fieldName: fieldName,
-        fieldContextLoader: contextLoader,
+        loader: typeOptionLoader,
       )..add(const FieldEditorEvent.initial()),
       child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
         buildWhen: (p, c) => false,
@@ -80,11 +80,14 @@ class _FieldTypeOptionCell extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return BlocBuilder<FieldEditorBloc, FieldEditorState>(
-      buildWhen: (p, c) => p.fieldContext != c.fieldContext,
+      buildWhen: (p, c) => p.field != c.field,
       builder: (context, state) {
-        return state.fieldContext.fold(
+        return state.field.fold(
           () => const SizedBox(),
-          (fieldContext) => FieldTypeOptionEditor(fieldContext: fieldContext),
+          (fieldContext) {
+            final dataController = context.read<FieldEditorBloc>().dataController;
+            return FieldTypeOptionEditor(dataController: dataController);
+          },
         );
       },
     );

+ 7 - 6
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart

@@ -22,10 +22,10 @@ typedef SwitchToFieldCallback = Future<Either<FieldTypeOptionData, FlowyError>>
 );
 
 class FieldTypeOptionEditor extends StatefulWidget {
-  final GridFieldContext fieldContext;
+  final TypeOptionDataController dataController;
 
   const FieldTypeOptionEditor({
-    required this.fieldContext,
+    required this.dataController,
     Key? key,
   }) : super(key: key);
 
@@ -39,10 +39,11 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
   @override
   Widget build(BuildContext context) {
     return BlocProvider(
-      create: (context) => FieldTypeOptionEditBloc(widget.fieldContext)..add(const FieldTypeOptionEditEvent.initial()),
+      create: (context) =>
+          FieldTypeOptionEditBloc(widget.dataController)..add(const FieldTypeOptionEditEvent.initial()),
       child: BlocBuilder<FieldTypeOptionEditBloc, FieldTypeOptionEditState>(
         builder: (context, state) {
-          List<Widget> children = [_switchFieldTypeButton(context, widget.fieldContext.field)];
+          List<Widget> children = [_switchFieldTypeButton(context, widget.dataController.field)];
           final typeOptionWidget = _typeOptionWidget(context: context, state: state);
 
           if (typeOptionWidget != null) {
@@ -68,7 +69,7 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
         hoverColor: theme.hover,
         onTap: () {
           final list = FieldTypeList(onSelectField: (newFieldType) {
-            widget.fieldContext.switchToField(newFieldType);
+            widget.dataController.switchToField(newFieldType);
           });
           _showOverlay(context, list);
         },
@@ -89,7 +90,7 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
 
     return makeTypeOptionWidget(
       context: context,
-      fieldContext: widget.fieldContext,
+      dataController: widget.dataController,
       overlayDelegate: overlayDelegate,
     );
   }

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart

@@ -151,7 +151,7 @@ class CreateFieldButton extends StatelessWidget {
       onTap: () => FieldEditor(
         gridId: gridId,
         fieldName: "",
-        contextLoader: NewFieldTypeOptionLoader(gridId: gridId),
+        typeOptionLoader: NewFieldTypeOptionLoader(gridId: gridId),
       ).show(context),
       leftIcon: svgWidget("home/add"),
     );

+ 11 - 11
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/builder.dart

@@ -36,27 +36,27 @@ abstract class TypeOptionWidgetBuilder {
 
 Widget? makeTypeOptionWidget({
   required BuildContext context,
-  required GridFieldContext fieldContext,
+  required TypeOptionDataController dataController,
   required TypeOptionOverlayDelegate overlayDelegate,
 }) {
-  final builder = makeTypeOptionWidgetBuilder(fieldContext, overlayDelegate);
+  final builder = makeTypeOptionWidgetBuilder(dataController, overlayDelegate);
   return builder.build(context);
 }
 
 TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
-  GridFieldContext fieldContext,
+  TypeOptionDataController dataController,
   TypeOptionOverlayDelegate overlayDelegate,
 ) {
-  switch (fieldContext.field.fieldType) {
+  switch (dataController.field.fieldType) {
     case FieldType.Checkbox:
       final context = CheckboxTypeOptionContext(
-        fieldContext: fieldContext,
+        dataController: dataController,
         dataParser: CheckboxTypeOptionWidgetDataParser(),
       );
       return CheckboxTypeOptionWidgetBuilder(context);
     case FieldType.DateTime:
       final context = DateTypeOptionContext(
-        fieldContext: fieldContext,
+        dataController: dataController,
         dataParser: DateTypeOptionDataParser(),
       );
       return DateTypeOptionWidgetBuilder(
@@ -65,7 +65,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
       );
     case FieldType.SingleSelect:
       final context = SingleSelectTypeOptionContext(
-        fieldContext: fieldContext,
+        fieldContext: dataController,
         dataBuilder: SingleSelectTypeOptionWidgetDataParser(),
       );
       return SingleSelectTypeOptionWidgetBuilder(
@@ -74,7 +74,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
       );
     case FieldType.MultiSelect:
       final context = MultiSelectTypeOptionContext(
-        fieldContext: fieldContext,
+        dataController: dataController,
         dataBuilder: MultiSelectTypeOptionWidgetDataParser(),
       );
       return MultiSelectTypeOptionWidgetBuilder(
@@ -83,7 +83,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
       );
     case FieldType.Number:
       final context = NumberTypeOptionContext(
-        fieldContext: fieldContext,
+        dataController: dataController,
         dataParser: NumberTypeOptionWidgetDataParser(),
       );
       return NumberTypeOptionWidgetBuilder(
@@ -92,14 +92,14 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
       );
     case FieldType.RichText:
       final context = RichTextTypeOptionContext(
-        fieldContext: fieldContext,
+        dataController: dataController,
         dataParser: RichTextTypeOptionWidgetDataParser(),
       );
       return RichTextTypeOptionWidgetBuilder(context);
 
     case FieldType.URL:
       final context = URLTypeOptionContext(
-        fieldContext: fieldContext,
+        dataController: dataController,
         dataParser: URLTypeOptionWidgetDataParser(),
       );
       return URLTypeOptionWidgetBuilder(context);

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart

@@ -183,7 +183,7 @@ class _RowDetailCell extends StatelessWidget {
     FieldEditor(
       gridId: cellId.gridId,
       fieldName: cellId.field.name,
-      contextLoader: FieldTypeOptionLoader(
+      typeOptionLoader: FieldTypeOptionLoader(
         gridId: cellId.gridId,
         field: cellId.field,
       ),

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart

@@ -116,7 +116,7 @@ class _GridPropertyCell extends StatelessWidget {
         FieldEditor(
           gridId: gridId,
           fieldName: field.name,
-          contextLoader: FieldTypeOptionLoader(gridId: gridId, field: field),
+          typeOptionLoader: FieldTypeOptionLoader(gridId: gridId, field: field),
         ).show(context, anchorDirection: AnchorDirection.bottomRight);
       },
     );