瀏覽代碼

chore: rename classes

appflowy 2 年之前
父節點
當前提交
4825d83d2f
共有 19 個文件被更改,包括 314 次插入316 次删除
  1. 13 13
      frontend/app_flowy/lib/workspace/application/grid/field/field_type_option_edit_bloc.dart
  2. 2 2
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart
  3. 4 3
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart
  4. 2 2
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart
  5. 3 3
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart
  6. 5 5
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart
  7. 1 1
      frontend/app_flowy/lib/workspace/application/grid/prelude.dart
  8. 8 8
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart
  9. 0 243
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart
  10. 126 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart
  11. 108 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/builder.dart
  12. 6 6
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart
  13. 7 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart
  14. 5 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart
  15. 6 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart
  16. 6 7
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart
  17. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart
  18. 5 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart
  19. 6 6
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/url.dart

+ 13 - 13
frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart → frontend/app_flowy/lib/workspace/application/grid/field/field_type_option_edit_bloc.dart

@@ -5,21 +5,21 @@ import 'dart:async';
 
 import 'field_service.dart';
 
-part 'field_editor_pannel_bloc.freezed.dart';
+part 'field_type_option_edit_bloc.freezed.dart';
 
-class FieldEditorPannelBloc extends Bloc<FieldEditorPannelEvent, FieldEditorPannelState> {
+class FieldTypeOptionEditBloc extends Bloc<FieldTypeOptionEditEvent, FieldTypeOptionEditState> {
   final GridFieldContext _fieldContext;
   void Function()? _fieldListenFn;
 
-  FieldEditorPannelBloc(GridFieldContext fieldContext)
+  FieldTypeOptionEditBloc(GridFieldContext fieldContext)
       : _fieldContext = fieldContext,
-        super(FieldEditorPannelState.initial(fieldContext)) {
-    on<FieldEditorPannelEvent>(
+        super(FieldTypeOptionEditState.initial(fieldContext)) {
+    on<FieldTypeOptionEditEvent>(
       (event, emit) async {
         event.when(
           initial: () {
             _fieldListenFn = fieldContext.addFieldListener((field) {
-              add(FieldEditorPannelEvent.didReceiveFieldUpdated(field));
+              add(FieldTypeOptionEditEvent.didReceiveFieldUpdated(field));
             });
           },
           didReceiveFieldUpdated: (field) {
@@ -40,18 +40,18 @@ class FieldEditorPannelBloc extends Bloc<FieldEditorPannelEvent, FieldEditorPann
 }
 
 @freezed
-class FieldEditorPannelEvent with _$FieldEditorPannelEvent {
-  const factory FieldEditorPannelEvent.initial() = _Initial;
-  const factory FieldEditorPannelEvent.didReceiveFieldUpdated(Field field) = _DidReceiveFieldUpdated;
+class FieldTypeOptionEditEvent with _$FieldTypeOptionEditEvent {
+  const factory FieldTypeOptionEditEvent.initial() = _Initial;
+  const factory FieldTypeOptionEditEvent.didReceiveFieldUpdated(Field field) = _DidReceiveFieldUpdated;
 }
 
 @freezed
-class FieldEditorPannelState with _$FieldEditorPannelState {
-  const factory FieldEditorPannelState({
+class FieldTypeOptionEditState with _$FieldTypeOptionEditState {
+  const factory FieldTypeOptionEditState({
     required Field field,
-  }) = _FieldEditorPannelState;
+  }) = _FieldTypeOptionEditState;
 
-  factory FieldEditorPannelState.initial(GridFieldContext fieldContext) => FieldEditorPannelState(
+  factory FieldTypeOptionEditState.initial(GridFieldContext fieldContext) => FieldTypeOptionEditState(
         field: fieldContext.field,
       );
 }

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

@@ -6,9 +6,9 @@ import 'dart:async';
 import 'package:protobuf/protobuf.dart';
 part 'date_bloc.freezed.dart';
 
-typedef DateTypeOptionContext = TypeOptionContext<DateTypeOption>;
+typedef DateTypeOptionContext = TypeOptionWidgetContext<DateTypeOption>;
 
-class DateTypeOptionDataBuilder extends TypeOptionDataBuilder<DateTypeOption> {
+class DateTypeOptionDataParser extends TypeOptionWidgetDataParser<DateTypeOption> {
   @override
   DateTypeOption fromBuffer(List<int> buffer) {
     return DateTypeOption.fromBuffer(buffer);

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

@@ -7,11 +7,12 @@ import 'package:protobuf/protobuf.dart';
 import 'select_option_type_option_bloc.dart';
 import 'type_option_service.dart';
 
-class MultiSelectTypeOptionContext extends TypeOptionContext<MultiSelectTypeOption> with SelectOptionTypeOptionAction {
+class MultiSelectTypeOptionContext extends TypeOptionWidgetContext<MultiSelectTypeOption>
+    with SelectOptionTypeOptionAction {
   final TypeOptionService service;
 
   MultiSelectTypeOptionContext({
-    required MultiSelectTypeOptionDataBuilder dataBuilder,
+    required MultiSelectTypeOptionWidgetDataParser dataBuilder,
     required GridFieldContext fieldContext,
   })  : service = TypeOptionService(
           gridId: fieldContext.gridId,
@@ -70,7 +71,7 @@ class MultiSelectTypeOptionContext extends TypeOptionContext<MultiSelectTypeOpti
   }
 }
 
-class MultiSelectTypeOptionDataBuilder extends TypeOptionDataBuilder<MultiSelectTypeOption> {
+class MultiSelectTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<MultiSelectTypeOption> {
   @override
   MultiSelectTypeOption fromBuffer(List<int> buffer) {
     return MultiSelectTypeOption.fromBuffer(buffer);

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

@@ -8,9 +8,9 @@ import 'package:protobuf/protobuf.dart';
 
 part 'number_bloc.freezed.dart';
 
-typedef NumberTypeOptionContext = TypeOptionContext<NumberTypeOption>;
+typedef NumberTypeOptionContext = TypeOptionWidgetContext<NumberTypeOption>;
 
-class NumberTypeOptionDataBuilder extends TypeOptionDataBuilder<NumberTypeOption> {
+class NumberTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<NumberTypeOption> {
   @override
   NumberTypeOption fromBuffer(List<int> buffer) {
     return NumberTypeOption.fromBuffer(buffer);

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

@@ -7,12 +7,12 @@ import 'package:protobuf/protobuf.dart';
 import 'select_option_type_option_bloc.dart';
 import 'type_option_service.dart';
 
-class SingleSelectTypeOptionContext extends TypeOptionContext<SingleSelectTypeOption>
+class SingleSelectTypeOptionContext extends TypeOptionWidgetContext<SingleSelectTypeOption>
     with SelectOptionTypeOptionAction {
   final TypeOptionService service;
 
   SingleSelectTypeOptionContext({
-    required SingleSelectTypeOptionDataBuilder dataBuilder,
+    required SingleSelectTypeOptionWidgetDataParser dataBuilder,
     required GridFieldContext fieldContext,
   })  : service = TypeOptionService(
           gridId: fieldContext.gridId,
@@ -71,7 +71,7 @@ class SingleSelectTypeOptionContext extends TypeOptionContext<SingleSelectTypeOp
   }
 }
 
-class SingleSelectTypeOptionDataBuilder extends TypeOptionDataBuilder<SingleSelectTypeOption> {
+class SingleSelectTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<SingleSelectTypeOption> {
   @override
   SingleSelectTypeOption fromBuffer(List<int> buffer) {
     return SingleSelectTypeOption.fromBuffer(buffer);

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

@@ -33,16 +33,16 @@ class TypeOptionService {
   }
 }
 
-abstract class TypeOptionDataBuilder<T> {
+abstract class TypeOptionWidgetDataParser<T> {
   T fromBuffer(List<int> buffer);
 }
 
-class TypeOptionContext<T extends GeneratedMessage> {
+class TypeOptionWidgetContext<T extends GeneratedMessage> {
   T? _typeOptionObject;
   final GridFieldContext _fieldContext;
-  final TypeOptionDataBuilder<T> dataBuilder;
+  final TypeOptionWidgetDataParser<T> dataBuilder;
 
-  TypeOptionContext({
+  TypeOptionWidgetContext({
     required this.dataBuilder,
     required GridFieldContext fieldContext,
   }) : _fieldContext = fieldContext;
@@ -77,7 +77,7 @@ class TypeOptionContext2<T> {
   final Field field;
   final FieldService _fieldService;
   T? _data;
-  final TypeOptionDataBuilder dataBuilder;
+  final TypeOptionWidgetDataParser dataBuilder;
 
   TypeOptionContext2({
     required this.gridId,

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/prelude.dart

@@ -8,7 +8,7 @@ export 'grid_header_bloc.dart';
 export 'field/field_service.dart';
 export 'field/field_action_sheet_bloc.dart';
 export 'field/field_editor_bloc.dart';
-export 'field/field_editor_pannel_bloc.dart';
+export 'field/field_type_option_edit_bloc.dart';
 
 // Field Type Option
 export 'field/type_option/date_bloc.dart';

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

@@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'field_name_input.dart';
-import 'field_editor_pannel.dart';
+import 'field_type_option_editor.dart';
 
 class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
   final String gridId;
@@ -38,9 +38,9 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
             children: [
               FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12),
               const VSpace(10),
-              const _FieldNameTextField(),
+              const _FieldNameCell(),
               const VSpace(10),
-              const _FieldPannel(),
+              const _FieldTypeOptionCell(),
             ],
           );
         },
@@ -74,8 +74,8 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
   bool asBarrier() => true;
 }
 
-class _FieldPannel extends StatelessWidget {
-  const _FieldPannel({Key? key}) : super(key: key);
+class _FieldTypeOptionCell extends StatelessWidget {
+  const _FieldTypeOptionCell({Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -84,15 +84,15 @@ class _FieldPannel extends StatelessWidget {
       builder: (context, state) {
         return state.fieldContext.fold(
           () => const SizedBox(),
-          (fieldContext) => FieldEditorPannel(fieldContext: fieldContext),
+          (fieldContext) => FieldTypeOptionEditor(fieldContext: fieldContext),
         );
       },
     );
   }
 }
 
-class _FieldNameTextField extends StatelessWidget {
-  const _FieldNameTextField({Key? key}) : super(key: key);
+class _FieldNameCell extends StatelessWidget {
+  const _FieldNameCell({Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {

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

@@ -1,243 +0,0 @@
-import 'dart:typed_data';
-
-import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.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';
-import 'package:flowy_infra_ui/flowy_infra_ui.dart';
-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/field_entities.pb.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:app_flowy/workspace/application/grid/prelude.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_type_list.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart';
-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';
-import 'type_option/url.dart';
-
-typedef UpdateFieldCallback = void Function(Field, Uint8List);
-typedef SwitchToFieldCallback = Future<Either<FieldTypeOptionData, FlowyError>> Function(
-  String fieldId,
-  FieldType fieldType,
-);
-
-class FieldEditorPannel extends StatefulWidget {
-  final GridFieldContext fieldContext;
-
-  const FieldEditorPannel({
-    required this.fieldContext,
-    Key? key,
-  }) : super(key: key);
-
-  @override
-  State<FieldEditorPannel> createState() => _FieldEditorPannelState();
-}
-
-class _FieldEditorPannelState extends State<FieldEditorPannel> {
-  String? currentOverlayIdentifier;
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocProvider(
-      create: (context) => FieldEditorPannelBloc(widget.fieldContext)..add(const FieldEditorPannelEvent.initial()),
-      child: BlocBuilder<FieldEditorPannelBloc, FieldEditorPannelState>(
-        builder: (context, state) {
-          List<Widget> children = [_switchFieldTypeButton(context, widget.fieldContext.field)];
-          final typeOptionWidget = _typeOptionWidget(context: context, state: state);
-
-          if (typeOptionWidget != null) {
-            children.add(typeOptionWidget);
-          }
-
-          return ListView(
-            shrinkWrap: true,
-            children: children,
-          );
-        },
-      ),
-    );
-  }
-
-  Widget _switchFieldTypeButton(BuildContext context, Field field) {
-    final theme = context.watch<AppTheme>();
-    return SizedBox(
-      height: GridSize.typeOptionItemHeight,
-      child: FlowyButton(
-        text: FlowyText.medium(field.fieldType.title(), fontSize: 12),
-        margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
-        hoverColor: theme.hover,
-        onTap: () {
-          final list = FieldTypeList(onSelectField: (newFieldType) {
-            widget.fieldContext.switchToField(newFieldType);
-          });
-          _showOverlay(context, list);
-        },
-        leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
-        rightIcon: svgWidget("grid/more", color: theme.iconColor),
-      ),
-    );
-  }
-
-  Widget? _typeOptionWidget({
-    required BuildContext context,
-    required FieldEditorPannelState state,
-  }) {
-    final overlayDelegate = TypeOptionOverlayDelegate(
-      showOverlay: _showOverlay,
-      hideOverlay: _hideOverlay,
-    );
-
-    final builder = _makeTypeOptionBuild(
-      typeOptionContext: _makeTypeOptionContext(widget.fieldContext),
-      overlayDelegate: overlayDelegate,
-    );
-
-    return builder.customWidget;
-  }
-
-  void _showOverlay(BuildContext context, Widget child, {VoidCallback? onRemoved}) {
-    final identifier = child.toString();
-    if (currentOverlayIdentifier != null) {
-      FlowyOverlay.of(context).remove(currentOverlayIdentifier!);
-    }
-
-    currentOverlayIdentifier = identifier;
-    FlowyOverlay.of(context).insertWithAnchor(
-      widget: OverlayContainer(
-        child: child,
-        constraints: BoxConstraints.loose(const Size(460, 440)),
-      ),
-      identifier: identifier,
-      anchorContext: context,
-      anchorDirection: AnchorDirection.leftWithCenterAligned,
-      style: FlowyOverlayStyle(blur: false),
-      anchorOffset: const Offset(-20, 0),
-    );
-  }
-
-  void _hideOverlay(BuildContext context) {
-    if (currentOverlayIdentifier != null) {
-      FlowyOverlay.of(context).remove(currentOverlayIdentifier!);
-    }
-  }
-}
-
-abstract class TypeOptionBuilder {
-  Widget? get customWidget;
-}
-
-TypeOptionBuilder _makeTypeOptionBuild({
-  required TypeOptionContext typeOptionContext,
-  required TypeOptionOverlayDelegate overlayDelegate,
-}) {
-  switch (typeOptionContext.field.fieldType) {
-    case FieldType.Checkbox:
-      return CheckboxTypeOptionBuilder(
-        typeOptionContext as CheckboxTypeOptionContext,
-      );
-    case FieldType.DateTime:
-      return DateTypeOptionBuilder(
-        typeOptionContext as DateTypeOptionContext,
-        overlayDelegate,
-      );
-    case FieldType.SingleSelect:
-      return SingleSelectTypeOptionBuilder(
-        typeOptionContext as SingleSelectTypeOptionContext,
-        overlayDelegate,
-      );
-    case FieldType.MultiSelect:
-      return MultiSelectTypeOptionBuilder(
-        typeOptionContext as MultiSelectTypeOptionContext,
-        overlayDelegate,
-      );
-    case FieldType.Number:
-      return NumberTypeOptionBuilder(
-        typeOptionContext as NumberTypeOptionContext,
-        overlayDelegate,
-      );
-    case FieldType.RichText:
-      return RichTextTypeOptionBuilder(
-        typeOptionContext as RichTextTypeOptionContext,
-      );
-
-    case FieldType.URL:
-      return URLTypeOptionBuilder(
-        typeOptionContext as URLTypeOptionContext,
-      );
-  }
-  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(),
-      );
-
-    case FieldType.URL:
-      return URLTypeOptionContext(
-        fieldContext: fieldContext,
-        dataBuilder: URLTypeOptionDataBuilder(),
-      );
-  }
-
-  throw UnimplementedError();
-}
-
-abstract class TypeOptionWidget extends StatelessWidget {
-  const TypeOptionWidget({Key? key}) : super(key: key);
-}
-
-typedef TypeOptionData = Uint8List;
-typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData);
-typedef ShowOverlayCallback = void Function(
-  BuildContext anchorContext,
-  Widget child, {
-  VoidCallback? onRemoved,
-});
-typedef HideOverlayCallback = void Function(BuildContext anchorContext);
-
-class TypeOptionOverlayDelegate {
-  ShowOverlayCallback showOverlay;
-  HideOverlayCallback hideOverlay;
-  TypeOptionOverlayDelegate({
-    required this.showOverlay,
-    required this.hideOverlay,
-  });
-}

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

@@ -0,0 +1,126 @@
+import 'dart:typed_data';
+import 'package:dartz/dartz.dart' show Either;
+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/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/field_entities.pb.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:app_flowy/workspace/application/grid/prelude.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_type_list.dart';
+import 'field_type_extension.dart';
+import 'type_option/builder.dart';
+
+typedef UpdateFieldCallback = void Function(Field, Uint8List);
+typedef SwitchToFieldCallback = Future<Either<FieldTypeOptionData, FlowyError>> Function(
+  String fieldId,
+  FieldType fieldType,
+);
+
+class FieldTypeOptionEditor extends StatefulWidget {
+  final GridFieldContext fieldContext;
+
+  const FieldTypeOptionEditor({
+    required this.fieldContext,
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  State<FieldTypeOptionEditor> createState() => _FieldTypeOptionEditorState();
+}
+
+class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
+  String? currentOverlayIdentifier;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider(
+      create: (context) => FieldTypeOptionEditBloc(widget.fieldContext)..add(const FieldTypeOptionEditEvent.initial()),
+      child: BlocBuilder<FieldTypeOptionEditBloc, FieldTypeOptionEditState>(
+        builder: (context, state) {
+          List<Widget> children = [_switchFieldTypeButton(context, widget.fieldContext.field)];
+          final typeOptionWidget = _typeOptionWidget(context: context, state: state);
+
+          if (typeOptionWidget != null) {
+            children.add(typeOptionWidget);
+          }
+
+          return ListView(
+            shrinkWrap: true,
+            children: children,
+          );
+        },
+      ),
+    );
+  }
+
+  Widget _switchFieldTypeButton(BuildContext context, Field field) {
+    final theme = context.watch<AppTheme>();
+    return SizedBox(
+      height: GridSize.typeOptionItemHeight,
+      child: FlowyButton(
+        text: FlowyText.medium(field.fieldType.title(), fontSize: 12),
+        margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
+        hoverColor: theme.hover,
+        onTap: () {
+          final list = FieldTypeList(onSelectField: (newFieldType) {
+            widget.fieldContext.switchToField(newFieldType);
+          });
+          _showOverlay(context, list);
+        },
+        leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
+        rightIcon: svgWidget("grid/more", color: theme.iconColor),
+      ),
+    );
+  }
+
+  Widget? _typeOptionWidget({
+    required BuildContext context,
+    required FieldTypeOptionEditState state,
+  }) {
+    final overlayDelegate = TypeOptionOverlayDelegate(
+      showOverlay: _showOverlay,
+      hideOverlay: _hideOverlay,
+    );
+
+    return makeTypeOptionWidget(
+      context: context,
+      fieldContext: widget.fieldContext,
+      overlayDelegate: overlayDelegate,
+    );
+  }
+
+  void _showOverlay(BuildContext context, Widget child, {VoidCallback? onRemoved}) {
+    final identifier = child.toString();
+    if (currentOverlayIdentifier != null) {
+      FlowyOverlay.of(context).remove(currentOverlayIdentifier!);
+    }
+
+    currentOverlayIdentifier = identifier;
+    FlowyOverlay.of(context).insertWithAnchor(
+      widget: OverlayContainer(
+        child: child,
+        constraints: BoxConstraints.loose(const Size(460, 440)),
+      ),
+      identifier: identifier,
+      anchorContext: context,
+      anchorDirection: AnchorDirection.leftWithCenterAligned,
+      style: FlowyOverlayStyle(blur: false),
+      anchorOffset: const Offset(-20, 0),
+    );
+  }
+
+  void _hideOverlay(BuildContext context) {
+    if (currentOverlayIdentifier != null) {
+      FlowyOverlay.of(context).remove(currentOverlayIdentifier!);
+    }
+  }
+}
+
+abstract class TypeOptionWidget extends StatelessWidget {
+  const TypeOptionWidget({Key? key}) : super(key: key);
+}

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

@@ -0,0 +1,108 @@
+import 'dart:typed_data';
+
+import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart';
+import 'package:app_flowy/workspace/application/grid/prelude.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
+import 'package:flutter/material.dart';
+import 'date.dart';
+import 'multi_select.dart';
+import 'number.dart';
+import 'rich_text.dart';
+import 'single_select.dart';
+import 'url.dart';
+
+typedef TypeOptionData = Uint8List;
+typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData);
+typedef ShowOverlayCallback = void Function(
+  BuildContext anchorContext,
+  Widget child, {
+  VoidCallback? onRemoved,
+});
+typedef HideOverlayCallback = void Function(BuildContext anchorContext);
+
+class TypeOptionOverlayDelegate {
+  ShowOverlayCallback showOverlay;
+  HideOverlayCallback hideOverlay;
+  TypeOptionOverlayDelegate({
+    required this.showOverlay,
+    required this.hideOverlay,
+  });
+}
+
+abstract class TypeOptionWidgetBuilder {
+  Widget? build(BuildContext context);
+}
+
+Widget? makeTypeOptionWidget({
+  required BuildContext context,
+  required GridFieldContext fieldContext,
+  required TypeOptionOverlayDelegate overlayDelegate,
+}) {
+  final builder = makeTypeOptionWidgetBuilder(fieldContext, overlayDelegate);
+  return builder.build(context);
+}
+
+TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
+  GridFieldContext fieldContext,
+  TypeOptionOverlayDelegate overlayDelegate,
+) {
+  switch (fieldContext.field.fieldType) {
+    case FieldType.Checkbox:
+      final context = CheckboxTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: CheckboxTypeOptionWidgetDataParser(),
+      );
+      return CheckboxTypeOptionWidgetBuilder(context);
+    case FieldType.DateTime:
+      final context = DateTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: DateTypeOptionDataParser(),
+      );
+      return DateTypeOptionWidgetBuilder(
+        context,
+        overlayDelegate,
+      );
+    case FieldType.SingleSelect:
+      final context = SingleSelectTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: SingleSelectTypeOptionWidgetDataParser(),
+      );
+      return SingleSelectTypeOptionWidgetBuilder(
+        context,
+        overlayDelegate,
+      );
+    case FieldType.MultiSelect:
+      final context = MultiSelectTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: MultiSelectTypeOptionWidgetDataParser(),
+      );
+      return MultiSelectTypeOptionWidgetBuilder(
+        context,
+        overlayDelegate,
+      );
+    case FieldType.Number:
+      final context = NumberTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: NumberTypeOptionWidgetDataParser(),
+      );
+      return NumberTypeOptionWidgetBuilder(
+        context,
+        overlayDelegate,
+      );
+    case FieldType.RichText:
+      final context = RichTextTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: RichTextTypeOptionWidgetDataParser(),
+      );
+      return RichTextTypeOptionWidgetBuilder(context);
+
+    case FieldType.URL:
+      final context = URLTypeOptionContext(
+        fieldContext: fieldContext,
+        dataBuilder: URLTypeOptionWidgetDataParser(),
+      );
+      return URLTypeOptionWidgetBuilder(context);
+  }
+  throw UnimplementedError;
+}

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

@@ -1,20 +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';
+import 'builder.dart';
 
-typedef CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOption>;
+typedef CheckboxTypeOptionContext = TypeOptionWidgetContext<CheckboxTypeOption>;
 
-class CheckboxTypeOptionDataBuilder extends TypeOptionDataBuilder<CheckboxTypeOption> {
+class CheckboxTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<CheckboxTypeOption> {
   @override
   CheckboxTypeOption fromBuffer(List<int> buffer) {
     return CheckboxTypeOption.fromBuffer(buffer);
   }
 }
 
-class CheckboxTypeOptionBuilder extends TypeOptionBuilder {
-  CheckboxTypeOptionBuilder(CheckboxTypeOptionContext typeOptionContext);
+class CheckboxTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
+  CheckboxTypeOptionWidgetBuilder(CheckboxTypeOptionContext typeOptionContext);
 
   @override
-  Widget? get customWidget => null;
+  Widget? build(BuildContext context) => null;
 }

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

@@ -1,6 +1,6 @@
 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';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart';
 import 'package:easy_localization/easy_localization.dart' hide DateFormat;
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:flowy_infra/image.dart';
@@ -12,11 +12,12 @@ import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'builder.dart';
 
-class DateTypeOptionBuilder extends TypeOptionBuilder {
+class DateTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
   final DateTypeOptionWidget _widget;
 
-  DateTypeOptionBuilder(
+  DateTypeOptionWidgetBuilder(
     DateTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
   ) : _widget = DateTypeOptionWidget(
@@ -25,7 +26,9 @@ class DateTypeOptionBuilder extends TypeOptionBuilder {
         );
 
   @override
-  Widget? get customWidget => _widget;
+  Widget? build(BuildContext context) {
+    return _widget;
+  }
 }
 
 class DateTypeOptionWidget extends TypeOptionWidget {

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

@@ -1,13 +1,14 @@
 import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart';
 import 'package:flutter/material.dart';
 
+import 'builder.dart';
 import 'select_option.dart';
 
-class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
+class MultiSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
   final MultiSelectTypeOptionWidget _widget;
 
-  MultiSelectTypeOptionBuilder(
+  MultiSelectTypeOptionWidgetBuilder(
     MultiSelectTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
   ) : _widget = MultiSelectTypeOptionWidget(
@@ -16,7 +17,7 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
         );
 
   @override
-  Widget? get customWidget => _widget;
+  Widget? build(BuildContext context) => _widget;
 }
 
 class MultiSelectTypeOptionWidget extends TypeOptionWidget {

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

@@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/number_bl
 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';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@@ -15,10 +15,12 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:easy_localization/easy_localization.dart' hide NumberFormat;
 import 'package:app_flowy/generated/locale_keys.g.dart';
 
-class NumberTypeOptionBuilder extends TypeOptionBuilder {
+import 'builder.dart';
+
+class NumberTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
   final NumberTypeOptionWidget _widget;
 
-  NumberTypeOptionBuilder(
+  NumberTypeOptionWidgetBuilder(
     NumberTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
   ) : _widget = NumberTypeOptionWidget(
@@ -27,7 +29,7 @@ class NumberTypeOptionBuilder extends TypeOptionBuilder {
         );
 
   @override
-  Widget? get customWidget => _widget;
+  Widget? build(BuildContext context) => _widget;
 }
 
 class NumberTypeOptionWidget extends TypeOptionWidget {

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

@@ -1,21 +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/text_type_option.pb.dart';
-
 import 'package:flutter/material.dart';
+import 'builder.dart';
 
-typedef RichTextTypeOptionContext = TypeOptionContext<RichTextTypeOption>;
+typedef RichTextTypeOptionContext = TypeOptionWidgetContext<RichTextTypeOption>;
 
-class RichTextTypeOptionDataBuilder extends TypeOptionDataBuilder<RichTextTypeOption> {
+class RichTextTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<RichTextTypeOption> {
   @override
   RichTextTypeOption fromBuffer(List<int> buffer) {
     return RichTextTypeOption.fromBuffer(buffer);
   }
 }
 
-class RichTextTypeOptionBuilder extends TypeOptionBuilder {
-  RichTextTypeOptionBuilder(RichTextTypeOptionContext typeOptionContext);
+class RichTextTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
+  RichTextTypeOptionWidgetBuilder(RichTextTypeOptionContext typeOptionContext);
 
   @override
-  Widget? get customWidget => null;
+  Widget? build(BuildContext context) => null;
 }

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

@@ -2,7 +2,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/select_op
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
@@ -14,6 +13,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 
+import 'builder.dart';
 import 'select_option_editor.dart';
 
 class SelectOptionTypeOptionWidget extends StatelessWidget {

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

@@ -1,12 +1,13 @@
 import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_type_option.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart';
 import 'package:flutter/material.dart';
+import 'builder.dart';
 import 'select_option.dart';
 
-class SingleSelectTypeOptionBuilder extends TypeOptionBuilder {
+class SingleSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
   final SingleSelectTypeOptionWidget _widget;
 
-  SingleSelectTypeOptionBuilder(
+  SingleSelectTypeOptionWidgetBuilder(
     SingleSelectTypeOptionContext typeOptionContext,
     TypeOptionOverlayDelegate overlayDelegate,
   ) : _widget = SingleSelectTypeOptionWidget(
@@ -15,7 +16,7 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder {
         );
 
   @override
-  Widget? get customWidget => _widget;
+  Widget? build(BuildContext context) => _widget;
 }
 
 class SingleSelectTypeOptionWidget extends TypeOptionWidget {

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

@@ -1,20 +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/url_type_option.pb.dart';
 import 'package:flutter/material.dart';
+import 'builder.dart';
 
-typedef URLTypeOptionContext = TypeOptionContext<URLTypeOption>;
+typedef URLTypeOptionContext = TypeOptionWidgetContext<URLTypeOption>;
 
-class URLTypeOptionDataBuilder extends TypeOptionDataBuilder<URLTypeOption> {
+class URLTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<URLTypeOption> {
   @override
   URLTypeOption fromBuffer(List<int> buffer) {
     return URLTypeOption.fromBuffer(buffer);
   }
 }
 
-class URLTypeOptionBuilder extends TypeOptionBuilder {
-  URLTypeOptionBuilder(URLTypeOptionContext typeOptionContext);
+class URLTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
+  URLTypeOptionWidgetBuilder(URLTypeOptionContext typeOptionContext);
 
   @override
-  Widget? get customWidget => null;
+  Widget? build(BuildContext context) => null;
 }