Kaynağa Gözat

chore: build board card ui

appflowy 2 yıl önce
ebeveyn
işleme
055868bae3
34 değiştirilmiş dosya ile 447 ekleme ve 189 silme
  1. 1 1
      frontend/.vscode/launch.json
  2. 19 16
      frontend/app_flowy/lib/plugins/board/application/board_bloc.dart
  3. 76 0
      frontend/app_flowy/lib/plugins/board/application/card/board_select_option_cell_bloc.dart
  4. 66 0
      frontend/app_flowy/lib/plugins/board/application/card/board_text_cell_bloc.dart
  5. 3 4
      frontend/app_flowy/lib/plugins/board/presentation/board_page.dart
  6. 51 0
      frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart
  7. 49 0
      frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart
  8. 1 1
      frontend/app_flowy/lib/plugins/board/presentation/card/card.dart
  9. 0 0
      frontend/app_flowy/lib/plugins/board/presentation/card/card_cell_builder.dart
  10. 10 8
      frontend/app_flowy/lib/plugins/grid/application/cell/checkbox_cell_bloc.dart
  11. 19 19
      frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart
  12. 6 6
      frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart
  13. 12 9
      frontend/app_flowy/lib/plugins/grid/application/cell/number_cell_bloc.dart
  14. 6 6
      frontend/app_flowy/lib/plugins/grid/application/cell/select_option_cell_bloc.dart
  15. 9 8
      frontend/app_flowy/lib/plugins/grid/application/cell/text_cell_bloc.dart
  16. 9 8
      frontend/app_flowy/lib/plugins/grid/application/cell/url_cell_bloc.dart
  17. 9 8
      frontend/app_flowy/lib/plugins/grid/application/cell/url_cell_editor_bloc.dart
  18. 3 3
      frontend/app_flowy/lib/plugins/grid/application/field/type_option/date_bloc.dart
  19. 3 3
      frontend/app_flowy/lib/plugins/grid/application/field/type_option/number_bloc.dart
  20. 20 20
      frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart
  21. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart
  22. 21 20
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart
  23. 14 13
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart
  24. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/cell_editor.dart
  25. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart
  26. 5 5
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart
  27. 5 5
      frontend/app_flowy/lib/startup/deps_resolver.dart
  28. 3 3
      frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart
  29. 1 1
      frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart
  30. 3 3
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart
  31. 10 10
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart
  32. 2 2
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart
  33. 2 2
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart
  34. 6 2
      frontend/rust-lib/flowy-test/src/event_builder.rs

+ 1 - 1
frontend/.vscode/launch.json

@@ -44,7 +44,7 @@
             "type": "dart",
             "preLaunchTask": "AF: Clean + Rebuild All",
             "env": {
-                "RUST_LOG": "info"
+                "RUST_LOG": "trace"
             },
             "cwd": "${workspaceRoot}/app_flowy"
         },

+ 19 - 16
frontend/app_flowy/lib/plugins/board/application/board_bloc.dart

@@ -41,8 +41,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
       ) {},
     );
 
-    // boardDataController.addColumns(_buildColumns());
-
     on<BoardEvent>(
       (event, emit) async {
         await event.when(
@@ -87,6 +85,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
           return AFBoardColumnData(
             id: group.groupId,
             desc: group.desc,
+            items: _buildRows(group.rows),
             customData: group,
           );
         }).toList();
@@ -99,6 +98,20 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
     );
   }
 
+  List<BoardColumnItem> _buildRows(List<RowPB> rows) {
+    return rows.map((row) {
+      final rowInfo = RowInfo(
+        gridId: _dataController.gridId,
+        blockId: row.blockId,
+        id: row.id,
+        fields: _dataController.fieldCache.unmodifiableFields,
+        height: row.height.toDouble(),
+        rawRow: row,
+      );
+      return BoardColumnItem(row: rowInfo);
+    }).toList();
+  }
+
   Future<void> _loadGrid(Emitter<BoardState> emit) async {
     final result = await _dataController.loadData();
     result.fold(
@@ -172,21 +185,11 @@ class GridFieldEquatable extends Equatable {
   UnmodifiableListView<FieldPB> get value => UnmodifiableListView(_fields);
 }
 
-class TextItem extends ColumnItem {
-  final String s;
-
-  TextItem(this.s);
-
-  @override
-  String get id => s;
-}
-
-class RichTextItem extends ColumnItem {
-  final String title;
-  final String subtitle;
+class BoardColumnItem extends AFColumnItem {
+  final RowInfo row;
 
-  RichTextItem({required this.title, required this.subtitle});
+  BoardColumnItem({required this.row});
 
   @override
-  String get id => title;
+  String get id => row.id;
 }

+ 76 - 0
frontend/app_flowy/lib/plugins/board/application/card/board_select_option_cell_bloc.dart

@@ -0,0 +1,76 @@
+import 'dart:async';
+import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
+
+part 'board_select_option_cell_bloc.freezed.dart';
+
+class BoardSelectOptionCellBloc
+    extends Bloc<BoardSelectOptionCellEvent, BoardSelectOptionCellState> {
+  final GridSelectOptionCellController cellController;
+  void Function()? _onCellChangedFn;
+
+  BoardSelectOptionCellBloc({
+    required this.cellController,
+  }) : super(BoardSelectOptionCellState.initial(cellController)) {
+    on<BoardSelectOptionCellEvent>(
+      (event, emit) async {
+        await event.when(
+          initial: () async {
+            _startListening();
+          },
+          didReceiveOptions: (List<SelectOptionPB> selectedOptions) {
+            emit(state.copyWith(selectedOptions: selectedOptions));
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    if (_onCellChangedFn != null) {
+      cellController.removeListener(_onCellChangedFn!);
+      _onCellChangedFn = null;
+    }
+    cellController.dispose();
+    return super.close();
+  }
+
+  void _startListening() {
+    _onCellChangedFn = cellController.startListening(
+      onCellChanged: ((selectOptionContext) {
+        if (!isClosed) {
+          add(BoardSelectOptionCellEvent.didReceiveOptions(
+            selectOptionContext?.selectOptions ?? [],
+          ));
+        }
+      }),
+    );
+  }
+}
+
+@freezed
+class BoardSelectOptionCellEvent with _$BoardSelectOptionCellEvent {
+  const factory BoardSelectOptionCellEvent.initial() = _InitialCell;
+  const factory BoardSelectOptionCellEvent.didReceiveOptions(
+    List<SelectOptionPB> selectedOptions,
+  ) = _DidReceiveOptions;
+}
+
+@freezed
+class BoardSelectOptionCellState with _$BoardSelectOptionCellState {
+  const factory BoardSelectOptionCellState({
+    required List<SelectOptionPB> selectedOptions,
+  }) = _BoardSelectOptionCellState;
+
+  factory BoardSelectOptionCellState.initial(
+      GridSelectOptionCellController context) {
+    final data = context.getCellData();
+
+    return BoardSelectOptionCellState(
+      selectedOptions: data?.selectOptions ?? [],
+    );
+  }
+}

+ 66 - 0
frontend/app_flowy/lib/plugins/board/application/card/board_text_cell_bloc.dart

@@ -0,0 +1,66 @@
+import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'dart:async';
+
+part 'board_text_cell_bloc.freezed.dart';
+
+class BoardTextCellBloc extends Bloc<BoardTextCellEvent, BoardTextCellState> {
+  final GridCellController cellController;
+  void Function()? _onCellChangedFn;
+  BoardTextCellBloc({
+    required this.cellController,
+  }) : super(BoardTextCellState.initial(cellController)) {
+    on<BoardTextCellEvent>(
+      (event, emit) async {
+        await event.when(
+          initial: () async {
+            _startListening();
+          },
+          didReceiveCellUpdate: (content) {
+            emit(state.copyWith(content: content));
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    if (_onCellChangedFn != null) {
+      cellController.removeListener(_onCellChangedFn!);
+      _onCellChangedFn = null;
+    }
+    cellController.dispose();
+    return super.close();
+  }
+
+  void _startListening() {
+    _onCellChangedFn = cellController.startListening(
+      onCellChanged: ((cellContent) {
+        if (!isClosed) {
+          add(BoardTextCellEvent.didReceiveCellUpdate(cellContent ?? ""));
+        }
+      }),
+    );
+  }
+}
+
+@freezed
+class BoardTextCellEvent with _$BoardTextCellEvent {
+  const factory BoardTextCellEvent.initial() = _InitialCell;
+  const factory BoardTextCellEvent.didReceiveCellUpdate(String cellContent) =
+      _DidReceiveCellUpdate;
+}
+
+@freezed
+class BoardTextCellState with _$BoardTextCellState {
+  const factory BoardTextCellState({
+    required String content,
+  }) = _BoardTextCellState;
+
+  factory BoardTextCellState.initial(GridCellController context) =>
+      BoardTextCellState(
+        content: context.getCellData() ?? "",
+      );
+}

+ 3 - 4
frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

@@ -1,13 +1,12 @@
 // ignore_for_file: unused_field
 
-import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
 import 'package:appflowy_board/appflowy_board.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import '../application/board_bloc.dart';
-import 'card.dart';
+import 'card/card.dart';
 
 class BoardPage extends StatelessWidget {
   final ViewPB view;
@@ -87,8 +86,8 @@ class BoardContent extends StatelessWidget {
     );
   }
 
-  Widget _buildCard(BuildContext context, ColumnItem item) {
-    final rowInfo = item as RowInfo;
+  Widget _buildCard(BuildContext context, AFColumnItem item) {
+    final rowInfo = (item as BoardColumnItem).row;
     return AppFlowyColumnItemCard(
       key: ObjectKey(item),
       child: BoardCard(rowInfo: rowInfo),

+ 51 - 0
frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart

@@ -0,0 +1,51 @@
+import 'package:app_flowy/plugins/board/application/card/board_select_option_cell_bloc.dart';
+import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
+import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class BoardSelectOptionCell extends StatefulWidget {
+  final GridCellControllerBuilder cellControllerBuilder;
+
+  const BoardSelectOptionCell({
+    required this.cellControllerBuilder,
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  State<BoardSelectOptionCell> createState() => _BoardSelectOptionCellState();
+}
+
+class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
+  late BoardSelectOptionCellBloc _cellBloc;
+
+  @override
+  void initState() {
+    final cellController =
+        widget.cellControllerBuilder.build() as GridSelectOptionCellController;
+    _cellBloc = BoardSelectOptionCellBloc(cellController: cellController)
+      ..add(const BoardSelectOptionCellEvent.initial());
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider.value(
+      value: _cellBloc,
+      child: BlocBuilder<BoardSelectOptionCellBloc, BoardSelectOptionCellState>(
+        builder: (context, state) {
+          return SelectOptionWrap(
+            selectOptions: state.selectedOptions,
+            cellControllerBuilder: widget.cellControllerBuilder,
+          );
+        },
+      ),
+    );
+  }
+
+  @override
+  Future<void> dispose() async {
+    _cellBloc.close();
+    super.dispose();
+  }
+}

+ 49 - 0
frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart

@@ -0,0 +1,49 @@
+import 'package:app_flowy/plugins/board/application/card/board_text_cell_bloc.dart';
+import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class BoardTextCell extends StatefulWidget {
+  final GridCellControllerBuilder cellControllerBuilder;
+  const BoardTextCell({required this.cellControllerBuilder, Key? key})
+      : super(key: key);
+
+  @override
+  State<BoardTextCell> createState() => _BoardTextCellState();
+}
+
+class _BoardTextCellState extends State<BoardTextCell> {
+  late BoardTextCellBloc _cellBloc;
+
+  @override
+  void initState() {
+    final cellController =
+        widget.cellControllerBuilder.build() as GridCellController;
+
+    _cellBloc = BoardTextCellBloc(cellController: cellController)
+      ..add(const BoardTextCellEvent.initial());
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider.value(
+      value: _cellBloc,
+      child: BlocBuilder<BoardTextCellBloc, BoardTextCellState>(
+        builder: (context, state) {
+          return SizedBox(
+            height: 30,
+            child: FlowyText.medium(state.content),
+          );
+        },
+      ),
+    );
+  }
+
+  @override
+  Future<void> dispose() async {
+    _cellBloc.close();
+    super.dispose();
+  }
+}

+ 1 - 1
frontend/app_flowy/lib/plugins/board/presentation/card.dart → frontend/app_flowy/lib/plugins/board/presentation/card/card.dart

@@ -8,6 +8,6 @@ class BoardCard extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return const Text('1234');
+    return const SizedBox(height: 20, child: Text('1234'));
   }
 }

+ 0 - 0
frontend/app_flowy/lib/plugins/board/presentation/card/card_cell_builder.dart


+ 10 - 8
frontend/app_flowy/lib/plugins/grid/application/cell/checkbox_cell_bloc.dart

@@ -6,13 +6,13 @@ import 'cell_service/cell_service.dart';
 part 'checkbox_cell_bloc.freezed.dart';
 
 class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
-  final GridCellController cellContext;
+  final GridCellController cellController;
   void Function()? _onCellChangedFn;
 
   CheckboxCellBloc({
     required CellService service,
-    required this.cellContext,
-  }) : super(CheckboxCellState.initial(cellContext)) {
+    required this.cellController,
+  }) : super(CheckboxCellState.initial(cellController)) {
     on<CheckboxCellEvent>(
       (event, emit) async {
         await event.when(
@@ -33,16 +33,17 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
 
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(onCellChanged: ((cellData) {
+    _onCellChangedFn =
+        cellController.startListening(onCellChanged: ((cellData) {
       if (!isClosed) {
         add(CheckboxCellEvent.didReceiveCellUpdate(cellData));
       }
@@ -50,7 +51,7 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
   }
 
   void _updateCellData() {
-    cellContext.saveCellData(!state.isSelected ? "Yes" : "No");
+    cellController.saveCellData(!state.isSelected ? "Yes" : "No");
   }
 }
 
@@ -58,7 +59,8 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
 class CheckboxCellEvent with _$CheckboxCellEvent {
   const factory CheckboxCellEvent.initial() = _Initial;
   const factory CheckboxCellEvent.select() = _Selected;
-  const factory CheckboxCellEvent.didReceiveCellUpdate(String? cellData) = _DidReceiveCellUpdate;
+  const factory CheckboxCellEvent.didReceiveCellUpdate(String? cellData) =
+      _DidReceiveCellUpdate;
 }
 
 @freezed

+ 19 - 19
frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart

@@ -18,14 +18,14 @@ import 'package:fixnum/fixnum.dart' as $fixnum;
 part 'date_cal_bloc.freezed.dart';
 
 class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
-  final GridDateCellController cellContext;
+  final GridDateCellController cellController;
   void Function()? _onCellChangedFn;
 
   DateCalBloc({
-    required DateTypeOption dateTypeOption,
+    required DateTypeOptionPB dateTypeOptionPB,
     required DateCellDataPB? cellData,
-    required this.cellContext,
-  }) : super(DateCalState.initial(dateTypeOption, cellData)) {
+    required this.cellController,
+  }) : super(DateCalState.initial(dateTypeOptionPB, cellData)) {
     on<DateCalEvent>(
       (event, emit) async {
         await event.when(
@@ -102,7 +102,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
       }
     }
 
-    cellContext.saveCellData(newCalData, resultCallback: (result) {
+    cellController.saveCellData(newCalData, resultCallback: (result) {
       result.fold(
         () => updateCalData(Some(newCalData), none()),
         (err) {
@@ -120,7 +120,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
 
   String timeFormatPrompt(FlowyError error) {
     String msg = LocaleKeys.grid_field_invalidTimeFormat.tr() + ". ";
-    switch (state.dateTypeOption.timeFormat) {
+    switch (state.dateTypeOptionPB.timeFormat) {
       case TimeFormat.TwelveHour:
         msg = msg + "e.g. 01: 00 AM";
         break;
@@ -136,15 +136,15 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(
+    _onCellChangedFn = cellController.startListening(
       onCellChanged: ((cell) {
         if (!isClosed) {
           add(DateCalEvent.didReceiveCellUpdate(cell));
@@ -159,8 +159,8 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
     TimeFormat? timeFormat,
     bool? includeTime,
   }) async {
-    state.dateTypeOption.freeze();
-    final newDateTypeOption = state.dateTypeOption.rebuild((typeOption) {
+    state.dateTypeOptionPB.freeze();
+    final newDateTypeOption = state.dateTypeOptionPB.rebuild((typeOption) {
       if (dateFormat != null) {
         typeOption.dateFormat = dateFormat;
       }
@@ -175,14 +175,14 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
     });
 
     final result = await FieldService.updateFieldTypeOption(
-      gridId: cellContext.gridId,
-      fieldId: cellContext.field.id,
+      gridId: cellController.gridId,
+      fieldId: cellController.field.id,
       typeOptionData: newDateTypeOption.writeToBuffer(),
     );
 
     result.fold(
       (l) => emit(state.copyWith(
-          dateTypeOption: newDateTypeOption,
+          dateTypeOptionPB: newDateTypeOption,
           timeHintText: _timeHintText(newDateTypeOption))),
       (err) => Log.error(err),
     );
@@ -210,7 +210,7 @@ class DateCalEvent with _$DateCalEvent {
 @freezed
 class DateCalState with _$DateCalState {
   const factory DateCalState({
-    required DateTypeOption dateTypeOption,
+    required DateTypeOptionPB dateTypeOptionPB,
     required CalendarFormat format,
     required DateTime focusedDay,
     required Option<String> timeFormatError,
@@ -220,24 +220,24 @@ class DateCalState with _$DateCalState {
   }) = _DateCalState;
 
   factory DateCalState.initial(
-    DateTypeOption dateTypeOption,
+    DateTypeOptionPB dateTypeOptionPB,
     DateCellDataPB? cellData,
   ) {
     Option<CalendarData> calData = calDataFromCellData(cellData);
     final time = calData.foldRight("", (dateData, previous) => dateData.time);
     return DateCalState(
-      dateTypeOption: dateTypeOption,
+      dateTypeOptionPB: dateTypeOptionPB,
       format: CalendarFormat.month,
       focusedDay: DateTime.now(),
       time: time,
       calData: calData,
       timeFormatError: none(),
-      timeHintText: _timeHintText(dateTypeOption),
+      timeHintText: _timeHintText(dateTypeOptionPB),
     );
   }
 }
 
-String _timeHintText(DateTypeOption typeOption) {
+String _timeHintText(DateTypeOptionPB typeOption) {
   switch (typeOption.timeFormat) {
     case TimeFormat.TwelveHour:
       return LocaleKeys.document_date_timeHintTextInTwelveHour.tr();

+ 6 - 6
frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart

@@ -7,11 +7,11 @@ import 'cell_service/cell_service.dart';
 part 'date_cell_bloc.freezed.dart';
 
 class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
-  final GridDateCellController cellContext;
+  final GridDateCellController cellController;
   void Function()? _onCellChangedFn;
 
-  DateCellBloc({required this.cellContext})
-      : super(DateCellState.initial(cellContext)) {
+  DateCellBloc({required this.cellController})
+      : super(DateCellState.initial(cellController)) {
     on<DateCellEvent>(
       (event, emit) async {
         event.when(
@@ -30,15 +30,15 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(
+    _onCellChangedFn = cellController.startListening(
       onCellChanged: ((data) {
         if (!isClosed) {
           add(DateCellEvent.didReceiveCellUpdate(data));

+ 12 - 9
frontend/app_flowy/lib/plugins/grid/application/cell/number_cell_bloc.dart

@@ -8,12 +8,12 @@ import 'cell_service/cell_service.dart';
 part 'number_cell_bloc.freezed.dart';
 
 class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
-  final GridCellController cellContext;
+  final GridCellController cellController;
   void Function()? _onCellChangedFn;
 
   NumberCellBloc({
-    required this.cellContext,
-  }) : super(NumberCellState.initial(cellContext)) {
+    required this.cellController,
+  }) : super(NumberCellState.initial(cellController)) {
     on<NumberCellEvent>(
       (event, emit) async {
         event.when(
@@ -24,11 +24,13 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
             emit(state.copyWith(content: content));
           },
           updateCell: (text) {
-            cellContext.saveCellData(text, resultCallback: (result) {
+            cellController.saveCellData(text, resultCallback: (result) {
               result.fold(
                 () => null,
                 (err) {
-                  if (!isClosed) add(NumberCellEvent.didReceiveCellUpdate(right(err)));
+                  if (!isClosed) {
+                    add(NumberCellEvent.didReceiveCellUpdate(right(err)));
+                  }
                 },
               );
             });
@@ -41,15 +43,15 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(
+    _onCellChangedFn = cellController.startListening(
       onCellChanged: ((cellContent) {
         if (!isClosed) {
           add(NumberCellEvent.didReceiveCellUpdate(left(cellContent ?? "")));
@@ -63,7 +65,8 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
 class NumberCellEvent with _$NumberCellEvent {
   const factory NumberCellEvent.initial() = _Initial;
   const factory NumberCellEvent.updateCell(String text) = _UpdateCell;
-  const factory NumberCellEvent.didReceiveCellUpdate(Either<String, FlowyError> cellContent) = _DidReceiveCellUpdate;
+  const factory NumberCellEvent.didReceiveCellUpdate(
+      Either<String, FlowyError> cellContent) = _DidReceiveCellUpdate;
 }
 
 @freezed

+ 6 - 6
frontend/app_flowy/lib/plugins/grid/application/cell/select_option_cell_bloc.dart

@@ -8,12 +8,12 @@ part 'select_option_cell_bloc.freezed.dart';
 
 class SelectOptionCellBloc
     extends Bloc<SelectOptionCellEvent, SelectOptionCellState> {
-  final GridSelectOptionCellController cellContext;
+  final GridSelectOptionCellController cellController;
   void Function()? _onCellChangedFn;
 
   SelectOptionCellBloc({
-    required this.cellContext,
-  }) : super(SelectOptionCellState.initial(cellContext)) {
+    required this.cellController,
+  }) : super(SelectOptionCellState.initial(cellController)) {
     on<SelectOptionCellEvent>(
       (event, emit) async {
         await event.map(
@@ -33,15 +33,15 @@ class SelectOptionCellBloc
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(
+    _onCellChangedFn = cellController.startListening(
       onCellChanged: ((selectOptionContext) {
         if (!isClosed) {
           add(SelectOptionCellEvent.didReceiveOptions(

+ 9 - 8
frontend/app_flowy/lib/plugins/grid/application/cell/text_cell_bloc.dart

@@ -6,11 +6,11 @@ import 'cell_service/cell_service.dart';
 part 'text_cell_bloc.freezed.dart';
 
 class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
-  final GridCellController cellContext;
+  final GridCellController cellController;
   void Function()? _onCellChangedFn;
   TextCellBloc({
-    required this.cellContext,
-  }) : super(TextCellState.initial(cellContext)) {
+    required this.cellController,
+  }) : super(TextCellState.initial(cellController)) {
     on<TextCellEvent>(
       (event, emit) async {
         await event.when(
@@ -18,7 +18,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
             _startListening();
           },
           updateText: (text) {
-            cellContext.saveCellData(text);
+            cellController.saveCellData(text);
             emit(state.copyWith(content: text));
           },
           didReceiveCellUpdate: (content) {
@@ -32,15 +32,15 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(
+    _onCellChangedFn = cellController.startListening(
       onCellChanged: ((cellContent) {
         if (!isClosed) {
           add(TextCellEvent.didReceiveCellUpdate(cellContent ?? ""));
@@ -53,7 +53,8 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
 @freezed
 class TextCellEvent with _$TextCellEvent {
   const factory TextCellEvent.initial() = _InitialCell;
-  const factory TextCellEvent.didReceiveCellUpdate(String cellContent) = _DidReceiveCellUpdate;
+  const factory TextCellEvent.didReceiveCellUpdate(String cellContent) =
+      _DidReceiveCellUpdate;
   const factory TextCellEvent.updateText(String text) = _UpdateText;
 }
 

+ 9 - 8
frontend/app_flowy/lib/plugins/grid/application/cell/url_cell_bloc.dart

@@ -7,11 +7,11 @@ import 'cell_service/cell_service.dart';
 part 'url_cell_bloc.freezed.dart';
 
 class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
-  final GridURLCellController cellContext;
+  final GridURLCellController cellController;
   void Function()? _onCellChangedFn;
   URLCellBloc({
-    required this.cellContext,
-  }) : super(URLCellState.initial(cellContext)) {
+    required this.cellController,
+  }) : super(URLCellState.initial(cellController)) {
     on<URLCellEvent>(
       (event, emit) async {
         event.when(
@@ -25,7 +25,7 @@ class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
             ));
           },
           updateURL: (String url) {
-            cellContext.saveCellData(url, deduplicate: true);
+            cellController.saveCellData(url, deduplicate: true);
           },
         );
       },
@@ -35,15 +35,15 @@ class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(
+    _onCellChangedFn = cellController.startListening(
       onCellChanged: ((cellData) {
         if (!isClosed) {
           add(URLCellEvent.didReceiveCellUpdate(cellData));
@@ -57,7 +57,8 @@ class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
 class URLCellEvent with _$URLCellEvent {
   const factory URLCellEvent.initial() = _InitialCell;
   const factory URLCellEvent.updateURL(String url) = _UpdateURL;
-  const factory URLCellEvent.didReceiveCellUpdate(URLCellDataPB? cell) = _DidReceiveCellUpdate;
+  const factory URLCellEvent.didReceiveCellUpdate(URLCellDataPB? cell) =
+      _DidReceiveCellUpdate;
 }
 
 @freezed

+ 9 - 8
frontend/app_flowy/lib/plugins/grid/application/cell/url_cell_editor_bloc.dart

@@ -7,11 +7,11 @@ import 'cell_service/cell_service.dart';
 part 'url_cell_editor_bloc.freezed.dart';
 
 class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
-  final GridURLCellController cellContext;
+  final GridURLCellController cellController;
   void Function()? _onCellChangedFn;
   URLCellEditorBloc({
-    required this.cellContext,
-  }) : super(URLCellEditorState.initial(cellContext)) {
+    required this.cellController,
+  }) : super(URLCellEditorState.initial(cellController)) {
     on<URLCellEditorEvent>(
       (event, emit) async {
         event.when(
@@ -19,7 +19,7 @@ class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
             _startListening();
           },
           updateText: (text) {
-            cellContext.saveCellData(text, deduplicate: true);
+            cellController.saveCellData(text, deduplicate: true);
             emit(state.copyWith(content: text));
           },
           didReceiveCellUpdate: (cellData) {
@@ -33,15 +33,15 @@ class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {
-      cellContext.removeListener(_onCellChangedFn!);
+      cellController.removeListener(_onCellChangedFn!);
       _onCellChangedFn = null;
     }
-    cellContext.dispose();
+    cellController.dispose();
     return super.close();
   }
 
   void _startListening() {
-    _onCellChangedFn = cellContext.startListening(
+    _onCellChangedFn = cellController.startListening(
       onCellChanged: ((cellData) {
         if (!isClosed) {
           add(URLCellEditorEvent.didReceiveCellUpdate(cellData));
@@ -54,7 +54,8 @@ class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
 @freezed
 class URLCellEditorEvent with _$URLCellEditorEvent {
   const factory URLCellEditorEvent.initial() = _InitialCell;
-  const factory URLCellEditorEvent.didReceiveCellUpdate(URLCellDataPB? cell) = _DidReceiveCellUpdate;
+  const factory URLCellEditorEvent.didReceiveCellUpdate(URLCellDataPB? cell) =
+      _DidReceiveCellUpdate;
   const factory URLCellEditorEvent.updateText(String text) = _UpdateText;
 }
 

+ 3 - 3
frontend/app_flowy/lib/plugins/grid/application/field/type_option/date_bloc.dart

@@ -32,7 +32,7 @@ class DateTypeOptionBloc
     );
   }
 
-  DateTypeOption _updateTypeOption({
+  DateTypeOptionPB _updateTypeOption({
     DateFormat? dateFormat,
     TimeFormat? timeFormat,
     bool? includeTime,
@@ -72,9 +72,9 @@ class DateTypeOptionEvent with _$DateTypeOptionEvent {
 @freezed
 class DateTypeOptionState with _$DateTypeOptionState {
   const factory DateTypeOptionState({
-    required DateTypeOption typeOption,
+    required DateTypeOptionPB typeOption,
   }) = _DateTypeOptionState;
 
-  factory DateTypeOptionState.initial(DateTypeOption typeOption) =>
+  factory DateTypeOptionState.initial(DateTypeOptionPB typeOption) =>
       DateTypeOptionState(typeOption: typeOption);
 }

+ 3 - 3
frontend/app_flowy/lib/plugins/grid/application/field/type_option/number_bloc.dart

@@ -23,7 +23,7 @@ class NumberTypeOptionBloc
     );
   }
 
-  NumberTypeOption _updateNumberFormat(NumberFormat format) {
+  NumberTypeOptionPB _updateNumberFormat(NumberFormat format) {
     state.typeOption.freeze();
     return state.typeOption.rebuild((typeOption) {
       typeOption.format = format;
@@ -45,10 +45,10 @@ class NumberTypeOptionEvent with _$NumberTypeOptionEvent {
 @freezed
 class NumberTypeOptionState with _$NumberTypeOptionState {
   const factory NumberTypeOptionState({
-    required NumberTypeOption typeOption,
+    required NumberTypeOptionPB typeOption,
   }) = _NumberTypeOptionState;
 
-  factory NumberTypeOptionState.initial(NumberTypeOption typeOption) =>
+  factory NumberTypeOptionState.initial(NumberTypeOptionPB typeOption) =>
       NumberTypeOptionState(
         typeOption: typeOption,
       );

+ 20 - 20
frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart

@@ -18,56 +18,56 @@ abstract class TypeOptionDataParser<T> {
 }
 
 // Number
-typedef NumberTypeOptionContext = TypeOptionContext<NumberTypeOption>;
+typedef NumberTypeOptionContext = TypeOptionContext<NumberTypeOptionPB>;
 
 class NumberTypeOptionWidgetDataParser
-    extends TypeOptionDataParser<NumberTypeOption> {
+    extends TypeOptionDataParser<NumberTypeOptionPB> {
   @override
-  NumberTypeOption fromBuffer(List<int> buffer) {
-    return NumberTypeOption.fromBuffer(buffer);
+  NumberTypeOptionPB fromBuffer(List<int> buffer) {
+    return NumberTypeOptionPB.fromBuffer(buffer);
   }
 }
 
 // RichText
-typedef RichTextTypeOptionContext = TypeOptionContext<RichTextTypeOption>;
+typedef RichTextTypeOptionContext = TypeOptionContext<RichTextTypeOptionPB>;
 
 class RichTextTypeOptionWidgetDataParser
-    extends TypeOptionDataParser<RichTextTypeOption> {
+    extends TypeOptionDataParser<RichTextTypeOptionPB> {
   @override
-  RichTextTypeOption fromBuffer(List<int> buffer) {
-    return RichTextTypeOption.fromBuffer(buffer);
+  RichTextTypeOptionPB fromBuffer(List<int> buffer) {
+    return RichTextTypeOptionPB.fromBuffer(buffer);
   }
 }
 
 // Checkbox
-typedef CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOption>;
+typedef CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOptionPB>;
 
 class CheckboxTypeOptionWidgetDataParser
-    extends TypeOptionDataParser<CheckboxTypeOption> {
+    extends TypeOptionDataParser<CheckboxTypeOptionPB> {
   @override
-  CheckboxTypeOption fromBuffer(List<int> buffer) {
-    return CheckboxTypeOption.fromBuffer(buffer);
+  CheckboxTypeOptionPB fromBuffer(List<int> buffer) {
+    return CheckboxTypeOptionPB.fromBuffer(buffer);
   }
 }
 
 // URL
-typedef URLTypeOptionContext = TypeOptionContext<URLTypeOption>;
+typedef URLTypeOptionContext = TypeOptionContext<URLTypeOptionPB>;
 
 class URLTypeOptionWidgetDataParser
-    extends TypeOptionDataParser<URLTypeOption> {
+    extends TypeOptionDataParser<URLTypeOptionPB> {
   @override
-  URLTypeOption fromBuffer(List<int> buffer) {
-    return URLTypeOption.fromBuffer(buffer);
+  URLTypeOptionPB fromBuffer(List<int> buffer) {
+    return URLTypeOptionPB.fromBuffer(buffer);
   }
 }
 
 // Date
-typedef DateTypeOptionContext = TypeOptionContext<DateTypeOption>;
+typedef DateTypeOptionContext = TypeOptionContext<DateTypeOptionPB>;
 
-class DateTypeOptionDataParser extends TypeOptionDataParser<DateTypeOption> {
+class DateTypeOptionDataParser extends TypeOptionDataParser<DateTypeOptionPB> {
   @override
-  DateTypeOption fromBuffer(List<int> buffer) {
-    return DateTypeOption.fromBuffer(buffer);
+  DateTypeOptionPB fromBuffer(List<int> buffer) {
+    return DateTypeOptionPB.fromBuffer(buffer);
   }
 }
 

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart

@@ -84,7 +84,7 @@ class _DateCellState extends GridCellState<GridDateCell> {
         DateCellEditor(onDismissed: () => widget.onCellEditing.value = false);
     calendar.show(
       context,
-      cellController: bloc.cellContext.clone(),
+      cellController: bloc.cellController.clone(),
     );
   }
 

+ 21 - 20
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart

@@ -40,10 +40,10 @@ class DateCellEditor with FlowyOverlayDelegate {
     final result =
         await cellController.getFieldTypeOption(DateTypeOptionDataParser());
     result.fold(
-      (dateTypeOption) {
+      (dateTypeOptionPB) {
         final calendar = _CellCalendarWidget(
           cellContext: cellController,
-          dateTypeOption: dateTypeOption,
+          dateTypeOptionPB: dateTypeOptionPB,
         );
 
         FlowyOverlay.of(context).insertWithAnchor(
@@ -79,11 +79,11 @@ class DateCellEditor with FlowyOverlayDelegate {
 
 class _CellCalendarWidget extends StatelessWidget {
   final GridDateCellController cellContext;
-  final DateTypeOption dateTypeOption;
+  final DateTypeOptionPB dateTypeOptionPB;
 
   const _CellCalendarWidget({
     required this.cellContext,
-    required this.dateTypeOption,
+    required this.dateTypeOptionPB,
     Key? key,
   }) : super(key: key);
 
@@ -93,9 +93,9 @@ class _CellCalendarWidget extends StatelessWidget {
     return BlocProvider(
       create: (context) {
         return DateCalBloc(
-          dateTypeOption: dateTypeOption,
+          dateTypeOptionPB: dateTypeOptionPB,
           cellData: cellContext.getCellData(),
-          cellContext: cellContext,
+          cellController: cellContext,
         )..add(const DateCalEvent.initial());
       },
       child: BlocBuilder<DateCalBloc, DateCalState>(
@@ -197,7 +197,7 @@ class _IncludeTimeButton extends StatelessWidget {
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     return BlocSelector<DateCalBloc, DateCalState, bool>(
-      selector: (state) => state.dateTypeOption.includeTime,
+      selector: (state) => state.dateTypeOptionPB.includeTime,
       builder: (context, includeTime) {
         return SizedBox(
           height: 50,
@@ -244,7 +244,7 @@ class _TimeTextFieldState extends State<_TimeTextField> {
   void initState() {
     _focusNode = FocusNode();
     _controller = TextEditingController(text: widget.bloc.state.time);
-    if (widget.bloc.state.dateTypeOption.includeTime) {
+    if (widget.bloc.state.dateTypeOptionPB.includeTime) {
       _focusNode.addListener(() {
         if (mounted) {
           _CalDateTimeSetting.hide(context);
@@ -265,7 +265,7 @@ class _TimeTextFieldState extends State<_TimeTextField> {
       },
       listenWhen: (p, c) => p.time != c.time,
       builder: (context, state) {
-        if (state.dateTypeOption.includeTime) {
+        if (state.dateTypeOptionPB.includeTime) {
           return Padding(
             padding: kMargin,
             child: RoundedInputField(
@@ -307,23 +307,24 @@ class _DateTypeOptionButton extends StatelessWidget {
     final title = LocaleKeys.grid_field_dateFormat.tr() +
         " &" +
         LocaleKeys.grid_field_timeFormat.tr();
-    return BlocSelector<DateCalBloc, DateCalState, DateTypeOption>(
-      selector: (state) => state.dateTypeOption,
-      builder: (context, dateTypeOption) {
+    return BlocSelector<DateCalBloc, DateCalState, DateTypeOptionPB>(
+      selector: (state) => state.dateTypeOptionPB,
+      builder: (context, dateTypeOptionPB) {
         return FlowyButton(
           text: FlowyText.medium(title, fontSize: 12),
           hoverColor: theme.hover,
           margin: kMargin,
-          onTap: () => _showTimeSetting(dateTypeOption, context),
+          onTap: () => _showTimeSetting(dateTypeOptionPB, context),
           rightIcon: svgWidget("grid/more", color: theme.iconColor),
         );
       },
     );
   }
 
-  void _showTimeSetting(DateTypeOption dateTypeOption, BuildContext context) {
+  void _showTimeSetting(
+      DateTypeOptionPB dateTypeOptionPB, BuildContext context) {
     final setting = _CalDateTimeSetting(
-      dateTypeOption: dateTypeOption,
+      dateTypeOptionPB: dateTypeOptionPB,
       onEvent: (event) => context.read<DateCalBloc>().add(event),
     );
     setting.show(context);
@@ -331,10 +332,10 @@ class _DateTypeOptionButton extends StatelessWidget {
 }
 
 class _CalDateTimeSetting extends StatefulWidget {
-  final DateTypeOption dateTypeOption;
+  final DateTypeOptionPB dateTypeOptionPB;
   final Function(DateCalEvent) onEvent;
   const _CalDateTimeSetting(
-      {required this.dateTypeOption, required this.onEvent, Key? key})
+      {required this.dateTypeOptionPB, required this.onEvent, Key? key})
       : super(key: key);
 
   @override
@@ -371,17 +372,17 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
     List<Widget> children = [
       DateFormatButton(onTap: () {
         final list = DateFormatList(
-          selectedFormat: widget.dateTypeOption.dateFormat,
+          selectedFormat: widget.dateTypeOptionPB.dateFormat,
           onSelected: (format) =>
               widget.onEvent(DateCalEvent.setDateFormat(format)),
         );
         _showOverlay(context, list);
       }),
       TimeFormatButton(
-        timeFormat: widget.dateTypeOption.timeFormat,
+        timeFormat: widget.dateTypeOptionPB.timeFormat,
         onTap: () {
           final list = TimeFormatList(
-            selectedFormat: widget.dateTypeOption.timeFormat,
+            selectedFormat: widget.dateTypeOptionPB.timeFormat,
             onSelected: (format) =>
                 widget.onEvent(DateCalEvent.setTimeFormat(format)),
           );

+ 14 - 13
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart

@@ -59,7 +59,7 @@ class _SingleSelectCellState extends State<GridSingleSelectCell> {
       value: _cellBloc,
       child: BlocBuilder<SelectOptionCellBloc, SelectOptionCellState>(
         builder: (context, state) {
-          return _SelectOptionCell(
+          return SelectOptionWrap(
               selectOptions: state.selectedOptions,
               cellStyle: widget.cellStyle,
               onFocus: (value) => widget.onCellEditing.value = value,
@@ -115,11 +115,12 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
       value: _cellBloc,
       child: BlocBuilder<SelectOptionCellBloc, SelectOptionCellState>(
         builder: (context, state) {
-          return _SelectOptionCell(
-              selectOptions: state.selectedOptions,
-              cellStyle: widget.cellStyle,
-              onFocus: (value) => widget.onCellEditing.value = value,
-              cellControllerBuilder: widget.cellControllerBuilder);
+          return SelectOptionWrap(
+            selectOptions: state.selectedOptions,
+            cellStyle: widget.cellStyle,
+            onFocus: (value) => widget.onCellEditing.value = value,
+            cellControllerBuilder: widget.cellControllerBuilder,
+          );
         },
       ),
     );
@@ -132,16 +133,16 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
   }
 }
 
-class _SelectOptionCell extends StatelessWidget {
+class SelectOptionWrap extends StatelessWidget {
   final List<SelectOptionPB> selectOptions;
-  final void Function(bool) onFocus;
+  final void Function(bool)? onFocus;
   final SelectOptionCellStyle? cellStyle;
   final GridCellControllerBuilder cellControllerBuilder;
-  const _SelectOptionCell({
+  const SelectOptionWrap({
     required this.selectOptions,
-    required this.onFocus,
-    required this.cellStyle,
     required this.cellControllerBuilder,
+    this.onFocus,
+    this.cellStyle,
     Key? key,
   }) : super(key: key);
 
@@ -177,11 +178,11 @@ class _SelectOptionCell extends StatelessWidget {
         child,
         InkWell(
           onTap: () {
-            onFocus(true);
+            onFocus?.call(true);
             final cellContext =
                 cellControllerBuilder.build() as GridSelectOptionCellController;
             SelectOptionCellEditor.show(
-                context, cellContext, () => onFocus(false));
+                context, cellContext, () => onFocus?.call(false));
           },
         ),
       ],

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/cell_editor.dart

@@ -64,7 +64,7 @@ class _URLCellEditorState extends State<URLCellEditor> {
 
   @override
   void initState() {
-    _cellBloc = URLCellEditorBloc(cellContext: widget.cellController);
+    _cellBloc = URLCellEditorBloc(cellController: widget.cellController);
     _cellBloc.add(const URLCellEditorEvent.initial());
     _controller = TextEditingController(text: _cellBloc.state.content);
 

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart

@@ -92,7 +92,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
   void initState() {
     final cellContext =
         widget.cellControllerBuilder.build() as GridURLCellController;
-    _cellBloc = URLCellBloc(cellContext: cellContext);
+    _cellBloc = URLCellBloc(cellController: cellContext);
     _cellBloc.add(const URLCellEvent.initial());
     super.initState();
   }

+ 5 - 5
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart

@@ -64,7 +64,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
   switch (dataController.field.fieldType) {
     case FieldType.Checkbox:
       return CheckboxTypeOptionWidgetBuilder(
-        makeTypeOptionContextWithDataController<CheckboxTypeOption>(
+        makeTypeOptionContextWithDataController<CheckboxTypeOptionPB>(
           gridId: gridId,
           fieldType: fieldType,
           dataController: dataController,
@@ -72,7 +72,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
       );
     case FieldType.DateTime:
       return DateTypeOptionWidgetBuilder(
-        makeTypeOptionContextWithDataController<DateTypeOption>(
+        makeTypeOptionContextWithDataController<DateTypeOptionPB>(
           gridId: gridId,
           fieldType: fieldType,
           dataController: dataController,
@@ -99,7 +99,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
       );
     case FieldType.Number:
       return NumberTypeOptionWidgetBuilder(
-        makeTypeOptionContextWithDataController<NumberTypeOption>(
+        makeTypeOptionContextWithDataController<NumberTypeOptionPB>(
           gridId: gridId,
           fieldType: fieldType,
           dataController: dataController,
@@ -108,7 +108,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
       );
     case FieldType.RichText:
       return RichTextTypeOptionWidgetBuilder(
-        makeTypeOptionContextWithDataController<RichTextTypeOption>(
+        makeTypeOptionContextWithDataController<RichTextTypeOptionPB>(
           gridId: gridId,
           fieldType: fieldType,
           dataController: dataController,
@@ -117,7 +117,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
 
     case FieldType.URL:
       return URLTypeOptionWidgetBuilder(
-        makeTypeOptionContextWithDataController<URLTypeOption>(
+        makeTypeOptionContextWithDataController<URLTypeOptionPB>(
           gridId: gridId,
           fieldType: fieldType,
           dataController: dataController,

+ 5 - 5
frontend/app_flowy/lib/startup/deps_resolver.dart

@@ -170,33 +170,33 @@ void _resolveGridDeps(GetIt getIt) {
 
   getIt.registerFactoryParam<TextCellBloc, GridCellController, void>(
     (context, _) => TextCellBloc(
-      cellContext: context,
+      cellController: context,
     ),
   );
 
   getIt.registerFactoryParam<SelectOptionCellBloc,
       GridSelectOptionCellController, void>(
     (context, _) => SelectOptionCellBloc(
-      cellContext: context,
+      cellController: context,
     ),
   );
 
   getIt.registerFactoryParam<NumberCellBloc, GridCellController, void>(
     (context, _) => NumberCellBloc(
-      cellContext: context,
+      cellController: context,
     ),
   );
 
   getIt.registerFactoryParam<DateCellBloc, GridDateCellController, void>(
     (context, _) => DateCellBloc(
-      cellContext: context,
+      cellController: context,
     ),
   );
 
   getIt.registerFactoryParam<CheckboxCellBloc, GridCellController, void>(
     (cellData, _) => CheckboxCellBloc(
       service: CellService(),
-      cellContext: cellData,
+      cellController: cellData,
     ),
   );
 

+ 3 - 3
frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart

@@ -87,7 +87,7 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
     );
   }
 
-  Widget _buildCard(ColumnItem item) {
+  Widget _buildCard(AFColumnItem item) {
     if (item is TextItem) {
       return Align(
         alignment: Alignment.centerLeft,
@@ -126,7 +126,7 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
   }
 }
 
-class TextItem extends ColumnItem {
+class TextItem extends AFColumnItem {
   final String s;
 
   TextItem(this.s);
@@ -135,7 +135,7 @@ class TextItem extends ColumnItem {
   String get id => s;
 }
 
-class RichTextItem extends ColumnItem {
+class RichTextItem extends AFColumnItem {
   final String title;
   final String subtitle;
 

+ 1 - 1
frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart

@@ -50,7 +50,7 @@ class _RowWidget extends StatelessWidget {
   }
 }
 
-class TextItem extends ColumnItem {
+class TextItem extends AFColumnItem {
   final String s;
 
   TextItem(this.s);

+ 3 - 3
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart

@@ -24,7 +24,7 @@ typedef OnColumnInserted = void Function(String listId, int insertedIndex);
 
 typedef AFBoardColumnCardBuilder = Widget Function(
   BuildContext context,
-  ColumnItem item,
+  AFColumnItem item,
 );
 
 typedef AFBoardColumnHeaderBuilder = Widget Function(
@@ -46,7 +46,7 @@ abstract class AFBoardColumnDataDataSource extends ReoderFlextDataSource {
   String get identifier => columnData.id;
 
   @override
-  UnmodifiableListView<ColumnItem> get items => columnData.items;
+  UnmodifiableListView<AFColumnItem> get items => columnData.items;
 
   void debugPrint() {
     String msg = '[$AFBoardColumnDataDataSource] $columnData data: ';
@@ -194,7 +194,7 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
     );
   }
 
-  Widget _buildWidget(BuildContext context, ColumnItem item) {
+  Widget _buildWidget(BuildContext context, AFColumnItem item) {
     if (item is PhantomColumnItem) {
       return PassthroughPhantomWidget(
         key: UniqueKey(),

+ 10 - 10
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart

@@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
 import '../../utils/log.dart';
 import '../reorder_flex/reorder_flex.dart';
 
-abstract class ColumnItem extends ReoderFlexItem {
+abstract class AFColumnItem extends ReoderFlexItem {
   bool get isPhantom => false;
 
   @override
@@ -31,7 +31,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
   List<Object?> get props => columnData.props;
 
   /// Returns the readonly List<ColumnItem>
-  UnmodifiableListView<ColumnItem> get items =>
+  UnmodifiableListView<AFColumnItem> get items =>
       UnmodifiableListView(columnData.items);
 
   /// Remove the item at [index].
@@ -39,7 +39,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
   /// * [notify] the default value of [notify] is true, it will notify the
   /// listener. Set to [false] if you do not want to notify the listeners.
   ///
-  ColumnItem removeAt(int index, {bool notify = true}) {
+  AFColumnItem removeAt(int index, {bool notify = true}) {
     assert(index >= 0);
 
     Log.debug('[$BoardColumnDataController] $columnData remove item at $index');
@@ -50,7 +50,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
     return item;
   }
 
-  int removeWhere(bool Function(ColumnItem) condition) {
+  int removeWhere(bool Function(AFColumnItem) condition) {
     return items.indexWhere(condition);
   }
 
@@ -75,7 +75,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
   /// is true.
   ///
   /// The default value of [notify] is true.
-  bool insert(int index, ColumnItem item, {bool notify = true}) {
+  bool insert(int index, AFColumnItem item, {bool notify = true}) {
     assert(index >= 0);
     Log.debug(
         '[$BoardColumnDataController] $columnData insert $item at $index');
@@ -90,14 +90,14 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
     return true;
   }
 
-  bool add(ColumnItem item, {bool notify = true}) {
+  bool add(AFColumnItem item, {bool notify = true}) {
     columnData._items.add(item);
     if (notify) notifyListeners();
     return true;
   }
 
   /// Replace the item at index with the [newItem].
-  void replace(int index, ColumnItem newItem) {
+  void replace(int index, AFColumnItem newItem) {
     if (columnData._items.isEmpty) {
       columnData._items.add(newItem);
       Log.debug('[$BoardColumnDataController] $columnData add $newItem');
@@ -117,18 +117,18 @@ class AFBoardColumnData<CustomData> extends ReoderFlexItem with EquatableMixin {
   @override
   final String id;
   final String desc;
-  final List<ColumnItem> _items;
+  final List<AFColumnItem> _items;
   final CustomData? customData;
 
   AFBoardColumnData({
     this.customData,
     required this.id,
     this.desc = "",
-    List<ColumnItem> items = const [],
+    List<AFColumnItem> items = const [],
   }) : _items = items;
 
   /// Returns the readonly List<ColumnItem>
-  UnmodifiableListView<ColumnItem> get items => UnmodifiableListView(_items);
+  UnmodifiableListView<AFColumnItem> get items => UnmodifiableListView(_items);
 
   @override
   List<Object?> get props => [id, ..._items];

+ 2 - 2
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart

@@ -110,11 +110,11 @@ class AFBoardDataController extends ChangeNotifier
     }
   }
 
-  void addColumnItem(String columnId, ColumnItem item) {
+  void addColumnItem(String columnId, AFColumnItem item) {
     getColumnController(columnId)?.add(item);
   }
 
-  void insertColumnItem(String columnId, int index, ColumnItem item) {
+  void insertColumnItem(String columnId, int index, AFColumnItem item) {
     getColumnController(columnId)?.insert(index, item);
   }
 

+ 2 - 2
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart

@@ -253,7 +253,7 @@ class PhantomRecord {
   }
 }
 
-class PhantomColumnItem extends ColumnItem {
+class PhantomColumnItem extends AFColumnItem {
   final PassthroughPhantomContext phantomContext;
 
   PhantomColumnItem(PassthroughPhantomContext insertedPhantom)
@@ -290,7 +290,7 @@ class PassthroughPhantomContext extends FakeDragTargetEventTrigger
 
   Widget? get draggingWidget => dragTargetData.draggingWidget;
 
-  ColumnItem get itemData => dragTargetData.reorderFlexItem as ColumnItem;
+  AFColumnItem get itemData => dragTargetData.reorderFlexItem as AFColumnItem;
 
   @override
   VoidCallback? onInserted;

+ 6 - 2
frontend/rust-lib/flowy-test/src/event_builder.rs

@@ -86,9 +86,13 @@ where
         match response.parse::<R, E>() {
             Ok(Ok(data)) => data,
             Ok(Err(e)) => {
-                panic!("parse failed: {:?}", e)
+                panic!("Parser {:?} failed: {:?}", std::any::type_name::<R>(), e)
             }
-            Err(e) => panic!("Internal error: {:?}", e),
+            Err(e) => panic!(
+                "Internal error: {:?}, parser {:?} failed",
+                e,
+                std::any::type_name::<R>(),
+            ),
         }
     }