From 176c1375a13b4af1c3b461a5edb80624400e2459 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Sun, 31 Jul 2022 11:55:15 +0800 Subject: [PATCH] :sparkles: bookmark https://github.com/siyuan-note/siyuan/issues/5545 --- app/src/mobile/util/MobileBookmarks.ts | 69 ++++++++++++++++++++++++-- app/src/util/Tree.ts | 18 +++++-- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/app/src/mobile/util/MobileBookmarks.ts b/app/src/mobile/util/MobileBookmarks.ts index b92adf27e..5d483460d 100644 --- a/app/src/mobile/util/MobileBookmarks.ts +++ b/app/src/mobile/util/MobileBookmarks.ts @@ -2,9 +2,11 @@ import {Tree} from "../../util/Tree"; import {fetchPost} from "../../util/fetch"; import {Constants} from "../../constants"; import {hasClosestByClassName} from "../../protyle/util/hasClosest"; -import {onGet} from "../../protyle/util/onGet"; import {openMobileFileById} from "../editor"; -import {MenuItem} from "../../menus/Menu"; +import {confirmDialog} from "../../dialog/confirmDialog"; +import {escapeHtml} from "../../util/escape"; +import {Dialog} from "../../dialog"; +import {isMobile} from "../../util/functions"; export class MobileBookmarks { public element: HTMLElement; @@ -29,9 +31,66 @@ export class MobileBookmarks { this.tree = new Tree({ element: this.element.querySelector(".bookmarkList") as HTMLElement, data: null, - click(element: HTMLElement) { - openMobileFileById(element.getAttribute("data-node-id"), true, [Constants.CB_GET_FOCUS]); - } + click: (element: HTMLElement, event: MouseEvent) => { + const id = element.getAttribute("data-node-id"); + const actionElement = hasClosestByClassName(event.target as HTMLElement, "b3-list-item__action"); + if (actionElement) { + const bookmark = (id ? element.parentElement.previousElementSibling : element).querySelector(".b3-list-item__text").textContent; + if (actionElement.getAttribute("data-type") === "remove") { + confirmDialog(window.siyuan.languages.delete, `${window.siyuan.languages.confirmDelete} ${escapeHtml(bookmark)}?`, () => { + if (id) { + fetchPost("/api/attr/setBlockAttrs", {id, attrs: {bookmark: ""}}, () => { + this.update(); + }); + document.querySelectorAll(`.protyle-wysiwyg [data-node-id="${id}"]`).forEach((item) => { + item.setAttribute("bookmark", ""); + const bookmarkElement = item.querySelector(".protyle-attr--bookmark"); + if (bookmarkElement) { + bookmarkElement.remove(); + } + }); + } else { + fetchPost("/api/bookmark/removeBookmark", {bookmark}, () => { + this.update(); + }); + } + }); + } else { + const dialog = new Dialog({ + title: window.siyuan.languages.rename, + content: `
+
+
+ +
`, + width: isMobile() ? "80vw" : "520px", + }); + const btnsElement = dialog.element.querySelectorAll(".b3-button"); + btnsElement[0].addEventListener("click", () => { + dialog.destroy(); + }); + const inputElement = dialog.element.querySelector("input"); + dialog.bindInput(inputElement, () => { + (btnsElement[1] as HTMLButtonElement).click(); + }); + inputElement.value = bookmark; + inputElement.focus(); + inputElement.select(); + btnsElement[1].addEventListener("click", () => { + fetchPost("/api/bookmark/renameBookmark", { + oldBookmark: bookmark, + newBookmark: inputElement.value + }, () => { + dialog.destroy(); + }); + }); + } + } else { + openMobileFileById(id, true, [Constants.CB_GET_FOCUS]); + } + }, + blockExtHTML: '', + topExtHTML: '' }); this.element.addEventListener("click", (event) => { let target = event.target as HTMLElement; diff --git a/app/src/util/Tree.ts b/app/src/util/Tree.ts index c1d1c3c0a..9f537e878 100644 --- a/app/src/util/Tree.ts +++ b/app/src/util/Tree.ts @@ -1,5 +1,5 @@ import {getIconByType} from "../editor/getIcon"; -import {hasClosestByTag} from "../protyle/util/hasClosest"; +import {hasClosestByMatchTag, hasClosestByTag} from "../protyle/util/hasClosest"; import {isMobile} from "./functions"; import {mathRender} from "../protyle/markdown/mathRender"; import {unicode2Emoji} from "../emoji"; @@ -9,6 +9,7 @@ export class Tree { public element: HTMLElement; private data: IBlockTree[]; private blockExtHTML: string; + private topExtHTML: string; private click: (element: HTMLElement, event: MouseEvent) => void; @@ -21,6 +22,7 @@ export class Tree { element: HTMLElement, data: IBlockTree[], blockExtHTML?: string, + topExtHTML?: string, click?(element: HTMLElement, event: MouseEvent): void ctrlClick?(element: HTMLElement): void altClick?(element: HTMLElement): void @@ -34,6 +36,7 @@ export class Tree { this.rightClick = options.rightClick; this.element = options.element; this.blockExtHTML = options.blockExtHTML; + this.topExtHTML = options.topExtHTML; this.updateData(options.data); this.bindEvent(); } @@ -78,6 +81,7 @@ ${item.label ? "data-label='" + item.label + "'" : ""}> ${iconHTML} ${item.name} ${countHTML} + ${this.topExtHTML || ""} `; if (item.children && item.children.length > 0) { html += this.genHTML(item.children) + ""; @@ -184,8 +188,16 @@ data-def-path="${item.defPath}"> event.preventDefault(); break; } - - if (target.tagName === "LI") { + if (target.classList.contains("b3-list-item__action") && this.click) { + // 移动端书签父节点删除按钮 + const liElement = hasClosestByMatchTag(target, "LI") + if (liElement) { + this.click(liElement, event); + } + event.preventDefault(); + event.stopPropagation(); + break; + } else if (target.tagName === "LI") { this.setCurrent(target); if (target.getAttribute("data-node-id") || target.getAttribute("data-treetype") === "tag") { if (this.ctrlClick && window.siyuan.ctrlIsPressed) {