feat: open the duplicated space by default (#5638)

This commit is contained in:
Lucas.Xu 2024-06-27 14:12:52 +08:00 committed by GitHub
parent ecc5555a4e
commit 605a53f2ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 75 additions and 8 deletions

View File

@ -297,12 +297,11 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
if (currentSpace == null) { if (currentSpace == null) {
return; return;
} }
await ViewBackendService.duplicate( final newSpace = await _duplicateSpace(currentSpace);
view: currentSpace, // open the duplicated space
openAfterDuplicate: false, if (newSpace != null) {
includeChildren: true, add(SpaceEvent.open(newSpace));
); }
add(const SpaceEvent.didReceiveSpaceUpdate());
}, },
); );
}, },
@ -602,6 +601,40 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
return false; return false;
} }
Future<ViewPB?> _duplicateSpace(ViewPB space) async {
// if the space is not duplicated, try to create a new space
final icon = space.icon.value.isNotEmpty
? space.icon.value
: builtInSpaceIcons.first;
final iconColor = space.spaceIconColor ?? builtInSpaceColors.first;
final newSpace = await _createSpace(
name: '${space.name} (copy)',
icon: icon,
iconColor: iconColor,
permission: space.spacePermission,
);
if (newSpace == null) {
return null;
}
for (final view in space.childViews) {
unawaited(
ViewBackendService.duplicate(
view: view,
openAfterDuplicate: true,
includeChildren: true,
parentViewId: newSpace.id,
suffix: '',
),
);
}
Log.info('Space duplicated: $newSpace');
add(const SpaceEvent.didReceiveSpaceUpdate());
return newSpace;
}
} }
@freezed @freezed

View File

@ -141,11 +141,22 @@ class ViewBackendService {
required bool openAfterDuplicate, required bool openAfterDuplicate,
// should include children views // should include children views
required bool includeChildren, required bool includeChildren,
String? parentViewId,
String? suffix,
}) { }) {
final payload = DuplicateViewPayloadPB.create() final payload = DuplicateViewPayloadPB.create()
..viewId = view.id ..viewId = view.id
..openAfterDuplicate = openAfterDuplicate ..openAfterDuplicate = openAfterDuplicate
..includeChildren = includeChildren; ..includeChildren = includeChildren;
if (parentViewId != null) {
payload.parentViewId = parentViewId;
}
if (suffix != null) {
payload.suffix = suffix;
}
return FolderEventDuplicateView(payload).send(); return FolderEventDuplicateView(payload).send();
} }

View File

@ -584,6 +584,16 @@ pub struct DuplicateViewPayloadPB {
#[pb(index = 3)] #[pb(index = 3)]
pub include_children: bool, pub include_children: bool,
// duplicate the view to the specified parent view.
// if the parent_view_id is None, the view will be duplicated to the same parent view.
#[pb(index = 4, one_of)]
pub parent_view_id: Option<String>,
// The suffix of the duplicated view name.
// If the suffix is None, the duplicated view will have the same name with (copy) suffix.
#[pb(index = 5, one_of)]
pub suffix: Option<String>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -593,6 +603,10 @@ pub struct DuplicateViewParams {
pub open_after_duplicate: bool, pub open_after_duplicate: bool,
pub include_children: bool, pub include_children: bool,
pub parent_view_id: Option<String>,
pub suffix: Option<String>,
} }
impl TryInto<DuplicateViewParams> for DuplicateViewPayloadPB { impl TryInto<DuplicateViewParams> for DuplicateViewPayloadPB {
@ -604,6 +618,8 @@ impl TryInto<DuplicateViewParams> for DuplicateViewPayloadPB {
view_id, view_id,
open_after_duplicate: self.open_after_duplicate, open_after_duplicate: self.open_after_duplicate,
include_children: self.include_children, include_children: self.include_children,
parent_view_id: self.parent_view_id,
suffix: self.suffix,
}) })
} }
} }

View File

@ -741,12 +741,17 @@ impl FolderManager {
let view = self let view = self
.with_folder(|| None, |folder| folder.views.get_view(&params.view_id)) .with_folder(|| None, |folder| folder.views.get_view(&params.view_id))
.ok_or_else(|| FlowyError::record_not_found().with_context("Can't duplicate the view"))?; .ok_or_else(|| FlowyError::record_not_found().with_context("Can't duplicate the view"))?;
let parent_view_id = params
.parent_view_id
.clone()
.unwrap_or(view.parent_view_id.clone());
self self
.duplicate_view_with_parent_id( .duplicate_view_with_parent_id(
&view.id, &view.id,
&view.parent_view_id, &parent_view_id,
params.open_after_duplicate, params.open_after_duplicate,
params.include_children, params.include_children,
params.suffix,
) )
.await .await
} }
@ -761,6 +766,7 @@ impl FolderManager {
parent_view_id: &str, parent_view_id: &str,
open_after_duplicated: bool, open_after_duplicated: bool,
include_children: bool, include_children: bool,
suffix: Option<String>,
) -> Result<(), FlowyError> { ) -> Result<(), FlowyError> {
if view_id == parent_view_id { if view_id == parent_view_id {
return Err(FlowyError::new( return Err(FlowyError::new(
@ -777,6 +783,7 @@ impl FolderManager {
let mut is_source_view = true; let mut is_source_view = true;
// use a stack to duplicate the view and its children // use a stack to duplicate the view and its children
let mut stack = vec![(view_id.to_string(), parent_view_id.to_string())]; let mut stack = vec![(view_id.to_string(), parent_view_id.to_string())];
let suffix = suffix.unwrap_or(" (copy)".to_string());
while let Some((current_view_id, current_parent_id)) = stack.pop() { while let Some((current_view_id, current_parent_id)) = stack.pop() {
let view = self let view = self
@ -812,7 +819,7 @@ impl FolderManager {
); );
let name = if is_source_view { let name = if is_source_view {
format!("{} (copy)", &view.name) format!("{}{}", &view.name, suffix)
} else { } else {
view.name.clone() view.name.clone()
}; };