appflowy пре 3 година
родитељ
комит
90e7873135
43 измењених фајлова са 1371 додато и 326 уклоњено
  1. 222 0
      frontend/app_flowy/lib/startup/deps_resolver.dart
  2. 0 169
      frontend/app_flowy/lib/startup/home_deps_resolver.dart
  3. 2 4
      frontend/app_flowy/lib/startup/startup.dart
  4. 0 29
      frontend/app_flowy/lib/startup/user_deps_resolver.dart
  5. 4 0
      frontend/app_flowy/lib/user/application/prelude.dart
  6. 2 2
      frontend/app_flowy/lib/user/application/sign_in_bloc.dart
  7. 6 6
      frontend/app_flowy/lib/user/application/sign_up_bloc.dart
  8. 1 1
      frontend/app_flowy/lib/user/domain/auth_state.dart
  9. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart
  10. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart
  11. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart
  12. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart
  13. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart
  14. 5 4
      frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart
  15. 5 4
      frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart
  16. 12 9
      frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
  17. 61 0
      frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart
  18. 39 0
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart
  19. 39 0
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart
  20. 39 0
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart
  21. 2 2
      frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart
  22. 10 0
      frontend/app_flowy/lib/workspace/application/grid/prelude.dart
  23. 1 1
      frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart
  24. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart
  25. 8 16
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart
  26. 4 8
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart
  27. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart
  28. 193 6
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart
  29. 2 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart
  30. 1 1
      frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart
  31. 6 6
      frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart
  32. 138 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart
  33. 23 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart
  34. 2 2
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart
  35. 2 2
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart
  36. 19 9
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  37. 3 3
      frontend/rust-lib/flowy-grid/src/event_map.rs
  38. 7 7
      frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs
  39. 1 1
      frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto
  40. 2 3
      frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
  41. 21 0
      shared-lib/flowy-grid-data-model/src/entities/grid.rs
  42. 468 15
      shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
  43. 9 0
      shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto

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

@@ -0,0 +1,222 @@
+import 'package:app_flowy/core/network_monitor.dart';
+import 'package:app_flowy/user/application/user_listener.dart';
+import 'package:app_flowy/user/application/user_service.dart';
+import 'package:app_flowy/workspace/application/app/prelude.dart';
+import 'package:app_flowy/workspace/application/doc/prelude.dart';
+import 'package:app_flowy/workspace/application/grid/prelude.dart';
+import 'package:app_flowy/workspace/application/grid/row/row_listener.dart';
+import 'package:app_flowy/workspace/application/trash/prelude.dart';
+import 'package:app_flowy/workspace/application/workspace/prelude.dart';
+import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
+import 'package:app_flowy/workspace/application/home/home_bloc.dart';
+import 'package:app_flowy/workspace/application/view/prelude.dart';
+import 'package:app_flowy/workspace/application/home/prelude.dart';
+import 'package:app_flowy/workspace/application/menu/prelude.dart';
+import 'package:app_flowy/user/application/prelude.dart';
+import 'package:app_flowy/user/presentation/router.dart';
+import 'package:app_flowy/workspace/presentation/home/home_stack.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-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
+import 'package:get_it/get_it.dart';
+
+class DependencyResolver {
+  static Future<void> resolve(GetIt getIt) async {
+    _resolveUserDeps(getIt);
+
+    _resolveHomeDeps(getIt);
+
+    _resolveFolderDeps(getIt);
+
+    _resolveDocDeps(getIt);
+
+    _resolveGridDeps(getIt);
+  }
+}
+
+void _resolveUserDeps(GetIt getIt) {
+  getIt.registerFactory<AuthService>(() => AuthService());
+  getIt.registerFactory<AuthRouter>(() => AuthRouter());
+
+  getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<AuthService>()));
+  getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<AuthService>()));
+
+  getIt.registerFactory<SplashRoute>(() => SplashRoute());
+  getIt.registerFactory<HomeBloc>(() => HomeBloc());
+  getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
+  getIt.registerFactory<SplashBloc>(() => SplashBloc());
+  getIt.registerLazySingleton<NetworkListener>(() => NetworkListener());
+}
+
+void _resolveHomeDeps(GetIt getIt) {
+  getIt.registerFactoryParam<UserListener, UserProfile, void>(
+    (user, _) => UserListener(user: user),
+  );
+
+  getIt.registerFactoryParam<HomeListenBloc, UserProfile, void>(
+    (user, _) => HomeListenBloc(getIt<UserListener>(param1: user)),
+  );
+
+  //
+  getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
+
+  getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
+    (user, _) => WelcomeBloc(
+      userService: UserService(),
+      userListener: getIt<UserListener>(param1: user),
+    ),
+  );
+
+  // share
+  getIt.registerLazySingleton<ShareService>(() => ShareService());
+  getIt.registerFactoryParam<DocShareBloc, View, void>(
+      (view, _) => DocShareBloc(view: view, service: getIt<ShareService>()));
+}
+
+void _resolveFolderDeps(GetIt getIt) {
+  //workspace
+  getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>((user, workspaceId) =>
+      WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId)));
+
+  // View
+  getIt.registerFactoryParam<ViewListener, View, void>(
+    (view, _) => ViewListener(view: view),
+  );
+
+  getIt.registerFactoryParam<ViewBloc, View, void>(
+    (view, _) => ViewBloc(
+      view: view,
+      service: ViewService(),
+      listener: getIt<ViewListener>(param1: view),
+    ),
+  );
+
+  //Menu
+  getIt.registerFactoryParam<MenuBloc, UserProfile, String>(
+    (user, workspaceId) => MenuBloc(
+      workspaceId: workspaceId,
+      service: WorkspaceService(),
+      listener: getIt<WorkspaceListener>(param1: user, param2: workspaceId),
+    ),
+  );
+
+  getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
+    (user, _) => MenuUserBloc(
+      user,
+      UserService(),
+      getIt<UserListener>(param1: user),
+    ),
+  );
+
+  // App
+  getIt.registerFactoryParam<AppBloc, App, void>(
+    (app, _) => AppBloc(
+      app: app,
+      service: AppService(),
+      listener: AppListener(appId: app.id),
+    ),
+  );
+
+  // trash
+  getIt.registerLazySingleton<TrashService>(() => TrashService());
+  getIt.registerLazySingleton<TrashListener>(() => TrashListener());
+  getIt.registerFactory<TrashBloc>(
+    () => TrashBloc(
+      service: getIt<TrashService>(),
+      listener: getIt<TrashListener>(),
+    ),
+  );
+}
+
+void _resolveDocDeps(GetIt getIt) {
+// Doc
+  getIt.registerFactoryParam<DocumentBloc, View, void>(
+    (view, _) => DocumentBloc(
+      view: view,
+      service: DocumentService(),
+      listener: getIt<ViewListener>(param1: view),
+      trashService: getIt<TrashService>(),
+    ),
+  );
+}
+
+void _resolveGridDeps(GetIt getIt) {
+  // Grid
+  getIt.registerFactoryParam<GridBloc, View, void>(
+    (view, _) => GridBloc(view: view, service: GridService()),
+  );
+
+  getIt.registerFactoryParam<RowBloc, GridRowData, void>(
+    (data, _) => RowBloc(
+      rowService: RowService(data),
+      listener: RowListener(rowId: data.rowId),
+    ),
+  );
+
+  getIt.registerFactoryParam<GridHeaderBloc, String, List<Field>>(
+    (gridId, fields) => GridHeaderBloc(
+      data: GridHeaderData(gridId: gridId, fields: fields),
+      service: FieldService(gridId: gridId),
+    ),
+  );
+
+  getIt.registerFactoryParam<EditFieldBloc, GridFieldData, void>(
+    (data, _) => EditFieldBloc(
+      field: data.field,
+      service: FieldService(gridId: data.gridId),
+    ),
+  );
+
+  getIt.registerFactoryParam<CreateFieldBloc, String, void>(
+    (gridId, _) => CreateFieldBloc(
+      service: FieldService(gridId: gridId),
+    ),
+  );
+
+  getIt.registerFactoryParam<TextCellBloc, GridCellData, void>(
+    (context, _) => TextCellBloc(
+      service: CellService(context),
+    ),
+  );
+
+  getIt.registerFactoryParam<SelectionCellBloc, GridCellData, void>(
+    (context, _) => SelectionCellBloc(
+      service: CellService(context),
+    ),
+  );
+
+  getIt.registerFactoryParam<NumberCellBloc, GridCellData, void>(
+    (context, _) => NumberCellBloc(
+      service: CellService(context),
+    ),
+  );
+
+  getIt.registerFactoryParam<DateCellBloc, GridCellData, void>(
+    (context, _) => DateCellBloc(
+      service: CellService(context),
+    ),
+  );
+
+  getIt.registerFactoryParam<CheckboxCellBloc, GridCellData, void>(
+    (context, _) => CheckboxCellBloc(
+      service: CellService(context),
+    ),
+  );
+
+  getIt.registerFactoryParam<SwitchFieldTypeBloc, EditFieldContext, void>(
+    (editContext, _) => SwitchFieldTypeBloc(editContext),
+  );
+
+  getIt.registerFactory<SelectionTypeOptionBloc>(
+    () => SelectionTypeOptionBloc(),
+  );
+
+  getIt.registerFactory<DateTypeOptionBloc>(
+    () => DateTypeOptionBloc(),
+  );
+
+  getIt.registerFactory<NumberTypeOptionBloc>(
+    () => NumberTypeOptionBloc(),
+  );
+}

+ 0 - 169
frontend/app_flowy/lib/startup/home_deps_resolver.dart

@@ -1,169 +0,0 @@
-import 'package:app_flowy/user/application/user_listener.dart';
-import 'package:app_flowy/user/application/user_service.dart';
-import 'package:app_flowy/workspace/application/app/prelude.dart';
-import 'package:app_flowy/workspace/application/doc/prelude.dart';
-import 'package:app_flowy/workspace/application/grid/prelude.dart';
-import 'package:app_flowy/workspace/application/grid/row/row_listener.dart';
-import 'package:app_flowy/workspace/application/trash/prelude.dart';
-import 'package:app_flowy/workspace/application/workspace/prelude.dart';
-import 'package:app_flowy/workspace/application/view/prelude.dart';
-import 'package:app_flowy/workspace/application/home/prelude.dart';
-import 'package:app_flowy/workspace/application/menu/prelude.dart';
-
-import 'package:app_flowy/workspace/presentation/home/home_stack.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-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
-import 'package:get_it/get_it.dart';
-
-class HomeDepsResolver {
-  static Future<void> resolve(GetIt getIt) async {
-    getIt.registerFactoryParam<UserListener, UserProfile, void>(
-      (user, _) => UserListener(user: user),
-    );
-
-    getIt.registerFactoryParam<HomeListenBloc, UserProfile, void>(
-      (user, _) => HomeListenBloc(getIt<UserListener>(param1: user)),
-    );
-
-    //
-    getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
-    getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
-      (user, _) => WelcomeBloc(
-        userService: UserService(),
-        userListener: getIt<UserListener>(param1: user),
-      ),
-    );
-
-    //workspace
-    getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>((user, workspaceId) =>
-        WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId)));
-
-    // View
-    getIt.registerFactoryParam<ViewListener, View, void>(
-      (view, _) => ViewListener(view: view),
-    );
-
-    getIt.registerFactoryParam<ViewBloc, View, void>(
-      (view, _) => ViewBloc(
-        view: view,
-        service: ViewService(),
-        listener: getIt<ViewListener>(param1: view),
-      ),
-    );
-
-    //Menu Bloc
-    getIt.registerFactoryParam<MenuBloc, UserProfile, String>(
-      (user, workspaceId) => MenuBloc(
-        workspaceId: workspaceId,
-        service: WorkspaceService(),
-        listener: getIt<WorkspaceListener>(param1: user, param2: workspaceId),
-      ),
-    );
-
-    getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
-      (user, _) => MenuUserBloc(
-        user,
-        UserService(),
-        getIt<UserListener>(param1: user),
-      ),
-    );
-
-    // App
-    getIt.registerFactoryParam<AppBloc, App, void>(
-      (app, _) => AppBloc(
-        app: app,
-        service: AppService(),
-        listener: AppListener(appId: app.id),
-      ),
-    );
-
-    // Doc
-    getIt.registerFactoryParam<DocumentBloc, View, void>(
-      (view, _) => DocumentBloc(
-        view: view,
-        service: DocumentService(),
-        listener: getIt<ViewListener>(param1: view),
-        trashService: getIt<TrashService>(),
-      ),
-    );
-
-    // Grid
-    getIt.registerFactoryParam<GridBloc, View, void>(
-      (view, _) => GridBloc(view: view, service: GridService()),
-    );
-
-    getIt.registerFactoryParam<RowBloc, GridRowData, void>(
-      (data, _) => RowBloc(
-        rowService: RowService(data),
-        listener: RowListener(rowId: data.rowId),
-      ),
-    );
-
-    getIt.registerFactoryParam<GridHeaderBloc, String, List<Field>>(
-      (gridId, fields) => GridHeaderBloc(
-        data: GridHeaderData(gridId: gridId, fields: fields),
-        service: FieldService(gridId: gridId),
-      ),
-    );
-
-    getIt.registerFactoryParam<EditFieldBloc, GridFieldData, void>(
-      (data, _) => EditFieldBloc(
-        field: data.field,
-        service: FieldService(gridId: data.gridId),
-      ),
-    );
-
-    getIt.registerFactoryParam<CreateFieldBloc, String, void>(
-      (gridId, _) => CreateFieldBloc(
-        service: FieldService(gridId: gridId),
-      ),
-    );
-
-    getIt.registerFactoryParam<TextCellBloc, GridCellData, void>(
-      (context, _) => TextCellBloc(
-        service: CellService(context),
-      ),
-    );
-
-    getIt.registerFactoryParam<SelectionCellBloc, GridCellData, void>(
-      (context, _) => SelectionCellBloc(
-        service: CellService(context),
-      ),
-    );
-
-    getIt.registerFactoryParam<NumberCellBloc, GridCellData, void>(
-      (context, _) => NumberCellBloc(
-        service: CellService(context),
-      ),
-    );
-
-    getIt.registerFactoryParam<DateCellBloc, GridCellData, void>(
-      (context, _) => DateCellBloc(
-        service: CellService(context),
-      ),
-    );
-
-    getIt.registerFactoryParam<CheckboxCellBloc, GridCellData, void>(
-      (context, _) => CheckboxCellBloc(
-        service: CellService(context),
-      ),
-    );
-
-    // trash
-    getIt.registerLazySingleton<TrashService>(() => TrashService());
-    getIt.registerLazySingleton<TrashListener>(() => TrashListener());
-    getIt.registerFactory<TrashBloc>(
-      () => TrashBloc(
-        service: getIt<TrashService>(),
-        listener: getIt<TrashListener>(),
-      ),
-    );
-
-    // share
-    getIt.registerLazySingleton<ShareService>(() => ShareService());
-    getIt.registerFactoryParam<DocShareBloc, View, void>(
-        (view, _) => DocShareBloc(view: view, service: getIt<ShareService>()));
-  }
-}

+ 2 - 4
frontend/app_flowy/lib/startup/startup.dart

@@ -2,8 +2,7 @@ import 'dart:io';
 
 import 'package:app_flowy/plugin/plugin.dart';
 import 'package:app_flowy/startup/tasks/prelude.dart';
-import 'package:app_flowy/startup/home_deps_resolver.dart';
-import 'package:app_flowy/startup/user_deps_resolver.dart';
+import 'package:app_flowy/startup/deps_resolver.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:get_it/get_it.dart';
@@ -62,8 +61,7 @@ Future<void> initGetIt(
   getIt.registerLazySingleton<AppLauncher>(() => AppLauncher(env, getIt));
   getIt.registerSingleton<PluginSandbox>(PluginSandbox());
 
-  await UserDepsResolver.resolve(getIt);
-  await HomeDepsResolver.resolve(getIt);
+  await DependencyResolver.resolve(getIt);
 }
 
 class LaunchContext {

+ 0 - 29
frontend/app_flowy/lib/startup/user_deps_resolver.dart

@@ -1,29 +0,0 @@
-import 'package:app_flowy/user/application/auth_service.dart';
-import 'package:app_flowy/user/application/sign_in_bloc.dart';
-import 'package:app_flowy/user/application/sign_up_bloc.dart';
-import 'package:app_flowy/user/application/splash_bloc.dart';
-import 'package:app_flowy/user/presentation/router.dart';
-import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
-import 'package:app_flowy/workspace/application/home/home_bloc.dart';
-import 'package:get_it/get_it.dart';
-
-import '../core/network_monitor.dart';
-
-class UserDepsResolver {
-  static Future<void> resolve(GetIt getIt) async {
-    getIt.registerFactory<AuthService>(() => AuthService());
-
-    //Interface implementation
-    getIt.registerFactory<AuthRouter>(() => AuthRouter());
-
-    //Bloc
-    getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<AuthService>()));
-    getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<AuthService>()));
-
-    getIt.registerFactory<SplashRoute>(() => SplashRoute());
-    getIt.registerFactory<HomeBloc>(() => HomeBloc());
-    getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
-    getIt.registerFactory<SplashBloc>(() => SplashBloc());
-    getIt.registerLazySingleton<NetworkListener>(() => NetworkListener());
-  }
-}

+ 4 - 0
frontend/app_flowy/lib/user/application/prelude.dart

@@ -0,0 +1,4 @@
+export './auth_service.dart';
+export './sign_in_bloc.dart';
+export './sign_up_bloc.dart';
+export './splash_bloc.dart';

+ 2 - 2
frontend/app_flowy/lib/user/application/sign_in_bloc.dart

@@ -54,14 +54,14 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
 }
 
 @freezed
-abstract class SignInEvent with _$SignInEvent {
+class SignInEvent with _$SignInEvent {
   const factory SignInEvent.signedInWithUserEmailAndPassword() = SignedInWithUserEmailAndPassword;
   const factory SignInEvent.emailChanged(String email) = EmailChanged;
   const factory SignInEvent.passwordChanged(String password) = PasswordChanged;
 }
 
 @freezed
-abstract class SignInState with _$SignInState {
+class SignInState with _$SignInState {
   const factory SignInState({
     String? email,
     String? password,

+ 6 - 6
frontend/app_flowy/lib/user/application/sign_up_bloc.dart

@@ -15,11 +15,11 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
     on<SignUpEvent>((event, emit) async {
       await event.map(signUpWithUserEmailAndPassword: (e) async {
         await _performActionOnSignUp(emit);
-      }, emailChanged: (EmailChanged value) async {
+      }, emailChanged: (_EmailChanged value) async {
         emit(state.copyWith(email: value.email, emailError: none(), successOrFail: none()));
-      }, passwordChanged: (PasswordChanged value) async {
+      }, passwordChanged: (_PasswordChanged value) async {
         emit(state.copyWith(password: value.password, passwordError: none(), successOrFail: none()));
-      }, repeatPasswordChanged: (RepeatPasswordChanged value) async {
+      }, repeatPasswordChanged: (_RepeatPasswordChanged value) async {
         emit(state.copyWith(repeatedPassword: value.password, repeatPasswordError: none(), successOrFail: none()));
       });
     });
@@ -104,9 +104,9 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
 @freezed
 class SignUpEvent with _$SignUpEvent {
   const factory SignUpEvent.signUpWithUserEmailAndPassword() = SignUpWithUserEmailAndPassword;
-  const factory SignUpEvent.emailChanged(String email) = EmailChanged;
-  const factory SignUpEvent.passwordChanged(String password) = PasswordChanged;
-  const factory SignUpEvent.repeatPasswordChanged(String password) = RepeatPasswordChanged;
+  const factory SignUpEvent.emailChanged(String email) = _EmailChanged;
+  const factory SignUpEvent.passwordChanged(String password) = _PasswordChanged;
+  const factory SignUpEvent.repeatPasswordChanged(String password) = _RepeatPasswordChanged;
 }
 
 @freezed

+ 1 - 1
frontend/app_flowy/lib/user/domain/auth_state.dart

@@ -4,7 +4,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
 part 'auth_state.freezed.dart';
 
 @freezed
-abstract class AuthState with _$AuthState {
+class AuthState with _$AuthState {
   const factory AuthState.authenticated(UserProfile userProfile) = Authenticated;
   const factory AuthState.unauthenticated(FlowyError error) = Unauthenticated;
   const factory AuthState.initial() = _Initial;

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart

@@ -28,12 +28,12 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
 }
 
 @freezed
-abstract class CheckboxCellEvent with _$CheckboxCellEvent {
+class CheckboxCellEvent with _$CheckboxCellEvent {
   const factory CheckboxCellEvent.initial() = _InitialCell;
 }
 
 @freezed
-abstract class CheckboxCellState with _$CheckboxCellState {
+class CheckboxCellState with _$CheckboxCellState {
   const factory CheckboxCellState({
     required Cell? cell,
   }) = _CheckboxCellState;

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart

@@ -28,12 +28,12 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
 }
 
 @freezed
-abstract class DateCellEvent with _$DateCellEvent {
+class DateCellEvent with _$DateCellEvent {
   const factory DateCellEvent.initial() = _InitialCell;
 }
 
 @freezed
-abstract class DateCellState with _$DateCellState {
+class DateCellState with _$DateCellState {
   const factory DateCellState({
     required Cell? cell,
   }) = _DateCellState;

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart

@@ -28,12 +28,12 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
 }
 
 @freezed
-abstract class NumberCellEvent with _$NumberCellEvent {
+class NumberCellEvent with _$NumberCellEvent {
   const factory NumberCellEvent.initial() = _InitialCell;
 }
 
 @freezed
-abstract class NumberCellState with _$NumberCellState {
+class NumberCellState with _$NumberCellState {
   const factory NumberCellState({
     required Cell? cell,
   }) = _NumberCellState;

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart

@@ -28,12 +28,12 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
 }
 
 @freezed
-abstract class SelectionCellEvent with _$SelectionCellEvent {
+class SelectionCellEvent with _$SelectionCellEvent {
   const factory SelectionCellEvent.initial() = _InitialCell;
 }
 
 @freezed
-abstract class SelectionCellState with _$SelectionCellState {
+class SelectionCellState with _$SelectionCellState {
   const factory SelectionCellState({
     required Cell? cell,
   }) = _SelectionCellState;

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart

@@ -31,13 +31,13 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
 }
 
 @freezed
-abstract class TextCellEvent with _$TextCellEvent {
+class TextCellEvent with _$TextCellEvent {
   const factory TextCellEvent.initial() = _InitialCell;
   const factory TextCellEvent.updateText(String text) = _UpdateText;
 }
 
 @freezed
-abstract class TextCellState with _$TextCellState {
+class TextCellState with _$TextCellState {
   const factory TextCellState({
     required String content,
   }) = _TextCellState;

+ 5 - 4
frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart

@@ -1,5 +1,6 @@
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
@@ -16,9 +17,9 @@ class CreateFieldBloc extends Bloc<CreateFieldEvent, CreateFieldState> {
       (event, emit) async {
         await event.map(
           initial: (_InitialField value) async {
-            final result = await service.getDefaultField();
+            final result = await service.getEditFieldContext(FieldType.RichText);
             result.fold(
-              (field) => emit(state.copyWith(field: Some(field))),
+              (editContext) => emit(state.copyWith(editContext: Some(editContext))),
               (err) => Log.error(err),
             );
           },
@@ -46,11 +47,11 @@ class CreateFieldEvent with _$CreateFieldEvent {
 class CreateFieldState with _$CreateFieldState {
   const factory CreateFieldState({
     required String errorText,
-    required Option<Field> field,
+    required Option<EditFieldContext> editContext,
   }) = _CreateFieldState;
 
   factory CreateFieldState.initial() => CreateFieldState(
-        field: none(),
+        editContext: none(),
         errorText: '',
       );
 }

+ 5 - 4
frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart

@@ -9,7 +9,8 @@ part 'edit_field_bloc.freezed.dart';
 class EditFieldBloc extends Bloc<EditFieldEvent, EditFieldState> {
   final FieldService service;
 
-  EditFieldBloc({required Field field, required this.service}) : super(EditFieldState.initial(field)) {
+  EditFieldBloc({required Field field, required this.service})
+      : super(EditFieldState.initial(EditFieldContext.create()..gridField = field)) {
     on<EditFieldEvent>(
       (event, emit) async {
         await event.map(
@@ -43,12 +44,12 @@ class EditFieldEvent with _$EditFieldEvent {
 @freezed
 class EditFieldState with _$EditFieldState {
   const factory EditFieldState({
-    required Field field,
+    required EditFieldContext editContext,
     required String errorText,
   }) = _EditFieldState;
 
-  factory EditFieldState.initial(Field field) => EditFieldState(
-        field: field,
+  factory EditFieldState.initial(EditFieldContext editContext) => EditFieldState(
+        editContext: editContext,
         errorText: '',
       );
 }

+ 12 - 9
frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart

@@ -5,6 +5,7 @@ import 'package:equatable/equatable.dart';
 import 'package:flowy_sdk/dispatch/dispatch.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-data-model/meta.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
 
 class FieldService {
@@ -12,9 +13,12 @@ class FieldService {
 
   FieldService({required this.gridId});
 
-  Future<Either<Field, FlowyError>> getDefaultField() {
-    final payload = GridId.create()..value = gridId;
-    return GridEventCreateDefaultField(payload).send();
+  Future<Either<EditFieldContext, FlowyError>> getEditFieldContext(FieldType fieldType) {
+    final payload = CreateEditFieldContextParams.create()
+      ..gridId = gridId
+      ..fieldType = fieldType;
+
+    return GridEventCreateEditFieldContext(payload).send();
   }
 
   Future<Either<Unit, FlowyError>> createTextField(
@@ -24,7 +28,7 @@ class FieldService {
     String? startFieldId,
   ) {
     final typeOptionData = typeOption.writeToBuffer();
-    return createField(gridId, field, typeOptionData, startFieldId);
+    return createField(field, typeOptionData, startFieldId);
   }
 
   Future<Either<Unit, FlowyError>> createSingleSelectField(
@@ -34,7 +38,7 @@ class FieldService {
     String? startFieldId,
   ) {
     final typeOptionData = typeOption.writeToBuffer();
-    return createField(gridId, field, typeOptionData, startFieldId);
+    return createField(field, typeOptionData, startFieldId);
   }
 
   Future<Either<Unit, FlowyError>> createMultiSelectField(
@@ -44,7 +48,7 @@ class FieldService {
     String? startFieldId,
   ) {
     final typeOptionData = typeOption.writeToBuffer();
-    return createField(gridId, field, typeOptionData, startFieldId);
+    return createField(field, typeOptionData, startFieldId);
   }
 
   Future<Either<Unit, FlowyError>> createNumberField(
@@ -54,7 +58,7 @@ class FieldService {
     String? startFieldId,
   ) {
     final typeOptionData = typeOption.writeToBuffer();
-    return createField(gridId, field, typeOptionData, startFieldId);
+    return createField(field, typeOptionData, startFieldId);
   }
 
   Future<Either<Unit, FlowyError>> createDateField(
@@ -64,11 +68,10 @@ class FieldService {
     String? startFieldId,
   ) {
     final typeOptionData = typeOption.writeToBuffer();
-    return createField(gridId, field, typeOptionData, startFieldId);
+    return createField(field, typeOptionData, startFieldId);
   }
 
   Future<Either<Unit, FlowyError>> createField(
-    String gridId,
     Field field,
     Uint8List? typeOptionData,
     String? startFieldId,

+ 61 - 0
frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart

@@ -0,0 +1,61 @@
+import 'dart:typed_data';
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'dart:async';
+import 'field_service.dart';
+
+part 'switch_field_type_bloc.freezed.dart';
+
+class SwitchFieldTypeBloc extends Bloc<SwitchFieldTypeEvent, SwitchFieldTypeState> {
+  SwitchFieldTypeBloc(EditFieldContext editContext) : super(SwitchFieldTypeState.initial(editContext)) {
+    on<SwitchFieldTypeEvent>(
+      (event, emit) async {
+        await event.map(
+          toFieldType: (_ToFieldType value) async {
+            final fieldService = FieldService(gridId: state.gridId);
+            final result = await fieldService.getEditFieldContext(value.fieldType);
+            result.fold(
+              (newEditContext) {
+                emit(
+                  state.copyWith(
+                    field: newEditContext.gridField,
+                    typeOptionData: Uint8List.fromList(newEditContext.typeOptionData),
+                  ),
+                );
+              },
+              (err) => Log.error(err),
+            );
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    return super.close();
+  }
+}
+
+@freezed
+class SwitchFieldTypeEvent with _$SwitchFieldTypeEvent {
+  const factory SwitchFieldTypeEvent.toFieldType(FieldType fieldType) = _ToFieldType;
+}
+
+@freezed
+class SwitchFieldTypeState with _$SwitchFieldTypeState {
+  const factory SwitchFieldTypeState({
+    required String gridId,
+    required Field field,
+    required Uint8List typeOptionData,
+  }) = _SwitchFieldTypeState;
+
+  factory SwitchFieldTypeState.initial(EditFieldContext editContext) => SwitchFieldTypeState(
+        gridId: editContext.gridId,
+        field: editContext.gridField,
+        typeOptionData: Uint8List.fromList(editContext.typeOptionData),
+      );
+}

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

@@ -0,0 +1,39 @@
+import 'dart:typed_data';
+
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'dart:async';
+import 'package:dartz/dartz.dart';
+
+part 'date_bloc.freezed.dart';
+
+class DateTypeOptionBloc extends Bloc<DateTypeOptionEvent, DateTypeOptionState> {
+  DateTypeOptionBloc() : super(DateTypeOptionState.initial()) {
+    on<DateTypeOptionEvent>(
+      (event, emit) async {
+        await event.map(
+          initial: (_InitialField value) async {},
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    return super.close();
+  }
+}
+
+@freezed
+class DateTypeOptionEvent with _$DateTypeOptionEvent {
+  const factory DateTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField;
+}
+
+@freezed
+class DateTypeOptionState with _$DateTypeOptionState {
+  const factory DateTypeOptionState() = _DateTypeOptionState;
+
+  factory DateTypeOptionState.initial() => DateTypeOptionState();
+}

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

@@ -0,0 +1,39 @@
+import 'dart:typed_data';
+
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'dart:async';
+import 'package:dartz/dartz.dart';
+
+part 'number_bloc.freezed.dart';
+
+class NumberTypeOptionBloc extends Bloc<NumberTypeOptionEvent, NumberTypeOptionState> {
+  NumberTypeOptionBloc() : super(NumberTypeOptionState.initial()) {
+    on<NumberTypeOptionEvent>(
+      (event, emit) async {
+        await event.map(
+          initial: (_InitialField value) async {},
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    return super.close();
+  }
+}
+
+@freezed
+class NumberTypeOptionEvent with _$NumberTypeOptionEvent {
+  const factory NumberTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField;
+}
+
+@freezed
+class NumberTypeOptionState with _$NumberTypeOptionState {
+  const factory NumberTypeOptionState() = _NumberTypeOptionState;
+
+  factory NumberTypeOptionState.initial() => NumberTypeOptionState();
+}

+ 39 - 0
frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart

@@ -0,0 +1,39 @@
+import 'dart:typed_data';
+
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'dart:async';
+import 'package:dartz/dartz.dart';
+
+part 'selection_bloc.freezed.dart';
+
+class SelectionTypeOptionBloc extends Bloc<SelectionTypeOptionEvent, SelectionTypeOptionState> {
+  SelectionTypeOptionBloc() : super(SelectionTypeOptionState.initial()) {
+    on<SelectionTypeOptionEvent>(
+      (event, emit) async {
+        await event.map(
+          initial: (_InitialField value) async {},
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    return super.close();
+  }
+}
+
+@freezed
+class SelectionTypeOptionEvent with _$SelectionTypeOptionEvent {
+  const factory SelectionTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField;
+}
+
+@freezed
+class SelectionTypeOptionState with _$SelectionTypeOptionState {
+  const factory SelectionTypeOptionState() = _SelectionTypeOptionState;
+
+  factory SelectionTypeOptionState.initial() => SelectionTypeOptionState();
+}

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart

@@ -124,7 +124,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
 }
 
 @freezed
-abstract class GridEvent with _$GridEvent {
+class GridEvent with _$GridEvent {
   const factory GridEvent.initial() = InitialGrid;
   const factory GridEvent.rename(String gridId, String name) = _Rename;
   const factory GridEvent.updateDesc(String gridId, String desc) = _Desc;
@@ -135,7 +135,7 @@ abstract class GridEvent with _$GridEvent {
 }
 
 @freezed
-abstract class GridState with _$GridState {
+class GridState with _$GridState {
   const factory GridState({
     required GridLoadingState loadingState,
     required List<Field> fields,

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

@@ -3,10 +3,20 @@ export 'row/row_bloc.dart';
 export 'row/row_service.dart';
 export 'grid_service.dart';
 export 'data.dart';
+
+// Field
 export 'field/field_service.dart';
 export 'field/grid_header_bloc.dart';
 export 'field/edit_field_bloc.dart';
 export 'field/create_field_bloc.dart';
+export 'field/switch_field_type_bloc.dart';
+
+// Field Type Option
+export 'field/type_option/date_bloc.dart';
+export 'field/type_option/number_bloc.dart';
+export 'field/type_option/selection_bloc.dart';
+
+// Cell
 export 'cell_bloc/text_cell_bloc.dart';
 export 'cell_bloc/number_cell_bloc.dart';
 export 'cell_bloc/selection_cell_bloc.dart';

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

@@ -88,7 +88,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
 }
 
 @freezed
-abstract class RowEvent with _$RowEvent {
+class RowEvent with _$RowEvent {
   const factory RowEvent.initial() = _InitialRow;
   const factory RowEvent.createRow() = _CreateRow;
   const factory RowEvent.activeRow() = _ActiveRow;

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart

@@ -22,7 +22,7 @@ Widget buildGridCell(GridCellData cellData) {
     case FieldType.SingleSelect:
       return SingleSelectCell(cellContext: cellData);
     default:
-      return const BlankCell();
+      throw UnimplementedError;
   }
 }
 

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

@@ -37,8 +37,7 @@ class CreateFieldPannel extends FlowyOverlayDelegate {
 
   @override
   void didRemove() async {
-    await _createFieldBloc.close();
-    // TODO: implement didRemove
+    _createFieldBloc.add(const CreateFieldEvent.done());
   }
 }
 
@@ -52,16 +51,16 @@ class _CreateFieldPannelWidget extends StatelessWidget {
       value: createFieldBloc,
       child: BlocBuilder<CreateFieldBloc, CreateFieldState>(
         builder: (context, state) {
-          return state.field.fold(
+          return state.editContext.fold(
             () => const SizedBox(),
-            (field) => ListView(
+            (editContext) => ListView(
               shrinkWrap: true,
               children: [
                 const FlowyText.medium("Edit property", fontSize: 12),
                 const VSpace(10),
-                _FieldNameTextField(field),
+                _FieldNameTextField(editContext.gridField),
                 const VSpace(10),
-                _FieldTypeSwitcher(field),
+                _FieldTypeSwitcher(editContext),
                 const VSpace(10),
               ],
             ),
@@ -73,19 +72,12 @@ class _CreateFieldPannelWidget extends StatelessWidget {
 }
 
 class _FieldTypeSwitcher extends StatelessWidget {
-  final Field field;
-  const _FieldTypeSwitcher(this.field, {Key? key}) : super(key: key);
+  final EditFieldContext editContext;
+  const _FieldTypeSwitcher(this.editContext, {Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    return FieldTypeSwitcher(
-      field: field,
-      onSelectField: _switchToFieldType,
-    );
-  }
-
-  void _switchToFieldType(FieldType fieldType) {
-    throw UnimplementedError();
+    return FieldTypeSwitcher(editContext: editContext);
   }
 }
 

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

@@ -59,15 +59,11 @@ class _FieldTypeSwitcher extends StatelessWidget {
   Widget build(BuildContext context) {
     return BlocBuilder<EditFieldBloc, EditFieldState>(
       builder: (context, state) {
-        final field = context.read<EditFieldBloc>().state.field;
-        return FieldTypeSwitcher(field: field, onSelectField: _switchToFieldType);
+        final editContext = context.read<EditFieldBloc>().state.editContext;
+        return FieldTypeSwitcher(editContext: editContext);
       },
     );
   }
-
-  void _switchToFieldType(FieldType fieldType) {
-    throw UnimplementedError();
-  }
 }
 
 class _FieldNameTextField extends StatelessWidget {
@@ -76,10 +72,10 @@ class _FieldNameTextField extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return BlocBuilder<EditFieldBloc, EditFieldState>(
-      buildWhen: ((previous, current) => previous.field.name == current.field.name),
+      buildWhen: ((previous, current) => previous.editContext.gridField.name == current.editContext.gridField.name),
       builder: (context, state) {
         return FieldNameTextField(
-          name: state.field.name,
+          name: state.editContext.gridField.name,
           errorText: state.errorText,
           onNameChanged: (newName) {
             context.read<EditFieldBloc>().add(EditFieldEvent.updateFieldName(newName));

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

@@ -19,7 +19,7 @@ class FieldNameTextField extends StatelessWidget {
     final theme = context.watch<AppTheme>();
     return RoundedInputField(
       height: 36,
-      style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
+      style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500),
       initialValue: name,
       normalBorderColor: theme.shader4,
       errorBorderColor: theme.red,

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

@@ -1,3 +1,7 @@
+import 'dart:typed_data';
+
+import 'package:app_flowy/startup/startup.dart';
+import 'package:app_flowy/workspace/application/grid/prelude.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
@@ -5,34 +9,217 @@ import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.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-grid/selection_type_option.pb.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';
 
 typedef SelectFieldCallback = void Function(FieldType);
 
 class FieldTypeSwitcher extends StatelessWidget {
-  final Field field;
-  final SelectFieldCallback onSelectField;
+  final EditFieldContext editContext;
+
   const FieldTypeSwitcher({
-    required this.field,
-    required this.onSelectField,
+    required this.editContext,
     Key? key,
   }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
+    return BlocProvider(
+      create: (context) => getIt<SwitchFieldTypeBloc>(param1: editContext),
+      child: BlocBuilder<SwitchFieldTypeBloc, SwitchFieldTypeState>(
+        builder: (context, state) {
+          List<Widget> children = [
+            _switchFieldTypeButton(context, state.field),
+          ];
 
+          final builder = _makeTypeOptionBuild(
+            state.field.fieldType,
+            state.typeOptionData,
+          );
+
+          final typeOptionWidget = builder.customWidget;
+          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: 36,
       child: FlowyButton(
         text: FlowyText.medium(field.fieldType.title(), fontSize: 12),
         padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
         hoverColor: theme.hover,
-        onTap: () => FieldTypeList.show(context, onSelectField),
+        onTap: () => FieldTypeList.show(context, (fieldType) {
+          context.read<SwitchFieldTypeBloc>().add(SwitchFieldTypeEvent.toFieldType(fieldType));
+        }),
         leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor),
         rightIcon: svg("grid/more", color: theme.iconColor),
       ),
     );
   }
 }
+
+abstract class TypeOptionBuilder {
+  Uint8List? get typeOptionData;
+  Widget? get customWidget;
+}
+
+abstract class TypeOptionWidget extends StatelessWidget {
+  const TypeOptionWidget({Key? key}) : super(key: key);
+}
+
+TypeOptionBuilder _makeTypeOptionBuild(FieldType fieldType, Uint8List typeOptionData) {
+  switch (fieldType) {
+    case FieldType.Checkbox:
+      return CheckboxTypeOptionBuilder(typeOptionData);
+    case FieldType.DateTime:
+      return DateTypeOptionBuilder(typeOptionData);
+    case FieldType.MultiSelect:
+      return MultiSelectTypeOptionBuilder(typeOptionData);
+    case FieldType.Number:
+      return NumberTypeOptionBuilder(typeOptionData);
+    case FieldType.RichText:
+      return RichTextTypeOptionBuilder(typeOptionData);
+    case FieldType.SingleSelect:
+      return SingleSelectTypeOptionBuilder(typeOptionData);
+    default:
+      throw UnimplementedError;
+  }
+}
+
+class RichTextTypeOptionBuilder extends TypeOptionBuilder {
+  RichTextTypeOption typeOption;
+
+  RichTextTypeOptionBuilder(Uint8List typeOptionData) : typeOption = RichTextTypeOption.fromBuffer(typeOptionData);
+
+  @override
+  Uint8List? get typeOptionData => typeOption.writeToBuffer();
+
+  @override
+  Widget? get customWidget => null;
+}
+
+class NumberTypeOptionBuilder extends TypeOptionBuilder {
+  NumberTypeOption typeOption;
+
+  NumberTypeOptionBuilder(Uint8List typeOptionData) : typeOption = NumberTypeOption.fromBuffer(typeOptionData);
+
+  @override
+  Uint8List? get typeOptionData => typeOption.writeToBuffer();
+
+  @override
+  Widget? get customWidget => const NumberTypeOptionWidget();
+}
+
+class NumberTypeOptionWidget extends TypeOptionWidget {
+  const NumberTypeOptionWidget({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider(
+      create: (context) => getIt<NumberTypeOptionBloc>(),
+      child: Container(),
+    );
+  }
+}
+
+class DateTypeOptionBuilder extends TypeOptionBuilder {
+  DateTypeOption typeOption;
+
+  DateTypeOptionBuilder(Uint8List typeOptionData) : typeOption = DateTypeOption.fromBuffer(typeOptionData);
+
+  @override
+  Uint8List? get typeOptionData => typeOption.writeToBuffer();
+
+  @override
+  Widget? get customWidget => const DateTypeOptionWidget();
+}
+
+class DateTypeOptionWidget extends TypeOptionWidget {
+  const DateTypeOptionWidget({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider(
+      create: (context) => getIt<DateTypeOptionBloc>(),
+      child: Container(),
+    );
+  }
+}
+
+class CheckboxTypeOptionBuilder extends TypeOptionBuilder {
+  CheckboxTypeOption typeOption;
+
+  CheckboxTypeOptionBuilder(Uint8List typeOptionData) : typeOption = CheckboxTypeOption.fromBuffer(typeOptionData);
+
+  @override
+  Uint8List? get typeOptionData => throw UnimplementedError();
+
+  @override
+  Widget? get customWidget => null;
+}
+
+class SingleSelectTypeOptionBuilder extends TypeOptionBuilder {
+  SingleSelectTypeOption typeOption;
+
+  SingleSelectTypeOptionBuilder(Uint8List typeOptionData)
+      : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData);
+
+  @override
+  Uint8List? get typeOptionData => typeOption.writeToBuffer();
+
+  @override
+  Widget? get customWidget => const SingleSelectTypeOptionWidget();
+}
+
+class SingleSelectTypeOptionWidget extends TypeOptionWidget {
+  const SingleSelectTypeOptionWidget({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider(
+      create: (context) => getIt<SelectionTypeOptionBloc>(),
+      child: Container(),
+    );
+  }
+}
+
+class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
+  MultiSelectTypeOption typeOption;
+
+  MultiSelectTypeOptionBuilder(Uint8List typeOptionData)
+      : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData);
+
+  @override
+  Uint8List? get typeOptionData => typeOption.writeToBuffer();
+
+  @override
+  Widget? get customWidget => const MultiSelectTypeOptionWidget();
+}
+
+class MultiSelectTypeOptionWidget extends TypeOptionWidget {
+  const MultiSelectTypeOptionWidget({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider(
+      create: (context) => getIt<SelectionTypeOptionBloc>(),
+      child: Container(),
+    );
+  }
+}

+ 2 - 4
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart

@@ -104,8 +104,7 @@ extension FieldTypeListExtension on FieldType {
       case FieldType.SingleSelect:
         return "grid/field/single_select";
       default:
-        assert(false, "Unsupport field type");
-        return "grid/field/text";
+        throw UnimplementedError;
     }
   }
 
@@ -124,8 +123,7 @@ extension FieldTypeListExtension on FieldType {
       case FieldType.SingleSelect:
         return LocaleKeys.grid_field_singleSelectFieldName.tr();
       default:
-        assert(false, "Unsupport field type");
-        return LocaleKeys.grid_field_textFieldName.tr();
+        throw UnimplementedError;
     }
   }
 }

+ 1 - 1
frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart

@@ -21,7 +21,7 @@ class OverlayContainer extends StatelessWidget {
       type: MaterialType.transparency,
       child: Container(
         padding: padding,
-        decoration: FlowyDecoration.decoration(theme.surface, theme.shadowColor.withOpacity(0.1)),
+        decoration: FlowyDecoration.decoration(theme.surface, theme.shadowColor.withOpacity(0.15)),
         constraints: constraints,
         child: child,
       ),

+ 6 - 6
frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart

@@ -86,18 +86,18 @@ class GridEventCreateField {
     }
 }
 
-class GridEventCreateDefaultField {
-     GridId request;
-     GridEventCreateDefaultField(this.request);
+class GridEventCreateEditFieldContext {
+     CreateEditFieldContextParams request;
+     GridEventCreateEditFieldContext(this.request);
 
-    Future<Either<Field, FlowyError>> send() {
+    Future<Either<EditFieldContext, FlowyError>> send() {
     final request = FFIRequest.create()
-          ..event = GridEvent.CreateDefaultField.toString()
+          ..event = GridEvent.CreateEditFieldContext.toString()
           ..payload = requestToBytes(this.request);
 
     return Dispatch.asyncRequest(request)
         .then((bytesResult) => bytesResult.fold(
-           (okBytes) => left(Field.fromBuffer(okBytes)),
+           (okBytes) => left(EditFieldContext.fromBuffer(okBytes)),
            (errBytes) => right(FlowyError.fromBuffer(errBytes)),
         ));
     }

+ 138 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart

@@ -252,6 +252,144 @@ class FieldOrder extends $pb.GeneratedMessage {
   void clearFieldId() => clearField(1);
 }
 
+class CreateEditFieldContextParams extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateEditFieldContextParams', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
+    ..e<$0.FieldType>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: $0.FieldType.RichText, valueOf: $0.FieldType.valueOf, enumValues: $0.FieldType.values)
+    ..hasRequiredFields = false
+  ;
+
+  CreateEditFieldContextParams._() : super();
+  factory CreateEditFieldContextParams({
+    $core.String? gridId,
+    $0.FieldType? fieldType,
+  }) {
+    final _result = create();
+    if (gridId != null) {
+      _result.gridId = gridId;
+    }
+    if (fieldType != null) {
+      _result.fieldType = fieldType;
+    }
+    return _result;
+  }
+  factory CreateEditFieldContextParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory CreateEditFieldContextParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+  'Will be removed in next major version')
+  CreateEditFieldContextParams clone() => CreateEditFieldContextParams()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  CreateEditFieldContextParams copyWith(void Function(CreateEditFieldContextParams) updates) => super.copyWith((message) => updates(message as CreateEditFieldContextParams)) as CreateEditFieldContextParams; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static CreateEditFieldContextParams create() => CreateEditFieldContextParams._();
+  CreateEditFieldContextParams createEmptyInstance() => create();
+  static $pb.PbList<CreateEditFieldContextParams> createRepeated() => $pb.PbList<CreateEditFieldContextParams>();
+  @$core.pragma('dart2js:noInline')
+  static CreateEditFieldContextParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateEditFieldContextParams>(create);
+  static CreateEditFieldContextParams? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get gridId => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set gridId($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasGridId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearGridId() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $0.FieldType get fieldType => $_getN(1);
+  @$pb.TagNumber(2)
+  set fieldType($0.FieldType v) { setField(2, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasFieldType() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearFieldType() => clearField(2);
+}
+
+class EditFieldContext extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'EditFieldContext', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
+    ..aOM<Field>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridField', subBuilder: Field.create)
+    ..a<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionData', $pb.PbFieldType.OY)
+    ..hasRequiredFields = false
+  ;
+
+  EditFieldContext._() : super();
+  factory EditFieldContext({
+    $core.String? gridId,
+    Field? gridField,
+    $core.List<$core.int>? typeOptionData,
+  }) {
+    final _result = create();
+    if (gridId != null) {
+      _result.gridId = gridId;
+    }
+    if (gridField != null) {
+      _result.gridField = gridField;
+    }
+    if (typeOptionData != null) {
+      _result.typeOptionData = typeOptionData;
+    }
+    return _result;
+  }
+  factory EditFieldContext.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory EditFieldContext.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+  'Will be removed in next major version')
+  EditFieldContext clone() => EditFieldContext()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  EditFieldContext copyWith(void Function(EditFieldContext) updates) => super.copyWith((message) => updates(message as EditFieldContext)) as EditFieldContext; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static EditFieldContext create() => EditFieldContext._();
+  EditFieldContext createEmptyInstance() => create();
+  static $pb.PbList<EditFieldContext> createRepeated() => $pb.PbList<EditFieldContext>();
+  @$core.pragma('dart2js:noInline')
+  static EditFieldContext getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EditFieldContext>(create);
+  static EditFieldContext? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get gridId => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set gridId($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasGridId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearGridId() => clearField(1);
+
+  @$pb.TagNumber(2)
+  Field get gridField => $_getN(1);
+  @$pb.TagNumber(2)
+  set gridField(Field v) { setField(2, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasGridField() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearGridField() => clearField(2);
+  @$pb.TagNumber(2)
+  Field ensureGridField() => $_ensure(1);
+
+  @$pb.TagNumber(3)
+  $core.List<$core.int> get typeOptionData => $_getN(2);
+  @$pb.TagNumber(3)
+  set typeOptionData($core.List<$core.int> v) { $_setBytes(2, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasTypeOptionData() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearTypeOptionData() => clearField(3);
+}
+
 class RepeatedField extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedField', createEmptyInstance: create)
     ..pc<Field>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Field.create)

+ 23 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart

@@ -46,6 +46,29 @@ const FieldOrder$json = const {
 
 /// Descriptor for `FieldOrder`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List fieldOrderDescriptor = $convert.base64Decode('CgpGaWVsZE9yZGVyEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElk');
+@$core.Deprecated('Use createEditFieldContextParamsDescriptor instead')
+const CreateEditFieldContextParams$json = const {
+  '1': 'CreateEditFieldContextParams',
+  '2': const [
+    const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'},
+    const {'1': 'field_type', '3': 2, '4': 1, '5': 14, '6': '.FieldType', '10': 'fieldType'},
+  ],
+};
+
+/// Descriptor for `CreateEditFieldContextParams`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List createEditFieldContextParamsDescriptor = $convert.base64Decode('ChxDcmVhdGVFZGl0RmllbGRDb250ZXh0UGFyYW1zEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIpCgpmaWVsZF90eXBlGAIgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGU=');
+@$core.Deprecated('Use editFieldContextDescriptor instead')
+const EditFieldContext$json = const {
+  '1': 'EditFieldContext',
+  '2': const [
+    const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'},
+    const {'1': 'grid_field', '3': 2, '4': 1, '5': 11, '6': '.Field', '10': 'gridField'},
+    const {'1': 'type_option_data', '3': 3, '4': 1, '5': 12, '10': 'typeOptionData'},
+  ],
+};
+
+/// Descriptor for `EditFieldContext`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List editFieldContextDescriptor = $convert.base64Decode('ChBFZGl0RmllbGRDb250ZXh0EhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIlCgpncmlkX2ZpZWxkGAIgASgLMgYuRmllbGRSCWdyaWRGaWVsZBIoChB0eXBlX29wdGlvbl9kYXRhGAMgASgMUg50eXBlT3B0aW9uRGF0YQ==');
 @$core.Deprecated('Use repeatedFieldDescriptor instead')
 const RepeatedField$json = const {
   '1': 'RepeatedField',

+ 2 - 2
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart

@@ -15,7 +15,7 @@ class GridEvent extends $pb.ProtobufEnum {
   static const GridEvent GetFields = GridEvent._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFields');
   static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField');
   static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField');
-  static const GridEvent CreateDefaultField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultField');
+  static const GridEvent CreateEditFieldContext = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext');
   static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
   static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
   static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
@@ -26,7 +26,7 @@ class GridEvent extends $pb.ProtobufEnum {
     GetFields,
     UpdateField,
     CreateField,
-    CreateDefaultField,
+    CreateEditFieldContext,
     CreateRow,
     GetRow,
     UpdateCell,

+ 2 - 2
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart

@@ -17,7 +17,7 @@ const GridEvent$json = const {
     const {'1': 'GetFields', '2': 10},
     const {'1': 'UpdateField', '2': 11},
     const {'1': 'CreateField', '2': 12},
-    const {'1': 'CreateDefaultField', '2': 13},
+    const {'1': 'CreateEditFieldContext', '2': 13},
     const {'1': 'CreateRow', '2': 21},
     const {'1': 'GetRow', '2': 22},
     const {'1': 'UpdateCell', '2': 30},
@@ -25,4 +25,4 @@ const GridEvent$json = const {
 };
 
 /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEhYKEkNyZWF0ZURlZmF1bHRGaWVsZBANEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg==');
+final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEhoKFkNyZWF0ZUVkaXRGaWVsZENvbnRleHQQDRINCglDcmVhdGVSb3cQFRIKCgZHZXRSb3cQFhIOCgpVcGRhdGVDZWxsEB4=');

+ 19 - 9
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -1,8 +1,9 @@
 use crate::manager::GridManager;
 use flowy_error::FlowyError;
 use flowy_grid_data_model::entities::{
-    CellMetaChangeset, CreateFieldPayload, CreateRowPayload, Field, FieldChangeset, Grid, GridId, QueryFieldPayload,
-    QueryGridBlocksPayload, QueryRowPayload, RepeatedField, RepeatedGridBlock, Row,
+    CellMetaChangeset, CreateEditFieldContextParams, CreateFieldPayload, CreateRowPayload, EditFieldContext, Field,
+    FieldChangeset, Grid, GridId, QueryFieldPayload, QueryGridBlocksPayload, QueryRowPayload, RepeatedField,
+    RepeatedGridBlock, Row,
 };
 use flowy_grid_data_model::parser::{
     CreateFieldParams, CreateRowParams, QueryFieldParams, QueryGridBlocksParams, QueryRowParams,
@@ -72,14 +73,23 @@ pub(crate) async fn create_field_handler(
 }
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
-pub(crate) async fn create_default_field_handler(
-    data: Data<GridId>,
+pub(crate) async fn create_field_edit_context_handler(
+    data: Data<CreateEditFieldContextParams>,
     manager: AppData<Arc<GridManager>>,
-) -> DataResult<Field, FlowyError> {
-    let grid_id: GridId = data.into_inner();
-    let editor = manager.get_grid_editor(grid_id.as_ref())?;
-    let field = editor.make_default_field().await?;
-    data_result(field)
+) -> DataResult<EditFieldContext, FlowyError> {
+    let params: CreateEditFieldContextParams = data.into_inner();
+    let editor = manager.get_grid_editor(&params.grid_id)?;
+    let field_meta = editor.make_field_meta_from_ty(&params.field_type).await?;
+    let type_option_data = field_meta.type_option.as_bytes().to_vec();
+    let field: Field = field_meta.into();
+
+    let edit_context = EditFieldContext {
+        grid_id: params.grid_id,
+        grid_field: field,
+        type_option_data,
+    };
+
+    data_result(edit_context)
 }
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]

+ 3 - 3
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -13,7 +13,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
         .event(GridEvent::GetFields, get_fields_handler)
         .event(GridEvent::UpdateField, update_field_handler)
         .event(GridEvent::CreateField, create_field_handler)
-        .event(GridEvent::CreateDefaultField, create_default_field_handler)
+        .event(GridEvent::CreateEditFieldContext, create_field_edit_context_handler)
         .event(GridEvent::CreateRow, create_row_handler)
         .event(GridEvent::GetRow, get_row_handler)
         .event(GridEvent::UpdateCell, update_cell_handler);
@@ -39,8 +39,8 @@ pub enum GridEvent {
     #[event(input = "CreateFieldPayload")]
     CreateField = 12,
 
-    #[event(input = "GridId", output = "Field")]
-    CreateDefaultField = 13,
+    #[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")]
+    CreateEditFieldContext = 13,
 
     #[event(input = "CreateRowPayload", output = "Row")]
     CreateRow = 21,

+ 7 - 7
frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs

@@ -30,7 +30,7 @@ pub enum GridEvent {
     GetFields = 10,
     UpdateField = 11,
     CreateField = 12,
-    CreateDefaultField = 13,
+    CreateEditFieldContext = 13,
     CreateRow = 21,
     GetRow = 22,
     UpdateCell = 30,
@@ -48,7 +48,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             10 => ::std::option::Option::Some(GridEvent::GetFields),
             11 => ::std::option::Option::Some(GridEvent::UpdateField),
             12 => ::std::option::Option::Some(GridEvent::CreateField),
-            13 => ::std::option::Option::Some(GridEvent::CreateDefaultField),
+            13 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext),
             21 => ::std::option::Option::Some(GridEvent::CreateRow),
             22 => ::std::option::Option::Some(GridEvent::GetRow),
             30 => ::std::option::Option::Some(GridEvent::UpdateCell),
@@ -63,7 +63,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             GridEvent::GetFields,
             GridEvent::UpdateField,
             GridEvent::CreateField,
-            GridEvent::CreateDefaultField,
+            GridEvent::CreateEditFieldContext,
             GridEvent::CreateRow,
             GridEvent::GetRow,
             GridEvent::UpdateCell,
@@ -95,11 +95,11 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0fevent_map.proto*\xa3\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
+    \n\x0fevent_map.proto*\xa7\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
     \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\
-    \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x16\n\x12Cr\
-    eateDefaultField\x10\r\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\x10\
-    \x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\
+    \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x1a\n\x16Cr\
+    eateEditFieldContext\x10\r\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\
+    \x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 1 - 1
frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto

@@ -6,7 +6,7 @@ enum GridEvent {
     GetFields = 10;
     UpdateField = 11;
     CreateField = 12;
-    CreateDefaultField = 13;
+    CreateEditFieldContext = 13;
     CreateRow = 21;
     GetRow = 22;
     UpdateCell = 30;

+ 2 - 3
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -62,11 +62,10 @@ impl ClientGridEditor {
         Ok(())
     }
 
-    pub async fn make_default_field(&self) -> FlowyResult<Field> {
-        let field_type = FieldType::default();
+    pub async fn make_field_meta_from_ty(&self, field_type: &FieldType) -> FlowyResult<FieldMeta> {
         let name = format!("Property {}", self.pad.read().await.fields().len());
         let field_meta = FieldBuilder::from_field_type(&field_type).name(&name).build();
-        Ok(field_meta.into())
+        Ok(field_meta)
     }
 
     pub async fn contain_field(&self, field_id: &str) -> bool {

+ 21 - 0
shared-lib/flowy-grid-data-model/src/entities/grid.rs

@@ -67,6 +67,27 @@ impl std::convert::From<FieldMeta> for Field {
     }
 }
 
+#[derive(Debug, Default, ProtoBuf)]
+pub struct CreateEditFieldContextParams {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field_type: FieldType,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct EditFieldContext {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub grid_field: Field,
+
+    #[pb(index = 3)]
+    pub type_option_data: Vec<u8>,
+}
+
 #[derive(Debug, Default, ProtoBuf)]
 pub struct RepeatedField {
     #[pb(index = 1)]

+ 468 - 15
shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs

@@ -818,6 +818,454 @@ impl ::protobuf::reflect::ProtobufValue for FieldOrder {
     }
 }
 
+#[derive(PartialEq,Clone,Default)]
+pub struct CreateEditFieldContextParams {
+    // message fields
+    pub grid_id: ::std::string::String,
+    pub field_type: super::meta::FieldType,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a CreateEditFieldContextParams {
+    fn default() -> &'a CreateEditFieldContextParams {
+        <CreateEditFieldContextParams as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl CreateEditFieldContextParams {
+    pub fn new() -> CreateEditFieldContextParams {
+        ::std::default::Default::default()
+    }
+
+    // string grid_id = 1;
+
+
+    pub fn get_grid_id(&self) -> &str {
+        &self.grid_id
+    }
+    pub fn clear_grid_id(&mut self) {
+        self.grid_id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_grid_id(&mut self, v: ::std::string::String) {
+        self.grid_id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_grid_id(&mut self) -> &mut ::std::string::String {
+        &mut self.grid_id
+    }
+
+    // Take field
+    pub fn take_grid_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.grid_id, ::std::string::String::new())
+    }
+
+    // .FieldType field_type = 2;
+
+
+    pub fn get_field_type(&self) -> super::meta::FieldType {
+        self.field_type
+    }
+    pub fn clear_field_type(&mut self) {
+        self.field_type = super::meta::FieldType::RichText;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_field_type(&mut self, v: super::meta::FieldType) {
+        self.field_type = v;
+    }
+}
+
+impl ::protobuf::Message for CreateEditFieldContextParams {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.field_type, 2, &mut self.unknown_fields)?
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if !self.grid_id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.grid_id);
+        }
+        if self.field_type != super::meta::FieldType::RichText {
+            my_size += ::protobuf::rt::enum_size(2, self.field_type);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if !self.grid_id.is_empty() {
+            os.write_string(1, &self.grid_id)?;
+        }
+        if self.field_type != super::meta::FieldType::RichText {
+            os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.field_type))?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> CreateEditFieldContextParams {
+        CreateEditFieldContextParams::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "grid_id",
+                |m: &CreateEditFieldContextParams| { &m.grid_id },
+                |m: &mut CreateEditFieldContextParams| { &mut m.grid_id },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<super::meta::FieldType>>(
+                "field_type",
+                |m: &CreateEditFieldContextParams| { &m.field_type },
+                |m: &mut CreateEditFieldContextParams| { &mut m.field_type },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<CreateEditFieldContextParams>(
+                "CreateEditFieldContextParams",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static CreateEditFieldContextParams {
+        static instance: ::protobuf::rt::LazyV2<CreateEditFieldContextParams> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(CreateEditFieldContextParams::new)
+    }
+}
+
+impl ::protobuf::Clear for CreateEditFieldContextParams {
+    fn clear(&mut self) {
+        self.grid_id.clear();
+        self.field_type = super::meta::FieldType::RichText;
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for CreateEditFieldContextParams {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for CreateEditFieldContextParams {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+#[derive(PartialEq,Clone,Default)]
+pub struct EditFieldContext {
+    // message fields
+    pub grid_id: ::std::string::String,
+    pub grid_field: ::protobuf::SingularPtrField<Field>,
+    pub type_option_data: ::std::vec::Vec<u8>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a EditFieldContext {
+    fn default() -> &'a EditFieldContext {
+        <EditFieldContext as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl EditFieldContext {
+    pub fn new() -> EditFieldContext {
+        ::std::default::Default::default()
+    }
+
+    // string grid_id = 1;
+
+
+    pub fn get_grid_id(&self) -> &str {
+        &self.grid_id
+    }
+    pub fn clear_grid_id(&mut self) {
+        self.grid_id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_grid_id(&mut self, v: ::std::string::String) {
+        self.grid_id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_grid_id(&mut self) -> &mut ::std::string::String {
+        &mut self.grid_id
+    }
+
+    // Take field
+    pub fn take_grid_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.grid_id, ::std::string::String::new())
+    }
+
+    // .Field grid_field = 2;
+
+
+    pub fn get_grid_field(&self) -> &Field {
+        self.grid_field.as_ref().unwrap_or_else(|| <Field as ::protobuf::Message>::default_instance())
+    }
+    pub fn clear_grid_field(&mut self) {
+        self.grid_field.clear();
+    }
+
+    pub fn has_grid_field(&self) -> bool {
+        self.grid_field.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_grid_field(&mut self, v: Field) {
+        self.grid_field = ::protobuf::SingularPtrField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_grid_field(&mut self) -> &mut Field {
+        if self.grid_field.is_none() {
+            self.grid_field.set_default();
+        }
+        self.grid_field.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_grid_field(&mut self) -> Field {
+        self.grid_field.take().unwrap_or_else(|| Field::new())
+    }
+
+    // bytes type_option_data = 3;
+
+
+    pub fn get_type_option_data(&self) -> &[u8] {
+        &self.type_option_data
+    }
+    pub fn clear_type_option_data(&mut self) {
+        self.type_option_data.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_type_option_data(&mut self, v: ::std::vec::Vec<u8>) {
+        self.type_option_data = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_type_option_data(&mut self) -> &mut ::std::vec::Vec<u8> {
+        &mut self.type_option_data
+    }
+
+    // Take field
+    pub fn take_type_option_data(&mut self) -> ::std::vec::Vec<u8> {
+        ::std::mem::replace(&mut self.type_option_data, ::std::vec::Vec::new())
+    }
+}
+
+impl ::protobuf::Message for EditFieldContext {
+    fn is_initialized(&self) -> bool {
+        for v in &self.grid_field {
+            if !v.is_initialized() {
+                return false;
+            }
+        };
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.grid_field)?;
+                },
+                3 => {
+                    ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.type_option_data)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if !self.grid_id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.grid_id);
+        }
+        if let Some(ref v) = self.grid_field.as_ref() {
+            let len = v.compute_size();
+            my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
+        }
+        if !self.type_option_data.is_empty() {
+            my_size += ::protobuf::rt::bytes_size(3, &self.type_option_data);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if !self.grid_id.is_empty() {
+            os.write_string(1, &self.grid_id)?;
+        }
+        if let Some(ref v) = self.grid_field.as_ref() {
+            os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?;
+            os.write_raw_varint32(v.get_cached_size())?;
+            v.write_to_with_cached_sizes(os)?;
+        }
+        if !self.type_option_data.is_empty() {
+            os.write_bytes(3, &self.type_option_data)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> EditFieldContext {
+        EditFieldContext::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "grid_id",
+                |m: &EditFieldContext| { &m.grid_id },
+                |m: &mut EditFieldContext| { &mut m.grid_id },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<Field>>(
+                "grid_field",
+                |m: &EditFieldContext| { &m.grid_field },
+                |m: &mut EditFieldContext| { &mut m.grid_field },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "type_option_data",
+                |m: &EditFieldContext| { &m.type_option_data },
+                |m: &mut EditFieldContext| { &mut m.type_option_data },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<EditFieldContext>(
+                "EditFieldContext",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static EditFieldContext {
+        static instance: ::protobuf::rt::LazyV2<EditFieldContext> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(EditFieldContext::new)
+    }
+}
+
+impl ::protobuf::Clear for EditFieldContext {
+    fn clear(&mut self) {
+        self.grid_id.clear();
+        self.grid_field.clear();
+        self.type_option_data.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for EditFieldContext {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for EditFieldContext {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
 #[derive(PartialEq,Clone,Default)]
 pub struct RepeatedField {
     // message fields
@@ -4418,21 +4866,26 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     \x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\
     \x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\
     \x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"'\n\nFieldOrder\x12\
-    \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"-\n\rRepeatedField\
-    \x12\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Re\
-    peatedFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\
-    \x05items\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05ro\
-    wId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06he\
-    ight\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\
-    \x18\x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\
-    \x0b2\x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\
-    \x03\x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03k\
-    ey\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\
-    \x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\
-    \x01\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\
-    \x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockO\
-    rder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBloc\
-    k\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\
+    \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"b\n\x1cCreateEditFiel\
+    dContextParams\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12)\n\
+    \nfield_type\x18\x02\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditF\
+    ieldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ng\
+    rid_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_opt\
+    ion_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\
+    \x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\
+    edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\
+    ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\
+    \x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\
+    t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\
+    \x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\
+    \x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\
+    \x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\
+    \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\
+    .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\
+    \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\
+    items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\
+    \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\
+    \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\
     \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\
     \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\
     \x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b\

+ 9 - 0
shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto

@@ -18,6 +18,15 @@ message Field {
 message FieldOrder {
     string field_id = 1;
 }
+message CreateEditFieldContextParams {
+    string grid_id = 1;
+    FieldType field_type = 2;
+}
+message EditFieldContext {
+    string grid_id = 1;
+    Field grid_field = 2;
+    bytes type_option_data = 3;
+}
 message RepeatedField {
     repeated Field items = 1;
 }