From 381d2e6c7180562497089f777d2cb5ca69cb095a Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Wed, 7 Jun 2023 00:05:27 +0800 Subject: [PATCH] fix: reorder view when sibling view was deleted (#2724) * fix: reorder view when sibling view was deleted * ci: fix test * ci: rust fmt --- .../workspace/application/app/app_bloc.dart | 1 + frontend/appflowy_tauri/src-tauri/Cargo.toml | 12 +- frontend/rust-lib/Cargo.lock | 20 +-- frontend/rust-lib/Cargo.toml | 10 +- .../src/deps_resolve/collab_deps.rs | 10 +- .../rust-lib/flowy-database2/src/manager.rs | 1 - .../flowy-folder2/src/entities/view.rs | 17 +-- .../flowy-folder2/src/event_handler.rs | 4 +- .../rust-lib/flowy-folder2/src/manager.rs | 103 ++++++++++++--- .../2023-06-05-135652_collab_snapshot/up.sql | 2 + frontend/rust-lib/flowy-sqlite/src/schema.rs | 2 + frontend/rust-lib/flowy-test/src/lib.rs | 32 ++++- .../rust-lib/flowy-test/tests/folder/test.rs | 117 +++++++++++++----- 13 files changed, 248 insertions(+), 83 deletions(-) diff --git a/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart index 58bd51c32b..01bb49fc04 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart @@ -105,6 +105,7 @@ class AppBloc extends Bloc { } Future _createView(CreateView value, Emitter emit) async { + // create a child view for the current view final result = await ViewBackendService.createView( parentViewId: state.view.id, name: value.name, diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 82de264d69..3c8b57e6c5 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -34,12 +34,12 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } #collab = { path = "../../AppFlowy-Collab/collab" } #collab-folder = { path = "../../AppFlowy-Collab/collab-folder" } diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 879000150c..3824215f5e 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -85,7 +85,7 @@ checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "appflowy-integrate" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "anyhow", "collab", @@ -887,7 +887,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "anyhow", "bytes", @@ -905,7 +905,7 @@ dependencies = [ [[package]] name = "collab-client-ws" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "bytes", "collab-sync", @@ -923,7 +923,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "anyhow", "async-trait", @@ -949,7 +949,7 @@ dependencies = [ [[package]] name = "collab-derive" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "proc-macro2", "quote", @@ -961,7 +961,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "anyhow", "collab", @@ -978,7 +978,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "anyhow", "collab", @@ -997,7 +997,7 @@ dependencies = [ [[package]] name = "collab-persistence" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "bincode", "chrono", @@ -1017,7 +1017,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "anyhow", "async-trait", @@ -1048,7 +1048,7 @@ dependencies = [ [[package]] name = "collab-sync" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5c519e#5c519e988e93f6fbc7d98ce4373c5ff30a547fb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=a647d9#a647d922ef432510d6be0abb5f968d9a75dc7011" dependencies = [ "bytes", "collab", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index dadfa111c6..117b545839 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -33,11 +33,11 @@ opt-level = 3 incremental = false [patch.crates-io] -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } -appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5c519e" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } +appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "a647d9" } #collab = { path = "../AppFlowy-Collab/collab" } #collab-folder = { path = "../AppFlowy-Collab/collab-folder" } diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/collab_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/collab_deps.rs index 3312a32db2..e84b082f9c 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/collab_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/collab_deps.rs @@ -25,7 +25,7 @@ impl SnapshotDB for SnapshotDBImpl { .and_then(|pool| Ok(pool.get()?)) .and_then(|conn| { CollabSnapshotTableSql::get_all_snapshots(object_id, &conn) - .and_then(|rows| Ok(rows.into_iter().map(|row| row.into()).collect())) + .map(|rows| rows.into_iter().map(|row| row.into()).collect()) }) .unwrap_or_else(|_| vec![]) } @@ -34,6 +34,8 @@ impl SnapshotDB for SnapshotDBImpl { &self, uid: i64, object_id: &str, + title: String, + collab_type: String, snapshot: Snapshot, collab: Arc, ) -> Result<(), PersistenceError> { @@ -74,7 +76,9 @@ impl SnapshotDB for SnapshotDBImpl { CollabSnapshotRow { id: uuid::Uuid::new_v4().to_string(), object_id: object_id.clone(), + title, desc, + collab_type, timestamp: timestamp(), data: new_snapshot_data, }, @@ -97,7 +101,9 @@ impl SnapshotDB for SnapshotDBImpl { struct CollabSnapshotRow { id: String, object_id: String, + title: String, desc: String, + collab_type: String, timestamp: i64, data: Vec, } @@ -118,7 +124,9 @@ impl CollabSnapshotTableSql { let values = ( dsl::id.eq(row.id), dsl::object_id.eq(row.object_id), + dsl::title.eq(row.title), dsl::desc.eq(row.desc), + dsl::collab_type.eq(row.collab_type), dsl::data.eq(row.data), dsl::timestamp.eq(row.timestamp), ); diff --git a/frontend/rust-lib/flowy-database2/src/manager.rs b/frontend/rust-lib/flowy-database2/src/manager.rs index 4e028fa251..1548512d4d 100644 --- a/frontend/rust-lib/flowy-database2/src/manager.rs +++ b/frontend/rust-lib/flowy-database2/src/manager.rs @@ -84,7 +84,6 @@ impl DatabaseManager2 { self.get_database(&database_id).await } - #[tracing::instrument(level = "debug", skip(self), err)] pub async fn get_database_id_with_view_id(&self, view_id: &str) -> FlowyResult { let database_id = self.with_user_database(Err(FlowyError::internal()), |database| { database diff --git a/frontend/rust-lib/flowy-folder2/src/entities/view.rs b/frontend/rust-lib/flowy-folder2/src/entities/view.rs index 8adb556ccd..c9c53c9b39 100644 --- a/frontend/rust-lib/flowy-folder2/src/entities/view.rs +++ b/frontend/rust-lib/flowy-folder2/src/entities/view.rs @@ -1,12 +1,15 @@ -use crate::entities::parser::view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail}; -use crate::view_operation::gen_view_id; -use collab_folder::core::{View, ViewLayout}; -use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use flowy_error::ErrorCode; use std::collections::HashMap; use std::convert::TryInto; use std::ops::{Deref, DerefMut}; +use collab_folder::core::{View, ViewLayout}; + +use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use flowy_error::ErrorCode; + +use crate::entities::parser::view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail}; +use crate::view_operation::gen_view_id; + #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] pub struct ViewPB { #[pb(index = 1)] @@ -284,7 +287,7 @@ pub struct MoveViewPayloadPB { } pub struct MoveViewParams { - pub item_id: String, + pub view_id: String, pub from: usize, pub to: usize, } @@ -295,7 +298,7 @@ impl TryInto for MoveViewPayloadPB { fn try_into(self) -> Result { let view_id = ViewIdentify::parse(self.view_id)?.0; Ok(MoveViewParams { - item_id: view_id, + view_id, from: self.from as usize, to: self.to as usize, }) diff --git a/frontend/rust-lib/flowy-folder2/src/event_handler.rs b/frontend/rust-lib/flowy-folder2/src/event_handler.rs index 5d5c46bc34..3ebc9b82dd 100644 --- a/frontend/rust-lib/flowy-folder2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-folder2/src/event_handler.rs @@ -72,8 +72,6 @@ pub async fn read_cur_workspace_setting_handler( folder: AFPluginState>, ) -> DataResult { let workspace = folder.get_current_workspace().await?; - let views = folder.get_workspace_views(&workspace.id).await?; - let workspace: WorkspacePB = (workspace, views).into(); let latest_view: Option = folder.get_current_view().await; data_result_ok(WorkspaceSettingPB { workspace, @@ -149,7 +147,7 @@ pub(crate) async fn move_view_handler( ) -> Result<(), FlowyError> { let params: MoveViewParams = data.into_inner().try_into()?; folder - .move_view(¶ms.item_id, params.from, params.to) + .move_view(¶ms.view_id, params.from, params.to) .await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-folder2/src/manager.rs b/frontend/rust-lib/flowy-folder2/src/manager.rs index 0d1e43d8ce..e813da919e 100644 --- a/frontend/rust-lib/flowy-folder2/src/manager.rs +++ b/frontend/rust-lib/flowy-folder2/src/manager.rs @@ -19,7 +19,7 @@ use lib_infra::util::timestamp; use crate::deps::{FolderCloudService, FolderUser}; use crate::entities::{ view_pb_with_child_views, CreateViewParams, CreateWorkspaceParams, DeletedViewPB, - RepeatedTrashPB, RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, ViewPB, + RepeatedTrashPB, RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, ViewPB, WorkspacePB, }; use crate::notification::{ send_notification, send_workspace_notification, send_workspace_setting_notification, @@ -61,11 +61,17 @@ impl Folder2Manager { Ok(manager) } - pub async fn get_current_workspace(&self) -> FlowyResult { - match self.with_folder(None, |folder| folder.get_current_workspace()) { - None => Err(FlowyError::record_not_found().context("Can not find the workspace")), - Some(workspace) => Ok(workspace), - } + pub async fn get_current_workspace(&self) -> FlowyResult { + self.with_folder(Err(FlowyError::internal()), |folder| { + match folder.get_current_workspace() { + None => Err(FlowyError::record_not_found().context("Can not find the workspace")), + Some(workspace) => { + let views = get_workspace_view_pbs(&workspace.id, folder); + let workspace: WorkspacePB = (workspace, views).into(); + Ok(workspace) + }, + } + }) } /// Return a list of views of the current workspace. @@ -307,18 +313,48 @@ impl Folder2Manager { Ok(()) } - /// Move the view from one position to another position. - #[tracing::instrument(level = "debug", skip(self), err)] + /// Move the view with given id from one position to another position. + /// The view will be moved to the new position in the same parent view. + /// The passed in index is the index of the view that displayed in the UI. + /// We need to convert the index to the real index of the view in the parent view. + #[tracing::instrument(level = "trace", skip(self), err)] pub async fn move_view(&self, view_id: &str, from: usize, to: usize) -> FlowyResult<()> { - let view = self.with_folder(None, |folder| { - folder.move_view(view_id, from as u32, to as u32) - }); + if let Some((is_workspace, parent_view_id, child_views)) = self.get_view_relation(view_id).await + { + // The display parent view is the view that is displayed in the UI + let display_views = if is_workspace { + self + .get_current_workspace() + .await? + .views + .into_iter() + .map(|view| view.id) + .collect::>() + } else { + self + .get_view(&parent_view_id) + .await? + .child_views + .into_iter() + .map(|view| view.id) + .collect::>() + }; - match view { - None => tracing::error!("Couldn't find the view. It should not be empty"), - Some(view) => { - notify_parent_view_did_change(self.mutex_folder.clone(), vec![view.parent_view_id]); - }, + if display_views.len() > to { + let to_view_id = display_views[to].clone(); + + // Find the actual index of the view in the parent view + let actual_from_index = child_views.iter().position(|id| id == view_id); + let actual_to_index = child_views.iter().position(|id| id == &to_view_id); + if let (Some(actual_from_index), Some(actual_to_index)) = + (actual_from_index, actual_to_index) + { + self.with_folder((), |folder| { + folder.move_view(view_id, actual_from_index as u32, actual_to_index as u32); + }); + notify_parent_view_did_change(self.mutex_folder.clone(), vec![parent_view_id]); + } + } } Ok(()) } @@ -516,6 +552,40 @@ impl Folder2Manager { Some(processor) => Ok(processor.clone()), } } + + /// Returns the relation of the view. The relation is a tuple of (is_workspace, parent_view_id, + /// child_view_ids). If the view is a workspace, then the parent_view_id is the workspace id. + /// Otherwise, the parent_view_id is the parent view id of the view. The child_view_ids is the + /// child view ids of the view. + async fn get_view_relation(&self, view_id: &str) -> Option<(bool, String, Vec)> { + self.with_folder(None, |folder| { + let view = folder.views.get_view(view_id)?; + match folder.views.get_view(&view.parent_view_id) { + None => folder.get_current_workspace().map(|workspace| { + ( + true, + workspace.id, + workspace + .child_views + .items + .into_iter() + .map(|view| view.id) + .collect::>(), + ) + }), + Some(parent_view) => Some(( + false, + parent_view.id, + parent_view + .children + .items + .into_iter() + .map(|view| view.id) + .collect::>(), + )), + } + }) + } } /// Listen on the [ViewChange] after create/delete/update events happened @@ -594,6 +664,7 @@ fn listen_on_trash_change(mut rx: TrashChangeReceiver, weak_mutex_folder: &Weak< }); } +/// Return the views that belong to the workspace. The views are filtered by the trash. fn get_workspace_view_pbs(workspace_id: &str, folder: &Folder) -> Vec { let trash_ids = folder .trash diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2023-06-05-135652_collab_snapshot/up.sql b/frontend/rust-lib/flowy-sqlite/migrations/2023-06-05-135652_collab_snapshot/up.sql index 4686e488dc..8396f5da26 100644 --- a/frontend/rust-lib/flowy-sqlite/migrations/2023-06-05-135652_collab_snapshot/up.sql +++ b/frontend/rust-lib/flowy-sqlite/migrations/2023-06-05-135652_collab_snapshot/up.sql @@ -2,7 +2,9 @@ CREATE TABLE collab_snapshot ( id TEXT NOT NULL PRIMARY KEY DEFAULT '', object_id TEXT NOT NULL DEFAULT '', + title TEXT NOT NULL DEFAULT '', desc TEXT NOT NULL DEFAULT '', + collab_type TEXT NOT NULL DEFAULT '', timestamp BIGINT NOT NULL DEFAULT 0, data BLOB NOT NULL DEFAULT (x'') ); \ No newline at end of file diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index 48ad76b484..6b4825744c 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -4,7 +4,9 @@ diesel::table! { collab_snapshot (id) { id -> Text, object_id -> Text, + title -> Text, desc -> Text, + collab_type -> Text, timestamp -> BigInt, data -> Binary, } diff --git a/frontend/rust-lib/flowy-test/src/lib.rs b/frontend/rust-lib/flowy-test/src/lib.rs index b7b75e5b6c..1ec00bbcc7 100644 --- a/frontend/rust-lib/flowy-test/src/lib.rs +++ b/frontend/rust-lib/flowy-test/src/lib.rs @@ -1,14 +1,18 @@ -use nanoid::nanoid; -use parking_lot::RwLock; use std::env::temp_dir; use std::sync::Arc; -use crate::event_builder::EventBuilder; +use nanoid::nanoid; +use parking_lot::RwLock; + use flowy_core::{AppFlowyCore, AppFlowyCoreConfig}; -use flowy_folder2::entities::{CreateViewPayloadPB, RepeatedViewIdPB, ViewPB, WorkspaceSettingPB}; +use flowy_folder2::entities::{ + CreateViewPayloadPB, RepeatedViewIdPB, ViewIdPB, ViewPB, WorkspaceSettingPB, +}; use flowy_user::entities::{AuthTypePB, UserProfilePB}; +use crate::event_builder::EventBuilder; use crate::user_event::{async_sign_up, init_user_setting, SignUpContext}; + pub mod event_builder; pub mod folder_event; pub mod user_event; @@ -68,6 +72,15 @@ impl FlowyCoreTest { .parse::() } + pub async fn get_all_workspace_views(&self) -> Vec { + EventBuilder::new(self.clone()) + .event(flowy_folder2::event_map::FolderEvent::ReadWorkspaceViews) + .async_send() + .await + .parse::() + .items + } + pub async fn delete_view(&self, view_id: &str) { let payload = RepeatedViewIdPB { items: vec![view_id.to_string()], @@ -99,6 +112,17 @@ impl FlowyCoreTest { .await .parse::() } + + pub async fn get_view(&self, view_id: &str) -> ViewPB { + EventBuilder::new(self.clone()) + .event(flowy_folder2::event_map::FolderEvent::ReadView) + .payload(ViewIdPB { + value: view_id.to_string(), + }) + .async_send() + .await + .parse::() + } } impl std::ops::Deref for FlowyCoreTest { diff --git a/frontend/rust-lib/flowy-test/tests/folder/test.rs b/frontend/rust-lib/flowy-test/tests/folder/test.rs index af15741fba..d2a987992d 100644 --- a/frontend/rust-lib/flowy-test/tests/folder/test.rs +++ b/frontend/rust-lib/flowy-test/tests/folder/test.rs @@ -240,13 +240,7 @@ async fn multiple_hierarchy_view_test() { } } - let mut views = EventBuilder::new(test.clone()) - .event(flowy_folder2::event_map::FolderEvent::ReadWorkspaceViews) - .async_send() - .await - .parse::() - .items; - + let mut views = test.get_all_workspace_views().await; // There will be one default view when AppFlowy is initialized. So there will be 4 views in total assert_eq!(views.len(), 4); views.remove(0); @@ -294,15 +288,7 @@ async fn multiple_hierarchy_view_test() { for (k, _child_view) in child_view.child_views.into_iter().enumerate() { // Get the last level view - let sub_child = EventBuilder::new(test.clone()) - .event(flowy_folder2::event_map::FolderEvent::ReadView) - .payload(ViewIdPB { - value: child.id.clone(), - }) - .async_send() - .await - .parse::(); - + let sub_child = test.get_view(&child.id).await; assert_eq!(child.name, format!("My {}-{}-{} view", i + 1, j + 1, k + 1)); assert!(sub_child.child_views.is_empty()); } @@ -324,13 +310,7 @@ async fn move_view_event_test() { .await; } } - let views = EventBuilder::new(test.clone()) - .event(flowy_folder2::event_map::FolderEvent::ReadWorkspaceViews) - .async_send() - .await - .parse::() - .items; - + let views = test.get_all_workspace_views().await; // There will be one default view when AppFlowy is initialized. So there will be 4 views in total assert_eq!(views.len(), 4); assert_eq!(views[1].name, "My 1 view"); @@ -348,18 +328,95 @@ async fn move_view_event_test() { .async_send() .await; - let views = EventBuilder::new(test.clone()) - .event(flowy_folder2::event_map::FolderEvent::ReadWorkspaceViews) - .async_send() - .await - .parse::() - .items; - + let views = test.get_all_workspace_views().await; assert_eq!(views[1].name, "My 2 view"); assert_eq!(views[2].name, "My 1 view"); assert_eq!(views[3].name, "My 3 view"); } +#[tokio::test] +async fn move_view_event_after_delete_view_test() { + let test = FlowyCoreTest::new_with_user().await; + let current_workspace = test.get_current_workspace().await.workspace; + for i in 1..6 { + let _ = test + .create_view(¤t_workspace.id, format!("My {} view", i)) + .await; + } + let views = test.get_all_workspace_views().await; + assert_eq!(views[1].name, "My 1 view"); + assert_eq!(views[2].name, "My 2 view"); + assert_eq!(views[3].name, "My 3 view"); + assert_eq!(views[4].name, "My 4 view"); + assert_eq!(views[5].name, "My 5 view"); + test.delete_view(&views[3].id).await; + + // There will be one default view when AppFlowy is initialized. So there will be 4 views in total + let views = test.get_all_workspace_views().await; + assert_eq!(views[1].name, "My 1 view"); + assert_eq!(views[2].name, "My 2 view"); + assert_eq!(views[3].name, "My 4 view"); + assert_eq!(views[4].name, "My 5 view"); + + let payload = MoveViewPayloadPB { + view_id: views[1].id.clone(), + from: 1, + to: 3, + }; + let _ = EventBuilder::new(test.clone()) + .event(flowy_folder2::event_map::FolderEvent::MoveView) + .payload(payload) + .async_send() + .await; + + let views = test.get_all_workspace_views().await; + assert_eq!(views[1].name, "My 2 view"); + assert_eq!(views[2].name, "My 4 view"); + assert_eq!(views[3].name, "My 1 view"); + assert_eq!(views[4].name, "My 5 view"); +} + +#[tokio::test] +async fn move_view_event_after_delete_view_test2() { + let test = FlowyCoreTest::new_with_user().await; + let current_workspace = test.get_current_workspace().await.workspace; + let parent = test + .create_view(¤t_workspace.id, "My view".to_string()) + .await; + + for j in 1..6 { + let _ = test + .create_view(&parent.id, format!("My 1-{} view", j)) + .await; + } + + let views = test.get_view(&parent.id).await.child_views; + assert_eq!(views.len(), 5); + assert_eq!(views[0].name, "My 1-1 view"); + assert_eq!(views[1].name, "My 1-2 view"); + assert_eq!(views[2].name, "My 1-3 view"); + assert_eq!(views[3].name, "My 1-4 view"); + assert_eq!(views[4].name, "My 1-5 view"); + test.delete_view(&views[2].id).await; + + let payload = MoveViewPayloadPB { + view_id: views[0].id.clone(), + from: 0, + to: 2, + }; + let _ = EventBuilder::new(test.clone()) + .event(flowy_folder2::event_map::FolderEvent::MoveView) + .payload(payload) + .async_send() + .await; + + let views = test.get_view(&parent.id).await.child_views; + assert_eq!(views[0].name, "My 1-2 view"); + assert_eq!(views[1].name, "My 1-4 view"); + assert_eq!(views[2].name, "My 1-1 view"); + assert_eq!(views[3].name, "My 1-5 view"); +} + #[tokio::test] async fn create_parent_view_with_invalid_name() { for (name, code) in invalid_workspace_name_test_case() {