import {Dialog} from "../dialog"; import {isMobile, objEquals} from "../util/functions"; import {MenuItem} from "../menus/Menu"; import {Constants} from "../constants"; import {showMessage} from "../dialog/message"; import {fetchPost} from "../util/fetch"; import {escapeHtml} from "../util/escape"; import {setStorageVal} from "../protyle/util/compatibility"; import {confirmDialog} from "../dialog/confirmDialog"; import {goUnRef, updateSearchResult} from "../mobile/menu/search"; export const filterMenu = (config: Config.IUILayoutTabSearchConfig, cb: () => void) => { const filterDialog = new Dialog({ title: window.siyuan.languages.searchType, content: `
[1] ${window.siyuan.languages.containerBlockTip1}
`, width: isMobile() ? "92vw" : "520px", height: "70vh", }); filterDialog.element.setAttribute("data-key", Constants.DIALOG_SEARCHTYPE); 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) => { config.types[item.getAttribute("data-type") as keyof (typeof config.types)] = item.checked; }); cb(); filterDialog.destroy(); }); }; export const replaceFilterMenu = (config: Config.IUILayoutTabSearchConfig) => { let html = ""; Object.keys(Constants.SIYUAN_DEFAULT_REPLACETYPES).forEach((key: keyof Config.IUILayoutTabSearchConfigReplaceTypes) => { html += ``; }); const filterDialog = new Dialog({ title: window.siyuan.languages.replaceType, content: `
${html}
`, width: isMobile() ? "92vw" : "520px", height: "70vh", }); filterDialog.element.setAttribute("data-key", Constants.DIALOG_REPLACETYPE); 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) => { config.replaceTypes[item.getAttribute("data-type") as keyof (typeof config.replaceTypes)] = item.checked; }); filterDialog.destroy(); }); }; export const queryMenu = (config: Config.IUILayoutTabSearchConfig, cb: () => void) => { 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({ icon: "iconExact", label: window.siyuan.languages.keyword, current: config.method === 0, click() { config.method = 0; cb(); } }).element); window.siyuan.menus.menu.append(new MenuItem({ icon: "iconQuote", label: window.siyuan.languages.querySyntax, current: config.method === 1, click() { config.method = 1; cb(); } }).element); window.siyuan.menus.menu.append(new MenuItem({ icon: "iconDatabase", label: "SQL", current: config.method === 2, click() { config.method = 2; cb(); } }).element); window.siyuan.menus.menu.append(new MenuItem({ icon: "iconRegex", label: window.siyuan.languages.regex, current: config.method === 3, click() { config.method = 3; cb(); } }).element); }; const saveCriterionData = (config: Config.IUILayoutTabSearchConfig, criteriaData: Config.IUILayoutTabSearchConfig[], element: Element, value: string, saveDialog: Dialog) => { config.removed = false; const criterion = config; criterion.name = value; criteriaData.push(Object.assign({}, criterion)); window.siyuan.storage[Constants.LOCAL_SEARCHDATA] = Object.assign({}, config); setStorageVal(Constants.LOCAL_SEARCHDATA, window.siyuan.storage[Constants.LOCAL_SEARCHDATA]); fetchPost("/api/storage/setCriterion", {criterion}, () => { saveDialog.destroy(); const criteriaElement = element.querySelector("#criteria").firstElementChild; criteriaElement.classList.remove("fn__none"); criteriaElement.querySelector(".b3-chip--current")?.classList.remove("b3-chip--current"); criteriaElement.insertAdjacentHTML("beforeend", `
${criterion.name}
`); }); }; export const saveCriterion = (config: Config.IUILayoutTabSearchConfig, criteriaData: Config.IUILayoutTabSearchConfig[], element: Element) => { const saveDialog = new Dialog({ title: window.siyuan.languages.saveCriterion, content: `
`, width: isMobile() ? "92vw" : "520px", }); saveDialog.element.setAttribute("data-key", Constants.DIALOG_SAVECRITERION); const btnsElement = saveDialog.element.querySelectorAll(".b3-button"); saveDialog.bindInput(saveDialog.element.querySelector("input"), () => { btnsElement[1].dispatchEvent(new CustomEvent("click")); }); btnsElement[0].addEventListener("click", () => { saveDialog.destroy(); }); btnsElement[1].addEventListener("click", () => { const inputElement = saveDialog.element.querySelector("input"); const value = inputElement.value.trim(); if (!value) { showMessage(window.siyuan.languages["_kernel"]["142"]); return; } if (isMobile()) { config.k = (document.querySelector("#toolbarSearch") as HTMLInputElement).value; config.r = (element.querySelector("#toolbarReplace") as HTMLInputElement).value; } else { config.k = (element.querySelector("#searchInput") as HTMLInputElement).value; config.r = (element.querySelector("#replaceInput") as HTMLInputElement).value; } const criteriaElement = element.querySelector("#criteria").firstElementChild; let hasSameName = ""; let hasSameConfig = ""; criteriaData.forEach(item => { if (item.name === value) { hasSameName = item.name; } if (configIsSame(item, config)) { hasSameConfig = item.name; } }); inputElement.blur(); if (hasSameName && !hasSameConfig) { confirmDialog(window.siyuan.languages.confirm, window.siyuan.languages.searchOverwrite, () => { Array.from(criteriaElement.children).forEach(item => { if (item.textContent === value) { item.remove(); } }); criteriaData.find((item, index) => { if (item.name === value) { criteriaData.splice(index, 1); return true; } }); saveCriterionData(config, criteriaData, element, value, saveDialog); }); } else if (hasSameName && hasSameConfig) { if (hasSameName === hasSameConfig) { saveDialog.destroy(); } else { const removeName = hasSameName === value ? hasSameConfig : hasSameName; confirmDialog(window.siyuan.languages.confirm, window.siyuan.languages.searchRemoveName.replace("${x}", removeName).replace("${y}", value), () => { Array.from(criteriaElement.children).forEach(item => { if (item.textContent === hasSameConfig || item.textContent === hasSameName) { item.remove(); } }); criteriaData.find((item, index) => { if (item.name === removeName || item.name === hasSameName) { fetchPost("/api/storage/removeCriterion", {name: removeName}); criteriaData.splice(index, 1); return true; } }); saveCriterionData(config, criteriaData, element, value, saveDialog); }); } } else if (!hasSameName && hasSameConfig) { confirmDialog(window.siyuan.languages.confirm, window.siyuan.languages.searchUpdateName.replace("${x}", hasSameConfig).replace("${y}", value), () => { Array.from(criteriaElement.children).forEach(item => { if (item.textContent === hasSameConfig) { item.remove(); } }); criteriaData.find((item, index) => { if (item.name === hasSameConfig) { fetchPost("/api/storage/removeCriterion", {name: hasSameConfig}); criteriaData.splice(index, 1); return true; } }); saveCriterionData(config, criteriaData, element, value, saveDialog); }); } else { saveCriterionData(config, criteriaData, element, value, saveDialog); } }); }; export const moreMenu = async (config: Config.IUILayoutTabSearchConfig, criteriaData: Config.IUILayoutTabSearchConfig[], element: Element, cb: () => void, removeCriterion: () => void, layoutMenu?: () => void) => { if (!window.siyuan.menus.menu.element.classList.contains("fn__none") && window.siyuan.menus.menu.element.getAttribute("data-name") === "searchMore") { window.siyuan.menus.menu.remove(); return; } window.siyuan.menus.menu.remove(); window.siyuan.menus.menu.element.setAttribute("data-name", "searchMore"); /// #if MOBILE window.siyuan.menus.menu.append(new MenuItem({ iconHTML: "", label: window.siyuan.languages.listInvalidRefBlocks, click() { goUnRef(); } }).element); window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: "", label: window.siyuan.languages.searchType, click() { filterMenu(config, () => { updateSearchResult(config, element, true); }); } }).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: "", label: window.siyuan.languages.replaceType, click() { replaceFilterMenu(config); } }).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: "", label: window.siyuan.languages.searchMethod, type: "submenu", submenu: [{ iconHTML: "", label: window.siyuan.languages.keyword, current: config.method === 0, click() { config.method = 0; config.page = 1; updateSearchResult(config, element, true); } }, { iconHTML: "", label: window.siyuan.languages.querySyntax, current: config.method === 1, click() { config.method = 1; config.page = 1; updateSearchResult(config, element, true); } }, { iconHTML: "", label: "SQL", current: config.method === 2, click() { config.method = 2; config.page = 1; updateSearchResult(config, element, true); } }, { iconHTML: "", label: window.siyuan.languages.regex, current: config.method === 3, click() { config.method = 3; config.page = 1; updateSearchResult(config, element, true); } }] }).element); /// #endif const sortMenu = [{ iconHTML: "", label: window.siyuan.languages.type, current: config.sort === 0, click() { config.sort = 0; cb(); } }, { iconHTML: "", label: window.siyuan.languages.createdASC, current: config.sort === 1, click() { config.sort = 1; cb(); } }, { iconHTML: "", label: window.siyuan.languages.createdDESC, current: config.sort === 2, click() { config.sort = 2; cb(); } }, { iconHTML: "", label: window.siyuan.languages.modifiedASC, current: config.sort === 3, click() { config.sort = 3; cb(); } }, { iconHTML: "", label: window.siyuan.languages.modifiedDESC, current: config.sort === 4, click() { config.sort = 4; cb(); } }, { iconHTML: "", label: window.siyuan.languages.sortByRankAsc, current: config.sort === 6, click() { config.sort = 6; cb(); } }, { iconHTML: "", label: window.siyuan.languages.sortByRankDesc, current: config.sort === 7, click() { config.sort = 7; cb(); } }]; if (config.group === 1) { sortMenu.push({ iconHTML: "", label: window.siyuan.languages.sortByContent, current: config.sort === 5, click() { config.sort = 5; cb(); } }); } window.siyuan.menus.menu.append(new MenuItem({ iconHTML: "", label: window.siyuan.languages.sort, type: "submenu", submenu: sortMenu, }).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: "", label: window.siyuan.languages.group, type: "submenu", submenu: [{ iconHTML: "", label: window.siyuan.languages.noGroupBy, current: config.group === 0, click() { if (isMobile()) { element.querySelector('[data-type="expand"]').classList.add("fn__none"); element.querySelector('[data-type="contract"]').classList.add("fn__none"); } else { element.querySelector("#searchCollapse").parentElement.classList.add("fn__none"); } config.group = 0; if (config.sort === 5) { config.sort = 0; } cb(); } }, { iconHTML: "", label: window.siyuan.languages.groupByDoc, current: config.group === 1, click() { if (isMobile()) { element.querySelector('[data-type="expand"]').classList.remove("fn__none"); element.querySelector('[data-type="contract"]').classList.remove("fn__none"); } else { element.querySelector("#searchCollapse").parentElement.classList.remove("fn__none"); } config.group = 1; cb(); } }] }).element); if (layoutMenu) { layoutMenu(); } window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element); window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.saveCriterion, iconHTML: "", click() { saveCriterion(config, criteriaData, element); } }).element); window.siyuan.menus.menu.append(new MenuItem({ iconHTML: "", label: window.siyuan.languages.removeCriterion, click() { removeCriterion(); } }).element); }; const configIsSame = (config: Config.IUILayoutTabSearchConfig, config2: Config.IUILayoutTabSearchConfig) => { if (config2.group === config.group && config2.hPath === config.hPath && config2.hasReplace === config.hasReplace && config2.k === config.k && config2.method === config.method && config2.r === config.r && config2.sort === config.sort && objEquals(config2.types, config.types) && objEquals(config2.replaceTypes, config.replaceTypes) && objEquals(config2.idPath, config.idPath)) { return true; } return false; }; export const initCriteriaMenu = (element: HTMLElement, data: Config.IUILayoutTabSearchConfig[], config: Config.IUILayoutTabSearchConfig) => { fetchPost("/api/storage/getCriteria", {}, (response) => { let html = ""; response.data.forEach((item: Config.IUILayoutTabSearchConfig) => { data.push(item); let isSame = false; if (configIsSame(item, config)) { isSame = true; } html += `
${escapeHtml(item.name)}
`; }); /// #if MOBILE element.innerHTML = `
${html}
`; /// #else element.innerHTML = `
${html}
`; /// #endif }); }; export const getKeyByLiElement = (element: HTMLElement) => { const keys: string[] = []; element.querySelectorAll(".b3-list-item__text mark").forEach(item => { keys.push(item.textContent); }); if (keys.length === 0) { element.querySelectorAll(".b3-list-item__meta mark").forEach(item => { keys.push(item.textContent); }); } return [...new Set(keys)].join(" "); };