/// #if !BROWSER import {shell} from "electron"; import * as path from "path"; /// #endif import {Constants} from "../constants"; import {fetchPost} from "../util/fetch"; import {upDownHint} from "../util/upDownHint"; import {escapeHtml} from "../util/escape"; import {setStorageVal} from "../protyle/util/compatibility"; import {getQueryTip} from "./util"; import {MenuItem} from "../menus/Menu"; import {Dialog} from "../dialog"; export const openSearchAsset = (element: Element, isStick: boolean) => { 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 = `
↑/↓ ${window.siyuan.languages.searchTip1} ${enterTip} Esc ${window.siyuan.languages.searchTip5}
` const searchPanelElement = element.querySelector("#searchAssetList"); if (element.querySelector("#searchAssetList").innerHTML !== "") { return } 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]); }); const historyElement = element.querySelector("#searchAssetHistoryList") const lineHeight = 28; searchInputElement.addEventListener("keydown", (event: KeyboardEvent) => { if (event.isComposing) { return; } let currentList: HTMLElement = searchPanelElement.querySelector(".b3-list-item--focus"); const isHistory = !historyElement.classList.contains("fn__none"); if (event.key === "Enter") { if (!isHistory) { if (currentList) { /// #if !BROWSER shell.showItemInFolder(path.join(window.siyuan.config.system.dataDir, currentList.lastElementChild.getAttribute("aria-label"))); /// #endif } } else { searchInputElement.value = historyElement.querySelector(".b3-list-item--focus").textContent.trim(); assetInputEvent(element, localSearch); toggleAssetHistory(historyElement, searchInputElement); } event.preventDefault(); } if (event.key === "ArrowDown" && event.altKey) { toggleAssetHistory(historyElement, searchInputElement); return; } if (isHistory) { if (event.key === "Escape") { toggleAssetHistory(historyElement, searchInputElement); } else { upDownHint(historyElement, event); } event.stopPropagation(); event.preventDefault(); return; } if (!currentList) { return; } if (event.key === "ArrowDown") { currentList.classList.remove("b3-list-item--focus"); if (!currentList.nextElementSibling) { searchPanelElement.firstElementChild.classList.add("b3-list-item--focus"); } else { currentList.nextElementSibling.classList.add("b3-list-item--focus"); } currentList = searchPanelElement.querySelector(".b3-list-item--focus"); if (searchPanelElement.scrollTop < currentList.offsetTop - searchPanelElement.clientHeight + lineHeight || searchPanelElement.scrollTop > currentList.offsetTop) { searchPanelElement.scrollTop = currentList.offsetTop - searchPanelElement.clientHeight + lineHeight; } event.preventDefault(); } else if (event.key === "ArrowUp") { currentList.classList.remove("b3-list-item--focus"); if (!currentList.previousElementSibling) { searchPanelElement.lastElementChild.classList.add("b3-list-item--focus"); } else { currentList.previousElementSibling.classList.add("b3-list-item--focus"); } currentList = searchPanelElement.querySelector(".b3-list-item--focus"); if (searchPanelElement.scrollTop < currentList.offsetTop - searchPanelElement.clientHeight + lineHeight || searchPanelElement.scrollTop > currentList.offsetTop - lineHeight * 2) { searchPanelElement.scrollTop = currentList.offsetTop - lineHeight * 2; } event.preventDefault(); } renderPreview(element.querySelector('#searchAssetPreview'), currentList.dataset.id, searchInputElement.value, localSearch.method); }); assetInputEvent(element, localSearch); } 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") const nextElement = element.querySelector('[data-type="assetNext"]') const previewElement = element.querySelector('#searchAssetPreview') 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}
`; }); 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 reIndexAssets = (loadingElement: HTMLElement) => { loadingElement.classList.remove("fn__none") fetchPost("/api/asset/fullReindexAssetContent", {}, (response) => { // assetInputEvent() }) } export const toggleAssetHistory = (historyElement: Element, searchInputElement: HTMLInputElement) => { if (historyElement.classList.contains("fn__none")) { const keys = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys; if (!keys || keys.length === 0) { return; } let html = ""; keys.forEach((s: string) => { if (s !== searchInputElement.value && s) { html += `
${escapeHtml(s)}
`; } }); if (html === "") { return; } historyElement.classList.remove("fn__none"); historyElement.innerHTML = html; } else { historyElement.classList.add("fn__none"); } }; 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; }) } 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") === "searchMethod") { window.siyuan.menus.menu.remove(); return; } window.siyuan.menus.menu.remove(); window.siyuan.menus.menu.element.setAttribute("data-name", "searchMethod"); 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: "SQL", current: method === 2, click() { window.siyuan.storage[Constants.LOCAL_SEARCHASSET].method = 2 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); const rect = target.getBoundingClientRect(); window.siyuan.menus.menu.popup({x: rect.right, y: rect.bottom}, true); } export const assetFilterMenu = (assetsElement:Element) => { const localData = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].types const filterDialog = new Dialog({ title: window.siyuan.languages.type, content: `
`, 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(); }); };