浏览代码

fix: add event after bloc close

appflowy 3 年之前
父节点
当前提交
b65b4796d2

+ 1 - 1
frontend/app_flowy/lib/startup/tasks/app_widget.dart

@@ -112,7 +112,7 @@ class ApplicationBlocObserver extends BlocObserver {
   // ignore: unnecessary_overrides
   void onTransition(Bloc bloc, Transition transition) {
     // Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}");
-    Log.debug("${transition.nextState}");
+    // Log.debug("${transition.nextState}");
     super.onTransition(bloc, transition);
   }
 

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

@@ -15,8 +15,6 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
     required this.service,
     required FutureCellData cellData,
   }) : super(CheckboxCellState.initial()) {
-    cellData.then((a) {});
-
     on<CheckboxCellEvent>(
       (event, emit) async {
         await event.map(

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

@@ -12,13 +12,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
   TextCellBloc({
     required this.service,
     required FutureCellData cellData,
-  }) : super(TextCellState.initial()) {
-    cellData.then((cellData) {
-      if (cellData != null) {
-        add(TextCellEvent.didReceiveCellData(cellData));
-      }
-    });
-
+  }) : super(TextCellState.initial(cellData)) {
     on<TextCellEvent>(
       (event, emit) async {
         await event.map(
@@ -69,8 +63,11 @@ class TextCellEvent with _$TextCellEvent {
 class TextCellState with _$TextCellState {
   const factory TextCellState({
     required String content,
-    GridCellData? cellData,
+    required FutureCellData cellData,
   }) = _TextCellState;
 
-  factory TextCellState.initial() => const TextCellState(content: "");
+  factory TextCellState.initial(FutureCellData cellData) => TextCellState(
+        content: cellData?.cell?.content ?? "",
+        cellData: cellData,
+      );
 }

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

@@ -50,12 +50,11 @@ class RowBloc extends Bloc<RowEvent, RowState> {
             emit(state.copyWith(fields: value.fields));
             add(const RowEvent.didUpdateCell());
           },
-          didUpdateCell: (_DidUpdateCell value) {
-            final Future<CellDataMap> cellDataMap = state.row.then(
-              (someRow) => someRow.fold(
-                () => HashMap.identity(),
-                (row) => _makeCellDatas(row),
-              ),
+          didUpdateCell: (_DidUpdateCell value) async {
+            final optionRow = await state.row;
+            final CellDataMap cellDataMap = optionRow.fold(
+              () => HashMap.identity(),
+              (row) => _makeCellDatas(row),
             );
             emit(state.copyWith(cellDataMap: cellDataMap));
           },
@@ -147,7 +146,7 @@ class RowState with _$RowState {
     required double rowHeight,
     required List<Field> fields,
     required Future<Option<Row>> row,
-    required Future<CellDataMap> cellDataMap,
+    required CellDataMap? cellDataMap,
   }) = _RowState;
 
   factory RowState.initial(GridRowData data) => RowState(
@@ -156,6 +155,6 @@ class RowState with _$RowState {
         rowHeight: data.height,
         fields: data.fields,
         row: Future(() => none()),
-        cellDataMap: Future(() => CellDataMap.identity()),
+        cellDataMap: null,
       );
 }

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

@@ -29,7 +29,7 @@ class RowService {
   }
 }
 
-typedef FutureCellData = Future<GridCellData?>;
+typedef FutureCellData = GridCellData?;
 
 class GridCellData extends Equatable {
   final String gridId;

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

@@ -1,4 +1,5 @@
 import 'package:app_flowy/workspace/application/grid/row/row_service.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/widgets.dart';
 import 'checkbox_cell.dart';
@@ -7,20 +8,24 @@ import 'number_cell.dart';
 import 'selection_cell.dart';
 import 'text_cell.dart';
 
-Widget buildGridCell(FieldType fieldType, FutureCellData cellData) {
-  switch (fieldType) {
+Widget buildGridCell(String rowId, Field field, FutureCellData cellData) {
+  if (cellData == null) {
+    return const SizedBox();
+  }
+  final key = ValueKey(field.id + rowId);
+  switch (field.fieldType) {
     case FieldType.Checkbox:
-      return CheckboxCell(cellData: cellData, key: ObjectKey(cellData));
+      return CheckboxCell(cellData: cellData, key: key);
     case FieldType.DateTime:
-      return DateCell(cellData: cellData, key: ObjectKey(cellData));
+      return DateCell(cellData: cellData, key: key);
     case FieldType.MultiSelect:
-      return MultiSelectCell(cellData: cellData, key: ObjectKey(cellData));
+      return MultiSelectCell(cellData: cellData, key: key);
     case FieldType.Number:
-      return NumberCell(cellData: cellData, key: ObjectKey(cellData));
+      return NumberCell(cellData: cellData, key: key);
     case FieldType.RichText:
-      return GridTextCell(cellData: cellData, key: ObjectKey(cellData));
+      return GridTextCell(cellData: cellData, key: key);
     case FieldType.SingleSelect:
-      return SingleSelectCell(cellData: cellData, key: ObjectKey(cellData));
+      return SingleSelectCell(cellData: cellData, key: key);
     default:
       throw UnimplementedError;
   }

+ 55 - 30
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart

@@ -4,38 +4,61 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
-import 'package:flowy_sdk/log.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'cell_builder.dart';
 import 'cell_container.dart';
 
-class GridRowWidget extends StatelessWidget {
+class GridRowWidget extends StatefulWidget {
   final GridRowData data;
   const GridRowWidget({required this.data, Key? key}) : super(key: key);
 
+  @override
+  State<GridRowWidget> createState() => _GridRowWidgetState();
+}
+
+class _GridRowWidgetState extends State<GridRowWidget> {
+  late RowBloc _rowBloc;
+
+  @override
+  void initState() {
+    _rowBloc = getIt<RowBloc>(param1: widget.data)..add(const RowEvent.initial());
+    super.initState();
+  }
+
   @override
   Widget build(BuildContext context) {
-    return BlocProvider(
-      create: (context) => getIt<RowBloc>(param1: data)..add(const RowEvent.initial()),
-      child: BlocBuilder<RowBloc, RowState>(
-        buildWhen: (p, c) => p.rowHeight != c.rowHeight,
-        builder: (context, state) {
-          return SizedBox(
-            height: state.rowHeight,
-            child: Row(
-              crossAxisAlignment: CrossAxisAlignment.stretch,
-              children: const [
-                _RowLeading(),
-                _RowCells(),
-                _RowTrailing(),
-              ],
-            ),
-          );
-        },
+    return BlocProvider.value(
+      value: _rowBloc,
+      child: MouseRegion(
+        cursor: SystemMouseCursors.click,
+        onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()),
+        onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()),
+        child: BlocBuilder<RowBloc, RowState>(
+          buildWhen: (p, c) => p.rowHeight != c.rowHeight,
+          builder: (context, state) {
+            return SizedBox(
+              height: _rowBloc.state.rowHeight,
+              child: Row(
+                crossAxisAlignment: CrossAxisAlignment.stretch,
+                children: const [
+                  _RowLeading(),
+                  _RowCells(),
+                  _RowTrailing(),
+                ],
+              ),
+            );
+          },
+        ),
       ),
     );
   }
+
+  @override
+  Future<void> dispose() async {
+    _rowBloc.close();
+    super.dispose();
+  }
 }
 
 class _RowLeading extends StatelessWidget {
@@ -92,18 +115,20 @@ class _RowCells extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return BlocBuilder<RowBloc, RowState>(
+      buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap,
       builder: (context, state) {
-        return Row(children: [
-          ...state.fields.map(
-            (field) {
-              final cellData = state.cellDataMap.then((fut) => fut[field.id]);
-              return CellContainer(
-                width: field.width.toDouble(),
-                child: buildGridCell(field.fieldType, cellData),
-              );
-            },
-          ),
-        ]);
+        final children = state.fields
+            .map((field) => CellContainer(
+                  width: field.width.toDouble(),
+                  child: buildGridCell(
+                    state.rowId,
+                    field,
+                    state.cellDataMap?[field.id],
+                  ),
+                ))
+            .toList();
+
+        return Row(children: children);
       },
     );
   }

+ 8 - 7
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart

@@ -22,12 +22,12 @@ class _GridTextCellState extends State<GridTextCell> {
   late TextEditingController _controller;
   Timer? _delayOperation;
   final _focusNode = FocusNode();
-  TextCellBloc? _cellBloc;
+  late TextCellBloc _cellBloc;
 
   @override
   void initState() {
     _cellBloc = getIt<TextCellBloc>(param1: widget.cellData);
-    _controller = TextEditingController(text: _cellBloc!.state.content);
+    _controller = TextEditingController(text: _cellBloc.state.content);
     _focusNode.addListener(save);
     super.initState();
   }
@@ -35,7 +35,7 @@ class _GridTextCellState extends State<GridTextCell> {
   @override
   Widget build(BuildContext context) {
     return BlocProvider.value(
-      value: _cellBloc!,
+      value: _cellBloc,
       child: BlocConsumer<TextCellBloc, TextCellState>(
         listener: (context, state) {
           if (_controller.text != state.content) {
@@ -71,8 +71,7 @@ class _GridTextCellState extends State<GridTextCell> {
 
   @override
   Future<void> dispose() async {
-    _cellBloc?.close();
-    _cellBloc = null;
+    _cellBloc.close();
     _focusNode.removeListener(save);
     _focusNode.dispose();
     super.dispose();
@@ -80,8 +79,10 @@ class _GridTextCellState extends State<GridTextCell> {
 
   Future<void> save() async {
     _delayOperation?.cancel();
-    _delayOperation = Timer(const Duration(seconds: 2), () {
-      _cellBloc?.add(TextCellEvent.updateText(_controller.text));
+    _delayOperation = Timer(const Duration(milliseconds: 300), () {
+      if (_cellBloc.isClosed == false) {
+        _cellBloc.add(TextCellEvent.updateText(_controller.text));
+      }
     });
     // and later, before the timer goes off...
   }