import {Tab} from "../Tab"; import {Model} from "../Model"; import {Tree} from "../../util/Tree"; import {getDockByType, setPanelFocus} from "../util"; import {fetchPost} from "../../util/fetch"; import {updateHotkeyTip} from "../../protyle/util/compatibility"; import {openFileById} from "../../editor/util"; import {Constants} from "../../constants"; import {hasClosestByClassName} from "../../protyle/util/hasClosest"; import {openBookmarkMenu} from "../../menus/bookmark"; export class Bookmark extends Model { private openNodes: string[]; public tree: Tree; private element: Element; constructor(tab: Tab) { super({ id: tab.id, msgCallback(data) { if (data) { switch (data.cmd) { case "transactions": data.data[0].doOperations.forEach((item: IOperation) => { let needReload = false; if ((item.action === "update" || item.action === "insert") && item.data.indexOf('class="protyle-attr--bookmark"') > -1) { needReload = true; } else if (item.action === "delete") { needReload = true; } if (needReload) { fetchPost("/api/bookmark/getBookmark", {}, response => { this.update(response.data); }); } }); break; case "unmount": case "removeDoc": case "mount": if (data.cmd !== "mount" || data.code !== 1) { fetchPost("/api/bookmark/getBookmark", {}, response => { this.update(response.data); }); } break; } } } }); this.element = tab.panelElement; this.element.classList.add("fn__flex-column", "file-tree", "sy__bookmark"); this.element.innerHTML = `
`; this.tree = new Tree({ element: this.element.lastElementChild as HTMLElement, data: null, click:(element: HTMLElement, event: MouseEvent)=> { const actionElement = hasClosestByClassName(event.target as HTMLElement, "b3-list-item__action"); if (actionElement) { openBookmarkMenu(actionElement.parentElement, event, this); } else { const id = element.getAttribute("data-node-id"); fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => { openFileById({ id, action: foldResponse.data ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL] : [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT], zoomIn: foldResponse.data }); }); } }, rightClick: (element: HTMLElement, event: MouseEvent) => { openBookmarkMenu(element, event, this); }, ctrlClick(element: HTMLElement) { openFileById({ id: element.getAttribute("data-node-id"), keepCursor: true, action: [Constants.CB_GET_CONTEXT] }); }, altClick(element: HTMLElement) { openFileById({ id: element.getAttribute("data-node-id"), position: "right", action: [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT] }); }, shiftClick(element: HTMLElement) { openFileById({ id: element.getAttribute("data-node-id"), position: "bottom", action: [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT] }); }, blockExtHTML: '', topExtHTML: '', }); // 为了快捷键的 dispatch this.element.querySelector('[data-type="collapse"]').addEventListener("click", () => { this.tree.collapseAll(); }); this.element.querySelector('[data-type="expand"]').addEventListener("click", () => { this.tree.expandAll(); }); this.element.addEventListener("click", (event) => { setPanelFocus(this.element); let target = event.target as HTMLElement; while (target && !target.isEqualNode(this.element)) { if (target.classList.contains("block__icon")) { const type = target.getAttribute("data-type"); switch (type) { case "min": getDockByType("bookmark").toggleModel("bookmark"); break; case "refresh": this.update(); break; } } target = target.parentElement; } }); this.update(); setPanelFocus(this.element); } public update() { const element = this.element.querySelector('.block__icon[data-type="refresh"] svg'); if (element.classList.contains("fn__rotate")) { return; } element.classList.add("fn__rotate"); fetchPost("/api/bookmark/getBookmark", {}, response => { if (this.openNodes) { this.openNodes = this.tree.getExpandIds(); } this.tree.updateData(response.data); if (this.openNodes) { this.tree.setExpandIds(this.openNodes); } else { this.openNodes = this.tree.getExpandIds(); } element.classList.remove("fn__rotate"); }); } }