/// #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();
});
};