Forráskód Böngészése

fix: grid header cell refresh after field was changed

appflowy 3 éve
szülő
commit
fc4ed6c057

+ 66 - 0
frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart

@@ -0,0 +1,66 @@
+import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
+import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'dart:async';
+
+part 'field_cell_bloc.freezed.dart';
+
+class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
+  final FieldListener _fieldListener;
+
+  FieldCellBloc({
+    required GridFieldCellContext cellContext,
+  })  : _fieldListener = FieldListener(fieldId: cellContext.field.id),
+        super(FieldCellState.initial(cellContext)) {
+    on<FieldCellEvent>(
+      (event, emit) async {
+        await event.map(
+          initial: (_InitialCell value) async {
+            _startListening();
+          },
+          didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
+            emit(state.copyWith(field: value.field));
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    await _fieldListener.stop();
+    return super.close();
+  }
+
+  void _startListening() {
+    _fieldListener.updateFieldNotifier.addPublishListener((result) {
+      result.fold(
+        (field) => add(FieldCellEvent.didReceiveFieldUpdate(field)),
+        (err) => Log.error(err),
+      );
+    });
+    _fieldListener.start();
+  }
+}
+
+@freezed
+class FieldCellEvent with _$FieldCellEvent {
+  const factory FieldCellEvent.initial() = _InitialCell;
+  const factory FieldCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
+}
+
+@freezed
+class FieldCellState with _$FieldCellState {
+  const factory FieldCellState({
+    required String gridId,
+    required Field field,
+  }) = _FieldCellState;
+
+  factory FieldCellState.initial(GridFieldCellContext cellContext) => FieldCellState(
+        gridId: cellContext.gridId,
+        field: cellContext.field,
+      );
+}

+ 32 - 22
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart

@@ -1,3 +1,4 @@
+import 'package:app_flowy/workspace/application/grid/field/field_cell_bloc.dart';
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/image.dart';
@@ -12,46 +13,55 @@ import 'field_cell_action_sheet.dart';
 import 'field_editor.dart';
 import 'field_editor.dart';
 
 
 class GridFieldCell extends StatelessWidget {
 class GridFieldCell extends StatelessWidget {
-  final GridFieldCellContext fieldCellContext;
-  const GridFieldCell(this.fieldCellContext, {Key? key}) : super(key: key);
+  final GridFieldCellContext cellContext;
+  const GridFieldCell(this.cellContext, {Key? key}) : super(key: key);
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     final theme = context.watch<AppTheme>();
-    final field = fieldCellContext.field;
-
-    final button = FlowyButton(
-      hoverColor: theme.hover,
-      onTap: () => _showActionSheet(context),
-      rightIcon: svgWidget("editor/details", color: theme.iconColor),
-      leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
-      text: FlowyText.medium(field.name, fontSize: 12),
-      padding: GridSize.cellContentInsets,
-    );
 
 
-    final borderSide = BorderSide(color: theme.shader4, width: 0.4);
-    final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide));
+    return BlocProvider(
+      create: (context) => FieldCellBloc(cellContext: cellContext)..add(const FieldCellEvent.initial()),
+      child: BlocBuilder<FieldCellBloc, FieldCellState>(
+        builder: (context, state) {
+          final button = FlowyButton(
+            hoverColor: theme.hover,
+            onTap: () => _showActionSheet(context),
+            rightIcon: svgWidget("editor/details", color: theme.iconColor),
+            leftIcon: svgWidget(state.field.fieldType.iconName(), color: theme.iconColor),
+            text: FlowyText.medium(state.field.name, fontSize: 12),
+            padding: GridSize.cellContentInsets,
+          );
+
+          final borderSide = BorderSide(color: theme.shader4, width: 0.4);
+          final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide));
 
 
-    return Container(
-      width: field.width.toDouble(),
-      decoration: decoration,
-      child: button,
+          return Container(
+            width: state.field.width.toDouble(),
+            decoration: decoration,
+            child: button,
+          );
+        },
+      ),
     );
     );
   }
   }
 
 
   void _showActionSheet(BuildContext context) {
   void _showActionSheet(BuildContext context) {
+    final state = context.read<FieldCellBloc>().state;
     GridFieldCellActionSheet(
     GridFieldCellActionSheet(
-      fieldCellContext: fieldCellContext,
+      cellContext: GridFieldCellContext(gridId: state.gridId, field: state.field),
       onEdited: () => _showFieldEditor(context),
       onEdited: () => _showFieldEditor(context),
     ).show(context);
     ).show(context);
   }
   }
 
 
   void _showFieldEditor(BuildContext context) {
   void _showFieldEditor(BuildContext context) {
+    final state = context.read<FieldCellBloc>().state;
+
     FieldEditor(
     FieldEditor(
-      gridId: fieldCellContext.gridId,
+      gridId: state.gridId,
       fieldContextLoader: FieldContextLoaderAdaptor(
       fieldContextLoader: FieldContextLoaderAdaptor(
-        gridId: fieldCellContext.gridId,
-        field: fieldCellContext.field,
+        gridId: state.gridId,
+        field: state.field,
       ),
       ),
     ).show(context);
     ).show(context);
   }
   }

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

@@ -13,9 +13,9 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 
 
 class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate {
 class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate {
-  final GridFieldCellContext fieldCellContext;
+  final GridFieldCellContext cellContext;
   final VoidCallback onEdited;
   final VoidCallback onEdited;
-  const GridFieldCellActionSheet({required this.fieldCellContext, required this.onEdited, Key? key}) : super(key: key);
+  const GridFieldCellActionSheet({required this.cellContext, required this.onEdited, Key? key}) : super(key: key);
 
 
   void show(BuildContext overlayContext) {
   void show(BuildContext overlayContext) {
     FlowyOverlay.of(overlayContext).insertWithAnchor(
     FlowyOverlay.of(overlayContext).insertWithAnchor(
@@ -33,7 +33,7 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return BlocProvider(
     return BlocProvider(
-      create: (context) => getIt<FieldActionSheetBloc>(param1: fieldCellContext),
+      create: (context) => getIt<FieldActionSheetBloc>(param1: cellContext),
       child: SingleChildScrollView(
       child: SingleChildScrollView(
         child: Column(
         child: Column(
           children: [
           children: [
@@ -44,7 +44,7 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate
               },
               },
             ),
             ),
             const VSpace(6),
             const VSpace(6),
-            _FieldOperationList(fieldCellContext, () => FlowyOverlay.of(context).remove(identifier())),
+            _FieldOperationList(cellContext, () => FlowyOverlay.of(context).remove(identifier())),
           ],
           ],
         ),
         ),
       ),
       ),

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

@@ -58,7 +58,7 @@ class _GridHeaderDelegate extends SliverPersistentHeaderDelegate {
   @override
   @override
   bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
   bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
     if (oldDelegate is _GridHeaderDelegate) {
     if (oldDelegate is _GridHeaderDelegate) {
-      return fields != oldDelegate.fields;
+      return fields.length != oldDelegate.fields.length;
     }
     }
     return true;
     return true;
   }
   }

+ 1 - 1
frontend/rust-lib/dart-ffi/Cargo.toml

@@ -8,7 +8,7 @@ edition = "2018"
 name = "dart_ffi"
 name = "dart_ffi"
 # this value will change depending on the target os
 # this value will change depending on the target os
 # default static lib
 # default static lib
-crate-type = ["staticlib"]
+crate-type = ["cdylib"]
 
 
 
 
 [dependencies]
 [dependencies]

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

@@ -58,7 +58,7 @@ impl ClientGridEditor {
             start_field_id,
             start_field_id,
             grid_id,
             grid_id,
         } = params;
         } = params;
-
+        let field_id = field.id.clone();
         let _ = self
         let _ = self
             .modify(|grid| {
             .modify(|grid| {
                 if grid.contain_field(&field.id) {
                 if grid.contain_field(&field.id) {
@@ -84,6 +84,7 @@ impl ClientGridEditor {
             })
             })
             .await?;
             .await?;
         let _ = self.notify_did_update_grid().await?;
         let _ = self.notify_did_update_grid().await?;
+        let _ = self.notify_did_update_field(&field_id).await?;
         Ok(())
         Ok(())
     }
     }
 
 
@@ -409,12 +410,13 @@ impl ClientGridEditor {
         Ok(())
         Ok(())
     }
     }
 
 
+    #[tracing::instrument(level = "trace", skip_all, err)]
     async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> {
     async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> {
         let mut field_metas = self.get_field_metas(Some(vec![field_id])).await?;
         let mut field_metas = self.get_field_metas(Some(vec![field_id])).await?;
         debug_assert!(field_metas.len() == 1);
         debug_assert!(field_metas.len() == 1);
 
 
         if let Some(field_meta) = field_metas.pop() {
         if let Some(field_meta) = field_metas.pop() {
-            send_dart_notification(&self.grid_id, GridNotification::DidUpdateField)
+            send_dart_notification(&field_id, GridNotification::DidUpdateField)
                 .payload(field_meta)
                 .payload(field_meta)
                 .send();
                 .send();
         }
         }