import {Constants} from "../constants"; import {fetchPost} from "../util/fetch"; import {escapeAriaLabel, escapeHtml} from "../util/escape"; import {setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility"; /// #if !MOBILE import {getQueryTip} from "./util"; /// #endif import {MenuItem} from "../menus/Menu"; import {Dialog} from "../dialog"; import {Menu} from "../plugin/Menu"; import {hasClosestByClassName} from "../protyle/util/hasClosest"; import {addClearButton} from "../util/addClearButton"; export const openSearchAsset = (element: Element, isStick: boolean) => { /// #if !MOBILE window.siyuan.menus.menu.remove(); element.previousElementSibling.classList.add("fn__none"); element.classList.remove("fn__none"); if (element.innerHTML) { (element.querySelector("#searchAssetInput") as HTMLInputElement).select(); return; } const localSearch = window.siyuan.storage[Constants.LOCAL_SEARCHASSET] as ISearchAssetOption; const loadingElement = element.nextElementSibling; loadingElement.classList.remove("fn__none"); let enterTip = ""; /// #if !BROWSER enterTip = `Enter/Double Click ${window.siyuan.languages.showInFolder}`; /// #endif element.innerHTML = `
↑/↓/PageUp/PageDown ${window.siyuan.languages.searchTip1} ${enterTip} Click ${window.siyuan.languages.searchTip3} Esc ${window.siyuan.languages.searchTip5}
`; if (element.querySelector("#searchAssetList").innerHTML !== "") { return; } const previewElement = element.querySelector("#searchAssetPreview") as HTMLElement; if (localSearch.layout === 1) { if (localSearch.col) { previewElement.style.width = localSearch.col; previewElement.classList.remove("fn__flex-1"); } } else { if (localSearch.row) { previewElement.classList.remove("fn__flex-1"); previewElement.style.height = localSearch.row; } } const searchInputElement = element.querySelector("#searchAssetInput") as HTMLInputElement; searchInputElement.select(); searchInputElement.addEventListener("compositionend", (event: InputEvent) => { if (event.isComposing) { return; } assetInputEvent(element, localSearch); }); searchInputElement.addEventListener("input", (event: InputEvent) => { if (event.isComposing) { return; } assetInputEvent(element, localSearch); }); searchInputElement.addEventListener("blur", () => { if (!searchInputElement.value) { return; } let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys; list.splice(0, 0, searchInputElement.value); list = Array.from(new Set(list)); if (list.length > window.siyuan.config.search.limit) { list.splice(window.siyuan.config.search.limit, list.length - window.siyuan.config.search.limit); } window.siyuan.storage[Constants.LOCAL_SEARCHASSET].k = searchInputElement.value; window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = list; setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]); }); assetInputEvent(element, localSearch); addClearButton({ right: 8, height: searchInputElement.clientHeight, inputElement: searchInputElement, clearCB() { assetInputEvent(element, localSearch); } }); const dragElement = element.querySelector(".search__drag"); dragElement.addEventListener("mousedown", (event: MouseEvent) => { const documentSelf = document; const nextElement = dragElement.nextElementSibling as HTMLElement; const previousElement = dragElement.previousElementSibling as HTMLElement; const direction = localSearch.layout === 1 ? "lr" : "tb"; const x = event[direction === "lr" ? "clientX" : "clientY"]; const previousSize = direction === "lr" ? previousElement.clientWidth : previousElement.clientHeight; const nextSize = direction === "lr" ? nextElement.clientWidth : nextElement.clientHeight; nextElement.classList.remove("fn__flex-1"); nextElement.style[direction === "lr" ? "width" : "height"] = nextSize + "px"; documentSelf.onmousemove = (moveEvent: MouseEvent) => { moveEvent.preventDefault(); moveEvent.stopPropagation(); const previousNowSize = (previousSize + (moveEvent[direction === "lr" ? "clientX" : "clientY"] - x)); const nextNowSize = (nextSize - (moveEvent[direction === "lr" ? "clientX" : "clientY"] - x)); if (previousNowSize < 120 || nextNowSize < 120) { return; } nextElement.style[direction === "lr" ? "width" : "height"] = nextNowSize + "px"; }; documentSelf.onmouseup = () => { documentSelf.onmousemove = null; documentSelf.onmouseup = null; documentSelf.ondragstart = null; documentSelf.onselectstart = null; documentSelf.onselect = null; window.siyuan.storage[Constants.LOCAL_SEARCHASSET][direction === "lr" ? "col" : "row"] = nextElement[direction === "lr" ? "clientWidth" : "clientHeight"] + "px"; setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]); }; }); /// #endif }; let inputTimeout: number; export const assetInputEvent = (element: Element, localSearch?: ISearchAssetOption, page = 1) => { element.nextElementSibling.classList.remove("fn__none"); clearTimeout(inputTimeout); inputTimeout = window.setTimeout(() => { if (!localSearch) { localSearch = window.siyuan.storage[Constants.LOCAL_SEARCHASSET] as ISearchAssetOption; } const previousElement = element.querySelector('[data-type="assetPrevious"]'); if (page > 1) { previousElement.removeAttribute("disabled"); } else { previousElement.setAttribute("disabled", "disabled"); } const searchInputElement = element.querySelector("#searchAssetInput") as HTMLInputElement; fetchPost("/api/search/fullTextSearchAssetContent", { page, query: searchInputElement.value, types: localSearch.types, method: localSearch.method, orderBy: localSearch.sort }, (response) => { element.nextElementSibling.classList.add("fn__none"); if (response.code === 1) { element.querySelector("#searchAssetList").innerHTML = `
${window.siyuan.languages["_kernel"][214]}
`; return; } const nextElement = element.querySelector('[data-type="assetNext"]'); if (page < response.data.pageCount) { nextElement.removeAttribute("disabled"); } else { nextElement.setAttribute("disabled", "disabled"); } let resultHTML = ""; response.data.assetContents.forEach((item: { content: string ext: string id: string path: string name: string hSize: string }, index: number) => { resultHTML += `
${item.ext} ${item.content} ${item.hSize} ${item.name}
`; }); const previewElement = element.querySelector("#searchAssetPreview"); if (response.data.assetContents.length > 0) { previewElement.classList.remove("fn__none"); element.querySelector(".search__drag")?.classList.remove("fn__none"); renderPreview(previewElement, response.data.assetContents[0].id, searchInputElement.value, localSearch.method); } else { previewElement.classList.add("fn__none"); element.querySelector(".search__drag")?.classList.add("fn__none"); } element.querySelector("#searchAssetResult").innerHTML = `${page}/${response.data.pageCount || 1} ${window.siyuan.languages.total} ${response.data.matchedAssetCount}`; element.querySelector("#searchAssetList").innerHTML = resultHTML || `
${window.siyuan.languages.emptyContent}
`; }); }, Constants.TIMEOUT_INPUT); }; export const toggleAssetHistory = (assetElement: Element) => { const keys = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys; if (!keys || keys.length === 0) { return; } const menu = new Menu("search-asset-history"); if (menu.isOpen) { return; } menu.element.classList.add("b3-menu--list"); menu.addItem({ iconHTML: "", label: window.siyuan.languages.clearHistory, click() { window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = []; setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]); } }); const separatorElement = menu.addSeparator(1); let current = true; const assetInputElement = assetElement.querySelector("#searchAssetInput") as HTMLInputElement; keys.forEach((s: string) => { if (s !== assetInputElement.value && s) { const menuItem = menu.addItem({ iconHTML: "", label: escapeHtml(s), action: "iconCloseRound", bind(element) { element.addEventListener("click", (itemEvent) => { if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) { keys.find((item: string, index: number) => { if (item === s) { keys.splice(index, 1); return true; } }); window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = keys; setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]); if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) { window.siyuan.menus.menu.remove(); } else { element.remove(); } } else { assetInputElement.value = element.textContent; assetInputEvent(assetElement); window.siyuan.menus.menu.remove(); } itemEvent.preventDefault(); itemEvent.stopPropagation(); }); } }); if (current) { menuItem.classList.add("b3-menu__item--current"); } current = false; } }); if (current) { separatorElement.remove(); } const rect = assetInputElement.getBoundingClientRect(); menu.open({ x: rect.left, y: rect.bottom }); }; export const renderPreview = (element: Element, id: string, query: string, queryMethod: number) => { fetchPost("/api/search/getAssetContent", {id, query, queryMethod}, (response) => { element.innerHTML = `

${response.data.assetContent.content}

`; const matchElement = element.querySelector("mark"); if (matchElement) { matchElement.classList.add("mark--hl"); const contentRect = element.getBoundingClientRect(); element.scrollTop = element.scrollTop + matchElement.getBoundingClientRect().top - contentRect.top - contentRect.height / 2; } }); }; export const renderNextAssetMark = (element: Element) => { let matchElement; const allMatchElements = Array.from(element.querySelectorAll("mark")); allMatchElements.find((item, itemIndex) => { if (item.classList.contains("mark--hl")) { item.classList.remove("mark--hl"); matchElement = allMatchElements[itemIndex + 1]; return; } }); if (!matchElement) { matchElement = allMatchElements[0]; } if (matchElement) { matchElement.classList.add("mark--hl"); const contentRect = element.getBoundingClientRect(); element.scrollTop = element.scrollTop + matchElement.getBoundingClientRect().top - contentRect.top - contentRect.height / 2; } }; export const assetMethodMenu = (target: HTMLElement, cb: () => void) => { const method = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].method; if (!window.siyuan.menus.menu.element.classList.contains("fn__none") && window.siyuan.menus.menu.element.getAttribute("data-name") === "searchAssetMethod") { window.siyuan.menus.menu.remove(); return; } window.siyuan.menus.menu.remove(); window.siyuan.menus.menu.element.setAttribute("data-name", "searchAssetMethod"); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.keyword, current: method === 0, click() { window.siyuan.storage[Constants.LOCAL_SEARCHASSET].method = 0; cb(); } }).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.querySyntax, current: method === 1, click() { window.siyuan.storage[Constants.LOCAL_SEARCHASSET].method = 1; cb(); } }).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.regex, current: method === 3, click() { window.siyuan.storage[Constants.LOCAL_SEARCHASSET].method = 3; cb(); } }).element); /// #if MOBILE window.siyuan.menus.menu.fullscreen(); /// #else const rect = target.getBoundingClientRect(); window.siyuan.menus.menu.popup({x: rect.right, y: rect.bottom, isLeft: true}); /// #endif }; const filterTypesHTML = (types: IObject) => { let html = ""; Constants.SIYUAN_ASSETS_SEARCH.sort((a: string, b: string) => { return a.localeCompare(b); }).forEach((type: string) => { html += ``; }); return html; }; export const assetFilterMenu = (assetsElement: Element) => { const localData = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].types; const filterDialog = new Dialog({ title: window.siyuan.languages.type, content: `
${filterTypesHTML(localData)}
`, width: "520px", height: "70vh", }); const btnsElement = filterDialog.element.querySelectorAll(".b3-button"); btnsElement[0].addEventListener("click", () => { filterDialog.destroy(); }); btnsElement[1].addEventListener("click", () => { filterDialog.element.querySelectorAll(".b3-switch").forEach((item: HTMLInputElement) => { localData[item.getAttribute("data-type")] = item.checked; }); assetInputEvent(assetsElement); setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]); filterDialog.destroy(); }); }; export const assetMoreMenu = (target: Element, element: Element, cb: () => void) => { if (!window.siyuan.menus.menu.element.classList.contains("fn__none") && window.siyuan.menus.menu.element.getAttribute("data-name") === "searchAssetMore") { window.siyuan.menus.menu.remove(); return; } window.siyuan.menus.menu.remove(); window.siyuan.menus.menu.element.setAttribute("data-name", "searchAssetMore"); const localData = window.siyuan.storage[Constants.LOCAL_SEARCHASSET]; const sortMenu = [{ iconHTML: Constants.ZWSP, label: window.siyuan.languages.sortByRankAsc, current: localData.sort === 1, click() { localData.sort = 1; cb(); } }, { iconHTML: Constants.ZWSP, label: window.siyuan.languages.sortByRankDesc, current: localData.sort === 0, click() { localData.sort = 0; cb(); } }, { iconHTML: Constants.ZWSP, label: window.siyuan.languages.modifiedASC, current: localData.sort === 3, click() { localData.sort = 3; cb(); } }, { iconHTML: Constants.ZWSP, label: window.siyuan.languages.modifiedDESC, current: localData.sort === 2, click() { localData.sort = 2; cb(); } }]; window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.sort, type: "submenu", submenu: sortMenu, }).element); /// #if !MOBILE window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.layout, type: "submenu", submenu: [{ iconHTML: Constants.ZWSP, label: window.siyuan.languages.topBottomLayout, current: localData.layout === 0, click() { element.querySelector(".search__layout").classList.remove("search__layout--row"); const previewElement = element.querySelector("#searchAssetPreview") as HTMLElement; previewElement.style.width = ""; if (localData.row) { previewElement.style.height = localData.row; previewElement.classList.remove("fn__flex-1"); } else { previewElement.classList.add("fn__flex-1"); } localData.layout = 0; setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]); } }, { iconHTML: Constants.ZWSP, label: window.siyuan.languages.leftRightLayout, current: localData.layout === 1, click() { const previewElement = element.querySelector("#searchAssetPreview") as HTMLElement; element.querySelector(".search__layout").classList.add("search__layout--row"); previewElement.style.height = ""; if (localData.col) { previewElement.style.width = localData.col; previewElement.classList.remove("fn__flex-1"); } else { previewElement.classList.add("fn__flex-1"); } localData.layout = 1; setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]); } }] }).element); /// #endif window.siyuan.menus.menu.append(new MenuItem({ iconHTML: Constants.ZWSP, label: window.siyuan.languages.rebuildIndex, click() { element.nextElementSibling.classList.remove("fn__none"); fetchPost("/api/asset/fullReindexAssetContent", {}, () => { assetInputEvent(element, localData); }); }, }).element); /// #if MOBILE window.siyuan.menus.menu.fullscreen(); /// #else const rect = target.getBoundingClientRect(); window.siyuan.menus.menu.popup({x: rect.right, y: rect.bottom, isLeft: true}); /// #endif };