diff --git a/app/src/assets/scss/component/_chip.scss b/app/src/assets/scss/component/_chip.scss index 573df4012..5925d251f 100644 --- a/app/src/assets/scss/component/_chip.scss +++ b/app/src/assets/scss/component/_chip.scss @@ -40,36 +40,70 @@ &--secondary { background-color: var(--b3-theme-secondary); color: var(--b3-theme-on-secondary); + + &.b3-chip--current { + box-shadow: 0 0 0 2px var(--b3-theme-secondary) inset; + } } &--primary { background-color: var(--b3-theme-primary); color: var(--b3-theme-on-primary); + + &.b3-chip--current { + box-shadow: 0 0 0 2px var(--b3-theme-primary) inset; + } } &--pink { color: var(--b3-theme-on-secondary); background-color: #ea4aaa; + + &.b3-chip--current { + box-shadow: 0 0 0 2px #ea4aaa inset; + } } &--info { color: var(--b3-card-info-color); background-color: var(--b3-card-info-background); + + &.b3-chip--current { + box-shadow: 0 0 0 2px var(--b3-card-info-background) inset; + } } &--warning { color: var(--b3-card-warning-color); background-color: var(--b3-card-warning-background); + + &.b3-chip--current { + box-shadow: 0 0 0 2px var(--b3-card-warning-background) inset; + } } &--error { color: var(--b3-card-error-color); background-color: var(--b3-card-error-background); + + &.b3-chip--current { + box-shadow: 0 0 0 2px var(--b3-card-error-background) inset; + } } &--success { color: var(--b3-card-success-color); background-color: var(--b3-card-success-background); + + &.b3-chip--current { + box-shadow: 0 0 0 2px var(--b3-card-success-background) inset; + } + } + + &--current { + background-color: var(--b3-theme-surface); + color: var(--b3-theme-on-surface); + box-shadow: 0 0 0 2px var(--b3-list-hover) inset; } &--pointer { diff --git a/app/src/search/menu.ts b/app/src/search/menu.ts index 63698e017..816341fdb 100644 --- a/app/src/search/menu.ts +++ b/app/src/search/menu.ts @@ -1,5 +1,5 @@ import {Dialog} from "../dialog"; -import {isMobile} from "../util/functions"; +import {isMobile, objEquals} from "../util/functions"; import {MenuItem} from "../menus/Menu"; import {Constants} from "../constants"; import {showMessage} from "../dialog/message"; @@ -229,8 +229,9 @@ export const saveCriterion = (config: ISearchOption, fetchPost("/api/storage/setCriterion", {criterion}, () => { saveDialog.destroy(); const criteriaElement = element.querySelector("#criteria"); + criteriaElement.querySelector(".b3-chip--current")?.classList.remove("b3-chip--current"); criteriaElement.classList.remove("fn__none"); - criteriaElement.firstElementChild.insertAdjacentHTML("beforeend", `
${criterion.name}
`); + criteriaElement.firstElementChild.insertAdjacentHTML("beforeend", `
${criterion.name}
`); }); }); }; @@ -379,12 +380,18 @@ export const moreMenu = async (config: ISearchOption, }).element); }; -export const initCriteriaMenu = (element: HTMLElement, data: ISearchOption[]) => { +export const initCriteriaMenu = (element: HTMLElement, data: ISearchOption[], config: ISearchOption) => { fetchPost("/api/storage/getCriteria", {}, (response) => { let html = ""; response.data.forEach((item: ISearchOption, index: number) => { data.push(item); - html += `
${escapeHtml(item.name)}
`; + let isSame = false; + if (item.group === config.group && item.hPath === config.hPath && item.hasReplace === config.hasReplace && + item.k === config.k && item.method === config.method && item.r === config.r && + item.sort === config.sort && objEquals(item.types, config.types) && objEquals(item.idPath, config.idPath)) { + isSame = true; + } + html += `
${escapeHtml(item.name)}
`; }); /// #if MOBILE element.innerHTML = `
diff --git a/app/src/search/util.ts b/app/src/search/util.ts index 79c786020..781859ebd 100644 --- a/app/src/search/util.ts +++ b/app/src/search/util.ts @@ -223,7 +223,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo
`; const criteriaData: ISearchOption[] = []; - initCriteriaMenu(element.querySelector("#criteria"), criteriaData); + initCriteriaMenu(element.querySelector("#criteria"), criteriaData, config); const searchPanelElement = element.querySelector("#searchList"); const searchInputElement = element.querySelector("#searchInput") as HTMLInputElement; const replaceInputElement = element.querySelector("#replaceInput") as HTMLInputElement; @@ -343,6 +343,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo embedBlock: window.siyuan.config.search.embedBlock, } }, config, edit); + element.querySelector(".b3-chip--current")?.classList.remove("b3-chip--current"); event.stopPropagation(); event.preventDefault(); break; @@ -369,6 +370,8 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo break; } else if (target.classList.contains("b3-chip") && type === "set-criteria") { config.removed = false; + target.parentElement.querySelector(".b3-chip--current")?.classList.remove("b3-chip--current"); + target.classList.add("b3-chip--current"); criteriaData.find(item => { if (item.name === target.innerText.trim()) { updateConfig(element, item, config, edit); @@ -397,7 +400,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo config.page = 1; searchPathInputElement.innerHTML = config.hPath; searchPathInputElement.setAttribute("title", ""); - inputTimeout = inputEvent(element, config, inputTimeout, edit); + inputTimeout = inputEvent(element, config, inputTimeout, edit, true); const includeElement = element.querySelector("#searchInclude"); includeElement.classList.remove("b3-button--cancel"); includeElement.setAttribute("disabled", "disabled"); @@ -453,7 +456,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo } else { includeElement.setAttribute("disabled", "disabled"); } - inputTimeout = inputEvent(element, config, inputTimeout, edit); + inputTimeout = inputEvent(element, config, inputTimeout, edit, true); }); }, [], undefined, window.siyuan.languages.specifyPath); event.stopPropagation(); @@ -475,7 +478,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo }); } config.page = 1; - inputTimeout = inputEvent(element, config, inputTimeout, edit); + inputTimeout = inputEvent(element, config, inputTimeout, edit, true); event.stopPropagation(); event.preventDefault(); break; @@ -504,7 +507,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo } else if (target.id === "searchMore") { moreMenu(config, criteriaData, element, () => { config.page = 1; - inputEvent(element, config, undefined, edit); + inputEvent(element, config, undefined, edit, true); }, () => { updateConfig(element, { removed: true, @@ -532,6 +535,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo embedBlock: window.siyuan.config.search.embedBlock, } }, config, edit); + element.querySelector("#criteria .b3-chip--current")?.classList.remove("b3-chip--current"); }, () => { const localData = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]; const isPopover = hasClosestByClassName(element, "b3-dialog__container"); @@ -592,7 +596,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo } else if (target.id === "searchFilter") { filterMenu(config, () => { config.page = 1; - inputEvent(element, config, undefined, edit); + inputEvent(element, config, undefined, edit, true); }); event.stopPropagation(); event.preventDefault(); @@ -601,7 +605,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo queryMenu(config, () => { element.querySelector("#searchSyntaxCheck").setAttribute("aria-label", getQueryTip(config.method)); config.page = 1; - inputEvent(element, config, undefined, edit); + inputEvent(element, config, undefined, edit, true); }); const rect = target.getBoundingClientRect(); window.siyuan.menus.menu.popup({x: rect.right, y: rect.bottom}, true); @@ -638,7 +642,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo if (target.parentElement.id === "searchHistoryList") { searchInputElement.value = target.textContent; config.page = 1; - inputTimeout = inputEvent(element, config, inputTimeout, edit); + inputTimeout = inputEvent(element, config, inputTimeout, edit, true); } else if (target.parentElement.id === "replaceHistoryList") { replaceInputElement.value = target.textContent; replaceHistoryElement.classList.add("fn__none"); @@ -712,11 +716,17 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo searchInputElement.addEventListener("compositionend", (event: InputEvent) => { config.page = 1; - inputTimeout = inputEvent(element, config, inputTimeout, edit, event); + if (event.isComposing) { + return; + } + inputTimeout = inputEvent(element, config, inputTimeout, edit, true); }); searchInputElement.addEventListener("input", (event: InputEvent) => { config.page = 1; - inputTimeout = inputEvent(element, config, inputTimeout, edit, event); + if (event.isComposing) { + return; + } + inputTimeout = inputEvent(element, config, inputTimeout, edit, true); }); searchInputElement.addEventListener("blur", () => { if (config.removed) { @@ -778,7 +788,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo } else { searchInputElement.value = historyElement.querySelector(".b3-list-item--focus").textContent.trim(); config.page = 1; - inputTimeout = inputEvent(element, config, inputTimeout, edit); + inputTimeout = inputEvent(element, config, inputTimeout, edit, true); toggleSearchHistory(historyElement, replaceHistoryElement, searchInputElement); } event.preventDefault(); @@ -1110,12 +1120,12 @@ const replace = (element: Element, config: ISearchOption, edit: Protyle, isAll: }); }; -const inputEvent = (element: Element, config: ISearchOption, inputTimeout: number, edit: Protyle, event?: InputEvent) => { - if (event && event.isComposing) { - return; - } +const inputEvent = (element: Element, config: ISearchOption, inputTimeout: number, edit: Protyle, rmCurrentCriteria = false) => { clearTimeout(inputTimeout); inputTimeout = window.setTimeout(() => { + if (rmCurrentCriteria) { + element.querySelector("#criteria .b3-chip--current")?.classList.remove("b3-chip--current"); + } const searchInputElement = element.querySelector("#searchInput") as HTMLInputElement; const loadingElement = element.querySelector(".fn__loading--top"); loadingElement.classList.remove("fn__none");