diff --git a/app/src/assets/scss/_search.scss b/app/src/assets/scss/_search.scss
index 16b440209..17ceef469 100644
--- a/app/src/assets/scss/_search.scss
+++ b/app/src/assets/scss/_search.scss
@@ -28,7 +28,7 @@
max-width: 70%;
max-height: 50vh;
overflow: auto;
- top: 48px;
+ top: 42px;
position: absolute;
left: 8px;
}
diff --git a/app/src/config/editor.ts b/app/src/config/editor.ts
index 854457ad1..9dea7a13d 100644
--- a/app/src/config/editor.ts
+++ b/app/src/config/editor.ts
@@ -42,9 +42,9 @@ export const editor = {
});
allModels.search.forEach(search => {
if (readOnly) {
- disabledProtyle(search.protyle.protyle);
+ disabledProtyle(search.edit.protyle);
} else {
- enableProtyle(search.protyle.protyle);
+ enableProtyle(search.edit.protyle);
}
});
window.siyuan.blockPanels.forEach(item => {
diff --git a/app/src/constants.ts b/app/src/constants.ts
index 166d4071c..003c1c48d 100644
--- a/app/src/constants.ts
+++ b/app/src/constants.ts
@@ -58,7 +58,6 @@ export abstract class Constants {
// localstorage
public static readonly LOCAL_SEARCHEDATA = "local-searchedata";
- public static readonly LOCAL_SEARCHETABDATA = "local-searchetabdata";
public static readonly LOCAL_DOCINFO = "local-docinfo"; // only mobile
public static readonly LOCAL_DAILYNOTEID = "local-dailynoteid";
public static readonly LOCAL_HISTORYNOTEID = "local-historynoteid";
diff --git a/app/src/layout/Wnd.ts b/app/src/layout/Wnd.ts
index dd799aba0..9d9d536be 100644
--- a/app/src/layout/Wnd.ts
+++ b/app/src/layout/Wnd.ts
@@ -563,8 +563,8 @@ export class Wnd {
return;
}
if (model instanceof Search) {
- if (model.protyle) {
- model.protyle.destroy();
+ if (model.edit) {
+ model.edit.destroy();
}
return;
}
diff --git a/app/src/layout/util.ts b/app/src/layout/util.ts
index 0b2959061..5da8ffa6e 100644
--- a/app/src/layout/util.ts
+++ b/app/src/layout/util.ts
@@ -268,7 +268,7 @@ const JSONToCenter = (json: any, layout?: Layout | Wnd | Tab | Model) => {
} else if (json.instance === "Search") {
(layout as Tab).addModel(new Search({
tab: (layout as Tab),
- text: json.text
+ config: json.config
}));
}
if (json.children) {
@@ -377,7 +377,7 @@ export const layoutToJSON = (layout: Layout | Wnd | Tab | Model, json: any) => {
json.instance = "Tag";
} else if (layout instanceof Search) {
json.instance = "Search";
- json.text = layout.text;
+ json.config = layout.config;
}
if (layout instanceof Layout || layout instanceof Wnd) {
@@ -524,7 +524,7 @@ export const copyTab = (tab: Tab) => {
} else if (tab.model instanceof Search) {
model = new Search({
tab: newTab,
- text: tab.model.text
+ config: tab.model.config
});
} else if (!tab.model && tab.headElement) {
const initData = JSON.parse(tab.headElement.getAttribute("data-initdata") || "{}");
diff --git a/app/src/search/index.ts b/app/src/search/index.ts
index 202cf7609..9e687a11f 100644
--- a/app/src/search/index.ts
+++ b/app/src/search/index.ts
@@ -1,242 +1,20 @@
import {Model} from "../layout/Model";
import {Tab} from "../layout/Tab";
import {Protyle} from "../protyle";
-import {Constants} from "../constants";
-import {getIconByType} from "../editor/getIcon";
-import {getDisplayName, getNotebookName} from "../util/pathName";
-import {escapeHtml} from "../util/escape";
-import {fetchPost} from "../util/fetch";
-import {disabledProtyle, onGet} from "../protyle/util/onGet";
-import {addLoading} from "../protyle/ui/initUI";
-import {unicode2Emoji} from "../emoji";
import {genSearch} from "./util";
export class Search extends Model {
- public text: string;
private element: HTMLElement;
- public protyle: Protyle;
- private inputTimeout: number;
- private config: ISearchOption;
+ public config: ISearchOption;
+ public edit: Protyle;
- constructor(options: { tab: Tab, text: string }) {
+ constructor(options: { tab: Tab, config: ISearchOption }) {
super({
id: options.tab.id,
});
this.element = options.tab.panelElement as HTMLElement;
- options.tab.updateTitle(options.text || "");
- genSearch({
- k: options.text,
- r: "",
- hasReplace: false,
- querySyntax: false,
- hPath: "",
- notebookId: "",
- idPath: "",
- types: {
- mathBlock: true,
- table: true,
- blockquote: true,
- superBlock: true,
- paragraph: true,
- document: true,
- heading: true,
- list: true,
- listItem: true,
- codeBlock: true,
- htmlBlock: true,
- }
- }, this.element)
-
- // const historyElement = this.element.querySelector("#searchHistoryList") as HTMLInputElement;
- // const lineHeight = 30;
- // const searchPanelElement = this.element.querySelector("#globalSearchList");
- // inputElement.addEventListener("keydown", (event) => {
- // let currentList: HTMLElement = searchPanelElement.querySelector(".b3-list-item--focus");
- // if (!currentList || event.isComposing) {
- // return;
- // }
- //
- // if (event.key === "ArrowDown") {
- // currentList.classList.remove("b3-list-item--focus");
- // if (!currentList.nextElementSibling) {
- // searchPanelElement.children[0].classList.add("b3-list-item--focus");
- // } else {
- // currentList.nextElementSibling.classList.add("b3-list-item--focus");
- // }
- // currentList = searchPanelElement.querySelector(".b3-list-item--focus");
- // if (searchPanelElement.scrollTop < currentList.offsetTop - searchPanelElement.clientHeight + lineHeight ||
- // searchPanelElement.scrollTop > currentList.offsetTop) {
- // searchPanelElement.scrollTop = currentList.offsetTop - searchPanelElement.clientHeight + lineHeight;
- // }
- // this.getArticle(currentList.getAttribute("data-node-id"), inputElement.value);
- // event.preventDefault();
- // } else if (event.key === "ArrowUp") {
- // currentList.classList.remove("b3-list-item--focus");
- // if (!currentList.previousElementSibling) {
- // const length = searchPanelElement.children.length;
- // searchPanelElement.children[length - 1].classList.add("b3-list-item--focus");
- // } else {
- // currentList.previousElementSibling.classList.add("b3-list-item--focus");
- // }
- // currentList = searchPanelElement.querySelector(".b3-list-item--focus");
- // if (searchPanelElement.scrollTop < currentList.offsetTop - searchPanelElement.clientHeight + lineHeight ||
- // searchPanelElement.scrollTop > currentList.offsetTop - lineHeight * 2) {
- // searchPanelElement.scrollTop = currentList.offsetTop - lineHeight * 2;
- // }
- // this.getArticle(currentList.getAttribute("data-node-id"), inputElement.value);
- // event.preventDefault();
- // }
- // });
- // inputElement.select();
- // this.inputEvent(inputElement);
- // let clickTimeout: number;
- // this.element.addEventListener("click", (event: MouseEvent) => {
- // setPanelFocus(this.element.parentElement.parentElement);
- // let target = event.target as HTMLElement;
- // let hideList = true;
- // while (target && !target.isEqualNode(this.element)) {
- // if (target.id === "globalSearchReload") {
- // this.inputEvent(inputElement);
- // } else if (target.classList.contains("b3-list-item")) {
- // if (target.getAttribute("data-node-id")) {
- // if (event.detail === 1) {
- // clickTimeout = window.setTimeout(() => {
- // if (window.siyuan.altIsPressed) {
- // const id = target.getAttribute("data-node-id");
- // fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
- // openFileById({
- // id,
- // action: foldResponse.data ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL] : [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT],
- // zoomIn: foldResponse.data,
- // position: "right",
- // });
- // });
- // } else {
- // this.element.querySelectorAll(".b3-list-item--focus").forEach((item) => {
- // item.classList.remove("b3-list-item--focus");
- // });
- // target.classList.add("b3-list-item--focus");
- // this.getArticle(target.getAttribute("data-node-id"), inputElement.value);
- // }
- // }, Constants.TIMEOUT_DBLCLICK);
- // } else if (event.detail === 2) {
- // clearTimeout(clickTimeout);
- // const id = target.getAttribute("data-node-id");
- // fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
- // openFileById({
- // id,
- // action: foldResponse.data ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL] : [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT],
- // zoomIn: foldResponse.data
- // });
- // });
- // }
- // window.siyuan.menus.menu.remove();
- // } else {
- // this.text = target.textContent;
- // this.parent.updateTitle(this.text);
- // inputElement.value = this.text;
- // inputElement.select();
- // this.inputEvent(inputElement);
- // }
- // event.preventDefault();
- // event.stopPropagation();
- // break;
- // } else if (target.id === "searchHistoryBtn") {
- // hideList = false;
- // let html = "";
- // const data = JSON.parse(localStorage.getItem(Constants.LOCAL_SEARCHETABDATA) || "[]");
- // data.forEach((s: string) => {
- // if (s !== inputElement.value) {
- // html += `
${escapeHtml(s)}
`;
- // }
- // });
- // historyElement.classList.remove("fn__none");
- // historyElement.innerHTML = html;
- // event.preventDefault();
- // event.stopPropagation();
- // break;
- // }
- // target = target.parentElement;
- // }
- // if (hideList) {
- // historyElement.classList.add("fn__none");
- // }
- // }, false);
- }
-
- private getArticle(id: string, value: string) {
- fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
- if (this.protyle) {
- this.protyle.protyle.element.classList.remove("fn__none");
- this.protyle.protyle.scroll.lastScrollTop = 0;
- addLoading(this.protyle.protyle);
-
- fetchPost("/api/filetree/getDoc", {
- id,
- k: value,
- mode: foldResponse.data ? 0 : 3,
- size: foldResponse.data ? Constants.SIZE_GET_MAX : window.siyuan.config.editor.dynamicLoadBlocks,
- }, getResponse => {
- onGet(getResponse, this.protyle.protyle, foldResponse.data ? [Constants.CB_GET_ALL, Constants.CB_GET_HTML] : [Constants.CB_GET_HL, Constants.CB_GET_HTML]);
- const matchElement = this.protyle.protyle.wysiwyg.element.querySelector(`div[data-node-id="${id}"] span[data-type="search-mark"]`);
- if (matchElement) {
- matchElement.scrollIntoView();
- }
- });
- } else {
- this.protyle = new Protyle(this.element.querySelector("#searchPreview") as HTMLElement, {
- blockId: id,
- action: foldResponse.data ? [Constants.CB_GET_HL, Constants.CB_GET_ALL, Constants.CB_GET_HTML] : [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT, Constants.CB_GET_HTML],
- key: value,
- render: {
- gutter: true,
- breadcrumbDocName: true,
- },
- after: (editor) => {
- if (window.siyuan.config.readonly || window.siyuan.config.editor.readOnly) {
- disabledProtyle(editor.protyle);
- }
- setTimeout(() => {
- const matchElement = this.protyle.protyle.wysiwyg.element.querySelector(`div[data-node-id="${id}"] span[data-type="search-mark"]`);
- if (matchElement) {
- matchElement.scrollIntoView();
- }
- }, Constants.TIMEOUT_SEARCH);
- }
- });
- }
- });
- }
-
- private setLocalStorage(value: string) {
- if (!value) {
- return;
- }
- let searches: string[] = JSON.parse(localStorage.getItem(Constants.LOCAL_SEARCHETABDATA) || "[]");
- searches.splice(0, 0, value);
- searches = Array.from(new Set(searches));
- if (searches.length > window.siyuan.config.search.limit) {
- searches.splice(window.siyuan.config.search.limit, searches.length - window.siyuan.config.search.limit);
- }
- localStorage.setItem(Constants.LOCAL_SEARCHETABDATA, JSON.stringify(searches));
- }
-
- private inputEvent(inputElement: HTMLInputElement, event?: InputEvent) {
- if (event && event.isComposing) {
- return;
- }
- clearTimeout(this.inputTimeout);
- const loadElement = this.element.querySelector(".fn__loading--top");
- this.inputTimeout = window.setTimeout(() => {
- this.text = inputElement.value;
- this.parent.updateTitle(this.text);
- loadElement.classList.remove("fn__none");
- fetchPost("/api/search/fullTextSearchBlock", {query: this.text}, (response) => {
- this.onSearch(response.data.blocks);
- this.element.querySelector("#globalSearchResult").innerHTML = window.siyuan.languages.findInDoc.replace("${x}", response.data.matchedRootCount).replace("${y}", response.data.matchedBlockCount);
- loadElement.classList.add("fn__none");
- });
- }, Constants.TIMEOUT_SEARCH);
+ this.config = options.config;
+ this.edit = genSearch(this.config, this.element)
}
public updateSearch(text: string, replace: boolean) {
@@ -256,31 +34,8 @@ export class Search extends Model {
text = oldText + " " + text;
}
}
- this.text = text;
- this.parent.updateTitle(this.text);
- inputElement.value = this.text;
+ inputElement.value = text;
inputElement.select();
- this.inputEvent(inputElement);
- this.setLocalStorage(text);
- }
-
- private onSearch(data: IBlock[]) {
- let resultHTML = "";
- data.forEach((item, index) => {
- const title = escapeHtml(getNotebookName(item.box)) + getDisplayName(item.hPath, false);
- resultHTML += `
-
- ${unicode2Emoji(item.ial.icon)}${item.ial.icon ? " " : ""}${item.content}
- ${title}
-
`;
- });
- this.element.querySelector("#globalSearchList").innerHTML = resultHTML || `${window.siyuan.languages.emptyContent}
`;
- if (data.length === 0) {
- if (this.protyle) {
- this.protyle.protyle.element.classList.add("fn__none");
- }
- return;
- }
- this.getArticle(data[0].id, (this.element.querySelector(".b3-text-field") as HTMLInputElement).value);
+ inputElement.dispatchEvent(new CustomEvent("input"));
}
}
diff --git a/app/src/search/util.ts b/app/src/search/util.ts
index 9d92d60aa..ce8a4adfb 100644
--- a/app/src/search/util.ts
+++ b/app/src/search/util.ts
@@ -38,9 +38,34 @@ export const openGlobalSearch = (text: string, replace: boolean) => {
icon: "iconSearch",
title: text,
callback(tab) {
+ const localData = JSON.parse(localStorage.getItem(Constants.LOCAL_SEARCHEDATA) || "{}");
+ if (!localData.types) {
+ localData.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,
+ };
+ }
const asset = new Search({
tab,
- text
+ config: {
+ k: text,
+ r: "",
+ hasReplace: false,
+ querySyntax: localData.querySyntax || false,
+ hPath: "",
+ notebookId: "",
+ idPath: "",
+ types: localData.types
+ }
});
tab.addModel(asset);
resizeTabs();
@@ -151,17 +176,17 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
break;
} else if (target.id === "searchFilter") {
window.siyuan.menus.menu.remove();
- addConfigMenu(config, window.siyuan.languages.math, "mathBlock", edit, element);
- addConfigMenu(config, window.siyuan.languages.table, "table", edit, element);
- addConfigMenu(config, window.siyuan.languages.quote, "blockquote", edit, element);
- addConfigMenu(config, window.siyuan.languages.superBlock, "superBlock", edit, element);
- addConfigMenu(config, window.siyuan.languages.paragraph, "paragraph", edit, element);
- addConfigMenu(config, window.siyuan.languages.doc, "document", edit, element);
- addConfigMenu(config, window.siyuan.languages.headings, "heading", edit, element);
- addConfigMenu(config, window.siyuan.languages.list1, "list", edit, element);
- addConfigMenu(config, window.siyuan.languages.listItem, "listItem", edit, element);
- addConfigMenu(config, window.siyuan.languages.code, "codeBlock", edit, element);
- addConfigMenu(config, "HTML", "htmlBlock", edit, element);
+ addConfigMenu(config, window.siyuan.languages.math, "mathBlock", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.table, "table", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.quote, "blockquote", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.superBlock, "superBlock", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.paragraph, "paragraph", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.doc, "document", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.headings, "heading", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.list1, "list", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.listItem, "listItem", edit, element, closeCB);
+ addConfigMenu(config, window.siyuan.languages.code, "codeBlock", edit, element, closeCB);
+ addConfigMenu(config, "HTML", "htmlBlock", edit, element, closeCB);
window.siyuan.menus.menu.popup({x: event.clientX - 16, y: event.clientY - 16}, true);
event.stopPropagation();
event.preventDefault();
@@ -184,7 +209,9 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
}
}
if (reload) {
- localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ if (closeCB) {
+ localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ }
inputTimeout = inputEvent(element, config, inputTimeout, edit);
}
event.stopPropagation();
@@ -194,7 +221,9 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
target.classList.toggle("b3-button--cancel");
config.querySyntax = !target.classList.contains("b3-button--cancel");
inputTimeout = inputEvent(element, config, inputTimeout, edit);
- localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ if (closeCB) {
+ localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ }
event.stopPropagation();
event.preventDefault();
break;
@@ -226,11 +255,17 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
return;
} else if (target.id === "replaceAllBtn") {
replace(element, config, edit, true);
+ if (closeCB) {
+ localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ }
event.stopPropagation();
event.preventDefault();
break;
} else if (target.id === "replaceBtn") {
replace(element, config, edit, false);
+ if (closeCB) {
+ localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ }
event.stopPropagation();
event.preventDefault();
break;
@@ -242,6 +277,14 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
} else if (target.parentElement.id === "replaceHistoryList") {
replaceInputElement.value = target.textContent;
replaceHistoryElement.classList.add("fn__none");
+ } else if (target.parentElement.id === "searchList" && !target.classList.contains("b3-list-item--focus")) {
+ target.parentElement.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus")
+ target.classList.add("b3-list-item--focus")
+ getArticle({
+ id: target.getAttribute("data-node-id"),
+ k: getKey(target),
+ edit
+ });
}
event.stopPropagation();
event.preventDefault();
@@ -313,7 +356,9 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
}
config.list = searches;
config.k = searchInputElement.value;
- localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ if (closeCB) {
+ localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ }
});
searchInputElement.addEventListener("focus", () => {
historyElement.classList.add("fn__none");
@@ -385,13 +430,17 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
return;
}
replace(element, config, edit, false);
+ if (closeCB) {
+ localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ }
event.preventDefault();
});
inputTimeout = inputEvent(element, config, inputTimeout, edit);
+ return edit;
}
const addConfigMenu = (config: ISearchOption, lang: string, key: "mathBlock" | "table" | "blockquote" | "superBlock" | "paragraph" | "document" | "heading" | "list" | "listItem" | "codeBlock" | "htmlBlock",
- edit: Protyle, element: Element) => {
+ edit: Protyle, element: Element, closeCB?: () => void) => {
window.siyuan.menus.menu.append(new MenuItem({
label: `${lang}
`,
@@ -403,7 +452,9 @@ const addConfigMenu = (config: ISearchOption, lang: string, key: "mathBlock" | "
}
config.types[key] = inputElement.checked;
inputEvent(element, config, undefined, edit);
- localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ if (closeCB) {
+ localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
+ }
window.siyuan.menus.menu.remove();
});
}
@@ -458,7 +509,6 @@ const replace = (element: Element, config: ISearchOption, edit: Protyle, isAll:
}
config.replaceList = searches;
config.r = replaceInputElement.value;
- localStorage.setItem(Constants.LOCAL_SEARCHEDATA, JSON.stringify(config));
let currentList: HTMLElement = searchPanelElement.querySelector(".b3-list-item--focus");
if (!currentList) {