Explorar el Código

refactor: TypeOptionContext

appflowy hace 3 años
padre
commit
1267c7524e
Se han modificado 16 ficheros con 211 adiciones y 114 borrados
  1. 0 10
      frontend/app_flowy/lib/startup/deps_resolver.dart
  2. 12 1
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart
  3. 15 3
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart
  4. 12 1
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart
  5. 11 4
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart
  6. 19 2
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart
  7. 0 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart
  8. 0 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart
  9. 63 41
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart
  10. 20 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart
  11. 7 11
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart
  12. 8 12
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart
  13. 10 12
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart
  14. 21 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart
  15. 5 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart
  16. 8 12
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart

+ 0 - 10
frontend/app_flowy/lib/startup/deps_resolver.dart

@@ -15,8 +15,6 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:get_it/get_it.dart';
 
@@ -187,14 +185,6 @@ void _resolveGridDeps(GetIt getIt) {
     ),
   );
 
-  getIt.registerFactoryParam<DateTypeOptionBloc, DateTypeOption, void>(
-    (typeOption, _) => DateTypeOptionBloc(typeOption: typeOption),
-  );
-
-  getIt.registerFactoryParam<NumberTypeOptionBloc, NumberTypeOption, void>(
-    (typeOption, _) => NumberTypeOptionBloc(typeOption: typeOption),
-  );
-
   getIt.registerFactoryParam<GridPropertyBloc, String, GridFieldCache>(
     (gridId, cache) => GridPropertyBloc(gridId: gridId, fieldCache: cache),
   );

+ 12 - 1
frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart

@@ -1,3 +1,4 @@
+import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -5,8 +6,18 @@ import 'dart:async';
 import 'package:protobuf/protobuf.dart';
 part 'date_bloc.freezed.dart';
 
+typedef DateTypeOptionContext = TypeOptionContext<DateTypeOption>;
+
+class DateTypeOptionDataBuilder extends TypeOptionDataBuilder<DateTypeOption> {
+  @override
+  DateTypeOption fromBuffer(List<int> buffer) {
+    return DateTypeOption.fromBuffer(buffer);
+  }
+}
+
 class DateTypeOptionBloc extends Bloc<DateTypeOptionEvent, DateTypeOptionState> {
-  DateTypeOptionBloc({required DateTypeOption typeOption}) : super(DateTypeOptionState.initial(typeOption)) {
+  DateTypeOptionBloc({required DateTypeOptionContext typeOptionContext})
+      : super(DateTypeOptionState.initial(typeOptionContext.typeOption)) {
     on<DateTypeOptionEvent>(
       (event, emit) async {
         event.map(

+ 15 - 3
frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart

@@ -8,12 +8,24 @@ import 'type_option_service.dart';
 
 part 'multi_select_bloc.freezed.dart';
 
+typedef MultiSelectTypeOptionContext = TypeOptionContext<MultiSelectTypeOption>;
+
+class MultiSelectTypeOptionDataBuilder extends TypeOptionDataBuilder<MultiSelectTypeOption> {
+  @override
+  MultiSelectTypeOption fromBuffer(List<int> buffer) {
+    return MultiSelectTypeOption.fromBuffer(buffer);
+  }
+}
+
 class MultiSelectTypeOptionBloc extends Bloc<MultiSelectTypeOptionEvent, MultiSelectTypeOptionState> {
   final TypeOptionService service;
 
-  MultiSelectTypeOptionBloc(TypeOptionContext typeOptionContext)
-      : service = TypeOptionService(gridId: typeOptionContext.gridId, fieldId: typeOptionContext.field.id),
-        super(MultiSelectTypeOptionState.initial(MultiSelectTypeOption.fromBuffer(typeOptionContext.data))) {
+  MultiSelectTypeOptionBloc(MultiSelectTypeOptionContext typeOptionContext)
+      : service = TypeOptionService(
+          gridId: typeOptionContext.gridId,
+          fieldId: typeOptionContext.field.id,
+        ),
+        super(MultiSelectTypeOptionState.initial(typeOptionContext.typeOption)) {
     on<MultiSelectTypeOptionEvent>(
       (event, emit) async {
         await event.map(

+ 12 - 1
frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart

@@ -1,3 +1,4 @@
+import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -6,8 +7,18 @@ import 'package:protobuf/protobuf.dart';
 
 part 'number_bloc.freezed.dart';
 
+typedef NumberTypeOptionContext = TypeOptionContext<NumberTypeOption>;
+
+class NumberTypeOptionDataBuilder extends TypeOptionDataBuilder<NumberTypeOption> {
+  @override
+  NumberTypeOption fromBuffer(List<int> buffer) {
+    return NumberTypeOption.fromBuffer(buffer);
+  }
+}
+
 class NumberTypeOptionBloc extends Bloc<NumberTypeOptionEvent, NumberTypeOptionState> {
-  NumberTypeOptionBloc({required NumberTypeOption typeOption}) : super(NumberTypeOptionState.initial(typeOption)) {
+  NumberTypeOptionBloc({required NumberTypeOptionContext typeOptionContext})
+      : super(NumberTypeOptionState.initial(typeOptionContext.typeOption)) {
     on<NumberTypeOptionEvent>(
       (event, emit) async {
         event.map(

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

@@ -8,15 +8,22 @@ import 'type_option_service.dart';
 
 part 'single_select_bloc.freezed.dart';
 
+typedef SingleSelectTypeOptionContext = TypeOptionContext<SingleSelectTypeOption>;
+
+class SingleSelectTypeOptionDataBuilder extends TypeOptionDataBuilder<SingleSelectTypeOption> {
+  @override
+  SingleSelectTypeOption fromBuffer(List<int> buffer) {
+    return SingleSelectTypeOption.fromBuffer(buffer);
+  }
+}
+
 class SingleSelectTypeOptionBloc extends Bloc<SingleSelectTypeOptionEvent, SingleSelectTypeOptionState> {
   final TypeOptionService service;
 
   SingleSelectTypeOptionBloc(
-    TypeOptionContext typeOptionContext,
+    SingleSelectTypeOptionContext typeOptionContext,
   )   : service = TypeOptionService(gridId: typeOptionContext.gridId, fieldId: typeOptionContext.field.id),
-        super(
-          SingleSelectTypeOptionState.initial(SingleSelectTypeOption.fromBuffer(typeOptionContext.data)),
-        ) {
+        super(SingleSelectTypeOptionState.initial(typeOptionContext.typeOption)) {
     on<SingleSelectTypeOptionEvent>(
       (event, emit) async {
         await event.map(

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

@@ -8,6 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
+import 'package:protobuf/protobuf.dart';
 
 class TypeOptionService {
   final String gridId;
@@ -37,10 +38,13 @@ abstract class TypeOptionDataBuilder<T> {
   T fromBuffer(List<int> buffer);
 }
 
-class TypeOptionContext {
+class TypeOptionContext<T extends GeneratedMessage> {
+  T? _typeOptionObject;
   final GridFieldContext _fieldContext;
+  final TypeOptionDataBuilder<T> dataBuilder;
 
   TypeOptionContext({
+    required this.dataBuilder,
     required GridFieldContext fieldContext,
   }) : _fieldContext = fieldContext;
 
@@ -48,7 +52,20 @@ class TypeOptionContext {
 
   Field get field => _fieldContext.field;
 
-  Uint8List get data => Uint8List.fromList(_fieldContext.typeOptionData);
+  T get typeOption {
+    if (_typeOptionObject != null) {
+      return _typeOptionObject!;
+    }
+
+    final T object = dataBuilder.fromBuffer(_fieldContext.typeOptionData);
+    _typeOptionObject = object;
+    return object;
+  }
+
+  set typeOption(T typeOption) {
+    _fieldContext.typeOptionData = typeOption.writeToBuffer();
+    _typeOptionObject = null;
+  }
 }
 
 abstract class TypeOptionFieldDelegate {

+ 0 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart

@@ -1,8 +1,6 @@
-import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
-import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:easy_localization/easy_localization.dart';

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart

@@ -7,7 +7,6 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
-import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';

+ 63 - 41
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart

@@ -1,6 +1,8 @@
 import 'dart:typed_data';
 
+import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart';
 import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart';
 import 'package:dartz/dartz.dart' show Either;
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
@@ -9,8 +11,6 @@ import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:app_flowy/workspace/application/grid/prelude.dart';
@@ -20,6 +20,7 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header
 import 'field_type_extension.dart';
 import 'type_option/multi_select.dart';
 import 'type_option/number.dart';
+import 'type_option/rich_text.dart';
 import 'type_option/single_select.dart';
 
 typedef UpdateFieldCallback = void Function(Field, Uint8List);
@@ -94,14 +95,9 @@ class _FieldEditorPannelState extends State<FieldEditorPannel> {
       hideOverlay: _hideOverlay,
     );
 
-    final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) {
-      widget.fieldContext.typeOptionData = data;
-    });
-
     final builder = _makeTypeOptionBuild(
-      typeOptionContext: TypeOptionContext(fieldContext: widget.fieldContext),
+      typeOptionContext: _makeTypeOptionContext(widget.fieldContext),
       overlayDelegate: overlayDelegate,
-      dataDelegate: dataDelegate,
     );
 
     return builder.customWidget;
@@ -141,27 +137,79 @@ abstract class TypeOptionBuilder {
 TypeOptionBuilder _makeTypeOptionBuild({
   required TypeOptionContext typeOptionContext,
   required TypeOptionOverlayDelegate overlayDelegate,
-  required TypeOptionDataDelegate dataDelegate,
 }) {
   switch (typeOptionContext.field.fieldType) {
     case FieldType.Checkbox:
-      return CheckboxTypeOptionBuilder(typeOptionContext.data);
+      return CheckboxTypeOptionBuilder(
+        typeOptionContext as CheckboxTypeOptionContext,
+      );
     case FieldType.DateTime:
-      return DateTypeOptionBuilder(typeOptionContext.data, overlayDelegate, dataDelegate);
+      return DateTypeOptionBuilder(
+        typeOptionContext as DateTypeOptionContext,
+        overlayDelegate,
+      );
     case FieldType.SingleSelect:
-      return SingleSelectTypeOptionBuilder(typeOptionContext, overlayDelegate, dataDelegate);
+      return SingleSelectTypeOptionBuilder(
+        typeOptionContext as SingleSelectTypeOptionContext,
+        overlayDelegate,
+      );
     case FieldType.MultiSelect:
-      return MultiSelectTypeOptionBuilder(typeOptionContext, overlayDelegate, dataDelegate);
+      return MultiSelectTypeOptionBuilder(
+        typeOptionContext as MultiSelectTypeOptionContext,
+        overlayDelegate,
+      );
     case FieldType.Number:
-      return NumberTypeOptionBuilder(typeOptionContext.data, overlayDelegate, dataDelegate);
+      return NumberTypeOptionBuilder(
+        typeOptionContext as NumberTypeOptionContext,
+        overlayDelegate,
+      );
     case FieldType.RichText:
-      return RichTextTypeOptionBuilder(typeOptionContext.data);
+      return RichTextTypeOptionBuilder(
+        typeOptionContext as RichTextTypeOptionContext,
+      );
 
     default:
       throw UnimplementedError;
   }
 }
 
+TypeOptionContext _makeTypeOptionContext(GridFieldContext fieldContext) {
+  switch (fieldContext.field.fieldType) {
+    case FieldType.Checkbox:
+      return CheckboxTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: CheckboxTypeOptionDataBuilder(),
+      );
+    case FieldType.DateTime:
+      return DateTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: DateTypeOptionDataBuilder(),
+      );
+    case FieldType.MultiSelect:
+      return MultiSelectTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: MultiSelectTypeOptionDataBuilder(),
+      );
+    case FieldType.Number:
+      return NumberTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: NumberTypeOptionDataBuilder(),
+      );
+    case FieldType.RichText:
+      return RichTextTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: RichTextTypeOptionDataBuilder(),
+      );
+    case FieldType.SingleSelect:
+      return SingleSelectTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: SingleSelectTypeOptionDataBuilder(),
+      );
+    default:
+      throw UnimplementedError();
+  }
+}
+
 abstract class TypeOptionWidget extends StatelessWidget {
   const TypeOptionWidget({Key? key}) : super(key: key);
 }
@@ -183,29 +231,3 @@ class TypeOptionOverlayDelegate {
     required this.hideOverlay,
   });
 }
-
-class TypeOptionDataDelegate {
-  TypeOptionDataCallback didUpdateTypeOptionData;
-
-  TypeOptionDataDelegate({
-    required this.didUpdateTypeOptionData,
-  });
-}
-
-class RichTextTypeOptionBuilder extends TypeOptionBuilder {
-  RichTextTypeOption typeOption;
-
-  RichTextTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = RichTextTypeOption.fromBuffer(typeOptionData);
-
-  @override
-  Widget? get customWidget => null;
-}
-
-class CheckboxTypeOptionBuilder extends TypeOptionBuilder {
-  CheckboxTypeOption typeOption;
-
-  CheckboxTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = CheckboxTypeOption.fromBuffer(typeOptionData);
-
-  @override
-  Widget? get customWidget => null;
-}

+ 20 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart

@@ -0,0 +1,20 @@
+import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart';
+import 'package:flutter/material.dart';
+
+typedef CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOption>;
+
+class CheckboxTypeOptionDataBuilder extends TypeOptionDataBuilder<CheckboxTypeOption> {
+  @override
+  CheckboxTypeOption fromBuffer(List<int> buffer) {
+    return CheckboxTypeOption.fromBuffer(buffer);
+  }
+}
+
+class CheckboxTypeOptionBuilder extends TypeOptionBuilder {
+  CheckboxTypeOptionBuilder(CheckboxTypeOptionContext typeOptionContext);
+
+  @override
+  Widget? get customWidget => null;
+}

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

@@ -1,4 +1,3 @@
-import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/field/type_option/date_bloc.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
@@ -18,12 +17,10 @@ class DateTypeOptionBuilder extends TypeOptionBuilder {
   final DateTypeOptionWidget _widget;
 
   DateTypeOptionBuilder(
-    TypeOptionData typeOptionData,
+    DateTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
-    TypeOptionDataDelegate dataDelegate,
   ) : _widget = DateTypeOptionWidget(
-          typeOption: DateTypeOption.fromBuffer(typeOptionData),
-          dataDelegate: dataDelegate,
+          typeOptionContext: typeOptionContext,
           overlayDelegate: overlayDelegate,
         );
 
@@ -32,12 +29,11 @@ class DateTypeOptionBuilder extends TypeOptionBuilder {
 }
 
 class DateTypeOptionWidget extends TypeOptionWidget {
-  final DateTypeOption typeOption;
+  final DateTypeOptionContext typeOptionContext;
   final TypeOptionOverlayDelegate overlayDelegate;
-  final TypeOptionDataDelegate dataDelegate;
+
   const DateTypeOptionWidget({
-    required this.typeOption,
-    required this.dataDelegate,
+    required this.typeOptionContext,
     required this.overlayDelegate,
     Key? key,
   }) : super(key: key);
@@ -45,9 +41,9 @@ class DateTypeOptionWidget extends TypeOptionWidget {
   @override
   Widget build(BuildContext context) {
     return BlocProvider(
-      create: (context) => getIt<DateTypeOptionBloc>(param1: typeOption),
+      create: (context) => DateTypeOptionBloc(typeOptionContext: typeOptionContext),
       child: BlocConsumer<DateTypeOptionBloc, DateTypeOptionState>(
-        listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()),
+        listener: (context, state) => typeOptionContext.typeOption = state.typeOption,
         builder: (context, state) {
           return Column(children: [
             _renderDateFormatButton(context, state.typeOption.dateFormat),

+ 8 - 12
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart

@@ -1,5 +1,4 @@
 import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart';
-import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -10,13 +9,11 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
   final MultiSelectTypeOptionWidget _widget;
 
   MultiSelectTypeOptionBuilder(
-    TypeOptionContext typeOptionContext,
+    MultiSelectTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
-    TypeOptionDataDelegate dataDelegate,
   ) : _widget = MultiSelectTypeOptionWidget(
           typeOptionContext: typeOptionContext,
           overlayDelegate: overlayDelegate,
-          dataDelegate: dataDelegate,
         );
 
   @override
@@ -24,13 +21,12 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
 }
 
 class MultiSelectTypeOptionWidget extends TypeOptionWidget {
-  final TypeOptionContext typeOptionContext;
+  final MultiSelectTypeOptionContext typeOptionContext;
   final TypeOptionOverlayDelegate overlayDelegate;
-  final TypeOptionDataDelegate dataDelegate;
+
   const MultiSelectTypeOptionWidget({
     required this.typeOptionContext,
     required this.overlayDelegate,
-    required this.dataDelegate,
     Key? key,
   }) : super(key: key);
 
@@ -40,7 +36,7 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget {
       create: (context) => MultiSelectTypeOptionBloc(typeOptionContext),
       child: BlocConsumer<MultiSelectTypeOptionBloc, MultiSelectTypeOptionState>(
         listener: (context, state) {
-          dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer());
+          typeOptionContext.typeOption = state.typeOption;
         },
         builder: (context, state) {
           return SelectOptionTypeOptionWidget(
@@ -51,11 +47,11 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget {
             createSelectOptionCallback: (name) {
               context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.createOption(name));
             },
-            updateSelectOptionCallback: (updateOption) {
-              context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.updateOption(updateOption));
+            updateSelectOptionCallback: (option) {
+              context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.updateOption(option));
             },
-            deleteSelectOptionCallback: (deleteOption) {
-              context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.deleteOption(deleteOption));
+            deleteSelectOptionCallback: (option) {
+              context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.deleteOption(option));
             },
             overlayDelegate: overlayDelegate,
             // key: ValueKey(state.typeOption.hashCode),

+ 10 - 12
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart

@@ -1,4 +1,3 @@
-import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/field/type_option/number_bloc.dart';
 import 'package:app_flowy/workspace/application/grid/field/type_option/number_format_bloc.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
@@ -20,12 +19,10 @@ class NumberTypeOptionBuilder extends TypeOptionBuilder {
   final NumberTypeOptionWidget _widget;
 
   NumberTypeOptionBuilder(
-    TypeOptionData typeOptionData,
+    NumberTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
-    TypeOptionDataDelegate dataDelegate,
   ) : _widget = NumberTypeOptionWidget(
-          typeOption: NumberTypeOption.fromBuffer(typeOptionData),
-          dataDelegate: dataDelegate,
+          typeOptionContext: typeOptionContext,
           overlayDelegate: overlayDelegate,
         );
 
@@ -34,22 +31,23 @@ class NumberTypeOptionBuilder extends TypeOptionBuilder {
 }
 
 class NumberTypeOptionWidget extends TypeOptionWidget {
-  final TypeOptionDataDelegate dataDelegate;
   final TypeOptionOverlayDelegate overlayDelegate;
-  final NumberTypeOption typeOption;
-  const NumberTypeOptionWidget(
-      {required this.typeOption, required this.dataDelegate, required this.overlayDelegate, Key? key})
-      : super(key: key);
+  final NumberTypeOptionContext typeOptionContext;
+  const NumberTypeOptionWidget({
+    required this.typeOptionContext,
+    required this.overlayDelegate,
+    Key? key,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     return BlocProvider(
-      create: (context) => getIt<NumberTypeOptionBloc>(param1: typeOption),
+      create: (context) => NumberTypeOptionBloc(typeOptionContext: typeOptionContext),
       child: SizedBox(
         height: GridSize.typeOptionItemHeight,
         child: BlocConsumer<NumberTypeOptionBloc, NumberTypeOptionState>(
-          listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()),
+          listener: (context, state) => typeOptionContext.typeOption = state.typeOption,
           builder: (context, state) {
             return FlowyButton(
               text: Row(

+ 21 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart

@@ -0,0 +1,21 @@
+import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart';
+
+import 'package:flutter/material.dart';
+
+typedef RichTextTypeOptionContext = TypeOptionContext<RichTextTypeOption>;
+
+class RichTextTypeOptionDataBuilder extends TypeOptionDataBuilder<RichTextTypeOption> {
+  @override
+  RichTextTypeOption fromBuffer(List<int> buffer) {
+    return RichTextTypeOption.fromBuffer(buffer);
+  }
+}
+
+class RichTextTypeOptionBuilder extends TypeOptionBuilder {
+  RichTextTypeOptionBuilder(RichTextTypeOptionContext typeOptionContext);
+
+  @override
+  Widget? get customWidget => null;
+}

+ 5 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart

@@ -6,7 +6,6 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
-import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
@@ -63,7 +62,11 @@ class SelectOptionTypeOptionWidget extends StatelessWidget {
           List<Widget> children = [
             const TypeOptionSeparator(),
             const OptionTitle(),
-            if (state.isEditingOption) const _CreateOptionTextField(),
+            if (state.isEditingOption)
+              const Padding(
+                padding: EdgeInsets.only(bottom: 10),
+                child: _CreateOptionTextField(),
+              ),
             if (state.options.isEmpty && !state.isEditingOption) const _AddOptionButton(),
             _OptionList(overlayDelegate)
           ];

+ 8 - 12
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart

@@ -1,5 +1,4 @@
 import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart';
-import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -9,12 +8,10 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder {
   final SingleSelectTypeOptionWidget _widget;
 
   SingleSelectTypeOptionBuilder(
-    TypeOptionContext typeOptionContext,
+    SingleSelectTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
-    TypeOptionDataDelegate dataDelegate,
   ) : _widget = SingleSelectTypeOptionWidget(
           typeOptionContext: typeOptionContext,
-          dataDelegate: dataDelegate,
           overlayDelegate: overlayDelegate,
         );
 
@@ -23,12 +20,11 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder {
 }
 
 class SingleSelectTypeOptionWidget extends TypeOptionWidget {
-  final TypeOptionContext typeOptionContext;
+  final SingleSelectTypeOptionContext typeOptionContext;
   final TypeOptionOverlayDelegate overlayDelegate;
-  final TypeOptionDataDelegate dataDelegate;
+
   const SingleSelectTypeOptionWidget({
     required this.typeOptionContext,
-    required this.dataDelegate,
     required this.overlayDelegate,
     Key? key,
   }) : super(key: key);
@@ -39,7 +35,7 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget {
       create: (context) => SingleSelectTypeOptionBloc(typeOptionContext),
       child: BlocConsumer<SingleSelectTypeOptionBloc, SingleSelectTypeOptionState>(
         listener: (context, state) {
-          dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer());
+          typeOptionContext.typeOption = state.typeOption;
         },
         builder: (context, state) {
           return SelectOptionTypeOptionWidget(
@@ -50,11 +46,11 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget {
             createSelectOptionCallback: (name) {
               context.read<SingleSelectTypeOptionBloc>().add(SingleSelectTypeOptionEvent.createOption(name));
             },
-            updateSelectOptionCallback: (updateOption) {
-              context.read<SingleSelectTypeOptionBloc>().add(SingleSelectTypeOptionEvent.updateOption(updateOption));
+            updateSelectOptionCallback: (option) {
+              context.read<SingleSelectTypeOptionBloc>().add(SingleSelectTypeOptionEvent.updateOption(option));
             },
-            deleteSelectOptionCallback: (deleteOption) {
-              context.read<SingleSelectTypeOptionBloc>().add(SingleSelectTypeOptionEvent.deleteOption(deleteOption));
+            deleteSelectOptionCallback: (option) {
+              context.read<SingleSelectTypeOptionBloc>().add(SingleSelectTypeOptionEvent.deleteOption(option));
             },
             overlayDelegate: overlayDelegate,
             // key: ValueKey(state.typeOption.hashCode),