diff --git a/app/src/layout/dock/Outline.ts b/app/src/layout/dock/Outline.ts index 79abc2ccb..29f545e60 100644 --- a/app/src/layout/dock/Outline.ts +++ b/app/src/layout/dock/Outline.ts @@ -430,6 +430,23 @@ export class Outline extends Model { } } + public setCurrentByPreview(nodeElement: Element) { + if (!nodeElement) { + return; + } + let previousElement = nodeElement; + while (previousElement && !previousElement.classList.contains("b3-typography")) { + if (["H1", "H2", "H3", "H4", "H5", "H6"].includes(previousElement.tagName)) { + break; + } else { + previousElement = previousElement.previousElementSibling || previousElement.parentElement; + } + } + if (previousElement && previousElement.id) { + this.setCurrentById(previousElement.id); + } + } + private setCurrentById(id: string) { this.element.querySelectorAll(".b3-list-item.b3-list-item--focus").forEach(item => { item.classList.remove("b3-list-item--focus"); diff --git a/app/src/mobile/dock/MobileOutline.ts b/app/src/mobile/dock/MobileOutline.ts index 8d305a763..b57da58da 100644 --- a/app/src/mobile/dock/MobileOutline.ts +++ b/app/src/mobile/dock/MobileOutline.ts @@ -7,6 +7,7 @@ import {App} from "../../index"; import {closePanel} from "../util/closePanel"; import {checkFold} from "../../util/noRelyPCFunction"; import {hasClosestBlock} from "../../protyle/util/hasClosest"; +import {getPreviousBlock} from "../../protyle/wysiwyg/getBlock"; export class MobileOutline { private tree: Tree; @@ -60,6 +61,11 @@ export class MobileOutline { if (!window.siyuan.mobile.editor.protyle.preview.element.classList.contains("fn__none")) { window.siyuan.mobile.editor.protyle.preview.render(window.siyuan.mobile.editor.protyle, (outlineData) => { this.tree.updateData(outlineData); + const blockElement = window.siyuan.mobile.editor.protyle.preview.element.querySelector("selected") + if (blockElement) { + this.setCurrentByPreview(blockElement); + return; + } }); return; } @@ -87,11 +93,8 @@ export class MobileOutline { if (window.siyuan.mobile.editor?.protyle?.toolbar.range) { const blockElement = hasClosestBlock(window.siyuan.mobile.editor.protyle.toolbar.range.startContainer); if (blockElement) { - const currentElement = this.element.querySelector(`[data-node-id="${blockElement.dataset.nodeId}"]`); - if (currentElement) { - currentElement.classList.add("b3-list-item--focus"); - return; - } + this.setCurrent(blockElement); + return; } } if (currentId) { @@ -102,4 +105,68 @@ export class MobileOutline { } }); } + + private setCurrentByPreview(nodeElement: Element) { + if (!nodeElement) { + return; + } + let previousElement = nodeElement; + while (previousElement && !previousElement.classList.contains("b3-typography")) { + if (["H1", "H2", "H3", "H4", "H5", "H6"].includes(previousElement.tagName)) { + break; + } else { + previousElement = previousElement.previousElementSibling || previousElement.parentElement; + } + } + if (previousElement.id) { + this.setCurrentById(previousElement.id); + } + } + + private setCurrentById(id: string) { + this.element.querySelectorAll(".b3-list-item.b3-list-item--focus").forEach(item => { + item.classList.remove("b3-list-item--focus"); + }); + let currentElement = this.element.querySelector(`.b3-list-item[data-node-id="${id}"]`) as HTMLElement; + while (currentElement && currentElement.clientHeight === 0) { + currentElement = currentElement.parentElement.previousElementSibling as HTMLElement; + } + if (currentElement) { + currentElement.classList.add("b3-list-item--focus"); + this.element.scrollTop = currentElement.offsetTop - this.element.clientHeight / 2 - 30; + } + } + + private setCurrent(nodeElement: HTMLElement) { + if (!nodeElement) { + return; + } + if (nodeElement.getAttribute("data-type") === "NodeHeading") { + this.setCurrentById(nodeElement.getAttribute("data-node-id")); + } else { + let previousElement = getPreviousBlock(nodeElement); + while (previousElement) { + if (previousElement.getAttribute("data-type") === "NodeHeading") { + break; + } else { + previousElement = getPreviousBlock(previousElement); + } + } + if (previousElement) { + this.setCurrentById(previousElement.getAttribute("data-node-id")); + } else { + fetchPost("/api/block/getBlockBreadcrumb", { + id: nodeElement.getAttribute("data-node-id"), + excludeTypes: [] + }, (response) => { + response.data.reverse().find((item: IBreadcrumb) => { + if (item.type === "NodeHeading") { + this.setCurrentById(item.id); + return true; + } + }); + }); + } + } + } } diff --git a/app/src/protyle/breadcrumb/index.ts b/app/src/protyle/breadcrumb/index.ts index 3bf96261b..056167857 100644 --- a/app/src/protyle/breadcrumb/index.ts +++ b/app/src/protyle/breadcrumb/index.ts @@ -450,7 +450,9 @@ ${padHTML} }, getResponse => { onGet({data: getResponse, protyle}); }); + /// #if !MOBILE saveLayout(); + /// #endif } }, { current: !protyle.preview.element.classList.contains("fn__none"), @@ -460,7 +462,9 @@ ${padHTML} click: () => { setEditMode(protyle, "preview"); window.siyuan.menus.menu.remove(); + /// #if !MOBILE saveLayout(); + /// #endif } }] }).element); diff --git a/app/src/protyle/preview/index.ts b/app/src/protyle/preview/index.ts index 08231d68b..8dcad4db0 100644 --- a/app/src/protyle/preview/index.ts +++ b/app/src/protyle/preview/index.ts @@ -19,6 +19,7 @@ import {highlightRender} from "../render/highlightRender"; import {speechRender} from "../render/speechRender"; import {avRender} from "../render/av/render"; import {getPadding} from "../ui/initUI"; +import {hasClosestByAttribute} from "../util/hasClosest"; export class Preview { public element: HTMLElement; @@ -141,6 +142,23 @@ export class Preview { } target = target.parentElement; } + const nodeElement = hasClosestByAttribute(event.target as HTMLElement, "id", undefined); + if (nodeElement) { + // 用于点击后大纲定位 + this.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { + item.classList.remove("selected"); + }); + nodeElement.classList.add("selected"); + /// #if !MOBILE + if (protyle.model) { + getAllModels().outline.forEach(item => { + if (item.blockId === protyle.block.rootID) { + item.setCurrentByPreview(nodeElement); + } + }); + } + /// #endif + } }); this.previewElement = previewElement;