Переглянути джерело

:art: https://github.com/siyuan-note/siyuan/issues/13415

Vanessa 7 місяців тому
батько
коміт
5c87b0cd7f

+ 1 - 19
app/src/assets/scss/base.scss

@@ -35,6 +35,7 @@
 @import "business/resize";
 @import "business/av";
 @import "business/emojis";
+@import "component/svg";
 
 /*
 .status: 2
@@ -93,25 +94,6 @@ html {
   }
 }
 
-.svg {
-  fill: currentColor;
-  display: inline-block;
-  stroke-width: 0;
-  stroke: currentColor;
-  width: 14px;
-  height: 14px;
-  flex-shrink: 0;
-
-  &--mid {
-    width: 16px;
-    height: 16px;
-  }
-
-  &--small {
-    width: 12px;
-    height: 12px;
-  }
-}
 
 .toolbar {
   background-color: var(--b3-toolbar-background);

+ 24 - 0
app/src/assets/scss/component/_svg.scss

@@ -0,0 +1,24 @@
+.svg {
+  fill: currentColor;
+  display: inline-block;
+  stroke-width: 0;
+  stroke: currentColor;
+  width: 14px;
+  height: 14px;
+  flex-shrink: 0;
+
+  &--mid {
+    width: 16px;
+    height: 16px;
+  }
+
+  &--small {
+    width: 12px;
+    height: 12px;
+  }
+
+  &--smaller {
+    width: 10px;
+    height: 10px;
+  }
+}

+ 16 - 4
app/src/assets/scss/mobile.scss

@@ -28,6 +28,7 @@
 @import "business/av";
 @import "business/search";
 @import "business/emojis";
+@import "component/svg";
 
 .block__popover {
   width: 80vw;
@@ -138,6 +139,15 @@
     &:not(.toolbar__icon-deactivate):hover {
       background-color: var(--b3-list-hover);
     }
+
+    &--history {
+      height: 36px;
+      width: 36px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      padding: 0;
+    }
   }
 
   &__title {
@@ -152,10 +162,6 @@
     color: var(--b3-theme-on-background);
   }
 
-  &__search {
-    margin: 8px;
-  }
-
   &__text {
     @include text-clamp(1);
     flex: 1;
@@ -395,6 +401,7 @@
   stroke: currentColor;
   width: 14px;
   height: 14px;
+  flex-shrink: 0;
 
   &--mid {
     width: 16px;
@@ -405,6 +412,11 @@
     width: 12px;
     height: 12px;
   }
+
+  &--smaller {
+    width: 10px;
+    height: 10px;
+  }
 }
 
 #empty {

+ 4 - 3
app/src/boot/globalEvent/searchKeydown.ts

@@ -10,13 +10,14 @@ import {App} from "../../index";
 import {Dialog} from "../../dialog";
 import {getAllModels} from "../../layout/getAll";
 import {hasClosestByClassName} from "../../protyle/util/hasClosest";
-import {getArticle, inputEvent, replace, toggleReplaceHistory, toggleSearchHistory} from "../../search/util";
+import {getArticle, inputEvent, replace} from "../../search/util";
 import {showFileInFolder} from "../../util/pathName";
-import {assetInputEvent, renderPreview, toggleAssetHistory} from "../../search/assets";
+import {assetInputEvent, renderPreview} from "../../search/assets";
 import {initSearchMenu} from "../../menus/search";
 import {writeText} from "../../protyle/util/compatibility";
 import {checkFold} from "../../util/noRelyPCFunction";
 import {getUnRefList} from "../../search/unRef";
+import {toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "../../search/toggleHistory";
 
 export const searchKeydown = (app: App, event: KeyboardEvent) => {
     if (getSelection().rangeCount === 0) {
@@ -72,7 +73,7 @@ export const searchKeydown = (app: App, event: KeyboardEvent) => {
             toggleAssetHistory(assetsElement);
         } else if (searchType === "doc") {
             if (targetId === "replaceInput") {
-                toggleReplaceHistory(element);
+                toggleReplaceHistory(element.querySelector("#replaceInput"));
             } else {
                 toggleSearchHistory(element, config, edit);
             }

+ 8 - 2
app/src/mobile/menu/model.ts

@@ -1,13 +1,19 @@
 export const openModel = (obj: {
     html: string,
-    icon: string,
+    icon?: string,
     title: string,
     bindEvent: (element: HTMLElement) => void
 }) => {
     const modelElement = document.getElementById("model");
     modelElement.style.transform = "translateY(0px)";
     modelElement.style.zIndex = (++window.siyuan.zIndex).toString();
-    modelElement.querySelector(".toolbar__icon use").setAttribute("xlink:href", "#" + obj.icon);
+    const iconElement  = modelElement.querySelector(".toolbar__icon")
+    if(obj.icon) {
+        iconElement.classList.remove("fn__none")
+        iconElement.querySelector("use").setAttribute("xlink:href", "#" + obj.icon);
+    } else {
+        iconElement.classList.add("fn__none")
+    }
     modelElement.querySelector(".toolbar__text").innerHTML = obj.title;
     const modelMainElement = modelElement.querySelector("#modelMain") as HTMLElement;
     modelMainElement.innerHTML = obj.html;

+ 28 - 4
app/src/mobile/menu/search.ts

@@ -26,6 +26,7 @@ import {
 import {addClearButton} from "../../util/addClearButton";
 import {checkFold} from "../../util/noRelyPCFunction";
 import {getDefaultType} from "../../search/getDefault";
+import {toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "../../search/toggleHistory";
 
 const replace = (element: Element, config: Config.IUILayoutTabSearchConfig, isAll: boolean) => {
     if (config.method === 1 || config.method === 2) {
@@ -313,7 +314,17 @@ const initSearchEvent = (app: App, element: Element, config: Config.IUILayoutTab
         let target = event.target as HTMLElement;
         while (target && !target.isSameNode(element)) {
             const type = target.getAttribute("data-type");
-            if (type === "previous") {
+            if (type === "replaceHistory") {
+                toggleReplaceHistory(target.nextElementSibling as HTMLInputElement)
+                event.stopPropagation();
+                event.preventDefault();
+                break;
+            } else if (type === "assetHistory") {
+                toggleAssetHistory(assetsElement)
+                event.stopPropagation();
+                event.preventDefault();
+                break;
+            } else if (type === "previous") {
                 if (!target.getAttribute("disabled")) {
                     config.page--;
                     updateSearchResult(config, element);
@@ -663,13 +674,19 @@ export const popSearch = (app: App, searchConfig?: any) => {
 
     openModel({
         title: `<div class="fn__flex">
+    <span data-menu="true" class="toolbar__icon toolbar__icon--history" data-type="history">
+        <svg class="svg--mid"><use xlink:href="#iconSearch"></use></svg>
+        <svg class="svg--smaller"><use xlink:href="#iconDown"></use></svg>
+    </span>
     <input id="toolbarSearch" placeholder="${window.siyuan.languages.showRecentUpdatedBlocks}" class="toolbar__title fn__block">
     <svg id="toolbarSearchNew" class="toolbar__icon"><use xlink:href="#iconFile"></use></svg>
 </div>`,
-        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>
+        <span data-menu="true" class="toolbar__icon toolbar__icon--history" data-type="replaceHistory">
+            <svg class="svg--mid"><use xlink:href="#iconReplace"></use></svg>
+            <svg class="svg--smaller"><use xlink:href="#iconDown"></use></svg>
+        </span>
         <input id="toolbarReplace" class="toolbar__title">
         <svg class="fn__rotate fn__none toolbar__icon"><use xlink:href="#iconRefresh"></use></svg>
         <div class="fn__space"></div>
@@ -707,7 +724,10 @@ export const popSearch = (app: App, searchConfig?: any) => {
      </div>
      <div class="fn__none fn__flex-column" style="position: fixed;top: 0;width: 100%;background: var(--b3-theme-surface);height: 100%;" id="searchAssetsPanel">
         <div class="toolbar toolbar--border">
-            <svg class="toolbar__icon"><use xlink:href="#iconSearch"></use></svg>
+           <span data-menu="true" class="toolbar__icon toolbar__icon--history" data-type="assetHistory">
+                <svg class="svg--mid"><use xlink:href="#iconSearch"></use></svg>
+                <svg class="svg--smaller"><use xlink:href="#iconDown"></use></svg>
+            </span>
             <input id="searchAssetInput" placeholder="${window.siyuan.languages.keyword}" class="toolbar__title fn__block">
         </div>
         <div class="toolbar">
@@ -750,6 +770,10 @@ export const popSearch = (app: App, searchConfig?: any) => {
             document.querySelector("#toolbarSearchNew").addEventListener("click", () => {
                 newFileByName(app, (document.querySelector("#toolbarSearch") as HTMLInputElement).value);
             });
+            const historyElement = document.querySelector('.toolbar [data-type="history"]')
+            historyElement.addEventListener("click", () => {
+                toggleSearchHistory(document.querySelector("#model"), config, undefined);
+            });
             initSearchEvent(app, element.firstElementChild, config);
             updateSearchResult(config, element);
         }

+ 0 - 69
app/src/search/assets.ts

@@ -242,75 +242,6 @@ export const assetInputEvent = (element: Element, localSearch?: ISearchAssetOpti
     }, Constants.TIMEOUT_INPUT);
 };
 
-export const toggleAssetHistory = (assetElement: Element) => {
-    const keys = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys;
-    if (!keys || keys.length === 0) {
-        return;
-    }
-    const menu = new Menu("search-asset-history");
-    if (menu.isOpen) {
-        return;
-    }
-    menu.element.classList.add("b3-menu--list");
-    menu.addItem({
-        iconHTML: "",
-        label: window.siyuan.languages.clearHistory,
-        click() {
-            window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = [];
-            setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
-        }
-    });
-    const separatorElement = menu.addSeparator(1);
-    let current = true;
-    const assetInputElement = assetElement.querySelector("#searchAssetInput") as HTMLInputElement;
-    keys.forEach((s: string) => {
-        if (s !== assetInputElement.value && s) {
-            const menuItem = menu.addItem({
-                iconHTML: "",
-                label: escapeHtml(s),
-                action: "iconCloseRound",
-                bind(element) {
-                    element.addEventListener("click", (itemEvent) => {
-                        if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
-                            keys.find((item: string, index: number) => {
-                                if (item === s) {
-                                    keys.splice(index, 1);
-                                    return true;
-                                }
-                            });
-                            window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = keys;
-                            setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
-                            if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
-                                window.siyuan.menus.menu.remove();
-                            } else {
-                                element.remove();
-                            }
-                        } else {
-                            assetInputElement.value = element.textContent;
-                            assetInputEvent(assetElement);
-                            window.siyuan.menus.menu.remove();
-                        }
-                        itemEvent.preventDefault();
-                        itemEvent.stopPropagation();
-                    });
-                }
-            });
-            if (current) {
-                menuItem.classList.add("b3-menu__item--current");
-            }
-            current = false;
-        }
-    });
-    if (current) {
-        separatorElement.remove();
-    }
-    const rect = assetInputElement.getBoundingClientRect();
-    menu.open({
-        x: rect.left,
-        y: rect.bottom
-    });
-};
-
 export const renderPreview = (element: Element, id: string, query: string, queryMethod: number) => {
     fetchPost("/api/search/getAssetContent", {id, query, queryMethod}, (response) => {
         element.innerHTML = `<p style="white-space: pre-wrap;">${response.data.assetContent.content}</p>`;

+ 222 - 0
app/src/search/toggleHistory.ts

@@ -0,0 +1,222 @@
+import {Constants} from "../constants";
+import {Menu} from "../plugin/Menu";
+import {setStorageVal} from "../protyle/util/compatibility";
+import {escapeHtml} from "../util/escape";
+import {hasClosestByClassName} from "../protyle/util/hasClosest";
+import {Protyle} from "../protyle";
+import {assetInputEvent} from "./assets";
+/// #if MOBILE
+import {updateSearchResult} from "../mobile/menu/search";
+/// #else
+import {inputEvent} from "./util";
+/// #endif
+
+export const toggleReplaceHistory = (replaceInputElement: HTMLInputElement) => {
+    const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
+    if (!list.replaceKeys || list.replaceKeys.length === 0) {
+        return;
+    }
+    const menu = new Menu("search-replace-history");
+    if (menu.isOpen) {
+        return;
+    }
+    menu.element.classList.add("b3-menu--list");
+    menu.addItem({
+        iconHTML: "",
+        label: window.siyuan.languages.clearHistory,
+        click() {
+            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = [];
+            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
+        }
+    });
+    const separatorElement = menu.addSeparator(1);
+    let current = true;
+    list.replaceKeys.forEach((s: string) => {
+        if (s !== replaceInputElement.value && s) {
+            const menuItem = menu.addItem({
+                iconHTML: "",
+                label: escapeHtml(s),
+                action: "iconCloseRound",
+                bind(element) {
+                    element.addEventListener("click", (itemEvent) => {
+                        if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
+                            list.replaceKeys.find((item: string, index: number) => {
+                                if (item === s) {
+                                    list.replaceKeys.splice(index, 1);
+                                    return true;
+                                }
+                            });
+                            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = list.replaceKeys;
+                            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
+                            if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
+                                window.siyuan.menus.menu.remove();
+                            } else {
+                                element.remove();
+                            }
+                        } else {
+                            replaceInputElement.value = element.textContent;
+                            window.siyuan.menus.menu.remove();
+                        }
+                        itemEvent.preventDefault();
+                        itemEvent.stopPropagation();
+                    });
+                }
+            });
+            if (current) {
+                menuItem.classList.add("b3-menu__item--current");
+            }
+            current = false;
+        }
+    });
+    if (current) {
+        separatorElement.remove();
+    }
+    const rect = replaceInputElement.previousElementSibling.getBoundingClientRect();
+    menu.open({
+        x: rect.left,
+        y: rect.bottom
+    });
+};
+
+export const toggleSearchHistory = (searchElement: Element, config: Config.IUILayoutTabSearchConfig, edit: Protyle) => {
+    const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
+    if (!list.keys || list.keys.length === 0) {
+        return;
+    }
+    const menu = new Menu("search-history");
+    if (menu.isOpen) {
+        return;
+    }
+    menu.element.classList.add("b3-menu--list");
+    menu.addItem({
+        iconHTML: "",
+        label: window.siyuan.languages.clearHistory,
+        click() {
+            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = [];
+            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
+        }
+    });
+    const separatorElement = menu.addSeparator(1);
+    let current = true;
+    const searchInputElement = searchElement.querySelector("#searchInput, #toolbarSearch") as HTMLInputElement;
+    list.keys.forEach((s: string) => {
+        if (s !== searchInputElement.value && s) {
+            const menuItem = menu.addItem({
+                iconHTML: "",
+                label: escapeHtml(s),
+                action: "iconCloseRound",
+                bind(element) {
+                    element.addEventListener("click", (itemEvent) => {
+                        if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
+                            list.keys.find((item: string, index: number) => {
+                                if (item === s) {
+                                    list.keys.splice(index, 1);
+                                    return true;
+                                }
+                            });
+                            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = list.keys;
+                            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
+                            if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
+                                window.siyuan.menus.menu.remove();
+                            } else {
+                                element.remove();
+                            }
+                        } else {
+                            searchInputElement.value = element.textContent;
+                            config.page = 1;
+                            /// #if MOBILE
+                            updateSearchResult(config, searchElement, true);
+                            /// #else
+                            inputEvent(searchElement, config, edit, true);
+                            /// #endif
+                            window.siyuan.menus.menu.remove();
+                        }
+                        itemEvent.preventDefault();
+                        itemEvent.stopPropagation();
+                    });
+                }
+            });
+            if (current) {
+                menuItem.classList.add("b3-menu__item--current");
+            }
+            current = false;
+        }
+    });
+    if (current) {
+        separatorElement.remove();
+    }
+    const rect = searchInputElement.previousElementSibling.getBoundingClientRect();
+    menu.open({
+        x: rect.left,
+        y: rect.bottom
+    });
+};
+
+export const toggleAssetHistory = (assetElement: Element) => {
+    const keys = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys;
+    if (!keys || keys.length === 0) {
+        return;
+    }
+    const menu = new Menu("search-asset-history");
+    if (menu.isOpen) {
+        return;
+    }
+    menu.element.classList.add("b3-menu--list");
+    menu.addItem({
+        iconHTML: "",
+        label: window.siyuan.languages.clearHistory,
+        click() {
+            window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = [];
+            setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
+        }
+    });
+    const separatorElement = menu.addSeparator(1);
+    let current = true;
+    const assetInputElement = assetElement.querySelector("#searchAssetInput") as HTMLInputElement;
+    keys.forEach((s: string) => {
+        if (s !== assetInputElement.value && s) {
+            const menuItem = menu.addItem({
+                iconHTML: "",
+                label: escapeHtml(s),
+                action: "iconCloseRound",
+                bind(element) {
+                    element.addEventListener("click", (itemEvent) => {
+                        if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
+                            keys.find((item: string, index: number) => {
+                                if (item === s) {
+                                    keys.splice(index, 1);
+                                    return true;
+                                }
+                            });
+                            window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = keys;
+                            setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
+                            if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
+                                window.siyuan.menus.menu.remove();
+                            } else {
+                                element.remove();
+                            }
+                        } else {
+                            assetInputElement.value = element.textContent;
+                            assetInputEvent(assetElement);
+                            window.siyuan.menus.menu.remove();
+                        }
+                        itemEvent.preventDefault();
+                        itemEvent.stopPropagation();
+                    });
+                }
+            });
+            if (current) {
+                menuItem.classList.add("b3-menu__item--current");
+            }
+            current = false;
+        }
+    });
+    if (current) {
+        separatorElement.remove();
+    }
+    const rect = assetInputElement.previousElementSibling.getBoundingClientRect();
+    menu.open({
+        x: rect.left,
+        y: rect.bottom
+    });
+};

+ 3 - 142
app/src/search/util.ts

@@ -43,153 +43,14 @@ import {
     openSearchAsset,
     renderNextAssetMark,
     renderPreview,
-    toggleAssetHistory
 } from "./assets";
 import {resize} from "../protyle/util/resize";
-import {Menu} from "../plugin/Menu";
 import {addClearButton} from "../util/addClearButton";
 import {checkFold} from "../util/noRelyPCFunction";
 import {getUnRefList, openSearchUnRef, unRefMoreMenu} from "./unRef";
 import {getDefaultType} from "./getDefault";
 import {isSupportCSSHL, searchMarkRender} from "../protyle/render/searchMarkRender";
-
-export const toggleReplaceHistory = (searchElement: Element) => {
-    const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
-    if (!list.replaceKeys || list.replaceKeys.length === 0) {
-        return;
-    }
-    const menu = new Menu("search-replace-history");
-    if (menu.isOpen) {
-        return;
-    }
-    menu.element.classList.add("b3-menu--list");
-    menu.addItem({
-        iconHTML: "",
-        label: window.siyuan.languages.clearHistory,
-        click() {
-            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = [];
-            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
-        }
-    });
-    const separatorElement = menu.addSeparator(1);
-    let current = true;
-    const replaceInputElement = searchElement.querySelector("#replaceInput") as HTMLInputElement;
-    list.replaceKeys.forEach((s: string) => {
-        if (s !== replaceInputElement.value && s) {
-            const menuItem = menu.addItem({
-                iconHTML: "",
-                label: escapeHtml(s),
-                action: "iconCloseRound",
-                bind(element) {
-                    element.addEventListener("click", (itemEvent) => {
-                        if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
-                            list.replaceKeys.find((item: string, index: number) => {
-                                if (item === s) {
-                                    list.replaceKeys.splice(index, 1);
-                                    return true;
-                                }
-                            });
-                            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = list.replaceKeys;
-                            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
-                            if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
-                                window.siyuan.menus.menu.remove();
-                            } else {
-                                element.remove();
-                            }
-                        } else {
-                            replaceInputElement.value = element.textContent;
-                            window.siyuan.menus.menu.remove();
-                        }
-                        itemEvent.preventDefault();
-                        itemEvent.stopPropagation();
-                    });
-                }
-            });
-            if (current) {
-                menuItem.classList.add("b3-menu__item--current");
-            }
-            current = false;
-        }
-    });
-    if (current) {
-        separatorElement.remove();
-    }
-    const rect = replaceInputElement.getBoundingClientRect();
-    menu.open({
-        x: rect.left,
-        y: rect.bottom
-    });
-};
-
-export const toggleSearchHistory = (searchElement: Element, config: Config.IUILayoutTabSearchConfig, edit: Protyle) => {
-    const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
-    if (!list.keys || list.keys.length === 0) {
-        return;
-    }
-    const menu = new Menu("search-history");
-    if (menu.isOpen) {
-        return;
-    }
-    menu.element.classList.add("b3-menu--list");
-    menu.addItem({
-        iconHTML: "",
-        label: window.siyuan.languages.clearHistory,
-        click() {
-            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = [];
-            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
-        }
-    });
-    const separatorElement = menu.addSeparator(1);
-    let current = true;
-    const searchInputElement = searchElement.querySelector("#searchInput") as HTMLInputElement;
-    list.keys.forEach((s: string) => {
-        if (s !== searchInputElement.value && s) {
-            const menuItem = menu.addItem({
-                iconHTML: "",
-                label: escapeHtml(s),
-                action: "iconCloseRound",
-                bind(element) {
-                    element.addEventListener("click", (itemEvent) => {
-                        if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
-                            list.keys.find((item: string, index: number) => {
-                                if (item === s) {
-                                    list.keys.splice(index, 1);
-                                    return true;
-                                }
-                            });
-                            window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = list.keys;
-                            setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
-                            if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
-                                window.siyuan.menus.menu.remove();
-                            } else {
-                                element.remove();
-                            }
-                        } else {
-                            searchInputElement.value = element.textContent;
-                            config.page = 1;
-                            inputEvent(searchElement, config, edit, true);
-                            window.siyuan.menus.menu.remove();
-                        }
-                        itemEvent.preventDefault();
-                        itemEvent.stopPropagation();
-                    });
-                }
-            });
-            if (current) {
-                menuItem.classList.add("b3-menu__item--current");
-            }
-            current = false;
-        }
-    });
-    if (current) {
-        separatorElement.remove();
-    }
-    const rect = searchInputElement.getBoundingClientRect();
-    menu.open({
-        x: rect.left,
-        y: rect.bottom
-    });
-};
+import {toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "./toggleHistory";
 
 const saveKeyList = (type: "keys" | "replaceKeys", value: string) => {
     let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type];
@@ -296,7 +157,7 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
     </div>
     <div class="b3-form__icon search__header">
         <div style="position: relative" class="fn__flex-1">
-             <span class="search__history-icon ariaLabel" id="searchHistoryBtn" aria-label="${updateHotkeyTip("⌥↓")}">
+            <span class="search__history-icon ariaLabel" id="searchHistoryBtn" aria-label="${updateHotkeyTip("⌥↓")}">
                 <svg data-menu="true" class="b3-form__icon-icon"><use xlink:href="#iconSearch"></use></svg>
                 <svg class="search__arrowdown"><use xlink:href="#iconDown"></use></svg>
             </span>
@@ -908,7 +769,7 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
                 event.preventDefault();
                 return;
             } else if (target.id === "replaceHistoryBtn") {
-                toggleReplaceHistory(element);
+                toggleReplaceHistory(element.querySelector("#replaceInput"));
                 event.stopPropagation();
                 event.preventDefault();
                 return;