diff --git a/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart index 8d0ecbf4b1..742b928c72 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart @@ -31,14 +31,21 @@ class UserWorkspaceBloc extends Bloc { final isCollabWorkspaceOn = userProfile.authenticator != AuthenticatorPB.Local && FeatureFlag.collaborativeWorkspace.isOn; - final currentWorkspace = result?.$1; - if (currentWorkspace != null && result?.$3 == true) { - await _userService.openWorkspace(currentWorkspace.workspaceId); + final currentWorkspace = result.$1; + if (currentWorkspace != null && result.$3 == true) { + final result = await _userService + .openWorkspace(currentWorkspace.workspaceId); + result.onSuccess((s) async { + await getIt().set( + KVKeys.lastOpenedWorkspaceId, + currentWorkspace.workspaceId, + ); + }); } emit( state.copyWith( currentWorkspace: currentWorkspace, - workspaces: result?.$2 ?? [], + workspaces: result.$2, isCollabWorkspaceOn: isCollabWorkspaceOn, actionResult: null, ), @@ -46,28 +53,12 @@ class UserWorkspaceBloc extends Bloc { }, fetchWorkspaces: () async { final result = await _fetchWorkspaces(); - if (result != null) { - emit( - state.copyWith( - currentWorkspace: result.$1, - workspaces: result.$2, - ), - ); - } else { - emit( - state.copyWith( - actionResult: UserWorkspaceActionResult( - actionType: UserWorkspaceActionType.none, - result: FlowyResult.failure( - FlowyError( - code: ErrorCode.Internal, - msg: LocaleKeys.workspace_fetchWorkspacesFailed.tr(), - ), - ), - ), - ), - ); - } + emit( + state.copyWith( + currentWorkspace: result.$1, + workspaces: result.$2, + ), + ); }, createWorkspace: (name) async { final result = await _userService.createUserWorkspace(name); @@ -256,10 +247,10 @@ class UserWorkspaceBloc extends Bloc { Future< ( - UserWorkspacePB currentWorkspace, + UserWorkspacePB? currentWorkspace, List workspaces, bool shouldOpenWorkspace, - )?> _fetchWorkspaces() async { + )> _fetchWorkspaces() async { try { final lastOpenedWorkspaceId = await getIt().get( KVKeys.lastOpenedWorkspaceId, @@ -267,8 +258,8 @@ class UserWorkspaceBloc extends Bloc { final currentWorkspace = await _userService.getCurrentWorkspace().getOrThrow(); final workspaces = await _userService.getWorkspaces().getOrThrow(); - UserWorkspacePB currentWorkspaceInList = - workspaces.firstWhere((e) => e.workspaceId == currentWorkspace.id); + UserWorkspacePB? currentWorkspaceInList = workspaces + .firstWhereOrNull((e) => e.workspaceId == currentWorkspace.id); if (lastOpenedWorkspaceId != null) { final lastOpenedWorkspace = workspaces .firstWhereOrNull((e) => e.workspaceId == lastOpenedWorkspaceId); @@ -276,6 +267,7 @@ class UserWorkspaceBloc extends Bloc { currentWorkspaceInList = lastOpenedWorkspace; } } + currentWorkspaceInList ??= workspaces.first; return ( currentWorkspaceInList, workspaces, @@ -283,7 +275,7 @@ class UserWorkspaceBloc extends Bloc { ); } catch (e) { Log.error('fetch workspace error: $e'); - return null; + return (null, [], false); } } } diff --git a/frontend/rust-lib/flowy-folder/src/event_handler.rs b/frontend/rust-lib/flowy-folder/src/event_handler.rs index 825a488f68..92d0c753aa 100644 --- a/frontend/rust-lib/flowy-folder/src/event_handler.rs +++ b/frontend/rust-lib/flowy-folder/src/event_handler.rs @@ -273,7 +273,7 @@ pub(crate) async fn read_recent_views_handler( folder: AFPluginState>, ) -> DataResult { let folder = upgrade_folder(folder)?; - let recent_items = folder.get_all_recent_sections().await; + let recent_items = folder.get_my_recent_sections().await; let mut views = vec![]; for item in recent_items { if let Ok(view) = folder.get_view_pb(&item.id).await { diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index 8ea4d3d06b..42cc4467e6 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -866,7 +866,7 @@ impl FolderManager { } async fn send_update_recent_views_notification(&self) { - let recent_views = self.get_all_recent_sections().await; + let recent_views = self.get_my_recent_sections().await; send_notification("recent_views", FolderNotification::DidUpdateRecentViews) .payload(RepeatedViewIdPB { items: recent_views.into_iter().map(|item| item.id).collect(), @@ -879,8 +879,8 @@ impl FolderManager { self.get_sections(Section::Favorite) } - #[tracing::instrument(level = "trace", skip(self))] - pub(crate) async fn get_all_recent_sections(&self) -> Vec { + #[tracing::instrument(level = "debug", skip(self))] + pub(crate) async fn get_my_recent_sections(&self) -> Vec { self.get_sections(Section::Recent) } @@ -1133,25 +1133,63 @@ impl FolderManager { ); } + /// Only support getting the Favorite and Recent sections. fn get_sections(&self, section_type: Section) -> Vec { self.with_folder(Vec::new, |folder| { - let trash_ids = folder - .get_all_trash_sections() - .into_iter() - .map(|trash| trash.id) - .collect::>(); - - let mut views = match section_type { + let views = match section_type { Section::Favorite => folder.get_my_favorite_sections(), Section::Recent => folder.get_my_recent_sections(), _ => vec![], }; - - // filter the views that are in the trash - views.retain(|view| !trash_ids.contains(&view.id)); + let view_ids_should_be_filtered = self.get_view_ids_should_be_filtered(folder); views + .into_iter() + .filter(|view| !view_ids_should_be_filtered.contains(&view.id)) + .collect() }) } + + /// Get all the view that are in the trash, including the child views of the child views. + /// For example, if A view which is in the trash has a child view B, this function will return + /// both A and B. + fn get_all_trash_ids(&self, folder: &Folder) -> Vec { + let trash_ids = folder + .get_all_trash_sections() + .into_iter() + .map(|trash| trash.id) + .collect::>(); + let mut all_trash_ids = trash_ids.clone(); + for trash_id in trash_ids { + all_trash_ids.extend(get_all_child_view_ids(folder, &trash_id)); + } + all_trash_ids + } + + /// Filter the views that are in the trash and belong to the other private sections. + fn get_view_ids_should_be_filtered(&self, folder: &Folder) -> Vec { + let trash_ids = self.get_all_trash_ids(folder); + let other_private_view_ids = self.get_other_private_view_ids(folder); + [trash_ids, other_private_view_ids].concat() + } + + fn get_other_private_view_ids(&self, folder: &Folder) -> Vec { + let my_private_view_ids = folder + .get_my_private_sections() + .into_iter() + .map(|view| view.id) + .collect::>(); + + let all_private_view_ids = folder + .get_all_private_sections() + .into_iter() + .map(|view| view.id) + .collect::>(); + + all_private_view_ids + .into_iter() + .filter(|id| !my_private_view_ids.contains(id)) + .collect() + } } /// Return the views that belong to the workspace. The views are filtered by the trash and all the private views. @@ -1189,6 +1227,21 @@ pub(crate) fn get_workspace_public_view_pbs(_workspace_id: &str, folder: &Folder .collect() } +/// Get all the child views belong to the view id, including the child views of the child views. +fn get_all_child_view_ids(folder: &Folder, view_id: &str) -> Vec { + let child_view_ids = folder + .views + .get_views_belong_to(view_id) + .into_iter() + .map(|view| view.id.clone()) + .collect::>(); + let mut all_child_view_ids = child_view_ids.clone(); + for child_view_id in child_view_ids { + all_child_view_ids.extend(get_all_child_view_ids(folder, &child_view_id)); + } + all_child_view_ids +} + /// Get the current private views of the user. pub(crate) fn get_workspace_private_view_pbs(_workspace_id: &str, folder: &Folder) -> Vec { // get the trash ids