mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-21 20:16:26 +08:00
refactor(core): refactor editor query string selector (#8058)
The editor selector is the information for locating a block, which can automatically focus on a certain content when a user opens a document.
```
export type EditorSelector = {
blockIds?: string[];
elementIds?: string[];
};
```
The selector can be set from multiple places, such as passing it in the center peek parameter, or passing it in the query part of the URL.
This pr decoupled the selector from the query string and now available at `editorService.editor.selector$`
This commit is contained in:
@@ -4,13 +4,20 @@ import type { DocService, WorkspaceService } from '@toeverything/infra';
|
||||
import { Entity, LiveData } from '@toeverything/infra';
|
||||
|
||||
import { EditorScope } from '../scopes/editor';
|
||||
import type { EditorSelector } from '../types';
|
||||
|
||||
export class Editor extends Entity<{ defaultMode: DocMode }> {
|
||||
export class Editor extends Entity<{
|
||||
defaultMode: DocMode;
|
||||
defaultEditorSelector?: EditorSelector;
|
||||
}> {
|
||||
readonly scope = this.framework.createScope(EditorScope, {
|
||||
editor: this as Editor,
|
||||
});
|
||||
|
||||
readonly mode$ = new LiveData(this.props.defaultMode);
|
||||
readonly selector$ = new LiveData<EditorSelector | undefined>(
|
||||
this.props.defaultEditorSelector
|
||||
);
|
||||
readonly doc = this.docService.doc;
|
||||
readonly isSharedMode =
|
||||
this.workspaceService.workspace.openOptions.isSharedMode;
|
||||
|
||||
@@ -15,6 +15,7 @@ export { Editor } from './entities/editor';
|
||||
export { EditorScope } from './scopes/editor';
|
||||
export { EditorService } from './services/editor';
|
||||
export { EditorsService } from './services/editors';
|
||||
export type { EditorSelector } from './types';
|
||||
|
||||
export function configureEditorModule(framework: Framework) {
|
||||
framework
|
||||
|
||||
@@ -2,9 +2,13 @@ import type { DocMode } from '@blocksuite/blocks';
|
||||
import { Service } from '@toeverything/infra';
|
||||
|
||||
import { Editor } from '../entities/editor';
|
||||
import type { EditorSelector } from '../types';
|
||||
|
||||
export class EditorsService extends Service {
|
||||
createEditor(defaultMode: DocMode) {
|
||||
return this.framework.createEntity(Editor, { defaultMode });
|
||||
createEditor(defaultMode: DocMode, defaultEditorSelector?: EditorSelector) {
|
||||
return this.framework.createEntity(Editor, {
|
||||
defaultMode,
|
||||
defaultEditorSelector,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export type EditorSelector = {
|
||||
blockIds?: string[];
|
||||
elementIds?: string[];
|
||||
};
|
||||
@@ -10,7 +10,12 @@ import { DebugLogger } from '@affine/debug';
|
||||
import { DocMode, type EdgelessRootService } from '@blocksuite/blocks';
|
||||
import { Bound, DisposableGroup } from '@blocksuite/global/utils';
|
||||
import type { AffineEditorContainer } from '@blocksuite/presets';
|
||||
import { DocsService, FrameworkScope, useService } from '@toeverything/infra';
|
||||
import {
|
||||
DocsService,
|
||||
FrameworkScope,
|
||||
useLiveData,
|
||||
useService,
|
||||
} from '@toeverything/infra';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
@@ -70,10 +75,14 @@ export function DocPeekPreview({
|
||||
mode?: DocMode;
|
||||
xywh?: `[${number},${number},${number},${number}]`;
|
||||
}) {
|
||||
const { doc, workspace, loading } = useEditor(docId, mode);
|
||||
const { doc, workspace, editor, loading } = useEditor(docId, mode, {
|
||||
blockIds,
|
||||
elementIds,
|
||||
});
|
||||
const { jumpToTag } = useNavigateHelper();
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
const peekView = useService(PeekViewService).peekView;
|
||||
const defaultEditorSelector = useLiveData(editor?.selector$);
|
||||
const [editorElement, setEditorElement] =
|
||||
useState<AffineEditorContainer | null>(null);
|
||||
|
||||
@@ -162,7 +171,7 @@ export function DocPeekPreview({
|
||||
}, [docId, peekView, workbench]);
|
||||
|
||||
// if sync engine has been synced and the page is null, show 404 page.
|
||||
if (!doc || !resolvedMode) {
|
||||
if (!doc || !resolvedMode || !editor) {
|
||||
return loading || !resolvedMode ? (
|
||||
<PageDetailSkeleton key="current-page-is-null" />
|
||||
) : (
|
||||
@@ -177,14 +186,15 @@ export function DocPeekPreview({
|
||||
className={clsx('affine-page-viewport', styles.affineDocViewport)}
|
||||
>
|
||||
<FrameworkScope scope={doc.scope}>
|
||||
<BlockSuiteEditor
|
||||
ref={onRef}
|
||||
className={styles.editor}
|
||||
mode={resolvedMode}
|
||||
blockIds={blockIds}
|
||||
elementIds={elementIds}
|
||||
page={doc.blockSuiteDoc}
|
||||
/>
|
||||
<FrameworkScope scope={editor.scope}>
|
||||
<BlockSuiteEditor
|
||||
ref={onRef}
|
||||
className={styles.editor}
|
||||
mode={resolvedMode}
|
||||
defaultEditorSelector={defaultEditorSelector}
|
||||
page={doc.blockSuiteDoc}
|
||||
/>
|
||||
</FrameworkScope>
|
||||
</FrameworkScope>
|
||||
<EditorOutlineViewer
|
||||
editor={editorElement}
|
||||
|
||||
@@ -8,15 +8,20 @@ import {
|
||||
} from '@toeverything/infra';
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
|
||||
import { type Editor, EditorsService } from '../../editor';
|
||||
import { type Editor, type EditorSelector, EditorsService } from '../../editor';
|
||||
|
||||
export const useEditor = (pageId: string, preferMode?: DocMode) => {
|
||||
export const useEditor = (
|
||||
pageId: string,
|
||||
preferMode?: DocMode,
|
||||
preferSelector?: EditorSelector
|
||||
) => {
|
||||
const currentWorkspace = useService(WorkspaceService).workspace;
|
||||
const docsService = useService(DocsService);
|
||||
const docRecordList = docsService.list;
|
||||
const docListReady = useLiveData(docRecordList.isReady$);
|
||||
const docRecord = docRecordList.doc$(pageId).value;
|
||||
const preferModeRef = useRef(preferMode);
|
||||
const preferSelectorRef = useRef(preferSelector);
|
||||
|
||||
const [doc, setDoc] = useState<Doc | null>(null);
|
||||
const [editor, setEditor] = useState<Editor | null>(null);
|
||||
@@ -38,7 +43,10 @@ export const useEditor = (pageId: string, preferMode?: DocMode) => {
|
||||
}
|
||||
const editor = doc.scope
|
||||
.get(EditorsService)
|
||||
.createEditor(preferModeRef.current || doc.primaryMode$.value);
|
||||
.createEditor(
|
||||
preferModeRef.current || doc.primaryMode$.value,
|
||||
preferSelectorRef.current
|
||||
);
|
||||
setEditor(editor);
|
||||
return () => {
|
||||
editor.dispose();
|
||||
|
||||
Reference in New Issue
Block a user