From c4514e421a775e3bfa33ac18380dea934a6071da Mon Sep 17 00:00:00 2001
From: appflowy <annie@appflowy.io>
Date: Wed, 17 Aug 2022 20:15:10 +0800
Subject: [PATCH] chore: move card from one column to another

---
 frontend/.vscode/launch.json                  |  2 +-
 .../plugins/board/application/board_bloc.dart | 32 ++++++++++++--
 .../board/application/group_controller.dart   | 28 +++---------
 .../grid/application/row/row_service.dart     | 39 ++---------------
 .../appflowy_board/lib/src/utils/log.dart     |  2 +-
 .../flowy-grid/src/entities/grid_entities.rs  | 25 ++---------
 .../src/services/block_manager_trait_impl.rs  |  2 +-
 .../flowy-grid/src/services/grid_editor.rs    | 43 ++++++++-----------
 .../src/services/grid_view_editor.rs          |  3 +-
 .../src/services/grid_view_manager.rs         |  4 +-
 .../group/group_generator/checkbox_group.rs   | 10 ++---
 .../group_generator/select_option_group.rs    | 32 ++++++--------
 .../src/client_grid/block_revision_pad.rs     |  2 +-
 13 files changed, 85 insertions(+), 139 deletions(-)

diff --git a/frontend/.vscode/launch.json b/frontend/.vscode/launch.json
index 0efc79b00e..e70b9ffb97 100644
--- a/frontend/.vscode/launch.json
+++ b/frontend/.vscode/launch.json
@@ -29,7 +29,7 @@
             "program": "./lib/main.dart",
             "type": "dart",
             "env": {
-                "RUST_LOG": "debug"
+                "RUST_LOG": "trace"
             },
             "cwd": "${workspaceRoot}/app_flowy"
         },
diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart
index e7668ffcc0..ac72b6e24e 100644
--- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart
+++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart
@@ -2,6 +2,7 @@ import 'dart:async';
 import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
 import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
 import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
+import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
 import 'package:appflowy_board/appflowy_board.dart';
 import 'package:dartz/dartz.dart';
 import 'package:equatable/equatable.dart';
@@ -21,13 +22,15 @@ part 'board_bloc.freezed.dart';
 class BoardBloc extends Bloc<BoardEvent, BoardState> {
   final BoardDataController _dataController;
   late final AFBoardDataController afBoardDataController;
+  final MoveRowFFIService _rowService;
   Map<String, GroupController> groupControllers = {};
 
   GridFieldCache get fieldCache => _dataController.fieldCache;
   String get gridId => _dataController.gridId;
 
   BoardBloc({required ViewPB view})
-      : _dataController = BoardDataController(view: view),
+      : _rowService = MoveRowFFIService(gridId: view.id),
+        _dataController = BoardDataController(view: view),
         super(BoardState.initial(view.id)) {
     afBoardDataController = AFBoardDataController(
       onMoveColumn: (
@@ -39,7 +42,9 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
         fromIndex,
         toIndex,
       ) {
-        groupControllers[columnId]?.moveRow(fromIndex, toIndex);
+        final fromRow = groupControllers[columnId]?.rowAtIndex(fromIndex);
+        final toRow = groupControllers[columnId]?.rowAtIndex(toIndex);
+        _moveRow(fromRow, toRow);
       },
       onMoveColumnItemToColumn: (
         fromColumnId,
@@ -47,7 +52,9 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
         toColumnId,
         toIndex,
       ) {
-        //
+        final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex);
+        final toRow = groupControllers[toColumnId]?.rowAtIndex(toIndex);
+        _moveRow(fromRow, toRow);
       },
     );
 
@@ -80,11 +87,27 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
           didReceiveRows: (List<RowInfo> rowInfos) {
             emit(state.copyWith(rowInfos: rowInfos));
           },
+          didReceiveError: (FlowyError error) {
+            emit(state.copyWith(noneOrError: some(error)));
+          },
         );
       },
     );
   }
 
+  void _moveRow(RowPB? fromRow, RowPB? toRow) {
+    if (fromRow != null && toRow != null) {
+      _rowService
+          .moveRow(
+        fromRowId: fromRow.id,
+        toRowId: toRow.id,
+      )
+          .then((result) {
+        result.fold((l) => null, (r) => add(BoardEvent.didReceiveError(r)));
+      });
+    }
+  }
+
   @override
   Future<void> close() async {
     await _dataController.dispose();
@@ -167,6 +190,7 @@ class BoardEvent with _$BoardEvent {
   const factory BoardEvent.initial() = InitialGrid;
   const factory BoardEvent.createRow(String groupId) = _CreateRow;
   const factory BoardEvent.endEditRow(String rowId) = _EndEditRow;
+  const factory BoardEvent.didReceiveError(FlowyError error) = _DidReceiveError;
   const factory BoardEvent.didReceiveRows(List<RowInfo> rowInfos) =
       _DidReceiveRows;
   const factory BoardEvent.didReceiveGridUpdate(
@@ -182,6 +206,7 @@ class BoardState with _$BoardState {
     required Option<RowPB> editingRow,
     required List<RowInfo> rowInfos,
     required GridLoadingState loadingState,
+    required Option<FlowyError> noneOrError,
   }) = _BoardState;
 
   factory BoardState.initial(String gridId) => BoardState(
@@ -189,6 +214,7 @@ class BoardState with _$BoardState {
         grid: none(),
         gridId: gridId,
         editingRow: none(),
+        noneOrError: none(),
         loadingState: const _Loading(),
       );
 }
diff --git a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart
index 62d2130194..3f545dae3b 100644
--- a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart
+++ b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart
@@ -1,4 +1,3 @@
-import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
@@ -16,36 +15,23 @@ abstract class GroupControllerDelegate {
 class GroupController {
   final GroupPB group;
   final GroupListener _listener;
-  final MoveRowFFIService _rowService;
   final GroupControllerDelegate delegate;
-  OnGroupError? _onError;
 
   GroupController({
     required String gridId,
     required this.group,
     required this.delegate,
-  })  : _rowService = MoveRowFFIService(gridId: gridId),
-        _listener = GroupListener(group);
+  }) : _listener = GroupListener(group);
 
-  Future<void> moveRow(int fromIndex, int toIndex) async {
-    if (fromIndex < group.rows.length && toIndex < group.rows.length) {
-      final fromRow = group.rows[fromIndex];
-      final toRow = group.rows[toIndex];
-
-      final result = await _rowService.moveRow(
-        rowId: fromRow.id,
-        fromIndex: fromIndex,
-        toIndex: toIndex,
-        upperRowId: toRow.id,
-        layout: GridLayout.Board,
-      );
-
-      result.fold((l) => null, (r) => _onError?.call(r));
+  RowPB? rowAtIndex(int index) {
+    if (index < group.rows.length) {
+      return group.rows[index];
+    } else {
+      return null;
     }
   }
 
-  void startListening({OnGroupError? onError}) {
-    _onError = onError;
+  void startListening() {
     _listener.start(onGroupChanged: (result) {
       result.fold(
         (GroupRowsChangesetPB changeset) {
diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart
index 594bd230f9..a18c0c8e75 100644
--- a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart
+++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart
@@ -4,7 +4,6 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
 
 class RowFFIService {
   final String gridId;
@@ -23,27 +22,6 @@ class RowFFIService {
     return GridEventCreateTableRow(payload).send();
   }
 
-  Future<Either<Unit, FlowyError>> moveRow({
-    required String rowId,
-    required int fromIndex,
-    required int toIndex,
-    required GridLayout layout,
-    String? upperRowId,
-  }) {
-    var payload = MoveRowPayloadPB.create()
-      ..viewId = gridId
-      ..rowId = rowId
-      ..layout = layout
-      ..fromIndex = fromIndex
-      ..toIndex = toIndex;
-
-    if (upperRowId != null) {
-      payload.upperRowId = upperRowId;
-    }
-
-    return GridEventMoveRow(payload).send();
-  }
-
   Future<Either<OptionalRowPB, FlowyError>> getRow(String rowId) {
     final payload = RowIdPB.create()
       ..gridId = gridId
@@ -80,22 +58,13 @@ class MoveRowFFIService {
   });
 
   Future<Either<Unit, FlowyError>> moveRow({
-    required String rowId,
-    required int fromIndex,
-    required int toIndex,
-    required GridLayout layout,
-    String? upperRowId,
+    required String fromRowId,
+    required String toRowId,
   }) {
     var payload = MoveRowPayloadPB.create()
       ..viewId = gridId
-      ..rowId = rowId
-      ..layout = layout
-      ..fromIndex = fromIndex
-      ..toIndex = toIndex;
-
-    if (upperRowId != null) {
-      payload.upperRowId = upperRowId;
-    }
+      ..fromRowId = fromRowId
+      ..toRowId = toRowId;
 
     return GridEventMoveRow(payload).send();
   }
diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart
index d11b5fd263..20f810a966 100644
--- a/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart
+++ b/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart
@@ -6,7 +6,7 @@ const DART_LOG = "Dart_LOG";
 class Log {
   // static const enableLog = bool.hasEnvironment(DART_LOG);
   // static final shared = Log();
-  static const enableLog = true;
+  static const enableLog = false;
 
   static void info(String? message) {
     if (enableLog) {
diff --git a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs
index b185f6702b..be8cfdeae1 100644
--- a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs
+++ b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs
@@ -1,4 +1,4 @@
-use crate::entities::{BlockPB, FieldIdPB, GridLayout};
+use crate::entities::{BlockPB, FieldIdPB};
 use flowy_derive::ProtoBuf;
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
@@ -98,24 +98,13 @@ pub struct MoveRowPayloadPB {
     #[pb(index = 2)]
     pub from_row_id: String,
 
-    // #[pb(index = 3)]
-    // pub from_index: i32,
-    //
-    // #[pb(index = 4)]
-    // pub to_index: i32,
-    #[pb(index = 5)]
-    pub layout: GridLayout,
-
-    #[pb(index = 6)]
+    #[pb(index = 4)]
     pub to_row_id: String,
 }
 
 pub struct MoveRowParams {
     pub view_id: String,
     pub from_row_id: String,
-    // pub from_index: i32,
-    // pub to_index: i32,
-    pub layout: GridLayout,
     pub to_row_id: String,
 }
 
@@ -126,17 +115,11 @@ impl TryInto<MoveRowParams> for MoveRowPayloadPB {
         let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::GridViewIdIsEmpty)?;
         let from_row_id = NotEmptyStr::parse(self.from_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
         let to_row_id = NotEmptyStr::parse(self.to_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
-        let upper_row_id = match self.to_row_id {
-            None => None,
-            Some(upper_row_id) => Some(NotEmptyStr::parse(upper_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?.0),
-        };
+
         Ok(MoveRowParams {
             view_id: view_id.0,
             from_row_id: from_row_id.0,
-            // from_index: self.from_index,
-            // to_index: self.to_index,
-            layout: self.layout,
-            to_row_id: upper_row_id,
+            to_row_id: to_row_id.0,
         })
     }
 }
diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs
index 1bb42310ff..3adea9a853 100644
--- a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs
+++ b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs
@@ -1,6 +1,6 @@
 use crate::services::block_manager::GridBlockManager;
 use crate::services::grid_view_manager::GridViewRowDelegate;
-use flowy_error::FlowyResult;
+
 use flowy_grid_data_model::revision::RowRevision;
 use lib_infra::future::{wrap_future, AFFuture};
 use std::sync::Arc;
diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
index 1f16f95475..d099b5b269 100644
--- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
+++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
@@ -495,38 +495,29 @@ impl GridRevisionEditor {
     pub async fn move_row(&self, params: MoveRowParams) -> FlowyResult<()> {
         let MoveRowParams {
             view_id: _,
-            from_row_id: row_id,
-            from_index,
-            to_index,
-            layout: _,
-            to_row_id: upper_row_id,
+            from_row_id,
+            to_row_id,
         } = params;
 
-        let from_index = from_index as usize;
-        let to_index = to_index as usize;
-
-        match self.block_manager.get_row_rev(&row_id).await? {
-            None => tracing::warn!("Move row failed, can not find the row:{}", row_id),
-            Some(row_rev) => match upper_row_id {
-                None => {
-                    tracing::trace!("Move row from {} to {}", from_index, to_index);
-                    let _ = self
-                        .block_manager
-                        .move_row(row_rev.clone(), from_index, to_index)
-                        .await?;
-                }
-                Some(to_row_id) => match self.block_manager.index_of_row(&to_row_id).await {
-                    None => tracing::error!("Can not find the row: {} when moving the row", to_row_id),
-                    Some(to_row_index) => {
-                        tracing::trace!("Move row from {} to {}", from_index, to_row_index);
+        match self.block_manager.get_row_rev(&from_row_id).await? {
+            None => tracing::warn!("Move row failed, can not find the row:{}", from_row_id),
+            Some(row_rev) => {
+                match (
+                    self.block_manager.index_of_row(&from_row_id).await,
+                    self.block_manager.index_of_row(&to_row_id).await,
+                ) {
+                    (Some(from_index), Some(to_index)) => {
+                        tracing::trace!("Move row from {} to {}", from_index, to_index);
                         let _ = self
                             .block_manager
-                            .move_row(row_rev.clone(), from_index, to_row_index)
+                            .move_row(row_rev.clone(), from_index, to_index)
                             .await?;
-                        self.view_manager.move_row(row_rev, to_row_id).await;
+                        self.view_manager.move_row(row_rev, to_row_id.clone()).await;
                     }
-                },
-            },
+                    (_, None) => tracing::error!("Can not find the from row id: {}", from_row_id),
+                    (None, _) => tracing::error!("Can not find the to row id: {}", to_row_id),
+                }
+            }
         }
         Ok(())
     }
diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs
index c8f2babf9f..5b4af736a3 100644
--- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs
+++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs
@@ -1,7 +1,6 @@
 use crate::dart_notification::{send_dart_notification, GridNotification};
 use crate::entities::{
-    CreateRowParams, GridFilterConfiguration, GridLayout, GridSettingPB, GroupPB, GroupRowsChangesetPB, InsertedRowPB,
-    RowPB,
+    CreateRowParams, GridFilterConfiguration, GridSettingPB, GroupPB, GroupRowsChangesetPB, InsertedRowPB, RowPB,
 };
 use crate::services::grid_editor_task::GridServiceTaskScheduler;
 use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs
index 4c320d527a..a71ac5722c 100644
--- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs
+++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs
@@ -1,8 +1,7 @@
 use crate::entities::{
-    CreateRowParams, GridFilterConfiguration, GridLayout, GridSettingPB, MoveRowParams, RepeatedGridGroupPB, RowPB,
+    CreateRowParams, GridFilterConfiguration, GridSettingPB, RepeatedGridGroupPB, RowPB,
 };
 use crate::manager::GridUser;
-
 use crate::services::grid_editor_task::GridServiceTaskScheduler;
 use crate::services::grid_view_editor::GridViewRevisionEditor;
 use bytes::Bytes;
@@ -11,7 +10,6 @@ use flowy_error::FlowyResult;
 use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
 use flowy_revision::disk::SQLiteGridViewRevisionPersistence;
 use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence};
-
 use flowy_sync::entities::grid::GridSettingChangesetParams;
 use flowy_sync::entities::revision::Revision;
 use flowy_sync::util::make_text_delta_from_revisions;
diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs
index ca6fd3a4bd..bfe5552867 100644
--- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs
+++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs
@@ -29,17 +29,17 @@ impl Groupable for CheckboxGroupController {
 
     fn remove_row_if_match(
         &mut self,
-        row_rev: &RowRevision,
-        cell_data: &Self::CellDataType,
+        _row_rev: &RowRevision,
+        _cell_data: &Self::CellDataType,
     ) -> Vec<GroupRowsChangesetPB> {
         todo!()
     }
 
     fn move_row_if_match(
         &mut self,
-        row_rev: &RowRevision,
-        cell_data: &Self::CellDataType,
-        to_row_id: &str,
+        _row_rev: &RowRevision,
+        _cell_data: &Self::CellDataType,
+        _to_row_id: &str,
     ) -> Vec<GroupRowsChangesetPB> {
         todo!()
     }
diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs
index efc2d4ff63..086d87a0d2 100644
--- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs
+++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs
@@ -177,15 +177,13 @@ fn add_row(
     row_rev: &RowRevision,
 ) {
     cell_data.select_options.iter().for_each(|option| {
-        if option.id == group.id {
-            if !group.contains_row(&row_rev.id) {
-                let row_pb = RowPB::from(row_rev);
-                changesets.push(GroupRowsChangesetPB::insert(
-                    group.id.clone(),
-                    vec![InsertedRowPB::new(row_pb.clone())],
-                ));
-                group.add_row(row_pb);
-            }
+        if option.id == group.id && !group.contains_row(&row_rev.id) {
+            let row_pb = RowPB::from(row_rev);
+            changesets.push(GroupRowsChangesetPB::insert(
+                group.id.clone(),
+                vec![InsertedRowPB::new(row_pb.clone())],
+            ));
+            group.add_row(row_pb);
         }
     });
 }
@@ -197,11 +195,9 @@ fn remove_row(
     row_rev: &RowRevision,
 ) {
     cell_data.select_options.iter().for_each(|option| {
-        if option.id == group.id {
-            if group.contains_row(&row_rev.id) {
-                changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
-                group.remove_row(&row_rev.id);
-            }
+        if option.id == group.id && group.contains_row(&row_rev.id) {
+            changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
+            group.remove_row(&row_rev.id);
         }
     });
 }
@@ -214,11 +210,9 @@ fn move_row(
     upper_row_id: &str,
 ) {
     cell_data.select_options.iter().for_each(|option| {
-        if option.id == group.id {
-            if group.contains_row(&row_rev.id) {
-                changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
-                group.remove_row(&row_rev.id);
-            }
+        if option.id == group.id && group.contains_row(&row_rev.id) {
+            changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
+            group.remove_row(&row_rev.id);
         }
 
         if let Some(index) = group.index_of_row(upper_row_id) {
diff --git a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs
index 5902fda35c..8abc1eaace 100644
--- a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs
+++ b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs
@@ -179,7 +179,7 @@ impl GridBlockRevisionPad {
                 debug_assert_eq!(from, position);
                 let row_rev = row_revs.remove(position);
                 if to > row_revs.len() {
-                    return Err(CollaborateError::out_of_bound());
+                    Err(CollaborateError::out_of_bound())
                 } else {
                     row_revs.insert(to, row_rev);
                     Ok(Some(()))