mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-21 17:10:12 +01:00
This commit is contained in:
parent
bedb811d6e
commit
fff0504935
10 changed files with 48 additions and 27 deletions
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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,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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 (scrollAttr) {
|
||||||
if (action.includes(Constants.CB_GET_SCROLL)) {
|
restoreScroll(protyle, scrollAttr === Constants.CB_GET_SCROLL ? undefined : scrollAttr);
|
||||||
restoreScroll(protyle);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)) {
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
export const saveScroll = (protyle: IProtyle, getString = false) => {
|
||||||
if (protyle.contentElement.clientHeight === protyle.contentElement.scrollHeight) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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) => {
|
export const restoreScroll = (protyle: IProtyle, scrollAttr?: string) => {
|
||||||
const attr = protyle.wysiwyg.element.getAttribute("scroll")
|
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) {
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
||||||
|
|
|
||||||
|
|
@ -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
app/src/types/protyle.d.ts
vendored
1
app/src/types/protyle.d.ts
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue