mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-13 22:04:21 +03:00
feat(core): support block or element reference links (#7946)
Upstreams: https://github.com/toeverything/blocksuite/pull/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
This commit is contained in:
parent
e7b53641d7
commit
98d9295259
@ -29,23 +29,23 @@ import * as styles from './styles.css';
|
||||
import { scrollAnchoring } from './utils';
|
||||
|
||||
export interface PageReferenceRendererOptions {
|
||||
docMode: DocMode | null;
|
||||
pageId: string;
|
||||
docCollection: DocCollection;
|
||||
pageMetaHelper: ReturnType<typeof useDocMetaHelper>;
|
||||
journalHelper: ReturnType<typeof useJournalHelper>;
|
||||
t: ReturnType<typeof useI18n>;
|
||||
docMode?: DocMode;
|
||||
// linking doc with block or element
|
||||
blockIds?: string[];
|
||||
elementIds?: string[];
|
||||
}
|
||||
// use a function to be rendered in the lit renderer
|
||||
export function pageReferenceRenderer({
|
||||
docMode,
|
||||
pageId,
|
||||
pageMetaHelper,
|
||||
journalHelper,
|
||||
t,
|
||||
docMode,
|
||||
blockIds,
|
||||
elementIds,
|
||||
}: PageReferenceRendererOptions) {
|
||||
@ -93,8 +93,8 @@ export function AffinePageReference({
|
||||
isSameDoc = false,
|
||||
std,
|
||||
}: {
|
||||
docCollection: DocCollection;
|
||||
pageId: string;
|
||||
docCollection: DocCollection;
|
||||
wrapper?: React.ComponentType<PropsWithChildren>;
|
||||
mode?: DocMode;
|
||||
params?: {
|
||||
|
@ -8,7 +8,7 @@ import { EditorService } from '@affine/core/modules/editor';
|
||||
import { I18n } from '@affine/i18n';
|
||||
import type { DatabaseBlockModel, MenuOptions } from '@blocksuite/blocks';
|
||||
import { LinkIcon } from '@blocksuite/icons/lit';
|
||||
import { type FrameworkProvider } from '@toeverything/infra';
|
||||
import type { FrameworkProvider } from '@toeverything/infra';
|
||||
import type { TemplateResult } from 'lit';
|
||||
|
||||
export function createDatabaseOptionsConfig(framework: FrameworkProvider) {
|
||||
@ -54,12 +54,12 @@ function createCopyLinkToBlockMenuItem(
|
||||
const baseUrl = getAffineCloudBaseUrl();
|
||||
if (!baseUrl) return;
|
||||
|
||||
const pageId = model.doc.id;
|
||||
const { editor } = framework.get(EditorService);
|
||||
const mode = editor.mode$.value;
|
||||
|
||||
if (mode === 'edgeless') return;
|
||||
|
||||
const pageId = editor.doc.id;
|
||||
const workspaceId = editor.doc.workspace.id;
|
||||
const options: UseSharingUrl = {
|
||||
workspaceId,
|
||||
|
@ -52,7 +52,6 @@ export const resolveRouteLinkMeta = (href: string) => {
|
||||
workspaceId,
|
||||
moduleName: 'doc' as const,
|
||||
docId: moduleName,
|
||||
blockId: hash.slice(1),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
|
||||
import {
|
||||
AffineReference,
|
||||
type DocMode,
|
||||
DocMode,
|
||||
type EmbedLinkedDocModel,
|
||||
type EmbedSyncedDocModel,
|
||||
type ImageBlockModel,
|
||||
@ -135,7 +135,7 @@ function resolvePeekInfoFromPeekTarget(
|
||||
return {
|
||||
type: 'doc',
|
||||
docId,
|
||||
mode: 'edgeless' as DocMode,
|
||||
mode: DocMode.Edgeless,
|
||||
xywh: refModel.xywh,
|
||||
};
|
||||
}
|
||||
|
@ -112,8 +112,7 @@ export const DocPeekViewControls = ({
|
||||
nameKey: 'open',
|
||||
onClick: () => {
|
||||
// TODO(@Peng): for frame blocks, we should mimic "view in edgeless" button behavior
|
||||
workbench.openDoc({ docId, blockId, mode });
|
||||
|
||||
workbench.openDoc({ docId, mode, blockId });
|
||||
peekView.close('none');
|
||||
},
|
||||
},
|
||||
@ -122,7 +121,7 @@ export const DocPeekViewControls = ({
|
||||
nameKey: 'new-tab',
|
||||
name: t['com.affine.peek-view-controls.open-doc-in-new-tab'](),
|
||||
onClick: () => {
|
||||
workbench.openDoc(docId, { at: 'new-tab' });
|
||||
workbench.openDoc({ docId, mode }, { at: 'new-tab' });
|
||||
peekView.close('none');
|
||||
},
|
||||
},
|
||||
@ -131,7 +130,7 @@ export const DocPeekViewControls = ({
|
||||
nameKey: 'split-view',
|
||||
name: t['com.affine.peek-view-controls.open-doc-in-split-view'](),
|
||||
onClick: () => {
|
||||
workbench.openDoc(docId, { at: 'beside' });
|
||||
workbench.openDoc({ docId, mode }, { at: 'beside' });
|
||||
peekView.close('none');
|
||||
},
|
||||
},
|
||||
|
@ -28,33 +28,34 @@ const useLoadDoc = (pageId: string) => {
|
||||
const docRecord = useLiveData(docRecordList.doc$(pageId));
|
||||
const viewService = useService(ViewService);
|
||||
|
||||
const queryString = useLiveData(
|
||||
viewService.view.queryString$<{
|
||||
mode?: string;
|
||||
blockIds?: string[];
|
||||
elementIds?: string[];
|
||||
}>({
|
||||
// Cannot handle single id situation correctly: `blockIds=xxx`
|
||||
arrayFormat: 'none',
|
||||
types: {
|
||||
mode: 'string',
|
||||
blockIds: value => (value.length ? value.split(',') : []),
|
||||
elementIds: value => (value.length ? value.split(',') : []),
|
||||
},
|
||||
const queryString$ = viewService.view.queryString$<{
|
||||
mode?: string;
|
||||
blockIds?: string[];
|
||||
elementIds?: string[];
|
||||
}>({
|
||||
// Cannot handle single id situation correctly: `blockIds=xxx`
|
||||
arrayFormat: 'none',
|
||||
types: {
|
||||
mode: 'string',
|
||||
blockIds: value => (value.length ? value.split(',') : []),
|
||||
elementIds: value => (value.length ? value.split(',') : []),
|
||||
},
|
||||
});
|
||||
|
||||
const modeInQuery = useLiveData(
|
||||
queryString$.map(q => {
|
||||
if (q.mode && DocModes.includes(q.mode)) {
|
||||
return q.mode as DocMode;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
|
||||
const queryStringMode =
|
||||
queryString.mode && DocModes.includes(queryString.mode)
|
||||
? (queryString.mode as DocMode)
|
||||
: null;
|
||||
|
||||
// We only read the querystring mode when entering, so use useState here.
|
||||
const [initialQueryStringMode] = useState(() => queryStringMode);
|
||||
const [initialQueryStringSelector] = useState(() => ({
|
||||
blockIds: queryString.blockIds,
|
||||
elementIds: queryString.elementIds,
|
||||
}));
|
||||
const [initialQueryStringSelector] = useState(() => {
|
||||
const { blockIds, elementIds } = queryString$.value;
|
||||
return { blockIds, elementIds };
|
||||
});
|
||||
|
||||
const [doc, setDoc] = useState<Doc | null>(null);
|
||||
const [editor, setEditor] = useState<Editor | null>(null);
|
||||
@ -75,17 +76,18 @@ const useLoadDoc = (pageId: string) => {
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = doc.scope
|
||||
.get(EditorsService)
|
||||
.createEditor(
|
||||
initialQueryStringMode || doc.getPrimaryMode() || ('page' as DocMode),
|
||||
modeInQuery || doc.getPrimaryMode() || ('page' as DocMode),
|
||||
initialQueryStringSelector
|
||||
);
|
||||
setEditor(editor);
|
||||
return () => {
|
||||
editor.dispose();
|
||||
};
|
||||
}, [doc, initialQueryStringMode, initialQueryStringSelector]);
|
||||
}, [doc, modeInQuery, initialQueryStringSelector]);
|
||||
|
||||
// update editor mode to queryString
|
||||
useEffect(() => {
|
||||
|
Loading…
Reference in New Issue
Block a user