feat: filter recent views not belong to current user (#5014)

* feat: filter recent views not belong to current user

* fix: filter the trash ids and other private view ids
This commit is contained in:
Lucas.Xu 2024-04-02 09:57:14 +08:00 committed by GitHub
parent 555649c535
commit 7576796e2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 90 additions and 45 deletions

View File

@ -31,14 +31,21 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
final isCollabWorkspaceOn = final isCollabWorkspaceOn =
userProfile.authenticator != AuthenticatorPB.Local && userProfile.authenticator != AuthenticatorPB.Local &&
FeatureFlag.collaborativeWorkspace.isOn; FeatureFlag.collaborativeWorkspace.isOn;
final currentWorkspace = result?.$1; final currentWorkspace = result.$1;
if (currentWorkspace != null && result?.$3 == true) { if (currentWorkspace != null && result.$3 == true) {
await _userService.openWorkspace(currentWorkspace.workspaceId); final result = await _userService
.openWorkspace(currentWorkspace.workspaceId);
result.onSuccess((s) async {
await getIt<KeyValueStorage>().set(
KVKeys.lastOpenedWorkspaceId,
currentWorkspace.workspaceId,
);
});
} }
emit( emit(
state.copyWith( state.copyWith(
currentWorkspace: currentWorkspace, currentWorkspace: currentWorkspace,
workspaces: result?.$2 ?? [], workspaces: result.$2,
isCollabWorkspaceOn: isCollabWorkspaceOn, isCollabWorkspaceOn: isCollabWorkspaceOn,
actionResult: null, actionResult: null,
), ),
@ -46,28 +53,12 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
}, },
fetchWorkspaces: () async { fetchWorkspaces: () async {
final result = await _fetchWorkspaces(); final result = await _fetchWorkspaces();
if (result != null) { emit(
emit( state.copyWith(
state.copyWith( currentWorkspace: result.$1,
currentWorkspace: result.$1, workspaces: result.$2,
workspaces: result.$2, ),
), );
);
} else {
emit(
state.copyWith(
actionResult: UserWorkspaceActionResult(
actionType: UserWorkspaceActionType.none,
result: FlowyResult.failure(
FlowyError(
code: ErrorCode.Internal,
msg: LocaleKeys.workspace_fetchWorkspacesFailed.tr(),
),
),
),
),
);
}
}, },
createWorkspace: (name) async { createWorkspace: (name) async {
final result = await _userService.createUserWorkspace(name); final result = await _userService.createUserWorkspace(name);
@ -256,10 +247,10 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
Future< Future<
( (
UserWorkspacePB currentWorkspace, UserWorkspacePB? currentWorkspace,
List<UserWorkspacePB> workspaces, List<UserWorkspacePB> workspaces,
bool shouldOpenWorkspace, bool shouldOpenWorkspace,
)?> _fetchWorkspaces() async { )> _fetchWorkspaces() async {
try { try {
final lastOpenedWorkspaceId = await getIt<KeyValueStorage>().get( final lastOpenedWorkspaceId = await getIt<KeyValueStorage>().get(
KVKeys.lastOpenedWorkspaceId, KVKeys.lastOpenedWorkspaceId,
@ -267,8 +258,8 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
final currentWorkspace = final currentWorkspace =
await _userService.getCurrentWorkspace().getOrThrow(); await _userService.getCurrentWorkspace().getOrThrow();
final workspaces = await _userService.getWorkspaces().getOrThrow(); final workspaces = await _userService.getWorkspaces().getOrThrow();
UserWorkspacePB currentWorkspaceInList = UserWorkspacePB? currentWorkspaceInList = workspaces
workspaces.firstWhere((e) => e.workspaceId == currentWorkspace.id); .firstWhereOrNull((e) => e.workspaceId == currentWorkspace.id);
if (lastOpenedWorkspaceId != null) { if (lastOpenedWorkspaceId != null) {
final lastOpenedWorkspace = workspaces final lastOpenedWorkspace = workspaces
.firstWhereOrNull((e) => e.workspaceId == lastOpenedWorkspaceId); .firstWhereOrNull((e) => e.workspaceId == lastOpenedWorkspaceId);
@ -276,6 +267,7 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
currentWorkspaceInList = lastOpenedWorkspace; currentWorkspaceInList = lastOpenedWorkspace;
} }
} }
currentWorkspaceInList ??= workspaces.first;
return ( return (
currentWorkspaceInList, currentWorkspaceInList,
workspaces, workspaces,
@ -283,7 +275,7 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
); );
} catch (e) { } catch (e) {
Log.error('fetch workspace error: $e'); Log.error('fetch workspace error: $e');
return null; return (null, <UserWorkspacePB>[], false);
} }
} }
} }

View File

@ -273,7 +273,7 @@ pub(crate) async fn read_recent_views_handler(
folder: AFPluginState<Weak<FolderManager>>, folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<RepeatedViewPB, FlowyError> { ) -> DataResult<RepeatedViewPB, FlowyError> {
let folder = upgrade_folder(folder)?; 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![]; let mut views = vec![];
for item in recent_items { for item in recent_items {
if let Ok(view) = folder.get_view_pb(&item.id).await { if let Ok(view) = folder.get_view_pb(&item.id).await {

View File

@ -866,7 +866,7 @@ impl FolderManager {
} }
async fn send_update_recent_views_notification(&self) { 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) send_notification("recent_views", FolderNotification::DidUpdateRecentViews)
.payload(RepeatedViewIdPB { .payload(RepeatedViewIdPB {
items: recent_views.into_iter().map(|item| item.id).collect(), items: recent_views.into_iter().map(|item| item.id).collect(),
@ -879,8 +879,8 @@ impl FolderManager {
self.get_sections(Section::Favorite) self.get_sections(Section::Favorite)
} }
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
pub(crate) async fn get_all_recent_sections(&self) -> Vec<SectionItem> { pub(crate) async fn get_my_recent_sections(&self) -> Vec<SectionItem> {
self.get_sections(Section::Recent) 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<SectionItem> { fn get_sections(&self, section_type: Section) -> Vec<SectionItem> {
self.with_folder(Vec::new, |folder| { self.with_folder(Vec::new, |folder| {
let trash_ids = folder let views = match section_type {
.get_all_trash_sections()
.into_iter()
.map(|trash| trash.id)
.collect::<Vec<String>>();
let mut views = match section_type {
Section::Favorite => folder.get_my_favorite_sections(), Section::Favorite => folder.get_my_favorite_sections(),
Section::Recent => folder.get_my_recent_sections(), Section::Recent => folder.get_my_recent_sections(),
_ => vec![], _ => vec![],
}; };
let view_ids_should_be_filtered = self.get_view_ids_should_be_filtered(folder);
// filter the views that are in the trash
views.retain(|view| !trash_ids.contains(&view.id));
views 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<String> {
let trash_ids = folder
.get_all_trash_sections()
.into_iter()
.map(|trash| trash.id)
.collect::<Vec<String>>();
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<String> {
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<String> {
let my_private_view_ids = folder
.get_my_private_sections()
.into_iter()
.map(|view| view.id)
.collect::<Vec<String>>();
let all_private_view_ids = folder
.get_all_private_sections()
.into_iter()
.map(|view| view.id)
.collect::<Vec<String>>();
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. /// 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() .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<String> {
let child_view_ids = folder
.views
.get_views_belong_to(view_id)
.into_iter()
.map(|view| view.id.clone())
.collect::<Vec<String>>();
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. /// Get the current private views of the user.
pub(crate) fn get_workspace_private_view_pbs(_workspace_id: &str, folder: &Folder) -> Vec<ViewPB> { pub(crate) fn get_workspace_private_view_pbs(_workspace_id: &str, folder: &Folder) -> Vec<ViewPB> {
// get the trash ids // get the trash ids