From d0b4abb0c839c46ed273ef75ef509736ff2e48ad Mon Sep 17 00:00:00 2001
From: appflowy <annie@appflowy.io>
Date: Wed, 27 Apr 2022 13:31:54 +0800
Subject: [PATCH] refactor: cell context builder

---
 .../application/grid/cell/cell_service.dart   | 43 ++++++++++++++++-
 .../grid/src/widgets/cell/cell_builder.dart   | 48 ++++---------------
 .../grid/src/widgets/cell/checkbox_cell.dart  |  8 ++--
 .../grid/src/widgets/cell/date_cell.dart      |  7 +--
 .../grid/src/widgets/cell/number_cell.dart    |  7 +--
 .../cell/selection_cell/selection_cell.dart   | 30 ++++++------
 .../grid/src/widgets/cell/text_cell.dart      |  7 +--
 7 files changed, 84 insertions(+), 66 deletions(-)

diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart
index 1aa090d443..251ca0ef29 100644
--- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart
+++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart
@@ -1,7 +1,9 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
 import 'package:dartz/dartz.dart';
+import 'package:equatable/equatable.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@@ -10,13 +12,52 @@ import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
+
 import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
-import 'package:equatable/equatable.dart';
+
 part 'cell_service.freezed.dart';
 
 typedef GridDefaultCellContext = GridCellContext<Cell>;
 typedef GridSelectOptionCellContext = GridCellContext<SelectOptionContext>;
 
+class GridCellContextBuilder {
+  final GridCellCache _cellCache;
+  final GridCell _gridCell;
+  GridCellContextBuilder({
+    required GridCellCache cellCache,
+    required GridCell gridCell,
+  })  : _cellCache = cellCache,
+        _gridCell = gridCell;
+
+  GridCellContext build() {
+    switch (_gridCell.field.fieldType) {
+      case FieldType.Checkbox:
+      case FieldType.DateTime:
+      case FieldType.Number:
+        return GridDefaultCellContext(
+          gridCell: _gridCell,
+          cellCache: _cellCache,
+          cellDataLoader: DefaultCellDataLoader(gridCell: _gridCell, reloadOnCellChanged: true),
+        );
+      case FieldType.RichText:
+        return GridDefaultCellContext(
+          gridCell: _gridCell,
+          cellCache: _cellCache,
+          cellDataLoader: DefaultCellDataLoader(gridCell: _gridCell),
+        );
+      case FieldType.MultiSelect:
+      case FieldType.SingleSelect:
+        return GridSelectOptionCellContext(
+          gridCell: _gridCell,
+          cellCache: _cellCache,
+          cellDataLoader: SelectOptionCellDataLoader(gridCell: _gridCell),
+        );
+      default:
+        throw UnimplementedError;
+    }
+  }
+}
+
 // ignore: must_be_immutable
 class GridCellContext<T> extends Equatable {
   final GridCell gridCell;
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart
index df72ba3ae1..8ebc70352b 100755
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart
@@ -1,5 +1,4 @@
 import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
-import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType;
 import 'package:flutter/widgets.dart';
@@ -12,49 +11,22 @@ import 'text_cell.dart';
 GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCache cellCache, {GridCellStyle? style}) {
   final key = ValueKey(gridCell.rowId + gridCell.field.id);
 
-  final cellContext = makeCellContext(gridCell, cellCache);
+  final cellContextBuilder = GridCellContextBuilder(gridCell: gridCell, cellCache: cellCache);
 
   switch (gridCell.field.fieldType) {
     case FieldType.Checkbox:
-      return CheckboxCell(cellContext: cellContext, key: key);
+      return CheckboxCell(cellContextBuilder: cellContextBuilder, key: key);
     case FieldType.DateTime:
-      return DateCell(cellContext: cellContext, key: key);
-    case FieldType.MultiSelect:
-      return MultiSelectCell(cellContext: cellContext as GridSelectOptionCellContext, style: style, key: key);
-    case FieldType.Number:
-      return NumberCell(cellContext: cellContext, key: key);
-    case FieldType.RichText:
-      return GridTextCell(cellContext: cellContext, style: style, key: key);
+      return DateCell(cellContextBuilder: cellContextBuilder, key: key);
     case FieldType.SingleSelect:
-      return SingleSelectCell(cellContext: cellContext as GridSelectOptionCellContext, style: style, key: key);
-    default:
-      throw UnimplementedError;
-  }
-}
+      return SingleSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
+    case FieldType.MultiSelect:
+      return MultiSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
+    case FieldType.Number:
+      return NumberCell(cellContextBuilder: cellContextBuilder, key: key);
+    case FieldType.RichText:
+      return GridTextCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
 
-GridCellContext makeCellContext(GridCell gridCell, GridCellCache cellCache) {
-  switch (gridCell.field.fieldType) {
-    case FieldType.Checkbox:
-    case FieldType.DateTime:
-    case FieldType.Number:
-      return GridDefaultCellContext(
-        gridCell: gridCell,
-        cellCache: cellCache,
-        cellDataLoader: DefaultCellDataLoader(gridCell: gridCell, reloadOnCellChanged: true),
-      );
-    case FieldType.RichText:
-      return GridDefaultCellContext(
-        gridCell: gridCell,
-        cellCache: cellCache,
-        cellDataLoader: DefaultCellDataLoader(gridCell: gridCell),
-      );
-    case FieldType.MultiSelect:
-    case FieldType.SingleSelect:
-      return GridSelectOptionCellContext(
-        gridCell: gridCell,
-        cellCache: cellCache,
-        cellDataLoader: SelectOptionCellDataLoader(gridCell: gridCell),
-      );
     default:
       throw UnimplementedError;
   }
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart
index 991b56a832..80d5c70f8d 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart
@@ -7,10 +7,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'cell_builder.dart';
 
 class CheckboxCell extends GridCellWidget {
-  final GridCellContext cellContext;
-
+  final GridCellContextBuilder cellContextBuilder;
   CheckboxCell({
-    required this.cellContext,
+    required this.cellContextBuilder,
     Key? key,
   }) : super(key: key);
 
@@ -23,7 +22,8 @@ class _CheckboxCellState extends State<CheckboxCell> {
 
   @override
   void initState() {
-    _cellBloc = getIt<CheckboxCellBloc>(param1: widget.cellContext)..add(const CheckboxCellEvent.initial());
+    final cellContext = widget.cellContextBuilder.build();
+    _cellBloc = getIt<CheckboxCellBloc>(param1: cellContext)..add(const CheckboxCellEvent.initial());
     super.initState();
   }
 
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart
index a3cc807266..a68bfcb4bc 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart
@@ -14,10 +14,10 @@ abstract class GridCellDelegate {
 }
 
 class DateCell extends GridCellWidget {
-  final GridCellContext cellContext;
+  final GridCellContextBuilder cellContextBuilder;
 
   DateCell({
-    required this.cellContext,
+    required this.cellContextBuilder,
     Key? key,
   }) : super(key: key);
 
@@ -30,7 +30,8 @@ class _DateCellState extends State<DateCell> {
 
   @override
   void initState() {
-    _cellBloc = getIt<DateCellBloc>(param1: widget.cellContext)..add(const DateCellEvent.initial());
+    final cellContext = widget.cellContextBuilder.build();
+    _cellBloc = getIt<DateCellBloc>(param1: cellContext)..add(const DateCellEvent.initial());
     super.initState();
   }
 
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart
index 168d2258d3..6d66ab7c3e 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart
@@ -8,10 +8,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'cell_builder.dart';
 
 class NumberCell extends GridCellWidget {
-  final GridCellContext cellContext;
+  final GridCellContextBuilder cellContextBuilder;
 
   NumberCell({
-    required this.cellContext,
+    required this.cellContextBuilder,
     Key? key,
   }) : super(key: key);
 
@@ -27,7 +27,8 @@ class _NumberCellState extends State<NumberCell> {
 
   @override
   void initState() {
-    _cellBloc = getIt<NumberCellBloc>(param1: widget.cellContext)..add(const NumberCellEvent.initial());
+    final cellContext = widget.cellContextBuilder.build();
+    _cellBloc = getIt<NumberCellBloc>(param1: cellContext)..add(const NumberCellEvent.initial());
     _controller = TextEditingController(text: _cellBloc.state.content);
     _focusNode = FocusNode();
     _focusNode.addListener(() {
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart
index 939594f19c..fe10341dcf 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart
@@ -20,11 +20,11 @@ class SelectOptionCellStyle extends GridCellStyle {
 }
 
 class SingleSelectCell extends GridCellWidget {
-  final GridSelectOptionCellContext cellContext;
+  final GridCellContextBuilder cellContextBuilder;
   late final SelectOptionCellStyle? cellStyle;
 
   SingleSelectCell({
-    required this.cellContext,
+    required this.cellContextBuilder,
     GridCellStyle? style,
     Key? key,
   }) : super(key: key) {
@@ -45,7 +45,8 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
   @override
   void initState() {
     // Log.trace("init widget $hashCode");
-    _cellBloc = getIt<SelectionCellBloc>(param1: widget.cellContext)..add(const SelectionCellEvent.initial());
+    final cellContext = _buildCellContext();
+    _cellBloc = getIt<SelectionCellBloc>(param1: cellContext)..add(const SelectionCellEvent.initial());
     super.initState();
   }
 
@@ -69,7 +70,7 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
                 widget.onFocus.value = true;
                 SelectOptionCellEditor.show(
                   context,
-                  widget.cellContext.clone(),
+                  _buildCellContext(),
                   () => widget.onFocus.value = false,
                 );
               },
@@ -81,12 +82,8 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
     );
   }
 
-  @override
-  void didUpdateWidget(covariant SingleSelectCell oldWidget) {
-    if (oldWidget.cellContext != widget.cellContext) {
-      // Log.trace("did update widget $hashCode");
-    }
-    super.didUpdateWidget(oldWidget);
+  GridSelectOptionCellContext _buildCellContext() {
+    return widget.cellContextBuilder.build() as GridSelectOptionCellContext;
   }
 
   @override
@@ -99,11 +96,11 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
 
 //----------------------------------------------------------------
 class MultiSelectCell extends GridCellWidget {
-  final GridSelectOptionCellContext cellContext;
+  final GridCellContextBuilder cellContextBuilder;
   late final SelectOptionCellStyle? cellStyle;
 
   MultiSelectCell({
-    required this.cellContext,
+    required this.cellContextBuilder,
     GridCellStyle? style,
     Key? key,
   }) : super(key: key) {
@@ -123,7 +120,8 @@ class _MultiSelectCellState extends State<MultiSelectCell> {
 
   @override
   void initState() {
-    _cellBloc = getIt<SelectionCellBloc>(param1: widget.cellContext)..add(const SelectionCellEvent.initial());
+    final cellContext = _buildCellContext();
+    _cellBloc = getIt<SelectionCellBloc>(param1: cellContext)..add(const SelectionCellEvent.initial());
     super.initState();
   }
 
@@ -145,7 +143,7 @@ class _MultiSelectCellState extends State<MultiSelectCell> {
                 widget.onFocus.value = true;
                 SelectOptionCellEditor.show(
                   context,
-                  widget.cellContext,
+                  _buildCellContext(),
                   () => widget.onFocus.value = false,
                 );
               },
@@ -162,4 +160,8 @@ class _MultiSelectCellState extends State<MultiSelectCell> {
     _cellBloc.close();
     super.dispose();
   }
+
+  GridSelectOptionCellContext _buildCellContext() {
+    return widget.cellContextBuilder.build() as GridSelectOptionCellContext;
+  }
 }
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart
index 6d77f5f2cf..a9d3d13532 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart
@@ -14,10 +14,10 @@ class GridTextCellStyle extends GridCellStyle {
 }
 
 class GridTextCell extends GridCellWidget {
-  final GridCellContext cellContext;
+  final GridCellContextBuilder cellContextBuilder;
   late final GridTextCellStyle? cellStyle;
   GridTextCell({
-    required this.cellContext,
+    required this.cellContextBuilder,
     GridCellStyle? style,
     Key? key,
   }) : super(key: key) {
@@ -41,7 +41,8 @@ class _GridTextCellState extends State<GridTextCell> {
 
   @override
   void initState() {
-    _cellBloc = getIt<TextCellBloc>(param1: widget.cellContext);
+    final cellContext = widget.cellContextBuilder.build();
+    _cellBloc = getIt<TextCellBloc>(param1: cellContext);
     _cellBloc.add(const TextCellEvent.initial());
     _controller = TextEditingController(text: _cellBloc.state.content);
     _focusNode = FocusNode();