Browse Source

fix: deserialize multiple select cell data issues

appflowy 3 years ago
parent
commit
c82c6d9c6e

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

@@ -1,9 +1,7 @@
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
 
 class CellService {
   CellService();

+ 19 - 11
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart

@@ -15,6 +15,7 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
   final SelectOptionService _selectOptionService;
   final FieldListener _fieldListener;
   final CellListener _cellListener;
+  Timer? _delayOperation;
 
   SelectOptionEditorBloc({
     required CellData cellData,
@@ -59,6 +60,7 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
 
   @override
   Future<void> close() async {
+    _delayOperation?.cancel();
     await _fieldListener.stop();
     await _cellListener.stop();
     return super.close();
@@ -106,18 +108,24 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
   }
 
   void _loadOptions() async {
-    final result = await _selectOptionService.getOpitonContext(
-      gridId: state.gridId,
-      fieldId: state.field.id,
-      rowId: state.rowId,
-    );
+    _delayOperation?.cancel();
+    _delayOperation = Timer(
+      const Duration(milliseconds: 300),
+      () async {
+        final result = await _selectOptionService.getOpitonContext(
+          gridId: state.gridId,
+          fieldId: state.field.id,
+          rowId: state.rowId,
+        );
 
-    result.fold(
-      (selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions(
-        selectOptionContext.options,
-        selectOptionContext.selectOptions,
-      )),
-      (err) => Log.error(err),
+        result.fold(
+          (selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions(
+            selectOptionContext.options,
+            selectOptionContext.selectOptions,
+          )),
+          (err) => Log.error(err),
+        );
+      },
     );
   }
 

+ 0 - 1
frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart

@@ -1,4 +1,3 @@
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

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

@@ -8,7 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'option_pannel.dart';
 
 class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
-  MultiSelectTypeOptionWidget _widget;
+  final MultiSelectTypeOptionWidget _widget;
 
   MultiSelectTypeOptionBuilder(
     String fieldId,

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

@@ -122,7 +122,7 @@ class OverlayItem {
 }
 
 class FlowyOverlayState extends State<FlowyOverlay> {
-  List<OverlayItem> _overlayList = [];
+  final List<OverlayItem> _overlayList = [];
   FlowyOverlayStyle style = FlowyOverlayStyle();
 
   /// Insert a overlay widget which frame is set by the widget, not the component.

+ 0 - 3
frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart

@@ -1,8 +1,5 @@
 import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
-import 'package:flowy_infra_ui/style_widget/decoration.dart';
 import 'package:flutter/material.dart';
-import 'package:flowy_infra/theme.dart';
-import 'package:provider/provider.dart';
 
 class ListOverlayFooter {
   Widget widget;

+ 21 - 2
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs

@@ -85,8 +85,10 @@ impl CellDataOperation for SingleSelectTypeOption {
         let select_option_changeset: SelectOptionCellChangeset = serde_json::from_str(&changeset)?;
         let new_cell_data: String;
         if let Some(insert_option_id) = select_option_changeset.insert_option_id {
+            tracing::trace!("Insert single select option: {}", &insert_option_id);
             new_cell_data = insert_option_id;
         } else {
+            tracing::trace!("Delete single select option");
             new_cell_data = "".to_string()
         }
 
@@ -127,6 +129,15 @@ pub struct MultiSelectTypeOption {
 }
 impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect);
 
+impl MultiSelectTypeOption {
+    pub fn get_cell_data(&self, cell_meta: &CellMeta) -> String {
+        match TypeOptionCellData::from_str(&cell_meta.data) {
+            Ok(type_option) => type_option.data,
+            Err(_) => String::new(),
+        }
+    }
+}
+
 impl SelectOptionOperation for MultiSelectTypeOption {
     fn insert_option(&mut self, new_option: SelectOption) {
         if let Some(index) = self.options.iter().position(|option| option.id == new_option.id) {
@@ -185,16 +196,24 @@ impl CellDataOperation for MultiSelectTypeOption {
                     .unwrap_or_else(|| "".to_owned());
             }
             Some(cell_meta) => {
-                let mut selected_options = select_option_ids(cell_meta.data);
+                let cell_data = self.get_cell_data(&cell_meta);
+                let mut selected_options = select_option_ids(cell_data);
                 if let Some(insert_option_id) = select_option_changeset.insert_option_id {
-                    selected_options.push(insert_option_id);
+                    tracing::trace!("Insert multi select option: {}", &insert_option_id);
+                    if selected_options.contains(&insert_option_id) {
+                        selected_options.retain(|id| id != &insert_option_id);
+                    } else {
+                        selected_options.push(insert_option_id);
+                    }
                 }
 
                 if let Some(delete_option_id) = select_option_changeset.delete_option_id {
+                    tracing::trace!("Delete multi select option: {}", &delete_option_id);
                     selected_options.retain(|id| id != &delete_option_id);
                 }
 
                 new_cell_data = selected_options.join(SELECTION_IDS_SEPARATOR);
+                tracing::trace!("Multi select cell data: {}", &new_cell_data);
             }
         }