Vanessa 2022-08-07 21:58:41 +08:00
parent ad2510dfb5
commit b5b46afabd
9 changed files with 124 additions and 97 deletions

View file

@ -15,7 +15,7 @@ export class Editor extends Model {
blockId: string,
mode?: TEditorMode,
action?: string[],
scrollAttr?: string
scrollAttr?: IScrollAttr
}) {
super({
id: options.tab.id,
@ -32,7 +32,7 @@ export class Editor extends Model {
blockId: string,
action?: string[]
mode?: TEditorMode,
scrollAttr?: string
scrollAttr?: IScrollAttr
}) {
this.editor = new Protyle(this.element, {
action: options.action,

View file

@ -271,13 +271,12 @@ export class Breadcrumb {
accelerator: window.siyuan.config.keymap.editor.general.refresh.custom,
label: window.siyuan.languages.refresh,
click: () => {
protyle.title?.render(protyle, true);
fetchPost("/api/filetree/getDoc", {
id: protyle.block.showAll ? protyle.block.id : protyle.block.rootID,
mode: 0,
size: protyle.block.showAll ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
}, getResponse => {
onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS], saveScroll(protyle, true), true);
});
}
}).element);

View file

@ -325,48 +325,37 @@ ${window.siyuan.languages.createdAt} ${dayjs(response.data.ial.id.substr(0, 14))
}
}
public render(protyle: IProtyle, refresh = false, scrollAttr?: string) {
public render(protyle: IProtyle, response: IWebSocketData, refresh = false) {
if (this.editElement.getAttribute("data-render") === "true" && !refresh) {
return false;
}
fetchPost("/api/block/getDocInfo", {
id: protyle.block.rootID
}, (response) => {
setTitle(response.data.ial.title);
protyle.background.render(response.data.ial, protyle.block.rootID);
protyle.wysiwyg.renderCustom(response.data.ial);
this.editElement.setAttribute("data-render", "true");
this.setTitle(response.data.ial.title);
let nodeAttrHTML = "";
if (response.data.ial.bookmark) {
nodeAttrHTML += `<div class="protyle-attr--bookmark">${Lute.EscapeHTMLStr(response.data.ial.bookmark)}</div>`;
}
if (response.data.ial.name) {
nodeAttrHTML += `<div class="protyle-attr--name"><svg><use xlink:href="#iconN"></use></svg>${Lute.EscapeHTMLStr(response.data.ial.name)}</div>`;
}
if (response.data.ial.alias) {
nodeAttrHTML += `<div class="protyle-attr--alias"><svg><use xlink:href="#iconA"></use></svg>${Lute.EscapeHTMLStr(response.data.ial.alias)}</div>`;
}
if (response.data.ial.memo) {
nodeAttrHTML += `<div class="protyle-attr--memo b3-tooltips b3-tooltips__sw" aria-label="${Lute.EscapeHTMLStr(response.data.ial.memo)}"><svg><use xlink:href="#iconM"></use></svg></div>`;
}
this.element.querySelector(".protyle-attr").innerHTML = nodeAttrHTML;
if (response.data.refCount !== 0) {
this.element.querySelector(".protyle-attr").insertAdjacentHTML("beforeend", `<div class="protyle-attr--refcount popover__block" data-defids='${JSON.stringify([protyle.block.rootID])}' data-id='${JSON.stringify(response.data.refIDs)}'>${response.data.refCount}</div>`);
}
// 存在设置新建文档名模板,不能使用 Untitled 进行判断https://ld246.com/article/1649301009888
if (new Date().getTime() - dayjs(response.data.id.split("-")[0]).toDate().getTime() < 2000) {
const range = this.editElement.ownerDocument.createRange();
range.selectNodeContents(this.editElement);
focusByRange(range);
}
const loadingElement = protyle.element.querySelector(".fn__loading");
if (loadingElement) {
loadingElement.remove();
}
if (scrollAttr) {
restoreScroll(protyle, scrollAttr === Constants.CB_GET_SCROLL ? undefined : scrollAttr);
}
});
setTitle(response.data.ial.title);
protyle.background.render(response.data.ial, protyle.block.rootID);
protyle.wysiwyg.renderCustom(response.data.ial);
this.editElement.setAttribute("data-render", "true");
this.setTitle(response.data.ial.title);
let nodeAttrHTML = "";
if (response.data.ial.bookmark) {
nodeAttrHTML += `<div class="protyle-attr--bookmark">${Lute.EscapeHTMLStr(response.data.ial.bookmark)}</div>`;
}
if (response.data.ial.name) {
nodeAttrHTML += `<div class="protyle-attr--name"><svg><use xlink:href="#iconN"></use></svg>${Lute.EscapeHTMLStr(response.data.ial.name)}</div>`;
}
if (response.data.ial.alias) {
nodeAttrHTML += `<div class="protyle-attr--alias"><svg><use xlink:href="#iconA"></use></svg>${Lute.EscapeHTMLStr(response.data.ial.alias)}</div>`;
}
if (response.data.ial.memo) {
nodeAttrHTML += `<div class="protyle-attr--memo b3-tooltips b3-tooltips__sw" aria-label="${Lute.EscapeHTMLStr(response.data.ial.memo)}"><svg><use xlink:href="#iconM"></use></svg></div>`;
}
this.element.querySelector(".protyle-attr").innerHTML = nodeAttrHTML;
if (response.data.refCount !== 0) {
this.element.querySelector(".protyle-attr").insertAdjacentHTML("beforeend", `<div class="protyle-attr--refcount popover__block" data-defids='${JSON.stringify([protyle.block.rootID])}' data-id='${JSON.stringify(response.data.refIDs)}'>${response.data.refCount}</div>`);
}
// 存在设置新建文档名模板,不能使用 Untitled 进行判断https://ld246.com/article/1649301009888
if (new Date().getTime() - dayjs(response.data.id.split("-")[0]).toDate().getTime() < 2000) {
const range = this.editElement.ownerDocument.createRange();
range.selectNodeContents(this.editElement);
focusByRange(range);
}
}
}

View file

@ -1,12 +1,16 @@
import {Constants} from "../../constants";
import {hasClosestBlock} from "../util/hasClosest";
import {focusByOffset, getSelectionOffset} from "../util/selection";
import {fetchPost} from "../../util/fetch";
import {zoomOut} from "../../menus/protyle";
import {preventScroll} from "./preventScroll";
import {pushBack} from "../../util/backForward";
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}`;
export const saveScroll = (protyle: IProtyle, getObject = false) => {
const attr: IScrollAttr = {
startId: protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id"),
endId: protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id"),
scrollTop: protyle.contentElement.scrollTop
}
let range: Range
if (getSelection().rangeCount > 0) {
range = getSelection().getRangeAt(0)
@ -16,45 +20,58 @@ export const saveScroll = (protyle: IProtyle, getString = false) => {
const blockElement = hasClosestBlock(range.startContainer);
if (blockElement) {
const position = getSelectionOffset(blockElement, undefined, range);
attr += `${Constants.ZWSP}${blockElement.getAttribute("data-node-id")}${Constants.ZWSP}${position.start}${Constants.ZWSP}${position.end}`;
attr.focusId = blockElement.getAttribute("data-node-id");
attr.focusStart = position.start
attr.focusEnd = position.end
}
}
if (protyle.block.showAll) {
attr += `${Constants.ZWSP}${protyle.block.id}`;
attr.zoomInId = protyle.block.id
}
if (getString) {
if (getObject) {
return attr;
}
fetchPost("/api/attr/setBlockAttrs", {id: protyle.block.rootID, attrs: {scroll: attr}}, () => {
protyle.wysiwyg.element.setAttribute("scroll", attr);
protyle.wysiwyg.element.setAttribute("scroll", JSON.stringify(attr));
});
}
export const restoreScroll = (protyle: IProtyle, scrollAttr?: string) => {
const attr = scrollAttr || protyle.wysiwyg.element.getAttribute("scroll")
if (!attr) {
return;
}
export const restoreScroll = (protyle: IProtyle, scrollAttr: IScrollAttr) => {
preventScroll(protyle);
const [startId, endId, scrollTop, focusId, focusStart, focusEnd, zoomInId] = attr.split(Constants.ZWSP);
if (protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id") === startId &&
protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id") === endId) {
protyle.contentElement.scrollTop = parseInt(scrollTop);
focusByOffset(protyle.wysiwyg.element.querySelector(`[data-node-id="${focusId}"]`), parseInt(focusStart), parseInt(focusEnd));
} else if (zoomInId && protyle.block.id !== zoomInId) {
zoomOut(protyle, zoomInId, undefined, false, () => {
protyle.contentElement.scrollTop = parseInt(scrollTop);
focusByOffset(protyle.wysiwyg.element.querySelector(`[data-node-id="${focusId}"]`), parseInt(focusStart), parseInt(focusEnd));
if (protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id") === scrollAttr.startId &&
protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id") === scrollAttr.endId) {
// 需等动画效果完毕,才能获得最大高度。否则尾部定位无法滚动到底部
setTimeout(() => {
protyle.contentElement.scrollTop = scrollAttr.scrollTop;
}, 256);
if (scrollAttr.focusId) {
const range = focusByOffset(protyle.wysiwyg.element.querySelector(`[data-node-id="${scrollAttr.focusId}"]`), scrollAttr.focusStart, scrollAttr.focusEnd);
/// #if !MOBILE
pushBack(protyle, range || undefined);
/// #endif
}
} else if (scrollAttr.zoomInId && protyle.block.id !== scrollAttr.zoomInId) {
zoomOut(protyle, scrollAttr.zoomInId, undefined, true, () => {
protyle.contentElement.scrollTop = scrollAttr.scrollTop;
if (scrollAttr.focusId) {
focusByOffset(protyle.wysiwyg.element.querySelector(`[data-node-id="${scrollAttr.focusId}"]`), scrollAttr.focusStart, scrollAttr.focusEnd);
}
});
} else if (!protyle.scroll.element.classList.contains("fn__none")) {
fetchPost("/api/filetree/getDoc", {
id: protyle.block.id,
startID: startId,
endID: endId,
startID: scrollAttr.startId,
endID: scrollAttr.endId,
}, getResponse => {
protyle.wysiwyg.element.innerHTML = getResponse.data.content;
protyle.contentElement.scrollTop = parseInt(scrollTop);
focusByOffset(protyle.wysiwyg.element.querySelector(`[data-node-id="${focusId}"]`), parseInt(focusStart), parseInt(focusEnd));
protyle.contentElement.scrollTop = scrollAttr.scrollTop;
if (scrollAttr.focusId) {
const range = focusByOffset(protyle.wysiwyg.element.querySelector(`[data-node-id="${scrollAttr.focusId}"]`), scrollAttr.focusStart, scrollAttr.focusEnd);
/// #if !MOBILE
pushBack(protyle, range || undefined);
/// #endif
}
})
}
}

View file

@ -16,7 +16,7 @@ import {hasClosestByAttribute, hasClosestByClassName} from "./hasClosest";
import {preventScroll} from "../scroll/preventScroll";
import {restoreScroll} from "../scroll/saveScroll";
export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[] = [], scrollAttr?: string) => {
export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[] = [], scrollAttr?: IScrollAttr, renderTitle = false) => {
protyle.wysiwyg.element.removeAttribute("data-top");
if (data.code === 1) {
// 其他报错
@ -76,35 +76,45 @@ export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[]
protyle.wysiwyg.element.setAttribute("data-doc-type", data.data.type);
}
if (protyle.options.render.title) {
// 页签没有打开
protyle.title.render(protyle, false, scrollAttr ? scrollAttr : (action.includes(Constants.CB_GET_SCROLL) ? Constants.CB_GET_SCROLL : null));
} else if (protyle.options.render.background) {
fetchPost("/api/block/getDocInfo", {
id: protyle.block.rootID
}, (response) => {
fetchPost("/api/block/getDocInfo", {
id: protyle.block.rootID
}, (response) => {
if (protyle.options.render.title) {
// 页签没有打开
protyle.title.render(protyle, response, renderTitle);
} else if (protyle.options.render.background) {
protyle.background.render(response.data.ial, protyle.block.rootID);
protyle.wysiwyg.renderCustom(response.data.ial);
});
}
}
setHTML({
content: html,
action,
}, protyle);
let scrollObj = scrollAttr;
if (!scrollObj) {
if (action.includes(Constants.CB_GET_SCROLL) && response.data.ial.scroll) {
try {
scrollObj = JSON.parse(response.data.ial.scroll)
} catch (e) {
scrollObj = undefined;
}
}
}
if ((protyle.options.render.title && protyle.title.editElement.getAttribute("data-render") === "true") || !protyle.options.render.title) {
setHTML({
content: html,
action,
unScroll: (scrollObj && scrollObj.focusId) ? true : false,
}, protyle);
if (scrollObj) {
restoreScroll(protyle, scrollObj);
}
const loadingElement = protyle.element.querySelector(".fn__loading");
if (loadingElement) {
loadingElement.remove();
}
if (scrollAttr) {
restoreScroll(protyle, scrollAttr);
}
}
});
};
const setHTML = (options: { content: string, action?: string[] }, protyle: IProtyle) => {
const setHTML = (options: { content: string, action?: string[], unScroll?: boolean }, protyle: IProtyle) => {
if (protyle.contentElement.classList.contains("fn__none")) {
return;
}
@ -155,7 +165,7 @@ const setHTML = (options: { content: string, action?: string[] }, protyle: IProt
if (protyle.options.render.scroll) {
protyle.scroll.update(protyle.block.blockCount, protyle);
}
if (options.action.includes(Constants.CB_GET_HL)) {
if (options.action.includes(Constants.CB_GET_HL) && !options.unScroll) {
preventScroll(protyle); // 搜索页签滚动会导致再次请求
const hlElement = highlightById(protyle, protyle.block.id, true);
/// #if !MOBILE
@ -163,7 +173,7 @@ const setHTML = (options: { content: string, action?: string[] }, protyle: IProt
pushBack(protyle, undefined, hlElement);
}
/// #endif
} else if (options.action.includes(Constants.CB_GET_FOCUS)) {
} else if (options.action.includes(Constants.CB_GET_FOCUS) && !options.unScroll) {
let focusElement: Element;
Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${protyle.block.id}"]`)).find((item: HTMLElement) => {
if (!hasClosestByAttribute(item, "data-type", "block-render", true)) {
@ -195,13 +205,15 @@ const setHTML = (options: { content: string, action?: string[] }, protyle: IProt
}
/// #endif
}
} else if (options.action.includes(Constants.CB_GET_FOCUSFIRST)) {
} else if (options.action.includes(Constants.CB_GET_FOCUSFIRST) && !options.unScroll) {
// settimeout 时间需短一点,否则定位后快速滚动无效
preventScroll(protyle, 8, 256);
protyle.contentElement.scrollTop = 8;
focusBlock(protyle.wysiwyg.element.firstElementChild);
/// #if !MOBILE
pushBack(protyle, undefined, protyle.wysiwyg.element.firstElementChild);
if (!options.action.includes(Constants.CB_GET_UNUNDO)) {
pushBack(protyle, undefined, protyle.wysiwyg.element.firstElementChild);
}
/// #endif
}
if (protyle.disabled) {

View file

@ -282,7 +282,7 @@ export const setFirstNodeRange = (editElement: Element, range: Range) => {
export const focusByOffset = (container: Node, start: number, end: number) => {
if (!container) {
return;
return false;
}
let startNode;
searchNode(container, container.firstChild, node => {
@ -342,6 +342,7 @@ export const focusByOffset = (container: Node, start: number, end: number) => {
}
}
focusByRange(range);
return range;
};
export const focusByWbr = (element: Element, range: Range) => {

View file

@ -22,14 +22,13 @@ export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent) => {
return true;
}
if (matchHotKey(window.siyuan.config.keymap.editor.general.refresh.custom, event)) {
protyle.title?.render(protyle, true);
addLoading(protyle);
fetchPost("/api/filetree/getDoc", {
id: protyle.block.showAll ? protyle.block.id : protyle.block.rootID,
mode: 0,
size: protyle.block.showAll ? Constants.SIZE_GET_MAX : Constants.SIZE_GET,
}, getResponse => {
onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS], saveScroll(protyle, true));
onGet(getResponse, protyle, protyle.block.showAll ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS], saveScroll(protyle, true), true);
});
event.preventDefault();
event.stopPropagation();

View file

@ -126,6 +126,16 @@ interface ISiyuan {
dialogs: import("../dialog").Dialog[],
}
interface IScrollAttr {
startId: string,
endId: string
scrollTop: number,
focusId?: string,
focusStart?: number
focusEnd?: number
zoomInId?: string
}
interface IOperation {
action: TOperation, // move delete 不需要传 data
id: string,

View file

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