Vanessa 2023-04-07 12:13:19 +08:00
parent 95ac0e828b
commit d99972a405
7 changed files with 837 additions and 503 deletions

View file

@ -89,6 +89,7 @@ a.b3-chip:hover {
transition: var(--b3-transition);
cursor: pointer;
opacity: .68;
flex-shrink: 0;
&:hover {
// 不明原因 https://github.com/siyuan-note/siyuan/issues/7756#issuecomment-1484057954

View file

@ -67,7 +67,6 @@ export abstract class Constants {
public static readonly LOCAL_ZOOM = "local-zoom";
public static readonly LOCAL_SEARCHDATA = "local-searchdata";
public static readonly LOCAL_SEARCHKEYS = "local-searchkeys";
public static readonly LOCAL_SEARCHKEY = "local-searchkey"; // only mobile
public static readonly LOCAL_DOCINFO = "local-docinfo"; // only mobile
public static readonly LOCAL_DAILYNOTEID = "local-dailynoteid"; // string
public static readonly LOCAL_HISTORYNOTEID = "local-historynoteid"; // string

View file

@ -4,10 +4,71 @@ import {Constants} from "../../constants";
import {fetchPost} from "../../util/fetch";
import {getIconByType} from "../../editor/getIcon";
import {preventScroll} from "../../protyle/scroll/preventScroll";
import {setStorageVal} from "../../protyle/util/compatibility";
import {openModel} from "./model";
import {getNotebookName, movePathTo, pathPosix} from "../../util/pathName";
import {filterMenu, initCriteriaMenu, moreMenu, queryMenu} from "../../search/menu";
import {setStorageVal} from "../../protyle/util/compatibility";
import {escapeHtml} from "../../util/escape";
const onRecentBlocks = (data: IBlock[], matchedRootCount?:number, matchedBlockCount?:number) => {
const updateConfig = (element: Element, newConfig: ISearchOption, config: ISearchOption) => {
newConfig.hPath = config.hPath;
newConfig.idPath = config.idPath.join(",").split(",");
if (config.hasReplace !== newConfig.hasReplace) {
if (newConfig.hasReplace) {
element.querySelector('[data-type="toggle-replace"]').classList.add("toolbar__icon--active");
element.querySelector(".toolbar").classList.remove("fn__none");
} else {
element.querySelector('[data-type="toggle-replace"]').classList.remove("toolbar__icon--active");
element.querySelector(".toolbar").classList.add("fn__none");
}
}
const searchPathElement = element.querySelector("#searchPath");
if (newConfig.hPath) {
searchPathElement.classList.remove("fn__none")
searchPathElement.innerHTML = `<div class="b3-chip b3-chip--middle">${escapeHtml(newConfig.hPath)}<svg data-type="remove-path" class="b3-chip__close"><use xlink:href="#iconCloseRound"></use></svg></div>`;
} else {
searchPathElement.classList.add("fn__none")
}
if (config.group !== newConfig.group) {
if (newConfig.group === 0) {
element.querySelector('[data-type="expand"]').classList.add("fn__none");
element.querySelector('[data-type="contract"]').classList.add("fn__none");
} else {
element.querySelector('[data-type="expand"]').classList.remove("fn__none");
element.querySelector('[data-type="contract"]').classList.remove("fn__none");
}
}
let includeChild = true;
let enableIncludeChild = false;
newConfig.idPath.forEach(newConfig => {
if (newConfig.endsWith(".sy")) {
includeChild = false;
}
if (newConfig.split("/").length > 1) {
enableIncludeChild = true;
}
});
const searchIncludeElement = element.querySelector('[data-type="include"]');
if (includeChild) {
searchIncludeElement.classList.add("toolbar__icon--active");
} else {
searchIncludeElement.classList.remove("toolbar__icon--active");
}
if (enableIncludeChild) {
searchIncludeElement.removeAttribute("disabled");
} else {
searchIncludeElement.setAttribute("disabled", "disabled");
}
(document.querySelector("#toolbarSearch") as HTMLInputElement).value = newConfig.k;
(element.querySelector("#toolbarReplace") as HTMLInputElement).value = newConfig.r;
Object.assign(config, newConfig);
window.siyuan.storage[Constants.LOCAL_SEARCHDATA] = Object.assign({}, config);
setStorageVal(Constants.LOCAL_SEARCHDATA, window.siyuan.storage[Constants.LOCAL_SEARCHDATA]);
updateSearchResult(config);
window.siyuan.menus.menu.remove();
};
const onRecentBlocks = (data: IBlock[], matchedRootCount?: number, matchedBlockCount?: number) => {
let resultHTML = "";
if (matchedBlockCount) {
resultHTML = '<div class="b3-list-item ft__smaller ft__on-surface">' + window.siyuan.languages.findInDoc.replace("${x}", matchedRootCount).replace("${y}", matchedBlockCount) + "</div>";
@ -21,12 +82,11 @@ const onRecentBlocks = (data: IBlock[], matchedRootCount?:number, matchedBlockCo
<div class="b3-list-item__meta">${Lute.EscapeHTMLStr(item.hPath)}</div>
</div>`;
});
document.querySelector("#searchPanel").innerHTML = resultHTML;
document.querySelector("#searchList").innerHTML = resultHTML;
};
let toolbarSearchTimeout = 0;
export const toolbarSearchEvent = () => {
export const updateSearchResult = (config: ISearchOption) => {
clearTimeout(toolbarSearchTimeout);
toolbarSearchTimeout = window.setTimeout(() => {
const inputElement = document.getElementById("toolbarSearch") as HTMLInputElement;
@ -36,75 +96,305 @@ export const toolbarSearchEvent = () => {
});
} else {
fetchPost("/api/search/fullTextSearchBlock", {query: inputElement.value,}, (response) => {
onRecentBlocks(response.data.blocks, response.data.matchedRootCount,response.data.matchedBlockCount);
onRecentBlocks(response.data.blocks, response.data.matchedRootCount, response.data.matchedBlockCount);
});
}
window.siyuan.storage[Constants.LOCAL_SEARCHKEY] = inputElement.value;
setStorageVal(Constants.LOCAL_SEARCHKEY, window.siyuan.storage[Constants.LOCAL_SEARCHKEY]);
}, Constants.TIMEOUT_SEARCH);
return toolbarSearchTimeout
};
const initToolbarSearch = () => {
const inputElement = document.getElementById("toolbarSearch") as HTMLInputElement;
inputElement.focus();
inputElement.value = window.siyuan.storage[Constants.LOCAL_SEARCHKEY] || "";
inputElement.addEventListener("compositionend", (event: InputEvent) => {
const initSearchEvent = (element: Element, config: ISearchOption) => {
const searchInputElement = document.getElementById("toolbarSearch") as HTMLInputElement;
searchInputElement.value = config.k || "";
searchInputElement.addEventListener("compositionend", (event: InputEvent) => {
if (event && event.isComposing) {
return;
}
toolbarSearchEvent();
updateSearchResult(config);
});
inputElement.addEventListener("input", (event: InputEvent) => {
searchInputElement.addEventListener("input", (event: InputEvent) => {
if (event && event.isComposing) {
return;
}
toolbarSearchEvent();
updateSearchResult(config);
});
};
const replaceInputElement = element.querySelector(".toolbar .b3-text-field") as HTMLInputElement
replaceInputElement.value = config.r || ""
export const popSearch = () => {
openModel({
title: `<input id="toolbarSearch" placeholder="${window.siyuan.languages.showRecentUpdatedBlocks}" style="background-color: var(--b3-theme-surface);border: 0;" class="b3-text-field fn__block">`,
icon:"iconSearch",
html: `<div class="fn__flex-column" style="height: 100%">
<div id="searchPanel" style="overflow:auto;" class="fn__flex-1"></div>
<div class="toolbar">
<span class="fn__flex-1"></span>
<svg class="toolbar__icon"><use xlink:href="#iconReplace"></use></svg>
<svg class="toolbar__icon"><use xlink:href="#iconRegex"></use></svg>
<svg class="toolbar__icon"><use xlink:href="#iconFilter"></use></svg>
<svg class="toolbar__icon"><use xlink:href="#iconCopy"></use></svg>
<svg class="toolbar__icon"><use xlink:href="#iconFolder"></use></svg>
<svg class="toolbar__icon"><use xlink:href="#iconExpand"></use></svg>
<svg class="toolbar__icon"><use xlink:href="#iconContract"></use></svg>
<svg class="toolbar__icon"><use xlink:href="#iconMore"></use></svg>
<span class="fn__flex-1"></span>
</div>
</div>`,
bindEvent() {
initToolbarSearch();
const searchElement = document.getElementById("searchPanel");
// 不能使用 getEventName() https://ld246.com/article/1638887457149
searchElement.addEventListener("click", (event) => {
const criteriaData: ISearchOption[] = [];
initCriteriaMenu(element.querySelector("#criteria"), criteriaData);
element.addEventListener("click", (event: MouseEvent) => {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(searchElement)) {
if (target.classList.contains("b3-list-item")) {
while (target && !target.isSameNode(element)) {
const type = target.getAttribute("data-type");
if (type === "set-criteria") {
config.removed = false;
criteriaData.find(item => {
if (item.name === target.innerText.trim()) {
updateConfig(element, item, config);
return true;
}
});
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "remove-criteria") {
const name = target.parentElement.innerText.trim();
fetchPost("/api/storage/removeCriterion", {name});
criteriaData.find((item, index) => {
if (item.name === name) {
criteriaData.splice(index, 1);
return true;
}
});
if (target.parentElement.parentElement.childElementCount === 1) {
target.parentElement.parentElement.classList.add("fn__none");
target.parentElement.remove();
} else {
target.parentElement.remove();
}
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "remove-path") {
config.idPath = [];
config.hPath = "";
element.querySelector("#searchPath").classList.add("fn__none")
toolbarSearchTimeout = updateSearchResult(config);
const includeElement = element.querySelector('[data-type="include"]');
includeElement.classList.remove("toolbar__icon--active");
includeElement.setAttribute("disabled", "disabled");
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "searchExpand") {
// Array.from(searchPanelElement.children).forEach(item => {
// if (item.classList.contains("b3-list-item")) {
// item.querySelector(".b3-list-item__arrow").classList.add("b3-list-item__arrow--open");
// item.nextElementSibling.classList.remove("fn__none");
// }
// });
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "searchCollapse") {
// Array.from(searchPanelElement.children).forEach(item => {
// if (item.classList.contains("b3-list-item")) {
// item.querySelector(".b3-list-item__arrow").classList.remove("b3-list-item__arrow--open");
// item.nextElementSibling.classList.add("fn__none");
// }
// });
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "path") {
movePathTo((toPath, toNotebook) => {
fetchPost("/api/filetree/getHPathsByPaths", {paths: toPath}, (response) => {
config.idPath = [];
const hPathList: string[] = [];
let enableIncludeChild = false;
toPath.forEach((item, index) => {
if (item === "/") {
config.idPath.push(toNotebook[index]);
hPathList.push(getNotebookName(toNotebook[index]));
} else {
enableIncludeChild = true;
config.idPath.push(pathPosix().join(toNotebook[index], item.replace(".sy", "")));
}
});
if (response.data) {
hPathList.push(...response.data);
}
config.hPath = hPathList.join(" ");
const searchPathElement = element.querySelector("#searchPath")
searchPathElement.classList.remove("fn__none");
element.querySelector("#searchPath").innerHTML = `<div class="b3-chip b3-chip--middle">${escapeHtml(config.hPath)}<svg data-type="remove-path" class="b3-chip__close"><use xlink:href="#iconCloseRound"></use></svg></div>`;
const includeElement = element.querySelector('[data-type="include"]');
includeElement.classList.add("toolbar__icon--active");
if (enableIncludeChild) {
includeElement.removeAttribute("disabled");
} else {
includeElement.setAttribute("disabled", "disabled");
}
toolbarSearchTimeout = updateSearchResult(config);
});
}, [], undefined, window.siyuan.languages.specifyPath);
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "searchInclude") {
target.classList.toggle("b3-button--cancel");
if (target.classList.contains("b3-button--cancel")) {
config.idPath.forEach((item, index) => {
if (!item.endsWith(".sy") && item.split("/").length > 1) {
config.idPath[index] = item + ".sy";
}
});
} else {
config.idPath.forEach((item, index) => {
if (item.endsWith(".sy")) {
config.idPath[index] = item.replace(".sy", "");
}
});
}
// inputTimeout = inputEvent(element, config, inputTimeout, edit);
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "toggle-replace") {
config.hasReplace = !config.hasReplace;
replaceInputElement.parentElement.classList.toggle("fn__none");
target.classList.toggle("toolbar__icon--active");
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "more") {
moreMenu(config, criteriaData, element, () => {
updateSearchResult(config);
}, () => {
updateConfig(element, {
removed: true,
sort: 0,
group: 0,
hasReplace: false,
method: 0,
hPath: "",
idPath: [],
k: "",
r: "",
types: {
document: window.siyuan.config.search.document,
heading: window.siyuan.config.search.heading,
list: window.siyuan.config.search.list,
listItem: window.siyuan.config.search.listItem,
codeBlock: window.siyuan.config.search.codeBlock,
htmlBlock: window.siyuan.config.search.htmlBlock,
mathBlock: window.siyuan.config.search.mathBlock,
table: window.siyuan.config.search.table,
blockquote: window.siyuan.config.search.blockquote,
superBlock: window.siyuan.config.search.superBlock,
paragraph: window.siyuan.config.search.paragraph,
embedBlock: window.siyuan.config.search.embedBlock,
}
}, config);
})
window.siyuan.menus.menu.element.style.zIndex = "220";
window.siyuan.menus.menu.fullscreen();
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "filter") {
filterMenu(config, () => {
updateSearchResult(config)
});
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "query") {
queryMenu(config, () => {
updateSearchResult(config)
});
window.siyuan.menus.menu.element.style.zIndex = "220";
window.siyuan.menus.menu.fullscreen();
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "replaceAllBtn") {
// replace(element, config, edit, true);
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "replaceBtn") {
// replace(element, config, edit, false);
event.stopPropagation();
event.preventDefault();
break;
} else if (target.classList.contains("b3-list-item__toggle")) {
target.parentElement.nextElementSibling.classList.toggle("fn__none");
target.firstElementChild.classList.toggle("b3-list-item__arrow--open");
event.stopPropagation();
event.preventDefault();
break;
} else if (target.classList.contains("b3-list-item")) {
if (target.parentElement.id === "searchHistoryList") {
searchInputElement.value = target.textContent;
// inputTimeout = inputEvent(element, config, inputTimeout, edit);
} else if (target.parentElement.id === "replaceHistoryList") {
replaceInputElement.value = target.textContent;
} else if (target.getAttribute("data-type") === "search-new") {
// newEmptyFileByInput(searchInputElement.value);
} else if (target.getAttribute("data-type") === "search-item") {
const id = target.getAttribute("data-id");
if (window.siyuan.mobile.editor.protyle) {
preventScroll(window.siyuan.mobile.editor.protyle);
}
fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
openMobileFileById(id,foldResponse.data ? [Constants.CB_GET_ALL, Constants.CB_GET_HL] : [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT]);
openMobileFileById(id, foldResponse.data ? [Constants.CB_GET_ALL, Constants.CB_GET_HL] : [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT]);
});
closePanel();
event.preventDefault();
} else if (target.querySelector(".b3-list-item__toggle")) {
target.nextElementSibling.classList.toggle("fn__none");
target.firstElementChild.firstElementChild.classList.toggle("b3-list-item__arrow--open");
}
event.stopPropagation();
event.preventDefault();
break;
}
target = target.parentElement;
}
}, false);
toolbarSearchEvent();
};
export const popSearch = (config = window.siyuan.storage[Constants.LOCAL_SEARCHDATA] as ISearchOption) => {
let includeChild = true;
let enableIncludeChild = false;
config.idPath.forEach(item => {
if (item.endsWith(".sy")) {
includeChild = false;
}
if (item.split("/").length > 1) {
enableIncludeChild = true;
}
});
openModel({
title: `<input id="toolbarSearch" placeholder="${window.siyuan.languages.showRecentUpdatedBlocks}" class="b3-text-field fn__block">`,
icon: "iconSearch",
html: `<div class="fn__flex-column" style="height: 100%">
<div class="toolbar toolbar--border${config.hasReplace ? "" : " fn__none"}">
<svg class="toolbar__icon"><use xlink:href="#iconReplace"></use></svg>
<input id="toolbarReplace" class="b3-text-field fn__flex-1">
<div class="fn__space"></div>
<button class="b3-button b3-button--outline fn__flex-center">${window.siyuan.languages.replaceAll}</button>
<div class="fn__space"></div>
<button class="b3-button b3-button--outline fn__flex-center">${window.siyuan.languages.replace}</button>
<div class="fn__space"></div>
</div>
<div id="criteria" style="background-color: var(--b3-theme-background);" class="b3-chips"></div>
<div id="searchList" style="overflow:auto;" class="fn__flex-1"></div>
<div id="searchPath" class="b3-chips${config.hPath ? "" : " fn__none"}" style="background-color: var(--b3-theme-background);">
<div class="b3-chip b3-chip--middle">
${escapeHtml(config.hPath)}
<svg data-type="remove-path" class="b3-chip__close"><use xlink:href="#iconCloseRound"></use></svg>
</div>
</div>
<div class="toolbar">
<span class="fn__flex-1"></span>
<svg data-type="toggle-replace" class="toolbar__icon${config.hasReplace ? " toolbar__icon--active" : ""}"><use xlink:href="#iconReplace"></use></svg>
<svg data-type="query" class="toolbar__icon"><use xlink:href="#iconRegex"></use></svg>
<svg data-type="filter" class="toolbar__icon"><use xlink:href="#iconFilter"></use></svg>
<svg ${enableIncludeChild ? "" : "disabled"} data-type="include" class="toolbar__icon${includeChild ? " toolbar__icon--active" : ""}"><use xlink:href="#iconCopy"></use></svg>
<svg data-type="path" class="toolbar__icon"><use xlink:href="#iconFolder"></use></svg>
<svg data-type="expand" class="toolbar__icon${config.group === 0 ? " fn__none" : ""}"><use xlink:href="#iconExpand"></use></svg>
<svg data-type="contract" class="toolbar__icon${config.group === 0 ? " fn__none" : ""}"><use xlink:href="#iconContract"></use></svg>
<svg data-type="more" class="toolbar__icon"><use xlink:href="#iconMore"></use></svg>
<span class="fn__flex-1"></span>
</div>
</div>`,
bindEvent(element) {
initSearchEvent(element.firstElementChild, config);
toolbarSearchTimeout = updateSearchResult(config);
}
});
};

View file

@ -5,7 +5,8 @@ import {MenuItem} from "../../menus/Menu";
import {Dialog} from "../../dialog";
import {confirmDialog} from "../../dialog/confirmDialog";
import {escapeHtml} from "../../util/escape";
import {popSearch, toolbarSearchEvent} from "../menu/search";
import {popSearch} from "../menu/search";
import {Constants} from "../../constants";
export class MobileTags {
public element: HTMLElement;
@ -65,9 +66,9 @@ export class MobileTags {
});
}
} else {
popSearch();
(document.getElementById("toolbarSearch") as HTMLInputElement).value = `#${element.getAttribute("data-label")}#`;
toolbarSearchEvent();
const searchOption = Object.assign({}, window.siyuan.storage[Constants.LOCAL_SEARCHDATA]);
searchOption.k = `#${element.getAttribute("data-label")}#`
popSearch(searchOption);
}
},
topExtHTML: window.siyuan.config.readonly ? undefined : '<span class="b3-list-item__action" data-type="edit"><svg><use xlink:href="#iconEdit"></use></svg></span><span class="b3-list-item__action" data-type="remove"><svg><use xlink:href="#iconTrashcan"></use></svg></span>'

View file

@ -154,7 +154,11 @@ export const getLocalStorage = (cb: () => void) => {
rowTab: "",
layoutTab: 0
};
defaultStorage[Constants.LOCAL_PDFTHEME] = {light: "light", dark: "dark", annoColor: "var(--b3-pdf-background1)"};
defaultStorage[Constants.LOCAL_PDFTHEME] = {
light: "light",
dark: "dark",
annoColor: "var(--b3-pdf-background1)"
};
defaultStorage[Constants.LOCAL_LAYOUTS] = []; // {name: "", layout:{}}
defaultStorage[Constants.LOCAL_AI] = []; // {name: "", memo: ""}
defaultStorage[Constants.LOCAL_BAZAAR] = {
@ -206,16 +210,15 @@ export const getLocalStorage = (cb: () => void) => {
}
};
defaultStorage[Constants.LOCAL_ZOOM] = 1;
defaultStorage[Constants.LOCAL_SEARCHKEY] = "";
[Constants.LOCAL_EXPORTIMG, Constants.LOCAL_SEARCHKEYS, Constants.LOCAL_PDFTHEME, Constants.LOCAL_BAZAAR, Constants.LOCAL_EXPORTWORD,
Constants.LOCAL_EXPORTPDF, Constants.LOCAL_DOCINFO, Constants.LOCAL_FONTSTYLES, Constants.LOCAL_SEARCHDATA,
Constants.LOCAL_ZOOM, Constants.LOCAL_SEARCHKEY, Constants.LOCAL_LAYOUTS, Constants.LOCAL_AI].forEach((key) => {
Constants.LOCAL_ZOOM, Constants.LOCAL_LAYOUTS, Constants.LOCAL_AI].forEach((key) => {
if (typeof response.data[key] === "string") {
try {
window.siyuan.storage[key] = Object.assign(defaultStorage[key], JSON.parse(response.data[key]));
} catch (e) {
window.siyuan.storage[key] = key === Constants.LOCAL_SEARCHKEY ? (response.data[key] || "") : defaultStorage[key];
window.siyuan.storage[key] = defaultStorage[key];
}
} else if (typeof response.data[key] === "undefined") {
window.siyuan.storage[key] = defaultStorage[key];
@ -226,7 +229,7 @@ export const getLocalStorage = (cb: () => void) => {
// 数据兼容移除历史数据3.8.4 移除
fetchPost("/api/storage/removeLocalStorageVals", {
app: Constants.SIYUAN_APPID,
keys:["leftColumn", "local-searchedata", "local-searchekeys", "local-searchetabdata", "rightColumn", "topBar"]
keys: ["leftColumn", "local-searchkey", "local-searchedata", "local-searchekeys", "local-searchetabdata", "rightColumn", "topBar"]
});
});
};

373
app/src/search/menu.ts Normal file
View file

@ -0,0 +1,373 @@
import {Dialog} from "../dialog";
import {isMobile} 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";
export const filterMenu = (config: ISearchOption, cb: () => void) => {
const filterDialog = new Dialog({
title: window.siyuan.languages.type,
content: `<div class="b3-dialog__content" style="height:calc(70vh - 45px);overflow: auto">
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconMath"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.math}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="mathBlock" type="checkbox"${config.types.mathBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconTable"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.table}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="table" type="checkbox"${config.types.table ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconQuote"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.quote}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="blockquote" type="checkbox"${config.types.blockquote ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconSuper"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.superBlock}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="superBlock" type="checkbox"${config.types.superBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconParagraph"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.paragraph}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="paragraph" type="checkbox"${config.types.paragraph ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconFile"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.doc}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="document" type="checkbox"${config.types.document ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconHeadings"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.headings}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="heading" type="checkbox"${config.types.heading ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconList"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.list1}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="list" type="checkbox"${config.types.list ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconListItem"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.listItem}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="listItem" type="checkbox"${config.types.listItem ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconCode"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.code}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="codeBlock" type="checkbox"${config.types.codeBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconHTML5"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
HTML
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="htmlBlock" type="checkbox"${config.types.htmlBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconSQL"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.embedBlock}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="embedBlock" type="checkbox"${config.types.embedBlock ? " checked" : ""}>
</label>
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
</div>`,
width: isMobile() ? "90vw" : "520px",
});
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 TSearchFilter] = item.checked;
});
cb();
filterDialog.destroy();
});
};
export const queryMenu = (config: ISearchOption, cb: () => void) => {
window.siyuan.menus.menu.remove();
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.keyword,
current: config.method === 0,
click() {
config.method = 0;
cb();
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.querySyntax,
current: config.method === 1,
click() {
config.method = 1;
cb();
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: "SQL",
current: config.method === 2,
click() {
config.method = 2;
cb();
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.regex,
current: config.method === 3,
click() {
config.method = 3;
cb();
}
}).element);
};
export const moreMenu = async (config: ISearchOption,
criteriaData: ISearchOption[],
element: Element,
cb: () => void,
removeCriterion: () => void,
layoutMenu?: () => void) => {
window.siyuan.menus.menu.remove();
const sortMenu = [{
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.type,
current: config.sort === 0,
click() {
config.sort = 0;
cb();
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.createdASC,
current: config.sort === 1,
click() {
config.sort = 1;
cb();
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.createdDESC,
current: config.sort === 2,
click() {
config.sort = 2;
cb();
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.modifiedASC,
current: config.sort === 3,
click() {
config.sort = 3;
cb();
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.modifiedDESC,
current: config.sort === 4,
click() {
config.sort = 4;
cb();
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sortByRankAsc,
current: config.sort === 6,
click() {
config.sort = 6;
cb();
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sortByRankDesc,
current: config.sort === 7,
click() {
config.sort = 7;
cb();
}
}];
if (config.group === 1) {
sortMenu.push({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sortByContent,
current: config.sort === 5,
click() {
config.sort = 5;
cb();
}
});
}
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sort,
type: "submenu",
submenu: sortMenu,
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.group,
type: "submenu",
submenu: [{
iconHTML: Constants.ZWSP,
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: Constants.ZWSP,
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: Constants.ZWSP,
click() {
const saveDialog = new Dialog({
title: window.siyuan.languages.saveCriterion,
content: `<div class="b3-dialog__content">
<input class="b3-text-field fn__block" placeholder="${window.siyuan.languages.memo}">
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
</div>`,
width: isMobile() ? "80vw" : "520px",
});
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 value = saveDialog.element.querySelector("input").value;
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 criterion = config;
criterion.name = value;
criteriaData.push(Object.assign({}, criterion));
fetchPost("/api/storage/setCriterion", {criterion}, () => {
saveDialog.destroy();
const criteriaElement = element.querySelector("#criteria");
criteriaElement.classList.remove("fn__none");
criteriaElement.insertAdjacentHTML("beforeend", `<div data-type="set-criteria" class="b3-chip b3-chip--middle b3-chip--pointer b3-chip--${["secondary", "primary", "info", "success", "warning", "error", ""][(criteriaElement.childElementCount) % 7]}">${criterion.name}<svg class="b3-chip__close" data-type="remove-criteria"><use xlink:href="#iconCloseRound"></use></svg></div>`);
});
});
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.removeCriterion,
click() {
removeCriterion();
}
}).element);
};
export const initCriteriaMenu = (element: HTMLElement, data: ISearchOption[]) => {
fetchPost("/api/storage/getCriteria", {}, (response) => {
let html = "";
response.data.forEach((item: ISearchOption, index: number) => {
data.push(item);
html += `<div data-type="set-criteria" class="b3-chip b3-chip--middle b3-chip--pointer b3-chip--${["secondary", "primary", "info", "success", "warning", "error", ""][index % 7]}">${escapeHtml(item.name)}<svg class="b3-chip__close" data-type="remove-criteria"><use xlink:href="#iconCloseRound"></use></svg></div>`;
});
element.innerHTML = html;
if (html === "") {
element.classList.add("fn__none");
} else {
element.classList.remove("fn__none");
}
});
};

View file

@ -23,22 +23,7 @@ import {replaceFileName} from "../editor/rename";
import {hideElements} from "../protyle/ui/hideElements";
import {getNewFilePath} from "../util/newFile";
import {matchHotKey} from "../protyle/util/hotKey";
const appendCriteria = (element: HTMLElement, data: ISearchOption[]) => {
fetchPost("/api/storage/getCriteria", {}, (response) => {
let html = "";
response.data.forEach((item: ISearchOption, index: number) => {
data.push(item);
html += `<div data-type="set-criteria" class="b3-chip b3-chip--middle b3-chip--pointer b3-chip--${["secondary", "primary", "info", "success", "warning", "error", ""][index % 7]}">${escapeHtml(item.name)}<svg class="b3-chip__close" data-type="remove-criteria"><use xlink:href="#iconCloseRound"></use></svg></div>`;
});
element.innerHTML = html;
if (html === "") {
element.classList.add("fn__none");
} else {
element.classList.remove("fn__none");
}
});
};
import {filterMenu, initCriteriaMenu, moreMenu, queryMenu} from "./menu";
const saveKeyList = (type: "keys" | "replaceKeys", value: string) => {
let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type];
@ -223,7 +208,7 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
<div class="fn__loading fn__loading--top"><img width="120px" src="/stage/loading-pure.svg"></div>`;
const criteriaData: ISearchOption[] = [];
appendCriteria(element.querySelector("#criteria"), criteriaData);
initCriteriaMenu(element.querySelector("#criteria"), criteriaData);
const searchPanelElement = element.querySelector("#searchList");
const searchInputElement = element.querySelector("#searchInput") as HTMLInputElement;
const replaceInputElement = element.querySelector("#replaceInput") as HTMLInputElement;
@ -472,18 +457,102 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
event.preventDefault();
break;
} else if (target.id === "searchMore") {
addConfigMoreMenu(config, edit, element, event, criteriaData);
moreMenu(config, criteriaData, element, () => {
inputEvent(element, config, undefined, edit);
}, ()=> {
updateConfig(element, {
removed: true,
sort: 0,
group: 0,
hasReplace: false,
method: 0,
hPath: "",
idPath: [],
k: "",
r: "",
types: {
document: window.siyuan.config.search.document,
heading: window.siyuan.config.search.heading,
list: window.siyuan.config.search.list,
listItem: window.siyuan.config.search.listItem,
codeBlock: window.siyuan.config.search.codeBlock,
htmlBlock: window.siyuan.config.search.htmlBlock,
mathBlock: window.siyuan.config.search.mathBlock,
table: window.siyuan.config.search.table,
blockquote: window.siyuan.config.search.blockquote,
superBlock: window.siyuan.config.search.superBlock,
paragraph: window.siyuan.config.search.paragraph,
embedBlock: window.siyuan.config.search.embedBlock,
}
}, config, edit);
}, () => {
const localData = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
const isPopover = hasClosestByClassName(element, "b3-dialog__container");
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: isPopover ? localData.layout === 0 : localData.layoutTab === 0,
click() {
element.querySelector(".search__layout").classList.remove("search__layout--row");
edit.protyle.element.style.width = "";
if ((isPopover && localData.row) || (!isPopover && localData.rowTab)) {
edit.protyle.element.style.height = isPopover ? localData.row : localData.rowTab;
edit.protyle.element.classList.remove("fn__flex-1");
} else {
edit.protyle.element.classList.add("fn__flex-1");
}
setPadding(edit.protyle);
if (isPopover) {
localData.layout = 0;
} else {
localData.layoutTab = 0;
}
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.leftRightLayout,
current: isPopover ? localData.layout === 1 : localData.layoutTab === 1,
click() {
element.querySelector(".search__layout").classList.add("search__layout--row");
edit.protyle.element.style.height = "";
if ((isPopover && localData.col) || (!isPopover && localData.colTab)) {
edit.protyle.element.style.width = isPopover ? localData.col : localData.colTab;
edit.protyle.element.classList.remove("fn__flex-1");
} else {
edit.protyle.element.classList.add("fn__flex-1");
}
setPadding(edit.protyle);
if (isPopover) {
localData.layout = 1;
} else {
localData.layoutTab = 1;
}
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
}
}]
}).element);
});
window.siyuan.menus.menu.popup({x: event.clientX - 16, y: event.clientY - 16}, true);
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "searchFilter") {
addConfigFilterMenu(config, edit, element);
filterMenu(config, () => {
inputEvent(element, config, undefined, edit);
});
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "searchSyntaxCheck") {
window.siyuan.menus.menu.remove();
addQueryMenu(config, edit, element);
queryMenu(config, () => {
element.querySelector("#searchSyntaxCheck").setAttribute("aria-label", getQueryTip(config.method));
inputEvent(element, config, undefined, edit);
});
window.siyuan.menus.menu.popup({x: event.clientX - 16, y: event.clientY - 16}, true);
event.stopPropagation();
event.preventDefault();
@ -729,235 +798,24 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
return edit;
};
const addConfigMoreMenu = async (config: ISearchOption, edit: Protyle, element: Element, event: MouseEvent, criteriaData: ISearchOption[]) => {
window.siyuan.menus.menu.remove();
const sortMenu = [{
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.type,
current: config.sort === 0,
click() {
config.sort = 0;
inputEvent(element, config, undefined, edit);
const getQueryTip = (method: number) => {
let methodTip = window.siyuan.languages.searchMethod + " ";
switch (method) {
case 0:
methodTip += window.siyuan.languages.keyword;
break;
case 1:
methodTip += window.siyuan.languages.querySyntax;
break;
case 2:
methodTip += "SQL";
break;
case 3:
methodTip += window.siyuan.languages.regex;
break;
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.createdASC,
current: config.sort === 1,
click() {
config.sort = 1;
inputEvent(element, config, undefined, edit);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.createdDESC,
current: config.sort === 2,
click() {
config.sort = 2;
inputEvent(element, config, undefined, edit);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.modifiedASC,
current: config.sort === 3,
click() {
config.sort = 3;
inputEvent(element, config, undefined, edit);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.modifiedDESC,
current: config.sort === 4,
click() {
config.sort = 4;
inputEvent(element, config, undefined, edit);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sortByRankAsc,
current: config.sort === 6,
click() {
config.sort = 6;
inputEvent(element, config, undefined, edit);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sortByRankDesc,
current: config.sort === 7,
click() {
config.sort = 7;
inputEvent(element, config, undefined, edit);
}
}];
if (config.group === 1) {
sortMenu.push({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sortByContent,
current: config.sort === 5,
click() {
config.sort = 5;
inputEvent(element, config, undefined, edit);
}
});
}
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.sort,
type: "submenu",
submenu: sortMenu,
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.group,
type: "submenu",
submenu: [{
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.noGroupBy,
current: config.group === 0,
click() {
element.querySelector("#searchCollapse").parentElement.classList.add("fn__none");
config.group = 0;
if (config.sort === 5) {
config.sort = 0;
}
inputEvent(element, config, undefined, edit);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.groupByDoc,
current: config.group === 1,
click() {
element.querySelector("#searchCollapse").parentElement.classList.remove("fn__none");
config.group = 1;
inputEvent(element, config, undefined, edit);
}
}]
}).element);
const localData = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
const isPopover = hasClosestByClassName(element, "b3-dialog__container");
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: isPopover ? localData.layout === 0 : localData.layoutTab === 0,
click() {
element.querySelector(".search__layout").classList.remove("search__layout--row");
edit.protyle.element.style.width = "";
if ((isPopover && localData.row) || (!isPopover && localData.rowTab)) {
edit.protyle.element.style.height = isPopover ? localData.row : localData.rowTab;
edit.protyle.element.classList.remove("fn__flex-1");
} else {
edit.protyle.element.classList.add("fn__flex-1");
}
setPadding(edit.protyle);
if (isPopover) {
localData.layout = 0;
} else {
localData.layoutTab = 0;
}
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
}
}, {
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.leftRightLayout,
current: isPopover ? localData.layout === 1 : localData.layoutTab === 1,
click() {
element.querySelector(".search__layout").classList.add("search__layout--row");
edit.protyle.element.style.height = "";
if ((isPopover && localData.col) || (!isPopover && localData.colTab)) {
edit.protyle.element.style.width = isPopover ? localData.col : localData.colTab;
edit.protyle.element.classList.remove("fn__flex-1");
} else {
edit.protyle.element.classList.add("fn__flex-1");
}
setPadding(edit.protyle);
if (isPopover) {
localData.layout = 1;
} else {
localData.layoutTab = 1;
}
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
}
}]
}).element);
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
window.siyuan.menus.menu.append(new MenuItem({
label: window.siyuan.languages.saveCriterion,
iconHTML: Constants.ZWSP,
click() {
const saveDialog = new Dialog({
title: window.siyuan.languages.saveCriterion,
content: `<div class="b3-dialog__content">
<input class="b3-text-field fn__block" placeholder="${window.siyuan.languages.memo}">
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
</div>`,
width: "520px",
});
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 value = saveDialog.element.querySelector("input").value;
if (!value) {
showMessage(window.siyuan.languages["_kernel"]["142"]);
return;
}
config.k = (element.querySelector("#searchInput") as HTMLInputElement).value;
config.r = (element.querySelector("#replaceInput") as HTMLInputElement).value;
const criterion = config;
criterion.name = value;
criteriaData.push(Object.assign({}, criterion));
fetchPost("/api/storage/setCriterion", {criterion}, () => {
saveDialog.destroy();
const criteriaElement = element.querySelector("#criteria");
criteriaElement.classList.remove("fn__none");
criteriaElement.insertAdjacentHTML("beforeend", `<div data-type="set-criteria" class="b3-chip b3-chip--middle b3-chip--pointer b3-chip--${["secondary", "primary", "info", "success", "warning", "error", ""][(criteriaElement.childElementCount) % 7]}">${criterion.name}<svg class="b3-chip__close" data-type="remove-criteria"><use xlink:href="#iconCloseRound"></use></svg></div>`);
});
});
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.removeCriterion,
click() {
updateConfig(element, {
removed: true,
sort: 0,
group: 0,
hasReplace: false,
method: 0,
hPath: "",
idPath: [],
k: "",
r: "",
types: {
document: window.siyuan.config.search.document,
heading: window.siyuan.config.search.heading,
list: window.siyuan.config.search.list,
listItem: window.siyuan.config.search.listItem,
codeBlock: window.siyuan.config.search.codeBlock,
htmlBlock: window.siyuan.config.search.htmlBlock,
mathBlock: window.siyuan.config.search.mathBlock,
table: window.siyuan.config.search.table,
blockquote: window.siyuan.config.search.blockquote,
superBlock: window.siyuan.config.search.superBlock,
paragraph: window.siyuan.config.search.paragraph,
embedBlock: window.siyuan.config.search.embedBlock,
}
}, config, edit);
}
}).element);
window.siyuan.menus.menu.popup({x: event.clientX - 16, y: event.clientY - 16}, true);
};
return methodTip
}
const updateConfig = (element: Element, item: ISearchOption, config: ISearchOption, edit: Protyle) => {
const dialogElement = hasClosestByClassName(element, "b3-dialog--open");
@ -1011,22 +869,7 @@ const updateConfig = (element: Element, item: ISearchOption, config: ISearchOpti
}
(element.querySelector("#searchInput") as HTMLInputElement).value = item.k;
(element.querySelector("#replaceInput") as HTMLInputElement).value = item.r;
let methodTip = window.siyuan.languages.searchMethod + " ";
switch (item.method) {
case 0:
methodTip += window.siyuan.languages.keyword;
break;
case 1:
methodTip += window.siyuan.languages.querySyntax;
break;
case 2:
methodTip += "SQL";
break;
case 3:
methodTip += window.siyuan.languages.regex;
break;
}
element.querySelector("#searchSyntaxCheck").setAttribute("aria-label", methodTip);
element.querySelector("#searchSyntaxCheck").setAttribute("aria-label", getQueryTip(item.method));
Object.assign(config, item);
window.siyuan.storage[Constants.LOCAL_SEARCHDATA] = Object.assign({}, config);
setStorageVal(Constants.LOCAL_SEARCHDATA, window.siyuan.storage[Constants.LOCAL_SEARCHDATA]);
@ -1034,182 +877,6 @@ const updateConfig = (element: Element, item: ISearchOption, config: ISearchOpti
window.siyuan.menus.menu.remove();
};
const addConfigFilterMenu = (config: ISearchOption, edit: Protyle, element: Element) => {
const filterDialog = new Dialog({
title: window.siyuan.languages.type,
content: `<div class="b3-dialog__content" style="height:calc(70vh - 45px);overflow: auto">
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconMath"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.math}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="mathBlock" type="checkbox"${config.types.mathBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconTable"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.table}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="table" type="checkbox"${config.types.table ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconQuote"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.quote}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="blockquote" type="checkbox"${config.types.blockquote ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconSuper"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.superBlock}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="superBlock" type="checkbox"${config.types.superBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconParagraph"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.paragraph}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="paragraph" type="checkbox"${config.types.paragraph ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconFile"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.doc}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="document" type="checkbox"${config.types.document ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconHeadings"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.headings}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="heading" type="checkbox"${config.types.heading ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconList"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.list1}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="list" type="checkbox"${config.types.list ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconListItem"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.listItem}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="listItem" type="checkbox"${config.types.listItem ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconCode"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.code}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="codeBlock" type="checkbox"${config.types.codeBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconHTML5"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
HTML
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="htmlBlock" type="checkbox"${config.types.htmlBlock ? " checked" : ""}>
</label>
<label class="fn__flex b3-label">
<svg class="ft__on-surface svg fn__flex-center"><use xlink:href="#iconSQL"></use></svg>
<span class="fn__space"></span>
<div class="fn__flex-1 fn__flex-center">
${window.siyuan.languages.embedBlock}
</div>
<span class="fn__space"></span>
<input id="removeAssets" class="b3-switch fn__flex-center" data-type="embedBlock" type="checkbox"${config.types.embedBlock ? " checked" : ""}>
</label>
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
</div>`,
width: "520px",
});
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 TSearchFilter] = item.checked;
});
inputEvent(element, config, undefined, edit);
filterDialog.destroy();
});
};
const addQueryMenu = (config: ISearchOption, edit: Protyle, element: Element) => {
const searchSyntaxCheckElement = element.querySelector("#searchSyntaxCheck");
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.keyword,
current: config.method === 0,
click() {
config.method = 0;
searchSyntaxCheckElement.setAttribute("aria-label", `${window.siyuan.languages.searchMethod} ${window.siyuan.languages.keyword}`);
inputEvent(element, config, undefined, edit);
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.querySyntax,
current: config.method === 1,
click() {
config.method = 1;
searchSyntaxCheckElement.setAttribute("aria-label", `${window.siyuan.languages.searchMethod} ${window.siyuan.languages.querySyntax}`);
inputEvent(element, config, undefined, edit);
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: "SQL",
current: config.method === 2,
click() {
config.method = 2;
searchSyntaxCheckElement.setAttribute("aria-label", `${window.siyuan.languages.searchMethod} SQL`);
inputEvent(element, config, undefined, edit);
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
iconHTML: Constants.ZWSP,
label: window.siyuan.languages.regex,
current: config.method === 3,
click() {
config.method = 3;
searchSyntaxCheckElement.setAttribute("aria-label", `${window.siyuan.languages.searchMethod} ${window.siyuan.languages.regex}`);
inputEvent(element, config, undefined, edit);
}
}).element);
};
const getKey = (element: HTMLElement) => {
const keys: string[] = [];
element.querySelectorAll("mark").forEach(item => {