Skip to content

Commit f4a1992

Browse files
committed
feat(core): extract DocDisplayMetaService to resolve doc icon/title (#8226)
AF-1315
1 parent f397815 commit f4a1992

File tree

26 files changed

+361
-383
lines changed

26 files changed

+361
-383
lines changed

packages/frontend/core/src/components/affine/page-properties/info-modal/links-row.css.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ globalStyle(`${wrapper} span`, {
3232
whiteSpace: 'nowrap',
3333
overflow: 'hidden',
3434
textOverflow: 'ellipsis',
35-
borderBottom: 'none',
35+
// don't modify border width to avoid layout shift
36+
borderBottomColor: 'transparent',
3637
});

packages/frontend/core/src/components/affine/page-properties/info-modal/links-row.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import type { Backlink, Link } from '@affine/core/modules/doc-link';
2-
import { useContext } from 'react';
32

43
import { AffinePageReference } from '../../reference-link';
5-
import { managerContext } from '../common';
64
import * as styles from './links-row.css';
75

86
export const LinksRow = ({
@@ -16,20 +14,18 @@ export const LinksRow = ({
1614
className?: string;
1715
onClick?: () => void;
1816
}) => {
19-
const manager = useContext(managerContext);
2017
return (
2118
<div className={className}>
2219
<div className={styles.title}>
2320
{label} · {references.length}
2421
</div>
25-
{references.map(link => (
22+
{references.map((link, index) => (
2623
<AffinePageReference
27-
key={link.docId}
24+
key={index}
2825
pageId={link.docId}
2926
wrapper={props => (
3027
<div className={styles.wrapper} onClick={onClick} {...props} />
3128
)}
32-
docCollection={manager.workspace.docCollection}
3329
/>
3430
))}
3531
</div>

packages/frontend/core/src/components/affine/page-properties/table.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,6 @@ export const PageBacklinksPopup = ({
379379
backlinks,
380380
children,
381381
}: PageBacklinksPopupProps) => {
382-
const manager = useContext(managerContext);
383-
384382
return (
385383
<Menu
386384
contentOptions={{
@@ -395,7 +393,6 @@ export const PageBacklinksPopup = ({
395393
key={link.docId + ':' + link.blockId}
396394
wrapper={MenuItem}
397395
pageId={link.docId}
398-
docCollection={manager.workspace.docCollection}
399396
/>
400397
))}
401398
</div>

packages/frontend/core/src/components/affine/reference-link/index.tsx

Lines changed: 40 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
2-
import { useJournalHelper } from '@affine/core/components/hooks/use-journal';
1+
import { useJournalInfoHelper } from '@affine/core/components/hooks/use-journal';
2+
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
33
import {
44
PeekViewService,
55
useInsidePeekView,
@@ -8,15 +8,8 @@ import { WorkbenchLink } from '@affine/core/modules/workbench';
88
import { useI18n } from '@affine/i18n';
99
import { track } from '@affine/track';
1010
import type { DocMode } from '@blocksuite/blocks';
11-
import {
12-
BlockLinkIcon,
13-
DeleteIcon,
14-
LinkedEdgelessIcon,
15-
LinkedPageIcon,
16-
TodayIcon,
17-
} from '@blocksuite/icons/rc';
1811
import type { DocCollection } from '@blocksuite/store';
19-
import { DocsService, useLiveData, useService } from '@toeverything/infra';
12+
import { useLiveData, useService } from '@toeverything/infra';
2013
import { nanoid } from 'nanoid';
2114
import {
2215
type PropsWithChildren,
@@ -29,77 +22,18 @@ import { Link } from 'react-router-dom';
2922

3023
import * as styles from './styles.css';
3124

32-
export interface PageReferenceRendererOptions {
33-
pageId: string;
34-
docCollection: DocCollection;
35-
pageMetaHelper: ReturnType<typeof useDocMetaHelper>;
36-
journalHelper: ReturnType<typeof useJournalHelper>;
37-
t: ReturnType<typeof useI18n>;
38-
docMode?: DocMode;
39-
// Link to block or element
40-
linkToNode?: boolean;
41-
}
42-
43-
// use a function to be rendered in the lit renderer
44-
export function pageReferenceRenderer({
45-
pageId,
46-
pageMetaHelper,
47-
journalHelper,
48-
t,
49-
docMode,
50-
linkToNode = false,
51-
}: PageReferenceRendererOptions) {
52-
const { isPageJournal, getLocalizedJournalDateString } = journalHelper;
53-
const referencedPage = pageMetaHelper.getDocMeta(pageId);
54-
let title =
55-
referencedPage?.title ?? t['com.affine.editor.reference-not-found']();
56-
57-
let Icon = DeleteIcon;
58-
59-
if (referencedPage) {
60-
if (docMode === 'edgeless') {
61-
Icon = LinkedEdgelessIcon;
62-
} else {
63-
Icon = LinkedPageIcon;
64-
}
65-
if (linkToNode) {
66-
Icon = BlockLinkIcon;
67-
}
68-
}
69-
70-
const isJournal = isPageJournal(pageId);
71-
const localizedJournalDate = getLocalizedJournalDateString(pageId);
72-
if (isJournal && localizedJournalDate) {
73-
title = localizedJournalDate;
74-
Icon = TodayIcon;
75-
}
76-
77-
return (
78-
<>
79-
<Icon className={styles.pageReferenceIcon} />
80-
<span className="affine-reference-title">
81-
{title ? title : t['Untitled']()}
82-
</span>
83-
</>
84-
);
85-
}
86-
8725
export function AffinePageReference({
8826
pageId,
89-
docCollection,
9027
wrapper: Wrapper,
9128
params,
9229
}: {
9330
pageId: string;
94-
docCollection: DocCollection;
9531
wrapper?: React.ComponentType<PropsWithChildren>;
9632
params?: URLSearchParams;
9733
}) {
34+
const docDisplayMetaService = useService(DocDisplayMetaService);
35+
const journalHelper = useJournalInfoHelper();
9836
const t = useI18n();
99-
const pageMetaHelper = useDocMetaHelper();
100-
const journalHelper = useJournalHelper(docCollection);
101-
const docsService = useService(DocsService);
102-
const mode = useLiveData(docsService.list.primaryMode$(pageId));
10337

10438
let linkWithMode: DocMode | null = null;
10539
let linkToNode = false;
@@ -111,15 +45,23 @@ export function AffinePageReference({
11145
linkToNode = params.has('blockIds') || params.has('elementIds');
11246
}
11347

114-
const el = pageReferenceRenderer({
115-
docMode: linkWithMode ?? mode ?? 'page',
116-
pageId,
117-
pageMetaHelper,
118-
journalHelper,
119-
docCollection,
120-
t,
121-
linkToNode,
122-
});
48+
const Icon = useLiveData(
49+
docDisplayMetaService.icon$(pageId, {
50+
mode: linkWithMode ?? undefined,
51+
reference: true,
52+
referenceToNode: linkToNode,
53+
})
54+
);
55+
const title = useLiveData(docDisplayMetaService.title$(pageId));
56+
57+
const el = (
58+
<>
59+
<Icon className={styles.pageReferenceIcon} />
60+
<span className="affine-reference-title">
61+
{typeof title === 'string' ? title : t[title.key]()}
62+
</span>
63+
</>
64+
);
12365

12466
const ref = useRef<HTMLAnchorElement>(null);
12567

@@ -186,11 +128,9 @@ export function AffineSharedPageReference({
186128
wrapper?: React.ComponentType<PropsWithChildren>;
187129
params?: URLSearchParams;
188130
}) {
131+
const docDisplayMetaService = useService(DocDisplayMetaService);
132+
const journalHelper = useJournalInfoHelper();
189133
const t = useI18n();
190-
const pageMetaHelper = useDocMetaHelper();
191-
const journalHelper = useJournalHelper(docCollection);
192-
const docsService = useService(DocsService);
193-
const mode = useLiveData(docsService.list.primaryMode$(pageId));
194134

195135
let linkWithMode: DocMode | null = null;
196136
let linkToNode = false;
@@ -202,15 +142,22 @@ export function AffineSharedPageReference({
202142
linkToNode = params.has('blockIds') || params.has('elementIds');
203143
}
204144

205-
const el = pageReferenceRenderer({
206-
docMode: linkWithMode ?? mode ?? 'page',
207-
pageId,
208-
pageMetaHelper,
209-
journalHelper,
210-
docCollection,
211-
t,
212-
linkToNode,
213-
});
145+
const Icon = useLiveData(
146+
docDisplayMetaService.icon$(pageId, {
147+
mode: linkWithMode ?? undefined,
148+
reference: true,
149+
referenceToNode: linkToNode,
150+
})
151+
);
152+
const title = useLiveData(docDisplayMetaService.title$(pageId));
153+
const el = (
154+
<>
155+
<Icon className={styles.pageReferenceIcon} />
156+
<span className="affine-reference-title">
157+
{typeof title === 'string' ? title : t[title.key]()}
158+
</span>
159+
</>
160+
);
214161

215162
const ref = useRef<HTMLAnchorElement>(null);
216163

packages/frontend/core/src/components/blocksuite/block-suite-editor/bi-directional-link-panel.tsx

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
import { DocLinksService } from '@affine/core/modules/doc-link';
22
import { useI18n } from '@affine/i18n';
3-
import {
4-
useLiveData,
5-
useServices,
6-
WorkspaceService,
7-
} from '@toeverything/infra';
3+
import { useLiveData, useServices } from '@toeverything/infra';
84
import { useCallback, useState } from 'react';
95

106
import { AffinePageReference } from '../../affine/reference-link';
117
import * as styles from './bi-directional-link-panel.css';
128

139
export const BiDirectionalLinkPanel = () => {
1410
const [show, setShow] = useState(false);
15-
const { docLinksService, workspaceService } = useServices({
11+
const { docLinksService } = useServices({
1612
DocLinksService,
17-
WorkspaceService,
1813
});
1914
const t = useI18n();
2015

@@ -50,11 +45,7 @@ export const BiDirectionalLinkPanel = () => {
5045
</div>
5146
{backlinks.map(link => (
5247
<div key={link.docId} className={styles.link}>
53-
<AffinePageReference
54-
key={link.docId}
55-
pageId={link.docId}
56-
docCollection={workspaceService.workspace.docCollection}
57-
/>
48+
<AffinePageReference key={link.docId} pageId={link.docId} />
5849
</div>
5950
))}
6051
</div>
@@ -68,11 +59,7 @@ export const BiDirectionalLinkPanel = () => {
6859
key={`${link.docId}-${link.params?.toString()}-${i}`}
6960
className={styles.link}
7061
>
71-
<AffinePageReference
72-
pageId={link.docId}
73-
params={link.params}
74-
docCollection={workspaceService.workspace.docCollection}
75-
/>
62+
<AffinePageReference pageId={link.docId} params={link.params} />
7663
</div>
7764
))}
7865
</div>

packages/frontend/core/src/components/blocksuite/block-suite-editor/journal-doc-title.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as styles from './styles.css';
66

77
export const BlocksuiteEditorJournalDocTitle = ({ page }: { page: Doc }) => {
88
const { localizedJournalDate, isTodayJournal, journalDate } =
9-
useJournalInfoHelper(page.collection, page.id);
9+
useJournalInfoHelper(page.id);
1010
const t = useI18n();
1111

1212
// TODO(catsjuice): i18n

packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ interface BlocksuiteEditorProps {
7272
shared?: boolean;
7373
}
7474

75-
const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
75+
const usePatchSpecs = (shared: boolean, mode: DocMode) => {
7676
const [reactToLit, portals] = useLitPortalFactory();
7777
const {
7878
peekViewService,
@@ -110,15 +110,9 @@ const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
110110
);
111111
}
112112

113-
return (
114-
<AffinePageReference
115-
docCollection={page.collection}
116-
pageId={pageId}
117-
params={params}
118-
/>
119-
);
113+
return <AffinePageReference pageId={pageId} params={params} />;
120114
};
121-
}, [page.collection, workspaceService]);
115+
}, [workspaceService]);
122116

123117
const specs = useMemo(() => {
124118
const enableAI = featureFlagService.flags.enable_ai.value;
@@ -184,7 +178,7 @@ export const BlocksuiteDocEditor = forwardRef<
184178
) {
185179
const titleRef = useRef<DocTitle | null>(null);
186180
const docRef = useRef<PageEditor | null>(null);
187-
const { isJournal } = useJournalInfoHelper(page.collection, page.id);
181+
const { isJournal } = useJournalInfoHelper(page.id);
188182

189183
const editorSettingService = useService(EditorSettingService);
190184

@@ -216,7 +210,7 @@ export const BlocksuiteDocEditor = forwardRef<
216210
[externalTitleRef]
217211
);
218212

219-
const [specs, portals] = usePatchSpecs(page, !!shared, 'page');
213+
const [specs, portals] = usePatchSpecs(!!shared, 'page');
220214

221215
const displayBiDirectionalLink = useLiveData(
222216
editorSettingService.editorSetting.settings$.selector(
@@ -257,7 +251,7 @@ export const BlocksuiteEdgelessEditor = forwardRef<
257251
EdgelessEditor,
258252
BlocksuiteEditorProps
259253
>(function BlocksuiteEdgelessEditor({ page, shared }, ref) {
260-
const [specs, portals] = usePatchSpecs(page, !!shared, 'edgeless');
254+
const [specs, portals] = usePatchSpecs(!!shared, 'edgeless');
261255
const editorRef = useRef<EdgelessEditor | null>(null);
262256

263257
const onDocRef = useCallback(

0 commit comments

Comments
 (0)