diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart b/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart index 5317539128316..a52f315e35553 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart @@ -207,13 +207,14 @@ class DatabaseController { } Future> moveGroupRow({ - required RowMetaPB fromRow, + required List fromRow, required String fromGroupId, required String toGroupId, RowMetaPB? toRow, }) { + final fromRowIds = fromRow.map((element) => element.id).toList(); return _databaseViewBackendSvc.moveGroupRow( - fromRowId: fromRow.id, + fromRowIds: fromRowIds, fromGroupId: fromGroupId, toGroupId: toGroupId, toRowId: toRow?.id, diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_cache.dart b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_cache.dart index be5ba29dfc76a..5cef5914cc503 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_cache.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_cache.dart @@ -78,6 +78,17 @@ class RowCache { return _rowList.get(rowId); } + List getRows(List rowIds) { + final rowInfos = []; + for (final rowId in rowIds) { + final rowInfo = _rowList.get(rowId); + if (rowInfo != null) { + rowInfos.add(rowInfo); + } + } + return rowInfos; + } + void setInitialRows(List rows) { for (final row in rows) { final rowInfo = buildGridRow(row); diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart index a2c6c895783c7..7d10c6f9f67c2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart @@ -72,7 +72,7 @@ class BoardBloc extends Bloc { final toRow = groupControllers[groupId]?.rowAtIndex(toIndex); if (fromRow != null) { databaseController.moveGroupRow( - fromRow: fromRow, + fromRow: [fromRow], toRow: toRow, fromGroupId: groupId, toGroupId: groupId, @@ -85,7 +85,7 @@ class BoardBloc extends Bloc { final toRow = groupControllers[toGroupId]?.rowAtIndex(toIndex); if (fromRow != null) { databaseController.moveGroupRow( - fromRow: fromRow, + fromRow: [fromRow], toRow: toRow, fromGroupId: fromGroupId, toGroupId: toGroupId, @@ -242,20 +242,49 @@ class BoardBloc extends Bloc { final rowIds = groupedRowIds.map((e) => e.rowId).toList(); await RowBackendService.deleteRows(viewId, rowIds); }, - moveGroupToAdjacentGroup: (groupedRowId, toPrevious) async { - final fromRow = - databaseController.rowCache.getRow(groupedRowId.rowId)?.rowMeta; - final currentGroupIndex = - boardController.groupIds.indexOf(groupedRowId.groupId); - final toGroupIndex = - toPrevious ? currentGroupIndex - 1 : currentGroupIndex + 1; - if (fromRow != null && + moveGroupToAdjacentGroup: (groupedRowIds, toPrevious) async { + final checkedGroupIndexs = groupedRowIds + .map( + (element) => + boardController.groupIds.indexOf(element.groupId), + ) + .toSet(); + + late final int currentGroupIndex; + late final int toGroupIndex; + if (checkedGroupIndexs.length == 1) { + currentGroupIndex = checkedGroupIndexs.first; + toGroupIndex = + toPrevious ? currentGroupIndex - 1 : currentGroupIndex + 1; + } else { + final sortedGroupIndex = + checkedGroupIndexs.sorted((a, b) => a - b); + currentGroupIndex = + toPrevious ? sortedGroupIndex.last : sortedGroupIndex.first; + toGroupIndex = + toPrevious ? sortedGroupIndex.first : sortedGroupIndex.last; + } + + final toGroupId = boardController.groupDatas[toGroupIndex].id; + final rowIds = groupedRowIds + .where((element) => element.groupId != toGroupId) + .map((element) => element.rowId) + .toList(); + + final fromRows = databaseController.rowCache + .getRows(rowIds) + .map((element) => element.rowMeta) + .toList(); + + if (fromRows.isNotEmpty && toGroupIndex > -1 && toGroupIndex < boardController.groupIds.length) { - final toGroupId = boardController.groupDatas[toGroupIndex].id; + final fromGroupId = + boardController.groupDatas[currentGroupIndex].id; + final result = await databaseController.moveGroupRow( - fromRow: fromRow, - fromGroupId: groupedRowId.groupId, + fromRow: fromRows, + fromGroupId: fromGroupId, toGroupId: toGroupId, ); result.fold( @@ -264,9 +293,11 @@ class BoardBloc extends Bloc { emit( BoardState.setFocus( groupedRowIds: [ - GroupedRowId( - groupId: toGroupId, - rowId: groupedRowId.rowId, + ...rowIds.map( + (element) => GroupedRowId( + groupId: toGroupId, + rowId: element, + ), ), ], ), @@ -608,7 +639,7 @@ class BoardEvent with _$BoardEvent { const factory BoardEvent.deleteCards(List groupedRowIds) = _DeleteCards; const factory BoardEvent.moveGroupToAdjacentGroup( - GroupedRowId groupedRowId, + List groupedRowIds, bool toPrevious, ) = _MoveGroupToAdjacentGroup; const factory BoardEvent.openRowDetail(RowMetaPB rowMeta) = _OpenRowDetail; diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart index 1079755216aa7..bd4b3f8fd4e17 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart @@ -129,7 +129,7 @@ class _DesktopBoardPageState extends State { final toRow = groupControllers[groupId]?.rowAtIndex(toIndex); if (fromRow != null) { widget.databaseController.moveGroupRow( - fromRow: fromRow, + fromRow: [fromRow], toRow: toRow, fromGroupId: groupId, toGroupId: groupId, @@ -142,7 +142,7 @@ class _DesktopBoardPageState extends State { final toRow = groupControllers[toGroupId]?.rowAtIndex(toIndex); if (fromRow != null) { widget.databaseController.moveGroupRow( - fromRow: fromRow, + fromRow: [fromRow], toRow: toRow, fromGroupId: fromGroupId, toGroupId: toGroupId, @@ -304,6 +304,9 @@ class _BoardContentState extends State<_BoardContent> { rowMeta: value.rowMeta, ); }, + setFocus: (value) { + widget.focusScope.focusedGroupedRows = value.groupedRowIds; + }, orElse: () {}, ); }, diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_shortcut_container.dart b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_shortcut_container.dart index c69269a1b7fea..38ffa86f94d52 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_shortcut_container.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_shortcut_container.dart @@ -162,12 +162,9 @@ class BoardShortcutContainer extends StatelessWidget { } bool _moveGroupToAdjacentGroup(BuildContext context, bool toPrevious) { - if (focusScope.value.length != 1) { - return false; - } context.read().add( BoardEvent.moveGroupToAdjacentGroup( - focusScope.value.first, + focusScope.value, toPrevious, ), ); diff --git a/frontend/appflowy_flutter/lib/plugins/database/domain/database_view_service.dart b/frontend/appflowy_flutter/lib/plugins/database/domain/database_view_service.dart index de06c8d1d80eb..a93e76fe20d5a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/domain/database_view_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/domain/database_view_service.dart @@ -37,16 +37,17 @@ class DatabaseViewBackendService { } Future> moveGroupRow({ - required RowId fromRowId, + required List fromRowIds, required String fromGroupId, required String toGroupId, RowId? toRowId, }) { - final payload = MoveGroupRowPayloadPB.create() - ..viewId = viewId - ..fromRowId = fromRowId - ..fromGroupId = fromGroupId - ..toGroupId = toGroupId; + final payload = MoveGroupRowPayloadPB( + viewId: viewId, + fromRowIds: fromRowIds, + fromGroupId: fromGroupId, + toGroupId: toGroupId, + ); if (toRowId != null) { payload.toRowId = toRowId; diff --git a/frontend/rust-lib/flowy-database2/src/entities/database_entities.rs b/frontend/rust-lib/flowy-database2/src/entities/database_entities.rs index 59b9e228aed06..4828b4757a936 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/database_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/database_entities.rs @@ -160,7 +160,7 @@ pub struct MoveGroupRowPayloadPB { pub view_id: String, #[pb(index = 2)] - pub from_row_id: String, + pub from_row_ids: Vec, #[pb(index = 3)] pub to_group_id: String, @@ -174,7 +174,7 @@ pub struct MoveGroupRowPayloadPB { pub struct MoveGroupRowParams { pub view_id: String, - pub from_row_id: RowId, + pub from_row_ids: Vec, pub from_group_id: String, pub to_group_id: String, pub to_row_id: Option, @@ -189,12 +189,16 @@ impl TryInto for MoveGroupRowPayloadPB { NotEmptyStr::parse(self.from_group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?; let to_group_id = NotEmptyStr::parse(self.to_group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?; - + let from_row_ids = self + .from_row_ids + .iter() + .map(|e| RowId::from(e.clone())) + .collect(); Ok(MoveGroupRowParams { view_id: view_id.0, to_group_id: to_group_id.0, from_group_id: from_group_id.0, - from_row_id: RowId::from(self.from_row_id), + from_row_ids, to_row_id: self.to_row_id.map(RowId::from), }) } diff --git a/frontend/rust-lib/flowy-database2/src/event_handler.rs b/frontend/rust-lib/flowy-database2/src/event_handler.rs index 596b4e613b329..fae94205be76c 100644 --- a/frontend/rust-lib/flowy-database2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-database2/src/event_handler.rs @@ -822,15 +822,17 @@ pub(crate) async fn move_group_row_handler( let database_editor = manager .get_database_editor_with_view_id(¶ms.view_id) .await?; - database_editor - .move_group_row( - ¶ms.view_id, - ¶ms.from_group_id, - ¶ms.to_group_id, - params.from_row_id, - params.to_row_id, - ) - .await?; + for from_row_id in params.from_row_ids { + database_editor + .move_group_row( + ¶ms.view_id, + ¶ms.from_group_id, + ¶ms.to_group_id, + from_row_id, + params.to_row_id.clone(), + ) + .await?; + } Ok(()) }