diff --git a/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx b/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx index 54e328af97..983b120555 100644 --- a/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx +++ b/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx @@ -31,10 +31,11 @@ const usePageOperationsRenderer = () => { const { setTrashModal } = useTrashModalHelper( currentWorkspace.blockSuiteWorkspace ); - const { toggleFavorite } = useBlockSuiteMetaHelper( + const { toggleFavorite, duplicate } = useBlockSuiteMetaHelper( currentWorkspace.blockSuiteWorkspace ); const t = useAFFiNEI18N(); + const pageOperationsRenderer = useCallback( (page: PageMeta) => { const onDisablePublicSharing = () => { @@ -42,12 +43,16 @@ const usePageOperationsRenderer = () => { portal: document.body, }); }; + return ( { + duplicate(page.id, false); + }} onRemoveToTrash={() => setTrashModal({ open: true, @@ -67,7 +72,7 @@ const usePageOperationsRenderer = () => { /> ); }, - [currentWorkspace.id, setTrashModal, t, toggleFavorite] + [currentWorkspace.id, setTrashModal, t, toggleFavorite, duplicate] ); return pageOperationsRenderer; diff --git a/packages/frontend/core/src/components/page-list/operation-cell.tsx b/packages/frontend/core/src/components/page-list/operation-cell.tsx index 58a6f32e37..cc63d2c0a4 100644 --- a/packages/frontend/core/src/components/page-list/operation-cell.tsx +++ b/packages/frontend/core/src/components/page-list/operation-cell.tsx @@ -11,6 +11,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { DeleteIcon, DeletePermanentlyIcon, + DuplicateIcon, EditIcon, FavoritedIcon, FavoriteIcon, @@ -39,6 +40,7 @@ export interface PageOperationCellProps { link: string; onToggleFavoritePage: () => void; onRemoveToTrash: () => void; + onDuplicate: () => void; onDisablePublicSharing: () => void; } @@ -48,6 +50,7 @@ export const PageOperationCell = ({ link, onToggleFavoritePage, onRemoveToTrash, + onDuplicate, onDisablePublicSharing, }: PageOperationCellProps) => { const t = useAFFiNEI18N(); @@ -98,6 +101,18 @@ export const PageOperationCell = ({ )} + + + + + } + onSelect={onDuplicate} + > + {t['com.affine.header.option.duplicate']()} + + ); diff --git a/packages/frontend/core/src/hooks/affine/use-block-suite-meta-helper.ts b/packages/frontend/core/src/hooks/affine/use-block-suite-meta-helper.ts index c5cfbcb4ed..b96c69282e 100644 --- a/packages/frontend/core/src/hooks/affine/use-block-suite-meta-helper.ts +++ b/packages/frontend/core/src/hooks/affine/use-block-suite-meta-helper.ts @@ -149,7 +149,7 @@ export function useBlockSuiteMetaHelper( ); const duplicate = useAsyncCallback( - async (pageId: string) => { + async (pageId: string, openPageAfterDuplication: boolean = true) => { const currentPageMeta = getPageMeta(pageId); const newPage = createPage(); const currentPage = blockSuiteWorkspace.getPage(pageId); @@ -166,9 +166,18 @@ export function useBlockSuiteMetaHelper( tags: currentPageMeta.tags, favorite: currentPageMeta.favorite, }); + + const lastDigitRegex = /\((\d+)\)$/; + const match = currentPageMeta.title.match(lastDigitRegex); + const newNumber = match ? parseInt(match[1], 10) + 1 : 1; + + const newPageTitle = + currentPageMeta.title.replace(lastDigitRegex, '') + `(${newNumber})`; + setPageMode(newPage.id, currentMode); - setPageTitle(newPage.id, `${currentPageMeta.title}(1)`); - openPage(blockSuiteWorkspace.id, newPage.id); + setPageTitle(newPage.id, newPageTitle); + + openPageAfterDuplication && openPage(blockSuiteWorkspace.id, newPage.id); }, [ blockSuiteWorkspace, diff --git a/packages/frontend/core/src/pages/workspace/trash-page.tsx b/packages/frontend/core/src/pages/workspace/trash-page.tsx index 5a4baeb602..511c65ac76 100644 --- a/packages/frontend/core/src/pages/workspace/trash-page.tsx +++ b/packages/frontend/core/src/pages/workspace/trash-page.tsx @@ -92,6 +92,7 @@ export const TrashPage = () => { permanentlyDeletePage(page.id); toast(t['com.affine.toastMessage.permanentlyDeleted']()); }; + return (