refactor: replace editor container with editor host (#10328)
### TL;DR Refactored editor access to use `EditorHost` instead of `AffineEditorContainer` and updated mode access through `DocModeProvider`. ### What changed? - Changed editor property types from `AffineEditorContainer` to `EditorHost` across multiple components - Updated mode access to use `DocModeProvider` service instead of direct editor mode access - Modified editor references to use `editor.host` where appropriate - Updated scroll and highlight utilities to work with `EditorHost` ### How to test? 1. Open a document in both page and edgeless modes 2. Verify outline panel functionality works as expected 3. Test outline viewer navigation and highlighting 4. Confirm mobile outline menu operates correctly 5. Check that frame panel and TOC features work in all modes ### Why make this change? This change improves architectural consistency by using `EditorHost` directly and accessing mode through the proper service provider. This makes the code more maintainable and follows better dependency practices by using the correct abstraction levels.
This commit is contained in:
@@ -22,7 +22,7 @@ export class CustomOutlinePanel extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
private _renderPanel() {
|
private _renderPanel() {
|
||||||
return html`<affine-outline-panel
|
return html`<affine-outline-panel
|
||||||
.editor=${this.editor}
|
.editor=${this.editor.host}
|
||||||
.fitPadding=${[50, 360, 50, 50]}
|
.fitPadding=${[50, 360, 50, 50]}
|
||||||
></affine-outline-panel>`;
|
></affine-outline-panel>`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class CustomOutlineViewer extends WithDisposable(LitElement) {
|
|||||||
|
|
||||||
private _renderViewer() {
|
private _renderViewer() {
|
||||||
return html`<affine-outline-viewer
|
return html`<affine-outline-viewer
|
||||||
.editor=${this.editor}
|
.editor=${this.editor.host}
|
||||||
.toggleOutlinePanel=${this.toggleOutlinePanel}
|
.toggleOutlinePanel=${this.toggleOutlinePanel}
|
||||||
></affine-outline-viewer>`;
|
></affine-outline-viewer>`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { effects } from '@blocksuite/affine-block-note/effects';
|
|||||||
import { ShadowlessElement, SurfaceSelection } from '@blocksuite/block-std';
|
import { ShadowlessElement, SurfaceSelection } from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
changeNoteDisplayMode,
|
changeNoteDisplayMode,
|
||||||
|
DocModeProvider,
|
||||||
matchModels,
|
matchModels,
|
||||||
NoteBlockModel,
|
NoteBlockModel,
|
||||||
NoteDisplayMode,
|
NoteDisplayMode,
|
||||||
@@ -224,7 +225,9 @@ export class OutlinePanelBody extends SignalWatcher(
|
|||||||
|
|
||||||
private _watchSelectedNotes() {
|
private _watchSelectedNotes() {
|
||||||
return effect(() => {
|
return effect(() => {
|
||||||
const { std, doc, mode } = this.editor;
|
const { std, doc } = this.editor;
|
||||||
|
const docModeService = this.editor.std.get(DocModeProvider);
|
||||||
|
const mode = docModeService.getEditorMode();
|
||||||
if (mode !== 'edgeless') return;
|
if (mode !== 'edgeless') return;
|
||||||
|
|
||||||
const currSelectedNotes = std.selection
|
const currSelectedNotes = std.selection
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import type { ParagraphBlockModel, Signal } from '@blocksuite/blocks';
|
import type { ParagraphBlockModel, Signal } from '@blocksuite/blocks';
|
||||||
import {
|
import {
|
||||||
AttachmentIcon,
|
AttachmentIcon,
|
||||||
@@ -22,8 +23,6 @@ import {
|
|||||||
import { createContext } from '@lit/context';
|
import { createContext } from '@lit/context';
|
||||||
import type { TemplateResult } from 'lit';
|
import type { TemplateResult } from 'lit';
|
||||||
|
|
||||||
import type { AffineEditorContainer } from '../../editors/editor-container.js';
|
|
||||||
|
|
||||||
const _16px = { width: '16px', height: '16px' };
|
const _16px = { width: '16px', height: '16px' };
|
||||||
|
|
||||||
const paragraphIconMap: Record<
|
const paragraphIconMap: Record<
|
||||||
@@ -85,7 +84,7 @@ export const headingKeys = new Set(
|
|||||||
export const outlineSettingsKey = 'outlinePanelSettings';
|
export const outlineSettingsKey = 'outlinePanelSettings';
|
||||||
|
|
||||||
export type TocContext = {
|
export type TocContext = {
|
||||||
editor$: Signal<AffineEditorContainer>;
|
editor$: Signal<EditorHost>;
|
||||||
enableSorting$: Signal<boolean>;
|
enableSorting$: Signal<boolean>;
|
||||||
showIcons$: Signal<boolean>;
|
showIcons$: Signal<boolean>;
|
||||||
fitPadding$: Signal<number[]>;
|
fitPadding$: Signal<number[]>;
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||||
import { PropTypes, requiredProperties } from '@blocksuite/block-std';
|
|
||||||
import {
|
import {
|
||||||
|
type EditorHost,
|
||||||
|
PropTypes,
|
||||||
|
requiredProperties,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
|
import {
|
||||||
|
DocModeProvider,
|
||||||
matchModels,
|
matchModels,
|
||||||
NoteDisplayMode,
|
NoteDisplayMode,
|
||||||
ParagraphBlockModel,
|
ParagraphBlockModel,
|
||||||
@@ -14,7 +19,6 @@ import { property } from 'lit/decorators.js';
|
|||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
import { repeat } from 'lit/directives/repeat.js';
|
import { repeat } from 'lit/directives/repeat.js';
|
||||||
|
|
||||||
import type { AffineEditorContainer } from '../../editors/editor-container.js';
|
|
||||||
import { getHeadingBlocksFromDoc } from './utils/query.js';
|
import { getHeadingBlocksFromDoc } from './utils/query.js';
|
||||||
import {
|
import {
|
||||||
observeActiveHeadingDuringScroll,
|
observeActiveHeadingDuringScroll,
|
||||||
@@ -162,8 +166,9 @@ export class MobileOutlineMenu extends SignalWatcher(
|
|||||||
};
|
};
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
if (this.editor.doc.root === null || this.editor.mode === 'edgeless')
|
const docModeService = this.editor.std.get(DocModeProvider);
|
||||||
return nothing;
|
const mode = docModeService.getEditorMode();
|
||||||
|
if (this.editor.doc.root === null || mode === 'edgeless') return nothing;
|
||||||
|
|
||||||
const headingBlocks = getHeadingBlocksFromDoc(
|
const headingBlocks = getHeadingBlocksFromDoc(
|
||||||
this.editor.doc,
|
this.editor.doc,
|
||||||
@@ -182,7 +187,7 @@ export class MobileOutlineMenu extends SignalWatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor editor!: AffineEditorContainer;
|
accessor editor!: EditorHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
|
type EditorHost,
|
||||||
PropTypes,
|
PropTypes,
|
||||||
requiredProperties,
|
requiredProperties,
|
||||||
ShadowlessElement,
|
ShadowlessElement,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
|
import { DocModeProvider } from '@blocksuite/blocks';
|
||||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
|
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { provide } from '@lit/context';
|
import { provide } from '@lit/context';
|
||||||
import { effect, signal } from '@preact/signals-core';
|
import { effect, signal } from '@preact/signals-core';
|
||||||
import { html, type PropertyValues } from 'lit';
|
import { html, type PropertyValues } from 'lit';
|
||||||
import { property } from 'lit/decorators.js';
|
import { property } from 'lit/decorators.js';
|
||||||
|
|
||||||
import type { AffineEditorContainer } from '../../editors/editor-container.js';
|
|
||||||
import { outlineSettingsKey, type TocContext, tocContext } from './config.js';
|
import { outlineSettingsKey, type TocContext, tocContext } from './config.js';
|
||||||
import * as styles from './outline-panel.css';
|
import * as styles from './outline-panel.css';
|
||||||
|
|
||||||
@@ -21,6 +22,12 @@ export const AFFINE_OUTLINE_PANEL = 'affine-outline-panel';
|
|||||||
export class OutlinePanel extends SignalWatcher(
|
export class OutlinePanel extends SignalWatcher(
|
||||||
WithDisposable(ShadowlessElement)
|
WithDisposable(ShadowlessElement)
|
||||||
) {
|
) {
|
||||||
|
private _getEditorMode(host: EditorHost) {
|
||||||
|
const docModeService = host.std.get(DocModeProvider);
|
||||||
|
const mode = docModeService.getEditorMode();
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
private _setContext() {
|
private _setContext() {
|
||||||
this._context = {
|
this._context = {
|
||||||
editor$: signal(this.editor),
|
editor$: signal(this.editor),
|
||||||
@@ -39,7 +46,7 @@ export class OutlinePanel extends SignalWatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const editor = this._context.editor$.value;
|
const editor = this._context.editor$.value;
|
||||||
if (editor.mode === 'edgeless') {
|
if (this._getEditorMode(editor) === 'edgeless') {
|
||||||
this._context.enableSorting$.value = true;
|
this._context.enableSorting$.value = true;
|
||||||
} else if (settings) {
|
} else if (settings) {
|
||||||
this._context.enableSorting$.value = settings.enableSorting;
|
this._context.enableSorting$.value = settings.enableSorting;
|
||||||
@@ -51,7 +58,8 @@ export class OutlinePanel extends SignalWatcher(
|
|||||||
private _watchSettingsChange() {
|
private _watchSettingsChange() {
|
||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
effect(() => {
|
effect(() => {
|
||||||
if (this._context.editor$.value.mode === 'edgeless') return;
|
if (this._getEditorMode(this._context.editor$.value) === 'edgeless')
|
||||||
|
return;
|
||||||
|
|
||||||
const showPreviewIcon = this._context.showIcons$.value;
|
const showPreviewIcon = this._context.showIcons$.value;
|
||||||
const enableNotesSorting = this._context.enableSorting$.value;
|
const enableNotesSorting = this._context.enableSorting$.value;
|
||||||
@@ -84,7 +92,7 @@ export class OutlinePanel extends SignalWatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
if (!this.editor.host) return;
|
if (!this.editor) return;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<affine-outline-panel-header></affine-outline-panel-header>
|
<affine-outline-panel-header></affine-outline-panel-header>
|
||||||
@@ -97,7 +105,7 @@ export class OutlinePanel extends SignalWatcher(
|
|||||||
private accessor _context!: TocContext;
|
private accessor _context!: TocContext;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor editor!: AffineEditorContainer;
|
accessor editor!: EditorHost;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor fitPadding!: number[];
|
accessor fitPadding!: number[];
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
|
type EditorHost,
|
||||||
PropTypes,
|
PropTypes,
|
||||||
requiredProperties,
|
requiredProperties,
|
||||||
ShadowlessElement,
|
ShadowlessElement,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { NoteDisplayMode, scrollbarStyle } from '@blocksuite/blocks';
|
import {
|
||||||
|
DocModeProvider,
|
||||||
|
NoteDisplayMode,
|
||||||
|
scrollbarStyle,
|
||||||
|
} from '@blocksuite/blocks';
|
||||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
|
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { TocIcon } from '@blocksuite/icons/lit';
|
import { TocIcon } from '@blocksuite/icons/lit';
|
||||||
import { provide } from '@lit/context';
|
import { provide } from '@lit/context';
|
||||||
@@ -13,7 +18,6 @@ import { property, query, state } from 'lit/decorators.js';
|
|||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
import { repeat } from 'lit/directives/repeat.js';
|
import { repeat } from 'lit/directives/repeat.js';
|
||||||
|
|
||||||
import type { AffineEditorContainer } from '../../editors/editor-container.js';
|
|
||||||
import { type TocContext, tocContext } from './config.js';
|
import { type TocContext, tocContext } from './config.js';
|
||||||
import { getHeadingBlocksFromDoc } from './utils/query.js';
|
import { getHeadingBlocksFromDoc } from './utils/query.js';
|
||||||
import {
|
import {
|
||||||
@@ -219,8 +223,9 @@ export class OutlineViewer extends SignalWatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
if (this.editor.doc.root === null || this.editor.mode === 'edgeless')
|
const docModeService = this.editor.std.get(DocModeProvider);
|
||||||
return nothing;
|
const mode = docModeService.getEditorMode();
|
||||||
|
if (this.editor.doc.root === null || mode === 'edgeless') return nothing;
|
||||||
|
|
||||||
const headingBlocks = getHeadingBlocksFromDoc(
|
const headingBlocks = getHeadingBlocksFromDoc(
|
||||||
this.editor.doc,
|
this.editor.doc,
|
||||||
@@ -308,7 +313,7 @@ export class OutlineViewer extends SignalWatcher(
|
|||||||
private accessor _showViewer: boolean = false;
|
private accessor _showViewer: boolean = false;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor editor!: AffineEditorContainer;
|
accessor editor!: EditorHost;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor toggleOutlinePanel: (() => void) | null = null;
|
accessor toggleOutlinePanel: (() => void) | null = null;
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import { getDocTitleByEditorHost, NoteDisplayMode } from '@blocksuite/blocks';
|
import {
|
||||||
|
DocModeProvider,
|
||||||
|
getDocTitleByEditorHost,
|
||||||
|
NoteDisplayMode,
|
||||||
|
} from '@blocksuite/blocks';
|
||||||
import { clamp, DisposableGroup } from '@blocksuite/global/utils';
|
import { clamp, DisposableGroup } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
import type { AffineEditorContainer } from '../../../editors/editor-container.js';
|
|
||||||
import { getHeadingBlocksFromDoc } from './query.js';
|
import { getHeadingBlocksFromDoc } from './query.js';
|
||||||
|
|
||||||
export function scrollToBlock(editor: AffineEditorContainer, blockId: string) {
|
export function scrollToBlock(host: EditorHost, blockId: string) {
|
||||||
const { host, mode } = editor;
|
const docModeService = host.std.get(DocModeProvider);
|
||||||
if (mode === 'edgeless' || !host) return;
|
const mode = docModeService.getEditorMode();
|
||||||
|
if (mode === 'edgeless') return;
|
||||||
|
|
||||||
if (editor.doc.root?.id === blockId) {
|
if (editor.doc.root?.id === blockId) {
|
||||||
const docTitle = getDocTitleByEditorHost(host);
|
const docTitle = getDocTitleByEditorHost(host);
|
||||||
@@ -49,12 +53,11 @@ export function isBlockBeforeViewportCenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const observeActiveHeadingDuringScroll = (
|
export const observeActiveHeadingDuringScroll = (
|
||||||
getEditor: () => AffineEditorContainer, // workaround for editor changed
|
getEditor: () => EditorHost, // workaround for editor changed
|
||||||
update: (activeHeading: string | null) => void
|
update: (activeHeading: string | null) => void
|
||||||
) => {
|
) => {
|
||||||
const handler = () => {
|
const handler = () => {
|
||||||
const { host } = getEditor();
|
const host = getEditor();
|
||||||
if (!host) return;
|
|
||||||
|
|
||||||
const headings = getHeadingBlocksFromDoc(
|
const headings = getHeadingBlocksFromDoc(
|
||||||
host.doc,
|
host.doc,
|
||||||
@@ -81,13 +84,10 @@ export const observeActiveHeadingDuringScroll = (
|
|||||||
let highlightMask: HTMLDivElement | null = null;
|
let highlightMask: HTMLDivElement | null = null;
|
||||||
let highlightTimeoutId: ReturnType<typeof setTimeout> | null = null;
|
let highlightTimeoutId: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
function highlightBlock(editor: AffineEditorContainer, blockId: string) {
|
function highlightBlock(host: EditorHost, blockId: string) {
|
||||||
const emptyClear = () => {};
|
const emptyClear = () => {};
|
||||||
|
|
||||||
const { host } = editor;
|
if (host.doc.root?.id === blockId) return emptyClear;
|
||||||
if (!host) return emptyClear;
|
|
||||||
|
|
||||||
if (editor.doc.root?.id === blockId) return emptyClear;
|
|
||||||
|
|
||||||
const rootComponent = host.querySelector('affine-page-root');
|
const rootComponent = host.querySelector('affine-page-root');
|
||||||
if (!rootComponent) return emptyClear;
|
if (!rootComponent) return emptyClear;
|
||||||
@@ -152,11 +152,11 @@ function highlightBlock(editor: AffineEditorContainer, blockId: string) {
|
|||||||
// this function is useful when the scroll need smooth animation
|
// this function is useful when the scroll need smooth animation
|
||||||
let highlightIntervalId: ReturnType<typeof setInterval> | null = null;
|
let highlightIntervalId: ReturnType<typeof setInterval> | null = null;
|
||||||
export async function scrollToBlockWithHighlight(
|
export async function scrollToBlockWithHighlight(
|
||||||
editor: AffineEditorContainer,
|
host: EditorHost,
|
||||||
blockId: string,
|
blockId: string,
|
||||||
timeout = 3000
|
timeout = 3000
|
||||||
) {
|
) {
|
||||||
scrollToBlock(editor, blockId);
|
scrollToBlock(host, blockId);
|
||||||
|
|
||||||
let timeCount = 0;
|
let timeCount = 0;
|
||||||
|
|
||||||
@@ -173,10 +173,9 @@ export async function scrollToBlockWithHighlight(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host } = editor;
|
const block = host.view.getBlock(blockId);
|
||||||
const block = host?.view.getBlock(blockId);
|
|
||||||
|
|
||||||
if (!host || !block || timeCount > timeout) {
|
if (!block || timeCount > timeout) {
|
||||||
clearInterval(highlightIntervalId);
|
clearInterval(highlightIntervalId);
|
||||||
resolve(() => {});
|
resolve(() => {});
|
||||||
return;
|
return;
|
||||||
@@ -194,7 +193,7 @@ export async function scrollToBlockWithHighlight(
|
|||||||
clearInterval(highlightIntervalId);
|
clearInterval(highlightIntervalId);
|
||||||
|
|
||||||
// highlight block
|
// highlight block
|
||||||
resolve(highlightBlock(editor, blockId));
|
resolve(highlightBlock(host, blockId));
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { AffineEditorContainer } from '@blocksuite/affine/presets';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import { OutlineViewer } from '@blocksuite/affine/presets';
|
import { OutlineViewer } from '@blocksuite/affine/presets';
|
||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ export const EditorOutlineViewer = ({
|
|||||||
show,
|
show,
|
||||||
openOutlinePanel,
|
openOutlinePanel,
|
||||||
}: {
|
}: {
|
||||||
editor: AffineEditorContainer | null;
|
editor: EditorHost | null;
|
||||||
show: boolean;
|
show: boolean;
|
||||||
openOutlinePanel?: () => void;
|
openOutlinePanel?: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
|
|||||||
/>
|
/>
|
||||||
</Scrollable.Root>
|
</Scrollable.Root>
|
||||||
<EditorOutlineViewer
|
<EditorOutlineViewer
|
||||||
editor={editorContainer}
|
editor={editorContainer?.host ?? null}
|
||||||
show={mode === 'page' && !isSideBarOpen}
|
show={mode === 'page' && !isSideBarOpen}
|
||||||
openOutlinePanel={openOutlinePanel}
|
openOutlinePanel={openOutlinePanel}
|
||||||
/>
|
/>
|
||||||
@@ -350,7 +350,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
|
|||||||
<ViewSidebarTab tabId="outline" icon={<TocIcon />}>
|
<ViewSidebarTab tabId="outline" icon={<TocIcon />}>
|
||||||
<Scrollable.Root className={styles.sidebarScrollArea}>
|
<Scrollable.Root className={styles.sidebarScrollArea}>
|
||||||
<Scrollable.Viewport>
|
<Scrollable.Viewport>
|
||||||
<EditorOutlinePanel editor={editorContainer} />
|
<EditorOutlinePanel editor={editorContainer?.host ?? null} />
|
||||||
</Scrollable.Viewport>
|
</Scrollable.Viewport>
|
||||||
<Scrollable.Scrollbar />
|
<Scrollable.Scrollbar />
|
||||||
</Scrollable.Root>
|
</Scrollable.Root>
|
||||||
@@ -359,7 +359,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
|
|||||||
<ViewSidebarTab tabId="frame" icon={<FrameIcon />}>
|
<ViewSidebarTab tabId="frame" icon={<FrameIcon />}>
|
||||||
<Scrollable.Root className={styles.sidebarScrollArea}>
|
<Scrollable.Root className={styles.sidebarScrollArea}>
|
||||||
<Scrollable.Viewport>
|
<Scrollable.Viewport>
|
||||||
<EditorFramePanel editor={editorContainer} />
|
<EditorFramePanel editor={editorContainer?.host ?? null} />
|
||||||
</Scrollable.Viewport>
|
</Scrollable.Viewport>
|
||||||
<Scrollable.Scrollbar />
|
<Scrollable.Scrollbar />
|
||||||
</Scrollable.Root>
|
</Scrollable.Root>
|
||||||
|
|||||||
@@ -1,34 +1,30 @@
|
|||||||
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import { FramePanel } from '@blocksuite/affine/blocks';
|
import { FramePanel } from '@blocksuite/affine/blocks';
|
||||||
import type { AffineEditorContainer } from '@blocksuite/affine/presets';
|
|
||||||
import { useCallback, useEffect, useRef } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
import * as styles from './frame.css';
|
import * as styles from './frame.css';
|
||||||
|
|
||||||
// A wrapper for FramePanel
|
// A wrapper for FramePanel
|
||||||
export const EditorFramePanel = ({
|
export const EditorFramePanel = ({ editor }: { editor: EditorHost | null }) => {
|
||||||
editor,
|
|
||||||
}: {
|
|
||||||
editor: AffineEditorContainer | null;
|
|
||||||
}) => {
|
|
||||||
const framePanelRef = useRef<FramePanel | null>(null);
|
const framePanelRef = useRef<FramePanel | null>(null);
|
||||||
|
|
||||||
const onRefChange = useCallback(
|
const onRefChange = useCallback(
|
||||||
(container: HTMLDivElement | null) => {
|
(container: HTMLDivElement | null) => {
|
||||||
if (editor?.host && container && container.children.length === 0) {
|
if (editor && container && container.children.length === 0) {
|
||||||
framePanelRef.current = new FramePanel();
|
framePanelRef.current = new FramePanel();
|
||||||
framePanelRef.current.host = editor.host;
|
framePanelRef.current.host = editor;
|
||||||
framePanelRef.current.fitPadding = [20, 20, 20, 20];
|
framePanelRef.current.fitPadding = [20, 20, 20, 20];
|
||||||
container.append(framePanelRef.current);
|
container.append(framePanelRef.current);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[editor?.host]
|
[editor]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editor?.host && framePanelRef.current) {
|
if (editor && framePanelRef.current) {
|
||||||
framePanelRef.current.host = editor.host;
|
framePanelRef.current.host = editor;
|
||||||
}
|
}
|
||||||
}, [editor?.host]);
|
}, [editor]);
|
||||||
|
|
||||||
return <div className={styles.root} ref={onRefChange} />;
|
return <div className={styles.root} ref={onRefChange} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { AffineEditorContainer } from '@blocksuite/affine/presets';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import { OutlinePanel } from '@blocksuite/affine/presets';
|
import { OutlinePanel } from '@blocksuite/affine/presets';
|
||||||
import { useCallback, useEffect, useRef } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ import * as styles from './outline.css';
|
|||||||
export const EditorOutlinePanel = ({
|
export const EditorOutlinePanel = ({
|
||||||
editor,
|
editor,
|
||||||
}: {
|
}: {
|
||||||
editor: AffineEditorContainer | null;
|
editor: EditorHost | null;
|
||||||
}) => {
|
}) => {
|
||||||
const outlinePanelRef = useRef<OutlinePanel | null>(null);
|
const outlinePanelRef = useRef<OutlinePanel | null>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ const SharePageInner = ({
|
|||||||
<Scrollable.Scrollbar />
|
<Scrollable.Scrollbar />
|
||||||
</Scrollable.Root>
|
</Scrollable.Root>
|
||||||
<EditorOutlineViewer
|
<EditorOutlineViewer
|
||||||
editor={editorContainer}
|
editor={editorContainer?.host ?? null}
|
||||||
show={publishMode === 'page'}
|
show={publishMode === 'page'}
|
||||||
/>
|
/>
|
||||||
{!BUILD_CONFIG.isElectron && <SharePageFooter />}
|
{!BUILD_CONFIG.isElectron && <SharePageFooter />}
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
import {
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
type AffineEditorContainer,
|
import { MobileOutlineMenu } from '@blocksuite/affine/presets';
|
||||||
MobileOutlineMenu,
|
|
||||||
} from '@blocksuite/affine/presets';
|
|
||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
|
|
||||||
export const MobileTocMenu = ({
|
export const MobileTocMenu = ({ editor }: { editor: EditorHost | null }) => {
|
||||||
editor,
|
|
||||||
}: {
|
|
||||||
editor: AffineEditorContainer | null;
|
|
||||||
}) => {
|
|
||||||
const outlineMenuRef = useRef<MobileOutlineMenu | null>(null);
|
const outlineMenuRef = useRef<MobileOutlineMenu | null>(null);
|
||||||
const onRefChange = useCallback((container: HTMLDivElement | null) => {
|
const onRefChange = useCallback((container: HTMLDivElement | null) => {
|
||||||
if (container) {
|
if (container) {
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ export const PageHeaderMenuButton = () => {
|
|||||||
title={t['com.affine.header.menu.toc']()}
|
title={t['com.affine.header.menu.toc']()}
|
||||||
items={
|
items={
|
||||||
<div className={styles.outlinePanel}>
|
<div className={styles.outlinePanel}>
|
||||||
<MobileTocMenu editor={editorContainer} />
|
<MobileTocMenu editor={editorContainer?.host ?? null} />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ function DocPeekPreviewEditor({
|
|||||||
</Scrollable.Root>
|
</Scrollable.Root>
|
||||||
{!BUILD_CONFIG.isMobileEdition && !BUILD_CONFIG.isMobileWeb ? (
|
{!BUILD_CONFIG.isMobileEdition && !BUILD_CONFIG.isMobileWeb ? (
|
||||||
<EditorOutlineViewer
|
<EditorOutlineViewer
|
||||||
editor={editorElement}
|
editor={editorElement?.host ?? null}
|
||||||
show={mode === 'page'}
|
show={mode === 'page'}
|
||||||
openOutlinePanel={openOutlinePanel}
|
openOutlinePanel={openOutlinePanel}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user