feat: fav page references (#2422)

Co-authored-by: Himself65 <himself65@outlook.com>
This commit is contained in:
Peng Xiao
2023-05-18 13:18:40 +08:00
committed by GitHub
parent b7cee3185e
commit 2f7b51d7ff
9 changed files with 270 additions and 38 deletions

View File

@@ -1,40 +1,103 @@
import { MenuLinkItem } from '@affine/component/app-sidebar';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
import type { PageMeta, Workspace } from '@blocksuite/store';
import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta';
import { useBlockSuitePageReferences } from '@toeverything/hooks/use-block-suite-page-references';
import { useAtomValue } from 'jotai';
import { useRouter } from 'next/router';
import { useMemo } from 'react';
import { useMemo, useState } from 'react';
import { workspacePreferredModeAtom } from '../../../../atoms';
import type { FavoriteListProps } from '../index';
import EmptyItem from './empty-item';
export const FavoriteList = ({ currentWorkspace }: FavoriteListProps) => {
interface FavoriteMenuItemProps {
workspace: Workspace;
pageId: string;
metaMapping: Record<string, PageMeta>;
parentIds: Set<string>;
}
function FavoriteMenuItem({
workspace,
pageId,
metaMapping,
parentIds,
}: FavoriteMenuItemProps) {
const router = useRouter();
const record = useAtomValue(workspacePreferredModeAtom);
const pageMeta = useBlockSuitePageMeta(currentWorkspace.blockSuiteWorkspace);
const workspaceId = currentWorkspace.id;
const active = router.query.pageId === pageId;
const icon = record[pageId] === 'edgeless' ? <EdgelessIcon /> : <PageIcon />;
const references = useBlockSuitePageReferences(workspace, pageId);
const referencesToShow = useMemo(() => {
return [...new Set(references.filter(ref => !parentIds.has(ref)))];
}, [references, parentIds]);
const [collapsed, setCollapsed] = useState(true);
const collapsible = referencesToShow.length > 0 && parentIds.size === 0;
const showReferences = collapsible ? !collapsed : referencesToShow.length > 0;
const nestedItem = parentIds.size > 0;
return (
<>
<MenuLinkItem
style={{
marginLeft: nestedItem ? '12px' : undefined,
width: nestedItem ? 'calc(100% - 12px)' : undefined,
}}
data-type="favorite-list-item"
data-testid={`favorite-list-item-${pageId}`}
active={active}
href={`/workspace/${workspace.id}/${pageId}`}
icon={icon}
collapsed={collapsible ? collapsed : undefined}
onCollapsedChange={setCollapsed}
>
<span>{metaMapping[pageId]?.title || 'Untitled'}</span>
</MenuLinkItem>
{showReferences &&
referencesToShow.map(ref => {
return (
<FavoriteMenuItem
key={ref}
workspace={workspace}
pageId={ref}
metaMapping={metaMapping}
parentIds={new Set([...parentIds, pageId])}
/>
);
})}
</>
);
}
export const FavoriteList = ({ currentWorkspace }: FavoriteListProps) => {
const metas = useBlockSuitePageMeta(currentWorkspace.blockSuiteWorkspace);
const favoriteList = useMemo(
() => pageMeta.filter(p => p.favorite && !p.trash),
[pageMeta]
() => metas.filter(p => p.favorite && !p.trash),
[metas]
);
const metaMapping = useMemo(
() =>
metas.reduce((acc, meta) => {
acc[meta.id] = meta;
return acc;
}, {} as Record<string, PageMeta>),
[metas]
);
return (
<>
{favoriteList.map((pageMeta, index) => {
const active = router.query.pageId === pageMeta.id;
const icon =
record[pageMeta.id] === 'edgeless' ? <EdgelessIcon /> : <PageIcon />;
return (
<MenuLinkItem
<FavoriteMenuItem
key={`${pageMeta}-${index}`}
data-testid={`favorite-list-item-${pageMeta.id}`}
active={active}
href={`/workspace/${workspaceId}/${pageMeta.id}`}
icon={icon}
>
<span>{pageMeta.title || 'Untitled'}</span>
</MenuLinkItem>
metaMapping={metaMapping}
pageId={pageMeta.id}
// memo?
parentIds={new Set()}
workspace={currentWorkspace.blockSuiteWorkspace}
/>
);
})}
{favoriteList.length === 0 && <EmptyItem />}