From 092c639b0a8a05d5a13315e5721d902c0bc75e82 Mon Sep 17 00:00:00 2001 From: EYHN Date: Wed, 26 Jun 2024 07:37:25 +0000 Subject: [PATCH] fix(core): optimize performance when editing doc title (#7328) --- .../infra/src/modules/doc/entities/doc.ts | 9 ++ .../infra/src/modules/doc/entities/record.ts | 9 ++ .../virtualized-collection-list.tsx | 9 +- .../page-list/docs/page-list-header.tsx | 5 +- .../page-list/docs/virtualized-page-list.tsx | 8 +- .../components/page-list/operation-cell.tsx | 8 +- .../page-list/view/collection-list.tsx | 28 +--- .../page-list/view/collection-operations.tsx | 5 +- .../view/edit-collection/edit-collection.tsx | 13 +- .../page-list/view/use-edit-collection.tsx | 8 +- .../collections/collections-list.tsx | 124 +++++++++++------- .../collections/styles.css.ts | 7 + .../hooks/affine/use-all-page-list-config.tsx | 3 + ...se-register-blocksuite-editor-commands.tsx | 32 ++--- .../pages/workspace/all-collection/index.tsx | 3 - .../src/pages/workspace/collection/index.tsx | 7 +- 16 files changed, 136 insertions(+), 142 deletions(-) diff --git a/packages/common/infra/src/modules/doc/entities/doc.ts b/packages/common/infra/src/modules/doc/entities/doc.ts index 97a36af65e..b7309be812 100644 --- a/packages/common/infra/src/modules/doc/entities/doc.ts +++ b/packages/common/infra/src/modules/doc/entities/doc.ts @@ -17,6 +17,7 @@ export class Doc extends Entity { readonly meta$ = this.record.meta$; readonly mode$ = this.record.mode$; readonly title$ = this.record.title$; + readonly trash$ = this.record.trash$; setMode(mode: DocMode) { return this.record.setMode(mode); @@ -33,4 +34,12 @@ export class Doc extends Entity { observeMode() { return this.record.observeMode(); } + + moveToTrash() { + return this.record.moveToTrash(); + } + + restoreFromTrash() { + return this.record.restoreFromTrash(); + } } diff --git a/packages/common/infra/src/modules/doc/entities/record.ts b/packages/common/infra/src/modules/doc/entities/record.ts index a5c97b7913..7a1e72e233 100644 --- a/packages/common/infra/src/modules/doc/entities/record.ts +++ b/packages/common/infra/src/modules/doc/entities/record.ts @@ -50,5 +50,14 @@ export class DocRecord extends Entity<{ id: string }> { return this.docsStore.watchDocModeSetting(this.id); } + moveToTrash() { + return this.setMeta({ trash: true }); + } + + restoreFromTrash() { + return this.setMeta({ trash: false }); + } + title$ = this.meta$.map(meta => meta.title ?? ''); + trash$ = this.meta$.map(meta => meta.trash ?? false); } diff --git a/packages/frontend/core/src/components/page-list/collections/virtualized-collection-list.tsx b/packages/frontend/core/src/components/page-list/collections/virtualized-collection-list.tsx index 32c0e9fe8b..d559199851 100644 --- a/packages/frontend/core/src/components/page-list/collections/virtualized-collection-list.tsx +++ b/packages/frontend/core/src/components/page-list/collections/virtualized-collection-list.tsx @@ -12,17 +12,14 @@ import { CollectionOperationCell } from '../operation-cell'; import { CollectionListItemRenderer } from '../page-group'; import { ListTableHeader } from '../page-header'; import type { CollectionMeta, ItemListHandle, ListItem } from '../types'; -import type { AllPageListConfig } from '../view'; import { VirtualizedList } from '../virtualized-list'; import { CollectionListHeader } from './collection-list-header'; const useCollectionOperationsRenderer = ({ info, service, - config, }: { info: DeleteCollectionInfo; - config: AllPageListConfig; service: CollectionService; }) => { const collectionOperationsRenderer = useCallback( @@ -32,11 +29,10 @@ const useCollectionOperationsRenderer = ({ info={info} collection={collection} service={service} - config={config} /> ); }, - [config, info, service] + [info, service] ); return collectionOperationsRenderer; @@ -48,11 +44,9 @@ export const VirtualizedCollectionList = ({ setHideHeaderCreateNewCollection, node, handleCreateCollection, - config, }: { collections: Collection[]; collectionMetas: CollectionMeta[]; - config: AllPageListConfig; node: ReactElement | null; handleCreateCollection: () => void; setHideHeaderCreateNewCollection: (hide: boolean) => void; @@ -69,7 +63,6 @@ export const VirtualizedCollectionList = ({ const collectionOperations = useCollectionOperationsRenderer({ info, service: collectionService, - config, }); const filteredSelectedCollectionIds = useMemo(() => { diff --git a/packages/frontend/core/src/components/page-list/docs/page-list-header.tsx b/packages/frontend/core/src/components/page-list/docs/page-list-header.tsx index 1961798a93..e42bd3382c 100644 --- a/packages/frontend/core/src/components/page-list/docs/page-list-header.tsx +++ b/packages/frontend/core/src/components/page-list/docs/page-list-header.tsx @@ -28,7 +28,6 @@ import { CollectionService } from '../../../modules/collection'; import { usePageHelper } from '../../blocksuite/block-suite-page-list/utils'; import { createTagFilter } from '../filter/utils'; import { createEmptyCollection } from '../use-collection-manager'; -import type { AllPageListConfig } from '../view/edit-collection/edit-collection'; import { useEditCollection, useEditCollectionName, @@ -87,9 +86,7 @@ export const PageListHeader = () => { export const CollectionPageListHeader = ({ collection, workspaceId, - config, }: { - config: AllPageListConfig; collection: Collection; workspaceId: string; }) => { @@ -101,7 +98,7 @@ export const CollectionPageListHeader = ({ }, [jumpToCollections, workspaceId]); const collectionService = useService(CollectionService); - const { node, open } = useEditCollection(config); + const { node, open } = useEditCollection(); const handleEdit = useAsyncCallback(async () => { const ret = await open({ ...collection }, 'page'); 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 8330f2179c..9a04b7fd94 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 @@ -18,7 +18,6 @@ import { PageListItemRenderer } from '../page-group'; import { ListTableHeader } from '../page-header'; import type { ItemListHandle, ListItem } from '../types'; import { useFilteredPageMetas } from '../use-filtered-page-metas'; -import type { AllPageListConfig } from '../view/edit-collection/edit-collection'; import { VirtualizedList } from '../virtualized-list'; import { CollectionPageListHeader, @@ -55,14 +54,12 @@ export const VirtualizedPageList = ({ tag, collection, filters, - config, listItem, setHideHeaderCreateNewPage, }: { tag?: Tag; collection?: Collection; filters?: Filter[]; - config?: AllPageListConfig; listItem?: DocMeta[]; setHideHeaderCreateNewPage?: (hide: boolean) => void; }) => { @@ -116,17 +113,16 @@ export const VirtualizedPageList = ({ if (tag) { return ; } - if (collection && config) { + if (collection) { return ( ); } return ; - }, [collection, config, currentWorkspace.id, tag]); + }, [collection, currentWorkspace.id, tag]); const { setTrashModal } = useTrashModalHelper(currentWorkspace.docCollection); 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 7d8e09cbd0..4b05d809a1 100644 --- a/packages/frontend/core/src/components/page-list/operation-cell.tsx +++ b/packages/frontend/core/src/components/page-list/operation-cell.tsx @@ -43,7 +43,6 @@ import { DisablePublicSharing, MoveToTrash } from './operation-menu-items'; import { CreateOrEditTag } from './tags/create-tag'; import type { TagMeta } from './types'; import { ColWrapper, stopPropagationWithoutPrevent } from './utils'; -import type { AllPageListConfig } from './view'; import { useEditCollection, useEditCollectionName } from './view'; export interface PageOperationCellProps { @@ -282,27 +281,26 @@ export const TrashOperationCell = ({ export interface CollectionOperationCellProps { collection: Collection; info: DeleteCollectionInfo; - config: AllPageListConfig; service: CollectionService; } export const CollectionOperationCell = ({ collection, - config, service, info, }: CollectionOperationCellProps) => { const t = useI18n(); const favAdapter = useService(FavoriteItemsAdapter); - const { createPage } = usePageHelper(config.docCollection); + const docCollection = useService(WorkspaceService).workspace.docCollection; + const { createPage } = usePageHelper(docCollection); const { openConfirmModal } = useConfirmModal(); const favourite = useLiveData( favAdapter.isFavorite$(collection.id, 'collection') ); const { open: openEditCollectionModal, node: editModal } = - useEditCollection(config); + useEditCollection(); const { open: openEditCollectionNameModal, node: editNameModal } = useEditCollectionName({ diff --git a/packages/frontend/core/src/components/page-list/view/collection-list.tsx b/packages/frontend/core/src/components/page-list/view/collection-list.tsx index 5e72001acf..8f7916b15a 100644 --- a/packages/frontend/core/src/components/page-list/view/collection-list.tsx +++ b/packages/frontend/core/src/components/page-list/view/collection-list.tsx @@ -1,36 +1,10 @@ import { Button, FlexWrapper, Menu } from '@affine/component'; -import type { Collection, Filter, PropertiesMeta } from '@affine/env/filter'; +import type { Filter, PropertiesMeta } from '@affine/env/filter'; import { useI18n } from '@affine/i18n'; import { FilterIcon } from '@blocksuite/icons/rc'; import { CreateFilterMenu } from '../filter/vars'; import * as styles from './collection-list.css'; -import { CollectionOperations } from './collection-operations'; -import type { AllPageListConfig } from './edit-collection/edit-collection'; - -export const CollectionPageListOperationsMenu = ({ - collection, - allPageListConfig, -}: { - collection: Collection; - allPageListConfig: AllPageListConfig; -}) => { - const t = useI18n(); - return ( - - - - - - ); -}; export const AllPageListOperationsMenu = ({ propertiesMeta, diff --git a/packages/frontend/core/src/components/page-list/view/collection-operations.tsx b/packages/frontend/core/src/components/page-list/view/collection-operations.tsx index 07ab1d7125..5a6707ab73 100644 --- a/packages/frontend/core/src/components/page-list/view/collection-operations.tsx +++ b/packages/frontend/core/src/components/page-list/view/collection-operations.tsx @@ -21,7 +21,6 @@ import { useCallback, useMemo } from 'react'; import { CollectionService } from '../../../modules/collection'; import * as styles from './collection-operations.css'; -import type { AllPageListConfig } from './index'; import { useEditCollection, useEditCollectionName, @@ -29,13 +28,11 @@ import { export const CollectionOperations = ({ collection, - config, openRenameModal, onAddDocToCollection, children, }: PropsWithChildren<{ collection: Collection; - config: AllPageListConfig; openRenameModal?: () => void; onAddDocToCollection?: () => void; }>) => { @@ -44,7 +41,7 @@ export const CollectionOperations = ({ const service = useService(CollectionService); const workbench = useService(WorkbenchService).workbench; const { open: openEditCollectionModal, node: editModal } = - useEditCollection(config); + useEditCollection(); const t = useI18n(); const { open: openEditCollectionNameModal, node: editNameModal } = useEditCollectionName({ diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx index 3597203225..edac81983a 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx @@ -4,6 +4,7 @@ import { RadioButton, RadioButtonGroup, } from '@affine/component'; +import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config'; import type { Collection } from '@affine/env/filter'; import { useI18n } from '@affine/i18n'; import type { DocCollection, DocMeta } from '@blocksuite/store'; @@ -24,7 +25,6 @@ export interface EditCollectionModalProps { mode?: EditCollectionMode; onOpenChange: (open: boolean) => void; onConfirm: (view: Collection) => void; - allPageListConfig: AllPageListConfig; } const contentOptions: DialogContentProps = { @@ -44,7 +44,6 @@ export const EditCollectionModal = ({ onOpenChange, title, mode, - allPageListConfig, }: EditCollectionModalProps) => { const t = useI18n(); const onConfirmOnCollection = useCallback( @@ -67,7 +66,7 @@ export const EditCollectionModal = ({ height="80%" contentOptions={contentOptions} > - {init ? ( + {open && init ? ( ) : null} @@ -89,7 +87,6 @@ export interface EditCollectionProps { mode?: EditCollectionMode; onCancel: () => void; onConfirm: (collection: Collection) => void; - allPageListConfig: AllPageListConfig; } export const EditCollection = ({ @@ -98,9 +95,9 @@ export const EditCollection = ({ onCancel, onConfirmText, mode: initMode, - allPageListConfig, }: EditCollectionProps) => { const t = useI18n(); + const config = useAllPageListConfig(); const [value, onChange] = useState(init); const [mode, setMode] = useState<'page' | 'rule'>( initMode ?? (init.filterList.length === 0 ? 'page' : 'rule') @@ -182,11 +179,11 @@ export const EditCollection = ({ updateCollection={onChange} switchMode={switchMode} buttons={buttons} - allPageListConfig={allPageListConfig} + allPageListConfig={config} > ) : ( { +export const useEditCollection = () => { const [data, setData] = useState<{ collection: Collection; mode?: 'page' | 'rule'; @@ -19,7 +16,6 @@ export const useEditCollection = (config: AllPageListConfig) => { return { node: data ? ( { - const pages = useBlockSuiteDocMeta(docCollection); const [collapsed, setCollapsed] = useState(true); const [open, setOpen] = useState(false); const collectionService = useService(CollectionService); - const favAdapter = useService(FavoriteItemsAdapter); const { createPage } = usePageHelper(docCollection); const { openConfirmModal } = useConfirmModal(); const t = useI18n(); - const favourites = useLiveData(favAdapter.favorites$); - - const removeFromAllowList = useCallback( - (id: string) => { - collectionService.deletePageFromCollection(collection.id, id); - toast(t['com.affine.collection.removePage.success']()); - }, - [collection, collectionService, t] - ); - const overlayPreview = useMemo(() => { return ( } title={collection.name} /> @@ -112,25 +100,6 @@ export const CollectionSidebarNavItem = ({ const isOver = over?.id === dndId && dragOverIntent === 'collection:add'; - const config = useAllPageListConfig(); - const allPagesMeta = useMemo( - () => Object.fromEntries(pages.map(v => [v.id, v])), - [pages] - ); - const allowList = useMemo( - () => new Set(collection.allowList), - [collection.allowList] - ); - - const pagesToRender = pages.filter(meta => { - if (meta.trash) return false; - const pageData = { - meta, - publicMode: config.getPublicMode(meta.id), - favorite: favourites.some(fav => fav.id === meta.id), - }; - return filterPage(collection, pageData); - }); const currentPath = useLiveData( useService(WorkbenchService).workbench.location$.map( location => location.pathname @@ -205,7 +174,6 @@ export const CollectionSidebarNavItem = ({ @@ -226,30 +194,90 @@ export const CollectionSidebarNavItem = ({ /> } - collapsed={pagesToRender.length > 0 ? collapsed : undefined} + collapsed={collapsed} > {collection.name} -
- {pagesToRender.map(page => { - return ( - - ); - })} -
+ {!collapsed && ( + + )}
); }; + +export const CollectionSidebarNavItemContent = ({ + collection, + docCollection, + dndId, +}: { + collection: Collection; + docCollection: DocCollection; + dndId: DNDIdentifier; +}) => { + const t = useI18n(); + const pages = useBlockSuiteDocMeta(docCollection); + const favAdapter = useService(FavoriteItemsAdapter); + const collectionService = useService(CollectionService); + + const config = useAllPageListConfig(); + const favourites = useLiveData(favAdapter.favorites$); + const allowList = useMemo( + () => new Set(collection.allowList), + [collection.allowList] + ); + const allPagesMeta = useMemo( + () => Object.fromEntries(pages.map(v => [v.id, v])), + [pages] + ); + const removeFromAllowList = useCallback( + (id: string) => { + collectionService.deletePageFromCollection(collection.id, id); + toast(t['com.affine.collection.removePage.success']()); + }, + [collection, collectionService, t] + ); + + const filtered = pages.filter(meta => { + if (meta.trash) return false; + const pageData = { + meta, + publicMode: config.getPublicMode(meta.id), + favorite: favourites.some(fav => fav.id === meta.id), + }; + return filterPage(collection, pageData); + }); + + return ( +
+ {filtered.length > 0 ? ( + filtered.map(page => { + return ( + + ); + }) + ) : ( +
+ {t['com.affine.collection.emptyCollection']()} +
+ )} +
+ ); +}; + export const CollectionsList = ({ docCollection: workspace, onCreate, diff --git a/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/styles.css.ts b/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/styles.css.ts index 5ecdb5601d..3810a90e7d 100644 --- a/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/styles.css.ts +++ b/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/styles.css.ts @@ -156,3 +156,10 @@ export const docsListContainer = style({ flexDirection: 'column', gap: 4, }); +export const emptyCollection = style({ + fontSize: cssVar('fontSm'), + textAlign: 'left', + paddingLeft: '32px', + color: cssVar('black30'), + userSelect: 'none', +}); diff --git a/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx b/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx index 6455f61376..ca648cfd5d 100644 --- a/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx +++ b/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx @@ -12,6 +12,9 @@ import { useCallback, useEffect, useMemo } from 'react'; import { usePageHelper } from '../../components/blocksuite/block-suite-page-list/utils'; +/** + * @deprecated very poor performance + */ export const useAllPageListConfig = () => { const currentWorkspace = useService(WorkspaceService).workspace; const shareDocService = useService(ShareDocsService); diff --git a/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx b/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx index aacc9bc8a3..19873f4a77 100644 --- a/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx +++ b/packages/frontend/core/src/hooks/affine/use-register-blocksuite-editor-commands.tsx @@ -3,12 +3,10 @@ import { PreconditionStrategy, registerAffineCommand, } from '@affine/core/commands'; -import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta'; import { FavoriteItemsAdapter } from '@affine/core/modules/properties'; import { mixpanel } from '@affine/core/utils'; import { WorkspaceFlavour } from '@affine/env/workspace'; import { useI18n } from '@affine/i18n'; -import { assertExists } from '@blocksuite/global/utils'; import { EdgelessIcon, HistoryIcon, PageIcon } from '@blocksuite/icons/rc'; import { DocService, @@ -31,15 +29,10 @@ export function useRegisterBlocksuiteEditorCommands() { const t = useI18n(); const workspace = useService(WorkspaceService).workspace; const docCollection = workspace.docCollection; - const { getDocMeta } = useDocMetaHelper(docCollection); - const currentPage = docCollection.getDoc(docId); - assertExists(currentPage); - const pageMeta = getDocMeta(docId); - assertExists(pageMeta); const favAdapter = useService(FavoriteItemsAdapter); const favorite = useLiveData(favAdapter.isFavorite$(docId, 'doc')); - const trash = pageMeta.trash ?? false; + const trash = useLiveData(doc.trash$); const setPageHistoryModalState = useSetAtom(pageHistoryModalAtom); @@ -52,15 +45,18 @@ export function useRegisterBlocksuiteEditorCommands() { const { restoreFromTrash, duplicate } = useBlockSuiteMetaHelper(docCollection); - const exportHandler = useExportPage(currentPage); + const exportHandler = useExportPage(doc.blockSuiteDoc); const { setTrashModal } = useTrashModalHelper(docCollection); - const onClickDelete = useCallback(() => { - setTrashModal({ - open: true, - pageIds: [docId], - pageTitles: [pageMeta.title], - }); - }, [docId, pageMeta.title, setTrashModal]); + const onClickDelete = useCallback( + (title: string) => { + setTrashModal({ + open: true, + pageIds: [docId], + pageTitles: [title], + }); + }, + [docId, setTrashModal] + ); const isCloudWorkspace = workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD; @@ -213,7 +209,7 @@ export function useRegisterBlocksuiteEditorCommands() { icon: mode === 'page' ? : , label: t['com.affine.moveToTrash.title'](), run() { - onClickDelete(); + onClickDelete(doc.title$.value); }, }) ); @@ -227,7 +223,7 @@ export function useRegisterBlocksuiteEditorCommands() { icon: mode === 'page' ? : , label: t['com.affine.cmdk.affine.editor.restore-from-trash'](), run() { - restoreFromTrash(docId); + doc.restoreFromTrash(); }, }) ); diff --git a/packages/frontend/core/src/pages/workspace/all-collection/index.tsx b/packages/frontend/core/src/pages/workspace/all-collection/index.tsx index 00b8ae9c35..d32c183e02 100644 --- a/packages/frontend/core/src/pages/workspace/all-collection/index.tsx +++ b/packages/frontend/core/src/pages/workspace/all-collection/index.tsx @@ -5,7 +5,6 @@ import { useEditCollectionName, VirtualizedCollectionList, } from '@affine/core/components/page-list'; -import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config'; import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper'; import { useI18n } from '@affine/i18n'; import { useLiveData, useService, WorkspaceService } from '@toeverything/infra'; @@ -25,7 +24,6 @@ export const AllCollection = () => { const collectionService = useService(CollectionService); const collections = useLiveData(collectionService.collections$); - const config = useAllPageListConfig(); const collectionMetas = useMemo(() => { const collectionsList: CollectionMeta[] = collections.map(collection => { @@ -71,7 +69,6 @@ export const AllCollection = () => { collectionMetas={collectionMetas} setHideHeaderCreateNewCollection={setHideHeaderCreateNew} node={node} - config={config} handleCreateCollection={handleCreateCollection} /> ) : ( diff --git a/packages/frontend/core/src/pages/workspace/collection/index.tsx b/packages/frontend/core/src/pages/workspace/collection/index.tsx index d408685915..c5544c311b 100644 --- a/packages/frontend/core/src/pages/workspace/collection/index.tsx +++ b/packages/frontend/core/src/pages/workspace/collection/index.tsx @@ -4,7 +4,6 @@ import { useEditCollection, VirtualizedPageList, } from '@affine/core/components/page-list'; -import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config'; import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks'; import { CollectionService } from '@affine/core/modules/collection'; import type { Collection } from '@affine/env/filter'; @@ -30,8 +29,7 @@ export const CollectionDetail = ({ }: { collection: Collection; }) => { - const config = useAllPageListConfig(); - const { node, open } = useEditCollection(useAllPageListConfig()); + const { node, open } = useEditCollection(); const collectionService = useService(CollectionService); const [hideHeaderCreateNew, setHideHeaderCreateNew] = useState(true); @@ -51,7 +49,6 @@ export const CollectionDetail = ({ @@ -104,7 +101,7 @@ export const Component = function CollectionPage() { const Placeholder = ({ collection }: { collection: Collection }) => { const workspace = useService(WorkspaceService).workspace; const collectionService = useService(CollectionService); - const { node, open } = useEditCollection(useAllPageListConfig()); + const { node, open } = useEditCollection(); const { jumpToCollections } = useNavigateHelper(); const openPageEdit = useAsyncCallback(async () => { const ret = await open({ ...collection }, 'page');