Преглед на файлове

:sparkles: https://github.com/siyuan-note/siyuan/issues/4042

Vanessa преди 3 години
родител
ревизия
fff0504935

+ 4 - 1
app/src/editor/index.ts

@@ -14,7 +14,8 @@ export class Editor extends Model {
         tab: Tab,
         tab: Tab,
         blockId: string,
         blockId: string,
         mode?: TEditorMode,
         mode?: TEditorMode,
-        action?: string[]
+        action?: string[],
+        scrollAttr?: string
     }) {
     }) {
         super({
         super({
             id: options.tab.id,
             id: options.tab.id,
@@ -31,6 +32,7 @@ export class Editor extends Model {
         blockId: string,
         blockId: string,
         action?: string[]
         action?: string[]
         mode?: TEditorMode,
         mode?: TEditorMode,
+        scrollAttr?: string
     }) {
     }) {
         this.editor = new Protyle(this.element, {
         this.editor = new Protyle(this.element, {
             action: options.action,
             action: options.action,
@@ -41,6 +43,7 @@ export class Editor extends Model {
                 background: true,
                 background: true,
                 scroll: true,
                 scroll: true,
             },
             },
+            scrollAttr: options.scrollAttr,
             typewriterMode: true,
             typewriterMode: true,
             after: (editor) => {
             after: (editor) => {
                 if (window.siyuan.config.readonly) {
                 if (window.siyuan.config.readonly) {

+ 6 - 2
app/src/layout/util.ts

@@ -25,6 +25,7 @@ import {getContenteditableElement} from "../protyle/wysiwyg/getBlock";
 import {updatePanelByEditor} from "../editor/util";
 import {updatePanelByEditor} from "../editor/util";
 import {Constants} from "../constants";
 import {Constants} from "../constants";
 import {openSearch} from "../search/spread";
 import {openSearch} from "../search/spread";
+import {saveScroll} from "../protyle/scroll/saveScroll";
 
 
 export const setPanelFocus = (element: Element) => {
 export const setPanelFocus = (element: Element) => {
     if (element.classList.contains("block__icons--active") || element.classList.contains("layout__wnd--active")) {
     if (element.classList.contains("block__icons--active") || element.classList.contains("layout__wnd--active")) {
@@ -210,7 +211,8 @@ const JSONToCenter = (json: any, layout?: Layout | Wnd | Tab | Model) => {
             tab: (layout as Tab),
             tab: (layout as Tab),
             blockId: json.blockId,
             blockId: json.blockId,
             mode: json.mode,
             mode: json.mode,
-            action: [json.action]
+            action: [json.action],
+            scrollAttr: json.scrollAttr,
         }));
         }));
     } else if (json.instance === "Asset") {
     } else if (json.instance === "Asset") {
         (layout as Tab).addModel(new Asset({
         (layout as Tab).addModel(new Asset({
@@ -364,6 +366,7 @@ export const layoutToJSON = (layout: Layout | Wnd | Tab | Model, json: any) => {
         json.mode = layout.editor.protyle.preview.element.classList.contains("fn__none") ? "wysiwyg" : "preview";
         json.mode = layout.editor.protyle.preview.element.classList.contains("fn__none") ? "wysiwyg" : "preview";
         json.action = layout.editor.protyle.block.showAll ? Constants.CB_GET_ALL : "";
         json.action = layout.editor.protyle.block.showAll ? Constants.CB_GET_ALL : "";
         json.instance = "Editor";
         json.instance = "Editor";
+        json.scrollAttr = saveScroll(layout.editor.protyle, true);
     } else if (layout instanceof Asset) {
     } else if (layout instanceof Asset) {
         json.path = layout.path;
         json.path = layout.path;
         json.instance = "Asset";
         json.instance = "Asset";
@@ -470,7 +473,8 @@ export const copyTab = (tab: Tab) => {
             if (tab.model instanceof Editor) {
             if (tab.model instanceof Editor) {
                 model = new Editor({
                 model = new Editor({
                     tab: newTab,
                     tab: newTab,
-                    blockId: tab.model.editor.protyle.block.rootID
+                    blockId: tab.model.editor.protyle.block.rootID,
+                    scrollAttr: saveScroll(tab.model.editor.protyle, true)
                 });
                 });
             } else if (tab.model instanceof Asset) {
             } else if (tab.model instanceof Asset) {
                 model = new Asset({
                 model = new Asset({

+ 5 - 2
app/src/protyle/breadcrumb/action.ts

@@ -5,12 +5,15 @@ import {addLoading, setPadding} from "../ui/initUI";
 import {fetchPost} from "../../util/fetch";
 import {fetchPost} from "../../util/fetch";
 import {Constants} from "../../constants";
 import {Constants} from "../../constants";
 import {onGet} from "../util/onGet";
 import {onGet} from "../util/onGet";
+import {saveScroll} from "../scroll/saveScroll";
+import {hideElements} from "../ui/hideElements";
 
 
 export const netImg2LocalAssets = (protyle: IProtyle) => {
 export const netImg2LocalAssets = (protyle: IProtyle) => {
     if (protyle.element.querySelector(".fn__loading")) {
     if (protyle.element.querySelector(".fn__loading")) {
         return;
         return;
     }
     }
     addLoading(protyle);
     addLoading(protyle);
+    hideElements(["toolbar"], protyle);
     fetchPost("/api/format/netImg2LocalAssets", {
     fetchPost("/api/format/netImg2LocalAssets", {
         id: protyle.block.rootID
         id: protyle.block.rootID
     }, () => {
     }, () => {
@@ -20,7 +23,7 @@ export const netImg2LocalAssets = (protyle: IProtyle) => {
             mode: 0,
             mode: 0,
             size: Constants.SIZE_GET,
             size: Constants.SIZE_GET,
         }, getResponse => {
         }, getResponse => {
-            onGet(getResponse, protyle, [Constants.CB_GET_FOCUS]);
+            onGet(getResponse, protyle, [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
         });
         });
         /// #else
         /// #else
         getAllModels().editor.forEach(item => {
         getAllModels().editor.forEach(item => {
@@ -30,7 +33,7 @@ export const netImg2LocalAssets = (protyle: IProtyle) => {
                     mode: 0,
                     mode: 0,
                     size: Constants.SIZE_GET,
                     size: Constants.SIZE_GET,
                 }, getResponse => {
                 }, getResponse => {
-                    onGet(getResponse, item.editor.protyle, [Constants.CB_GET_FOCUS]);
+                    onGet(getResponse, item.editor.protyle, [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
                 });
                 });
             }
             }
         });
         });

+ 7 - 4
app/src/protyle/breadcrumb/index.ts

@@ -22,6 +22,8 @@ import {getAllModels} from "../../layout/getAll";
 import {getCurrentWindow} from "@electron/remote";
 import {getCurrentWindow} from "@electron/remote";
 /// #endif
 /// #endif
 import {onGet} from "../util/onGet";
 import {onGet} from "../util/onGet";
+import {saveScroll} from "../scroll/saveScroll";
+import {hideElements} from "../ui/hideElements";
 
 
 export class Breadcrumb {
 export class Breadcrumb {
     public element: HTMLElement;
     public element: HTMLElement;
@@ -218,7 +220,7 @@ export class Breadcrumb {
                 label: window.siyuan.languages.netImg2LocalAsset,
                 label: window.siyuan.languages.netImg2LocalAsset,
                 icon: "iconTransform",
                 icon: "iconTransform",
                 accelerator: window.siyuan.config.keymap.editor.general.netImg2LocalAsset.custom,
                 accelerator: window.siyuan.config.keymap.editor.general.netImg2LocalAsset.custom,
-                click () {
+                click() {
                     netImg2LocalAssets(protyle);
                     netImg2LocalAssets(protyle);
                 }
                 }
             }).element);
             }).element);
@@ -226,6 +228,7 @@ export class Breadcrumb {
                 label: window.siyuan.languages.optimizeTypography,
                 label: window.siyuan.languages.optimizeTypography,
                 icon: "iconFormat",
                 icon: "iconFormat",
                 click: () => {
                 click: () => {
+                    hideElements(["toolbar"], protyle);
                     fetchPost("/api/format/autoSpace", {
                     fetchPost("/api/format/autoSpace", {
                         id: protyle.block.rootID
                         id: protyle.block.rootID
                     }, () => {
                     }, () => {
@@ -235,7 +238,7 @@ export class Breadcrumb {
                             mode: 0,
                             mode: 0,
                             size: Constants.SIZE_GET,
                             size: Constants.SIZE_GET,
                         }, getResponse => {
                         }, getResponse => {
-                            onGet(getResponse, protyle, [Constants.CB_GET_FOCUS]);
+                            onGet(getResponse, protyle, [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
                         });
                         });
                         /// #else
                         /// #else
                         getAllModels().editor.forEach(item => {
                         getAllModels().editor.forEach(item => {
@@ -245,7 +248,7 @@ export class Breadcrumb {
                                     mode: 0,
                                     mode: 0,
                                     size: Constants.SIZE_GET,
                                     size: Constants.SIZE_GET,
                                 }, getResponse => {
                                 }, getResponse => {
-                                    onGet(getResponse, item.editor.protyle, [Constants.CB_GET_FOCUS]);
+                                    onGet(getResponse, item.editor.protyle, [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
                                 });
                                 });
                             }
                             }
                         });
                         });
@@ -274,7 +277,7 @@ export class Breadcrumb {
                         mode: 0,
                         mode: 0,
                         size: protyle.block.showAll ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
                         size: protyle.block.showAll ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
                     }, getResponse => {
                     }, getResponse => {
-                        onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS]);
+                        onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
                     });
                     });
                 }
                 }
             }).element);
             }).element);

+ 4 - 5
app/src/protyle/header/Title.ts

@@ -325,9 +325,9 @@ ${window.siyuan.languages.createdAt} ${dayjs(response.data.ial.id.substr(0, 14))
         }
         }
     }
     }
 
 
-    public render(protyle: IProtyle, refresh = false, action:string[] = []) {
+    public render(protyle: IProtyle, refresh = false, scrollAttr?: string) {
         if (this.editElement.getAttribute("data-render") === "true" && !refresh) {
         if (this.editElement.getAttribute("data-render") === "true" && !refresh) {
-            return;
+            return false;
         }
         }
         fetchPost("/api/block/getDocInfo", {
         fetchPost("/api/block/getDocInfo", {
             id: protyle.block.rootID
             id: protyle.block.rootID
@@ -360,9 +360,8 @@ ${window.siyuan.languages.createdAt} ${dayjs(response.data.ial.id.substr(0, 14))
                 range.selectNodeContents(this.editElement);
                 range.selectNodeContents(this.editElement);
                 focusByRange(range);
                 focusByRange(range);
             }
             }
-
-            if (action.includes(Constants.CB_GET_SCROLL)) {
-                restoreScroll(protyle);
+            if (scrollAttr) {
+                restoreScroll(protyle, scrollAttr === Constants.CB_GET_SCROLL ? undefined : scrollAttr);
             }
             }
         });
         });
     }
     }

+ 1 - 1
app/src/protyle/index.ts

@@ -160,7 +160,7 @@ class Protyle {
             mode: (options.action && options.action.includes(Constants.CB_GET_CONTEXT)) ? 3 : 0, // 0: 仅当前 ID(默认值),1:向上 2:向下,3:上下都加载,4:加载最后
             mode: (options.action && options.action.includes(Constants.CB_GET_CONTEXT)) ? 3 : 0, // 0: 仅当前 ID(默认值),1:向上 2:向下,3:上下都加载,4:加载最后
             size: options.action?.includes(Constants.CB_GET_ALL) ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
             size: options.action?.includes(Constants.CB_GET_ALL) ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
         }, getResponse => {
         }, getResponse => {
-            onGet(getResponse, this.protyle, options.action);
+            onGet(getResponse, this.protyle, options.action, options.scrollAttr);
             if (this.protyle.model) {
             if (this.protyle.model) {
                 /// #if !MOBILE
                 /// #if !MOBILE
                 if (options.action?.includes(Constants.CB_GET_FOCUS)) {
                 if (options.action?.includes(Constants.CB_GET_FOCUS)) {

+ 9 - 8
app/src/protyle/scroll/saveScroll.ts

@@ -3,11 +3,9 @@ import {hasClosestBlock} from "../util/hasClosest";
 import {focusByOffset, getSelectionOffset} from "../util/selection";
 import {focusByOffset, getSelectionOffset} from "../util/selection";
 import {fetchPost} from "../../util/fetch";
 import {fetchPost} from "../../util/fetch";
 import {zoomOut} from "../../menus/protyle";
 import {zoomOut} from "../../menus/protyle";
+import {preventScroll} from "./preventScroll";
 
 
-export const saveScroll = (protyle: IProtyle) => {
-    if (protyle.contentElement.clientHeight === protyle.contentElement.scrollHeight) {
-        return;
-    }
+export const saveScroll = (protyle: IProtyle, getString = false) => {
     let attr = `${protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id")}${Constants.ZWSP}${protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id")}${Constants.ZWSP}${protyle.contentElement.scrollTop}`;
     let attr = `${protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id")}${Constants.ZWSP}${protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id")}${Constants.ZWSP}${protyle.contentElement.scrollTop}`;
     let range: Range
     let range: Range
     if (getSelection().rangeCount > 0) {
     if (getSelection().rangeCount > 0) {
@@ -24,17 +22,20 @@ export const saveScroll = (protyle: IProtyle) => {
     if (protyle.block.showAll) {
     if (protyle.block.showAll) {
         attr += `${Constants.ZWSP}${protyle.block.id}`;
         attr += `${Constants.ZWSP}${protyle.block.id}`;
     }
     }
-
+    if (getString) {
+        return attr;
+    }
     fetchPost("/api/attr/setBlockAttrs", {id: protyle.block.rootID, attrs: {scroll: attr}}, () => {
     fetchPost("/api/attr/setBlockAttrs", {id: protyle.block.rootID, attrs: {scroll: attr}}, () => {
         protyle.wysiwyg.element.setAttribute("scroll", attr);
         protyle.wysiwyg.element.setAttribute("scroll", attr);
     });
     });
 }
 }
 
 
-export const restoreScroll = (protyle: IProtyle) => {
-    const attr = protyle.wysiwyg.element.getAttribute("scroll")
+export const restoreScroll = (protyle: IProtyle, scrollAttr?: string) => {
+    const attr = scrollAttr || protyle.wysiwyg.element.getAttribute("scroll")
     if (!attr) {
     if (!attr) {
-        return
+        return;
     }
     }
+    preventScroll(protyle);
     const [startId, endId, scrollTop, focusId, focusStart, focusEnd, zoomInId] = attr.split(Constants.ZWSP);
     const [startId, endId, scrollTop, focusId, focusStart, focusEnd, zoomInId] = attr.split(Constants.ZWSP);
     if (protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id") === startId &&
     if (protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id") === startId &&
         protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id") === endId) {
         protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id") === endId) {

+ 8 - 2
app/src/protyle/util/onGet.ts

@@ -14,8 +14,9 @@ import {pushBack} from "../../util/backForward";
 import {focusBlock} from "./selection";
 import {focusBlock} from "./selection";
 import {hasClosestByAttribute, hasClosestByClassName} from "./hasClosest";
 import {hasClosestByAttribute, hasClosestByClassName} from "./hasClosest";
 import {preventScroll} from "../scroll/preventScroll";
 import {preventScroll} from "../scroll/preventScroll";
+import {restoreScroll} from "../scroll/saveScroll";
 
 
-export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[] = []) => {
+export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[] = [], scrollAttr?: string) => {
     const loadingElement = protyle.element.querySelector(".fn__loading");
     const loadingElement = protyle.element.querySelector(".fn__loading");
     if (loadingElement) {
     if (loadingElement) {
         loadingElement.remove();
         loadingElement.remove();
@@ -80,7 +81,8 @@ export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[]
     }
     }
 
 
     if (protyle.options.render.title) {
     if (protyle.options.render.title) {
-        protyle.title.render(protyle, false, action);
+        // 页签没有打开
+        protyle.title.render(protyle, false, scrollAttr ? scrollAttr : (action.includes(Constants.CB_GET_SCROLL) ? Constants.CB_GET_SCROLL : null));
     } else if (protyle.options.render.background) {
     } else if (protyle.options.render.background) {
         fetchPost("/api/block/getDocInfo", {
         fetchPost("/api/block/getDocInfo", {
             id: protyle.block.rootID
             id: protyle.block.rootID
@@ -94,6 +96,10 @@ export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[]
         content: html,
         content: html,
         action,
         action,
     }, protyle);
     }, protyle);
+
+    if (scrollAttr && ((protyle.options.render.title && protyle.title.editElement.getAttribute("data-render") === "true") || !protyle.options.render.title)) {
+        restoreScroll(protyle, scrollAttr);
+    }
 };
 };
 
 
 const setHTML = (options: { content: string, action?: string[] }, protyle: IProtyle) => {
 const setHTML = (options: { content: string, action?: string[] }, protyle: IProtyle) => {

+ 3 - 2
app/src/protyle/wysiwyg/commonHotkey.ts

@@ -7,6 +7,7 @@ import {addLoading, setPadding} from "../ui/initUI";
 import {Constants} from "../../constants";
 import {Constants} from "../../constants";
 import {onGet} from "../util/onGet";
 import {onGet} from "../util/onGet";
 import {openBacklink, openGraph, openOutline} from "../../layout/dock/util";
 import {openBacklink, openGraph, openOutline} from "../../layout/dock/util";
+import {saveScroll} from "../scroll/saveScroll";
 
 
 export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent) => {
 export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent) => {
     const target = event.target as HTMLElement;
     const target = event.target as HTMLElement;
@@ -21,14 +22,14 @@ export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent) => {
         return true;
         return true;
     }
     }
     if (matchHotKey(window.siyuan.config.keymap.editor.general.refresh.custom, event)) {
     if (matchHotKey(window.siyuan.config.keymap.editor.general.refresh.custom, event)) {
-        protyle.title.render(protyle, true);
+        protyle.title?.render(protyle, true);
         addLoading(protyle);
         addLoading(protyle);
         fetchPost("/api/filetree/getDoc", {
         fetchPost("/api/filetree/getDoc", {
             id: protyle.block.showAll ? protyle.block.id : protyle.block.rootID,
             id: protyle.block.showAll ? protyle.block.id : protyle.block.rootID,
             mode: 0,
             mode: 0,
             size: protyle.block.showAll ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
             size: protyle.block.showAll ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
         }, getResponse => {
         }, getResponse => {
-            onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS]);
+            onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
         });
         });
         event.preventDefault();
         event.preventDefault();
         event.stopPropagation();
         event.stopPropagation();

+ 1 - 0
app/src/types/protyle.d.ts

@@ -346,6 +346,7 @@ interface IOptions {
     mode?: TEditorMode,
     mode?: TEditorMode,
     blockId: string
     blockId: string
     key?: string
     key?: string
+    scrollAttr?: string
     defId?: string
     defId?: string
     render?: {
     render?: {
         background?: boolean
         background?: boolean