From c0a3635809c5c88ff9c14e7da7c076293b71f618 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Sat, 22 Nov 2025 21:05:10 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/16420 --- app/src/editor/index.ts | 3 +++ app/src/editor/util.ts | 18 +++++++++++++----- app/src/layout/dock/Outline.ts | 4 ++-- app/src/protyle/index.ts | 1 + app/src/protyle/util/onGet.ts | 16 ++++++++++------ app/src/types/index.d.ts | 2 +- app/src/types/protyle.d.ts | 1 + 7 files changed, 31 insertions(+), 14 deletions(-) diff --git a/app/src/editor/index.ts b/app/src/editor/index.ts index 6232e2278..3000dc615 100644 --- a/app/src/editor/index.ts +++ b/app/src/editor/index.ts @@ -23,6 +23,7 @@ export class Editor extends Model { mode?: TEditorMode, action?: TProtyleAction[], afterInitProtyle?: (editor: Protyle) => void, + scrollPosition?: ScrollLogicalPosition }) { super({ app: options.app, @@ -43,6 +44,7 @@ export class Editor extends Model { action?: TProtyleAction[] rootId: string, mode?: TEditorMode, + scrollPosition?: ScrollLogicalPosition, afterInitProtyle?: (editor: Protyle) => void, }) { this.editor = new Protyle(this.app, this.element, { @@ -56,6 +58,7 @@ export class Editor extends Model { scroll: true, }, typewriterMode: true, + scrollPosition: options.scrollPosition, after: (editor) => { if (window.siyuan.editorIsFullscreen) { fullscreen(editor.protyle.element); diff --git a/app/src/editor/util.ts b/app/src/editor/util.ts index 049a008d3..dfb8c2e5e 100644 --- a/app/src/editor/util.ts +++ b/app/src/editor/util.ts @@ -47,7 +47,7 @@ export const openFileById = async (options: { removeCurrentTab?: boolean openNewTab?: boolean afterOpen?: (model: Model) => void, - scrollPositon?: ScrollLogicalPosition + scrollPosition?: ScrollLogicalPosition }) => { const response = await fetchSyncPost("/api/block/getBlockInfo", {id: options.id}); if (response.code === -1) { @@ -72,7 +72,7 @@ export const openFileById = async (options: { removeCurrentTab: options.removeCurrentTab, afterOpen: options.afterOpen, openNewTab: options.openNewTab, - scrollPositon: options.scrollPositon, + scrollPosition: options.scrollPosition, }); }; @@ -378,7 +378,12 @@ const switchEditor = (editor: Editor, options: IOpenFileOptions, allModels: IMod mode: (options.action && options.action.includes(Constants.CB_GET_CONTEXT)) ? 3 : 0, size: window.siyuan.config.editor.dynamicLoadBlocks, }, getResponse => { - onGet({data: getResponse, protyle: editor.editor.protyle, action: options.action}); + onGet({ + data: getResponse, + protyle: editor.editor.protyle, + action: options.action, + scrollPosition: options.scrollPosition + }); // 大纲点击折叠标题下的内容时,需更新反链面板 updateBacklinkGraph(allModels, editor.editor.protyle); }); @@ -388,13 +393,14 @@ const switchEditor = (editor: Editor, options: IOpenFileOptions, allModels: IMod editor.editor.protyle.observerLoad?.disconnect(); if (options.action?.includes(Constants.CB_GET_HL)) { highlightById(editor.editor.protyle, options.id, "start"); - } else if (options.action?.includes(Constants.CB_GET_FOCUS)) { + } + if (options.action?.includes(Constants.CB_GET_FOCUS)) { if (nodeElement) { const newRange = focusBlock(nodeElement, undefined, !options.action?.includes(Constants.CB_GET_OUTLINE)); if (newRange) { editor.editor.protyle.toolbar.range = newRange; } - scrollCenter(editor.editor.protyle, (editor.editor.protyle.disabled || options.scrollPositon) ? nodeElement : null, options.scrollPositon); + scrollCenter(editor.editor.protyle, (editor.editor.protyle.disabled || options.scrollPosition) ? nodeElement : null, options.scrollPosition); editor.editor.protyle.observerLoad = new ResizeObserver(() => { if (document.contains(nodeElement)) { scrollCenter(editor.editor.protyle); @@ -506,6 +512,7 @@ const newTab = (options: IOpenFileOptions) => { blockId: options.id, rootId: options.rootID, action: [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS], + scrollPosition: options.scrollPosition, }); } else { editor = new Editor({ @@ -515,6 +522,7 @@ const newTab = (options: IOpenFileOptions) => { rootId: options.rootID, mode: options.mode, action: options.action, + scrollPosition: options.scrollPosition, }); } tab.addModel(editor); diff --git a/app/src/layout/dock/Outline.ts b/app/src/layout/dock/Outline.ts index c3e3a4ecd..49ca96a6f 100644 --- a/app/src/layout/dock/Outline.ts +++ b/app/src/layout/dock/Outline.ts @@ -177,7 +177,7 @@ export class Outline extends Model { openFileById({ app: options.app, id, - scrollPositon: "start", + scrollPosition: "start", action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HTML, Constants.CB_GET_OUTLINE] : [Constants.CB_GET_FOCUS, Constants.CB_GET_OUTLINE, Constants.CB_GET_SETID, Constants.CB_GET_CONTEXT, Constants.CB_GET_HTML], }); }); @@ -931,7 +931,7 @@ export class Outline extends Model { openFileById({ app: this.app, id, - scrollPositon: "start", + scrollPosition: "start", action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HTML, Constants.CB_GET_OUTLINE] : [Constants.CB_GET_FOCUS, Constants.CB_GET_OUTLINE, Constants.CB_GET_SETID, Constants.CB_GET_CONTEXT, Constants.CB_GET_HTML], }); }); diff --git a/app/src/protyle/index.ts b/app/src/protyle/index.ts index 86989d811..0ee2a037f 100644 --- a/app/src/protyle/index.ts +++ b/app/src/protyle/index.ts @@ -347,6 +347,7 @@ export class Protyle { data: getResponse, protyle: this.protyle, action: mergedOptions.action, + scrollPosition: mergedOptions.scrollPosition, afterCB: () => { this.afterOnGet(mergedOptions); } diff --git a/app/src/protyle/util/onGet.ts b/app/src/protyle/util/onGet.ts index ac7af0f78..a0874e0da 100644 --- a/app/src/protyle/util/onGet.ts +++ b/app/src/protyle/util/onGet.ts @@ -26,7 +26,8 @@ export const onGet = (options: { protyle: IProtyle, action?: TProtyleAction[], scrollAttr?: IScrollAttr - updateReadonly?: boolean + updateReadonly?: boolean, + scrollPosition?: ScrollLogicalPosition, afterCB?: () => void }) => { if (!options.action) { @@ -96,6 +97,7 @@ export const onGet = (options: { updateReadonly: options.updateReadonly, isSyncing: options.data.data.isSyncing, afterCB: options.afterCB, + scrollPosition: options.scrollPosition }, options.protyle); removeLoading(options.protyle); return; @@ -122,6 +124,7 @@ export const onGet = (options: { updateReadonly: options.updateReadonly, isSyncing: options.data.data.isSyncing, afterCB: options.afterCB, + scrollPosition: options.scrollPosition }, options.protyle); removeLoading(options.protyle); }); @@ -133,7 +136,8 @@ const setHTML = (options: { isSyncing: boolean, expand: boolean, updateReadonly?: boolean, - scrollAttr?: IScrollAttr + scrollAttr?: IScrollAttr, + scrollPosition?: ScrollLogicalPosition, afterCB?: () => void }, protyle: IProtyle) => { if (protyle.contentElement.classList.contains("fn__none") && protyle.wysiwyg.element.innerHTML !== "") { @@ -256,7 +260,7 @@ const setHTML = (options: { } } - focusElementById(protyle, options.action, options.scrollAttr); + focusElementById(protyle, options.action, options.scrollAttr, options.scrollPosition); if (options.action.includes(Constants.CB_GET_SETID)) { // 点击大纲后,如果需要动态加载,在定位后,需要重置 block.id https://github.com/siyuan-note/siyuan/issues/4487 @@ -448,7 +452,7 @@ export const enableProtyle = (protyle: IProtyle) => { hideTooltip(); }; -const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScrollAttr) => { +const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScrollAttr, scrollPosition?: ScrollLogicalPosition) => { let focusElement: Element; if (scrollAttr && scrollAttr.focusId) { focusElement = protyle.wysiwyg.element.querySelector(`[data-node-id="${scrollAttr.focusId}"]`); @@ -491,7 +495,7 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr protyle.observerLoad?.disconnect(); if (action.includes(Constants.CB_GET_FOCUS) || action.includes(Constants.CB_GET_SCROLL) || action.includes(Constants.CB_GET_HL) || action.includes(Constants.CB_GET_FOCUSFIRST)) { if (!hasScrollTop) { - scrollCenter(protyle, focusElement); + scrollCenter(protyle, focusElement, scrollPosition); } } else { return; @@ -503,7 +507,7 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr } if (action.includes(Constants.CB_GET_FOCUS) || action.includes(Constants.CB_GET_HL) || action.includes(Constants.CB_GET_FOCUSFIRST)) { if (!hasScrollTop) { - scrollCenter(protyle, focusElement); + scrollCenter(protyle, focusElement, scrollPosition); } } }); diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts index 05f4c6ea9..4a7f497f3 100644 --- a/app/src/types/index.d.ts +++ b/app/src/types/index.d.ts @@ -663,7 +663,7 @@ interface IOpenFileOptions { data: any, }) => import("../layout/Model").Model, // plugin 0.8.3 历史兼容 } - scrollPositon?: ScrollLogicalPosition, + scrollPosition?: ScrollLogicalPosition, assetPath?: string, // asset 必填 fileName?: string, // file 必填 rootIcon?: string, // 文档图标 diff --git a/app/src/types/protyle.d.ts b/app/src/types/protyle.d.ts index 4335af229..caefab99d 100644 --- a/app/src/types/protyle.d.ts +++ b/app/src/types/protyle.d.ts @@ -446,6 +446,7 @@ interface IProtyleOptions { expand: boolean }[], action?: TProtyleAction[], + scrollPosition?: ScrollLogicalPosition, mode?: TEditorMode, blockId?: string rootId?: string