Skip to content

Commit 98d9295

Browse files
committed
feat(core): support block or element reference links (#7946)
Upstreams: toeverything/blocksuite#8021 * open doc with mode * monitor mode changes in query string * scroll anchoring https://github.com/user-attachments/assets/681abff8-e51b-47ea-bb71-447e8b312142 https://github.com/user-attachments/assets/e73ed4c0-4e33-45f8-9db4-d8eed3525d05
1 parent e7b5364 commit 98d9295

File tree

6 files changed

+37
-37
lines changed

6 files changed

+37
-37
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,23 @@ import * as styles from './styles.css';
2929
import { scrollAnchoring } from './utils';
3030

3131
export interface PageReferenceRendererOptions {
32-
docMode: DocMode | null;
3332
pageId: string;
3433
docCollection: DocCollection;
3534
pageMetaHelper: ReturnType<typeof useDocMetaHelper>;
3635
journalHelper: ReturnType<typeof useJournalHelper>;
3736
t: ReturnType<typeof useI18n>;
37+
docMode?: DocMode;
3838
// linking doc with block or element
3939
blockIds?: string[];
4040
elementIds?: string[];
4141
}
4242
// use a function to be rendered in the lit renderer
4343
export function pageReferenceRenderer({
44-
docMode,
4544
pageId,
4645
pageMetaHelper,
4746
journalHelper,
4847
t,
48+
docMode,
4949
blockIds,
5050
elementIds,
5151
}: PageReferenceRendererOptions) {
@@ -93,8 +93,8 @@ export function AffinePageReference({
9393
isSameDoc = false,
9494
std,
9595
}: {
96-
docCollection: DocCollection;
9796
pageId: string;
97+
docCollection: DocCollection;
9898
wrapper?: React.ComponentType<PropsWithChildren>;
9999
mode?: DocMode;
100100
params?: {

packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/database-block.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { EditorService } from '@affine/core/modules/editor';
88
import { I18n } from '@affine/i18n';
99
import type { DatabaseBlockModel, MenuOptions } from '@blocksuite/blocks';
1010
import { LinkIcon } from '@blocksuite/icons/lit';
11-
import { type FrameworkProvider } from '@toeverything/infra';
11+
import type { FrameworkProvider } from '@toeverything/infra';
1212
import type { TemplateResult } from 'lit';
1313

1414
export function createDatabaseOptionsConfig(framework: FrameworkProvider) {
@@ -54,12 +54,12 @@ function createCopyLinkToBlockMenuItem(
5454
const baseUrl = getAffineCloudBaseUrl();
5555
if (!baseUrl) return;
5656

57+
const pageId = model.doc.id;
5758
const { editor } = framework.get(EditorService);
5859
const mode = editor.mode$.value;
5960

6061
if (mode === 'edgeless') return;
6162

62-
const pageId = editor.doc.id;
6363
const workspaceId = editor.doc.workspace.id;
6464
const options: UseSharingUrl = {
6565
workspaceId,

packages/frontend/core/src/modules/navigation/utils.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ export const resolveRouteLinkMeta = (href: string) => {
5252
workspaceId,
5353
moduleName: 'doc' as const,
5454
docId: moduleName,
55-
blockId: hash.slice(1),
5655
};
5756
}
5857
}

packages/frontend/core/src/modules/peek-view/entities/peek-view.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
22
import {
33
AffineReference,
4-
type DocMode,
4+
DocMode,
55
type EmbedLinkedDocModel,
66
type EmbedSyncedDocModel,
77
type ImageBlockModel,
@@ -135,7 +135,7 @@ function resolvePeekInfoFromPeekTarget(
135135
return {
136136
type: 'doc',
137137
docId,
138-
mode: 'edgeless' as DocMode,
138+
mode: DocMode.Edgeless,
139139
xywh: refModel.xywh,
140140
};
141141
}

packages/frontend/core/src/modules/peek-view/view/peek-view-controls.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ export const DocPeekViewControls = ({
112112
nameKey: 'open',
113113
onClick: () => {
114114
// TODO(@Peng): for frame blocks, we should mimic "view in edgeless" button behavior
115-
workbench.openDoc({ docId, blockId, mode });
116-
115+
workbench.openDoc({ docId, mode, blockId });
117116
peekView.close('none');
118117
},
119118
},
@@ -122,7 +121,7 @@ export const DocPeekViewControls = ({
122121
nameKey: 'new-tab',
123122
name: t['com.affine.peek-view-controls.open-doc-in-new-tab'](),
124123
onClick: () => {
125-
workbench.openDoc(docId, { at: 'new-tab' });
124+
workbench.openDoc({ docId, mode }, { at: 'new-tab' });
126125
peekView.close('none');
127126
},
128127
},
@@ -131,7 +130,7 @@ export const DocPeekViewControls = ({
131130
nameKey: 'split-view',
132131
name: t['com.affine.peek-view-controls.open-doc-in-split-view'](),
133132
onClick: () => {
134-
workbench.openDoc(docId, { at: 'beside' });
133+
workbench.openDoc({ docId, mode }, { at: 'beside' });
135134
peekView.close('none');
136135
},
137136
},

packages/frontend/core/src/pages/workspace/detail-page/detail-page-wrapper.tsx

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,34 @@ const useLoadDoc = (pageId: string) => {
2828
const docRecord = useLiveData(docRecordList.doc$(pageId));
2929
const viewService = useService(ViewService);
3030

31-
const queryString = useLiveData(
32-
viewService.view.queryString$<{
33-
mode?: string;
34-
blockIds?: string[];
35-
elementIds?: string[];
36-
}>({
37-
// Cannot handle single id situation correctly: `blockIds=xxx`
38-
arrayFormat: 'none',
39-
types: {
40-
mode: 'string',
41-
blockIds: value => (value.length ? value.split(',') : []),
42-
elementIds: value => (value.length ? value.split(',') : []),
43-
},
31+
const queryString$ = viewService.view.queryString$<{
32+
mode?: string;
33+
blockIds?: string[];
34+
elementIds?: string[];
35+
}>({
36+
// Cannot handle single id situation correctly: `blockIds=xxx`
37+
arrayFormat: 'none',
38+
types: {
39+
mode: 'string',
40+
blockIds: value => (value.length ? value.split(',') : []),
41+
elementIds: value => (value.length ? value.split(',') : []),
42+
},
43+
});
44+
45+
const modeInQuery = useLiveData(
46+
queryString$.map(q => {
47+
if (q.mode && DocModes.includes(q.mode)) {
48+
return q.mode as DocMode;
49+
}
50+
return null;
4451
})
4552
);
4653

47-
const queryStringMode =
48-
queryString.mode && DocModes.includes(queryString.mode)
49-
? (queryString.mode as DocMode)
50-
: null;
51-
5254
// We only read the querystring mode when entering, so use useState here.
53-
const [initialQueryStringMode] = useState(() => queryStringMode);
54-
const [initialQueryStringSelector] = useState(() => ({
55-
blockIds: queryString.blockIds,
56-
elementIds: queryString.elementIds,
57-
}));
55+
const [initialQueryStringSelector] = useState(() => {
56+
const { blockIds, elementIds } = queryString$.value;
57+
return { blockIds, elementIds };
58+
});
5859

5960
const [doc, setDoc] = useState<Doc | null>(null);
6061
const [editor, setEditor] = useState<Editor | null>(null);
@@ -75,17 +76,18 @@ const useLoadDoc = (pageId: string) => {
7576
if (!doc) {
7677
return;
7778
}
79+
7880
const editor = doc.scope
7981
.get(EditorsService)
8082
.createEditor(
81-
initialQueryStringMode || doc.getPrimaryMode() || ('page' as DocMode),
83+
modeInQuery || doc.getPrimaryMode() || ('page' as DocMode),
8284
initialQueryStringSelector
8385
);
8486
setEditor(editor);
8587
return () => {
8688
editor.dispose();
8789
};
88-
}, [doc, initialQueryStringMode, initialQueryStringSelector]);
90+
}, [doc, modeInQuery, initialQueryStringSelector]);
8991

9092
// update editor mode to queryString
9193
useEffect(() => {

0 commit comments

Comments
 (0)