mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-21 00:50:13 +01:00
This commit is contained in:
parent
c8765621ba
commit
57bc6db377
4 changed files with 232 additions and 103 deletions
|
|
@ -5,10 +5,93 @@ import {fetchPost} from "../../util/fetch";
|
||||||
import {getIconByType} from "../../editor/getIcon";
|
import {getIconByType} from "../../editor/getIcon";
|
||||||
import {preventScroll} from "../../protyle/scroll/preventScroll";
|
import {preventScroll} from "../../protyle/scroll/preventScroll";
|
||||||
import {openModel} from "./model";
|
import {openModel} from "./model";
|
||||||
import {getNotebookName, movePathTo, pathPosix} from "../../util/pathName";
|
import {getDisplayName, getNotebookIcon, getNotebookName, movePathTo, pathPosix} from "../../util/pathName";
|
||||||
import {filterMenu, initCriteriaMenu, moreMenu, queryMenu} from "../../search/menu";
|
import {filterMenu, getKeyByLiElement, initCriteriaMenu, moreMenu, queryMenu} from "../../search/menu";
|
||||||
import {setStorageVal} from "../../protyle/util/compatibility";
|
import {setStorageVal} from "../../protyle/util/compatibility";
|
||||||
import {escapeHtml} from "../../util/escape";
|
import {escapeGreat, escapeHtml} from "../../util/escape";
|
||||||
|
import {unicode2Emoji} from "../../emoji";
|
||||||
|
import {newFileByName} from "../../util/newFile";
|
||||||
|
import {showMessage} from "../../dialog/message";
|
||||||
|
import {reloadProtyle} from "../../protyle/util/reload";
|
||||||
|
|
||||||
|
const replace = (element: Element, config: ISearchOption, isAll: boolean) => {
|
||||||
|
if (config.method === 1 || config.method === 2) {
|
||||||
|
showMessage(window.siyuan.languages._kernel[132]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const searchListElement = element.querySelector("#searchList");
|
||||||
|
const replaceInputElement = element.querySelector("#toolbarReplace") as HTMLInputElement;
|
||||||
|
|
||||||
|
const loadElement = replaceInputElement.nextElementSibling;
|
||||||
|
if (!loadElement.classList.contains("fn__none")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let currentLiElement: HTMLElement = searchListElement.querySelector(".b3-list-item--focus");
|
||||||
|
if (!currentLiElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadElement.classList.remove("fn__none");
|
||||||
|
loadElement.nextElementSibling.classList.add("fn__none");
|
||||||
|
|
||||||
|
let ids: string[] = [];
|
||||||
|
if (isAll) {
|
||||||
|
searchListElement.querySelectorAll('.b3-list-item[data-type="search-item"]').forEach(item => {
|
||||||
|
ids.push(item.getAttribute("data-node-id"));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ids = [currentLiElement.getAttribute("data-node-id")];
|
||||||
|
}
|
||||||
|
fetchPost("/api/search/findReplace", {
|
||||||
|
k: config.method === 0 ? getKeyByLiElement(currentLiElement) : (document.querySelector("#toolbarSearch") as HTMLInputElement).value,
|
||||||
|
r: replaceInputElement.value,
|
||||||
|
ids,
|
||||||
|
types: config.types,
|
||||||
|
method: config.method,
|
||||||
|
}, (response) => {
|
||||||
|
loadElement.classList.add("fn__none");
|
||||||
|
loadElement.nextElementSibling.classList.remove("fn__none");
|
||||||
|
|
||||||
|
if (response.code === 1) {
|
||||||
|
showMessage(response.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ids.length > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reloadProtyle(window.siyuan.mobile.editor.protyle);
|
||||||
|
|
||||||
|
if (currentLiElement.nextElementSibling) {
|
||||||
|
currentLiElement.nextElementSibling.classList.add("b3-list-item--focus");
|
||||||
|
} else if (currentLiElement.previousElementSibling) {
|
||||||
|
currentLiElement.previousElementSibling.classList.add("b3-list-item--focus");
|
||||||
|
}
|
||||||
|
if (config.group === 1) {
|
||||||
|
if (currentLiElement.nextElementSibling || currentLiElement.previousElementSibling) {
|
||||||
|
currentLiElement.remove();
|
||||||
|
} else {
|
||||||
|
const nextDocElement = currentLiElement.parentElement.nextElementSibling || currentLiElement.parentElement.previousElementSibling.previousElementSibling?.previousElementSibling;
|
||||||
|
if (nextDocElement) {
|
||||||
|
nextDocElement.nextElementSibling.firstElementChild.classList.add("b3-list-item--focus");
|
||||||
|
nextDocElement.nextElementSibling.classList.remove("fn__none");
|
||||||
|
nextDocElement.firstElementChild.firstElementChild.classList.add("b3-list-item__arrow--open");
|
||||||
|
}
|
||||||
|
currentLiElement.parentElement.previousElementSibling.remove();
|
||||||
|
currentLiElement.parentElement.remove();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentLiElement.remove();
|
||||||
|
}
|
||||||
|
currentLiElement = searchListElement.querySelector(".b3-list-item--focus");
|
||||||
|
if (!currentLiElement) {
|
||||||
|
searchListElement.innerHTML = `<div class="b3-list--empty">${window.siyuan.languages.emptyContent}</div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (searchListElement.scrollTop < currentLiElement.offsetTop - searchListElement.clientHeight + 30 ||
|
||||||
|
searchListElement.scrollTop > currentLiElement.offsetTop) {
|
||||||
|
searchListElement.scrollTop = currentLiElement.offsetTop - searchListElement.clientHeight + 30;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const updateConfig = (element: Element, newConfig: ISearchOption, config: ISearchOption) => {
|
const updateConfig = (element: Element, newConfig: ISearchOption, config: ISearchOption) => {
|
||||||
newConfig.hPath = config.hPath;
|
newConfig.hPath = config.hPath;
|
||||||
|
|
@ -64,43 +147,84 @@ const updateConfig = (element: Element, newConfig: ISearchOption, config: ISearc
|
||||||
Object.assign(config, newConfig);
|
Object.assign(config, newConfig);
|
||||||
window.siyuan.storage[Constants.LOCAL_SEARCHDATA] = Object.assign({}, config);
|
window.siyuan.storage[Constants.LOCAL_SEARCHDATA] = Object.assign({}, config);
|
||||||
setStorageVal(Constants.LOCAL_SEARCHDATA, window.siyuan.storage[Constants.LOCAL_SEARCHDATA]);
|
setStorageVal(Constants.LOCAL_SEARCHDATA, window.siyuan.storage[Constants.LOCAL_SEARCHDATA]);
|
||||||
updateSearchResult(config);
|
updateSearchResult(config, element);
|
||||||
window.siyuan.menus.menu.remove();
|
window.siyuan.menus.menu.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRecentBlocks = (data: IBlock[], matchedRootCount?: number, matchedBlockCount?: number) => {
|
const onRecentBlocks = (data: IBlock[], matchedRootCount?: number, matchedBlockCount?: number) => {
|
||||||
|
const listElement = document.querySelector("#searchList")
|
||||||
let resultHTML = "";
|
let resultHTML = "";
|
||||||
if (matchedBlockCount) {
|
data.forEach((item: IBlock, index: number) => {
|
||||||
resultHTML = '<div class="b3-list-item ft__smaller ft__on-surface">' + window.siyuan.languages.findInDoc.replace("${x}", matchedRootCount).replace("${y}", matchedBlockCount) + "</div>";
|
const title = getNotebookName(item.box) + getDisplayName(item.hPath, false);
|
||||||
}
|
if (item.children) {
|
||||||
data.forEach((item: IBlock) => {
|
resultHTML += `<div class="b3-list-item">
|
||||||
resultHTML += `<div class="b3-list-item b3-list-item--two" data-url="${item.box}" data-path="${item.path}" data-id="${item.id}">
|
<span class="b3-list-item__toggle b3-list-item__toggle--hl">
|
||||||
<div class="b3-list-item__first">
|
<svg class="b3-list-item__arrow b3-list-item__arrow--open"><use xlink:href="#iconRight"></use></svg>
|
||||||
<svg class="b3-list-item__graphic"><use xlink:href="#${getIconByType(item.type)}"></use></svg>
|
</span>
|
||||||
<span class="b3-list-item__text">${item.content}</span>
|
${unicode2Emoji(getNotebookIcon(item.box) || Constants.SIYUAN_IMAGE_NOTE, false, "b3-list-item__graphic", true)}
|
||||||
</div>
|
<span class="b3-list-item__text" style="color: var(--b3-theme-on-surface)">${escapeGreat(title)}</span>
|
||||||
<div class="b3-list-item__meta">${Lute.EscapeHTMLStr(item.hPath)}</div>
|
</div><div>`;
|
||||||
|
item.children.forEach((childItem, childIndex) => {
|
||||||
|
resultHTML += `<div style="padding-left: 36px" data-type="search-item" class="b3-list-item${childIndex === 0 && index === 0 ? " b3-list-item--focus" : ""}" data-node-id="${childItem.id}">
|
||||||
|
<svg class="b3-list-item__graphic"><use xlink:href="#${getIconByType(childItem.type)}"></use></svg>
|
||||||
|
${unicode2Emoji(childItem.ial.icon, false, "b3-list-item__graphic", true)}
|
||||||
|
<span class="b3-list-item__text">${childItem.content}</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
document.querySelector("#searchList").innerHTML = resultHTML;
|
resultHTML += "</div>";
|
||||||
|
} else {
|
||||||
|
resultHTML += `<div class="b3-list-item b3-list-item--two${index === 0 ? " b3-list-item--focus" : ""}" data-type="search-item" data-node-id="${item.id}">
|
||||||
|
<div class="b3-list-item__first">
|
||||||
|
<svg class="b3-list-item__graphic"><use xlink:href="#${getIconByType(item.type)}"></use></svg>
|
||||||
|
${unicode2Emoji(item.ial.icon, false, "b3-list-item__graphic", true)}
|
||||||
|
<span class="b3-list-item__text">${item.content}</span>
|
||||||
|
</div>
|
||||||
|
<span class="b3-list-item__meta b3-list-item__meta--ellipsis"">${escapeGreat(title)}</span>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
listElement.innerHTML = resultHTML ||
|
||||||
|
`<div class="b3-list-item b3-list-item--focus" data-type="search-new">
|
||||||
|
<svg class="b3-list-item__graphic"><use xlink:href="#iconFile"></use></svg>
|
||||||
|
<span class="b3-list-item__text">
|
||||||
|
${window.siyuan.languages.newFile} <mark>${(document.querySelector("#toolbarSearch") as HTMLInputElement).value}</mark>
|
||||||
|
</span>
|
||||||
|
</div>`;
|
||||||
|
listElement.scrollTop = 0;
|
||||||
|
let countHTML = ""
|
||||||
|
if (matchedBlockCount) {
|
||||||
|
countHTML = `<div class="b3-list--empty">${window.siyuan.languages.findInDoc.replace("${x}", matchedRootCount).replace("${y}", matchedBlockCount)}</div>`;
|
||||||
|
}
|
||||||
|
listElement.previousElementSibling.innerHTML = countHTML;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let toolbarSearchTimeout = 0;
|
let toolbarSearchTimeout = 0;
|
||||||
export const updateSearchResult = (config: ISearchOption) => {
|
export const updateSearchResult = (config: ISearchOption, element: Element) => {
|
||||||
clearTimeout(toolbarSearchTimeout);
|
clearTimeout(toolbarSearchTimeout);
|
||||||
toolbarSearchTimeout = window.setTimeout(() => {
|
toolbarSearchTimeout = window.setTimeout(() => {
|
||||||
|
const loadingElement = element.querySelector(".fn__loading--top");
|
||||||
|
loadingElement.classList.remove("fn__none");
|
||||||
const inputElement = document.getElementById("toolbarSearch") as HTMLInputElement;
|
const inputElement = document.getElementById("toolbarSearch") as HTMLInputElement;
|
||||||
if (inputElement.value === "") {
|
if (inputElement.value === "" && (!config.idPath || config.idPath.length === 0)) {
|
||||||
fetchPost("/api/block/getRecentUpdatedBlocks", {}, (response) => {
|
fetchPost("/api/block/getRecentUpdatedBlocks", {}, (response) => {
|
||||||
onRecentBlocks(response.data);
|
onRecentBlocks(response.data);
|
||||||
|
loadingElement.classList.add("fn__none");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
fetchPost("/api/search/fullTextSearchBlock", {query: inputElement.value,}, (response) => {
|
fetchPost("/api/search/fullTextSearchBlock", {
|
||||||
|
query: inputElement.value,
|
||||||
|
method: config.method,
|
||||||
|
types: config.types,
|
||||||
|
paths: config.idPath || [],
|
||||||
|
groupBy: config.group,
|
||||||
|
orderBy: config.sort,
|
||||||
|
}, (response) => {
|
||||||
onRecentBlocks(response.data.blocks, response.data.matchedRootCount, response.data.matchedBlockCount);
|
onRecentBlocks(response.data.blocks, response.data.matchedRootCount, response.data.matchedBlockCount);
|
||||||
|
loadingElement.classList.add("fn__none");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, Constants.TIMEOUT_SEARCH);
|
}, Constants.TIMEOUT_SEARCH);
|
||||||
return toolbarSearchTimeout
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const initSearchEvent = (element: Element, config: ISearchOption) => {
|
const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
|
|
@ -110,13 +234,13 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
if (event && event.isComposing) {
|
if (event && event.isComposing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateSearchResult(config);
|
updateSearchResult(config, element);
|
||||||
});
|
});
|
||||||
searchInputElement.addEventListener("input", (event: InputEvent) => {
|
searchInputElement.addEventListener("input", (event: InputEvent) => {
|
||||||
if (event && event.isComposing) {
|
if (event && event.isComposing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateSearchResult(config);
|
updateSearchResult(config, element);
|
||||||
});
|
});
|
||||||
const replaceInputElement = element.querySelector(".toolbar .b3-text-field") as HTMLInputElement
|
const replaceInputElement = element.querySelector(".toolbar .b3-text-field") as HTMLInputElement
|
||||||
replaceInputElement.value = config.r || ""
|
replaceInputElement.value = config.r || ""
|
||||||
|
|
@ -124,6 +248,7 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
const criteriaData: ISearchOption[] = [];
|
const criteriaData: ISearchOption[] = [];
|
||||||
initCriteriaMenu(element.querySelector("#criteria"), criteriaData);
|
initCriteriaMenu(element.querySelector("#criteria"), criteriaData);
|
||||||
|
|
||||||
|
const searchListElement = element.querySelector("#searchList") as HTMLElement;
|
||||||
element.addEventListener("click", (event: MouseEvent) => {
|
element.addEventListener("click", (event: MouseEvent) => {
|
||||||
let target = event.target as HTMLElement;
|
let target = event.target as HTMLElement;
|
||||||
while (target && !target.isSameNode(element)) {
|
while (target && !target.isSameNode(element)) {
|
||||||
|
|
@ -161,30 +286,30 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
config.idPath = [];
|
config.idPath = [];
|
||||||
config.hPath = "";
|
config.hPath = "";
|
||||||
element.querySelector("#searchPath").classList.add("fn__none")
|
element.querySelector("#searchPath").classList.add("fn__none")
|
||||||
toolbarSearchTimeout = updateSearchResult(config);
|
updateSearchResult(config, element);
|
||||||
const includeElement = element.querySelector('[data-type="include"]');
|
const includeElement = element.querySelector('[data-type="include"]');
|
||||||
includeElement.classList.remove("toolbar__icon--active");
|
includeElement.classList.remove("toolbar__icon--active");
|
||||||
includeElement.setAttribute("disabled", "disabled");
|
includeElement.setAttribute("disabled", "disabled");
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "searchExpand") {
|
} else if (type === "expand") {
|
||||||
// Array.from(searchPanelElement.children).forEach(item => {
|
Array.from(searchListElement.children).forEach(item => {
|
||||||
// if (item.classList.contains("b3-list-item")) {
|
if (item.classList.contains("b3-list-item")) {
|
||||||
// item.querySelector(".b3-list-item__arrow").classList.add("b3-list-item__arrow--open");
|
item.querySelector(".b3-list-item__arrow").classList.add("b3-list-item__arrow--open");
|
||||||
// item.nextElementSibling.classList.remove("fn__none");
|
item.nextElementSibling.classList.remove("fn__none");
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "searchCollapse") {
|
} else if (type === "contract") {
|
||||||
// Array.from(searchPanelElement.children).forEach(item => {
|
Array.from(searchListElement.children).forEach(item => {
|
||||||
// if (item.classList.contains("b3-list-item")) {
|
if (item.classList.contains("b3-list-item")) {
|
||||||
// item.querySelector(".b3-list-item__arrow").classList.remove("b3-list-item__arrow--open");
|
item.querySelector(".b3-list-item__arrow").classList.remove("b3-list-item__arrow--open");
|
||||||
// item.nextElementSibling.classList.add("fn__none");
|
item.nextElementSibling.classList.add("fn__none");
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
|
|
@ -207,9 +332,11 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
hPathList.push(...response.data);
|
hPathList.push(...response.data);
|
||||||
}
|
}
|
||||||
config.hPath = hPathList.join(" ");
|
config.hPath = hPathList.join(" ");
|
||||||
|
|
||||||
const searchPathElement = element.querySelector("#searchPath")
|
const searchPathElement = element.querySelector("#searchPath")
|
||||||
searchPathElement.classList.remove("fn__none");
|
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>`;
|
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"]');
|
const includeElement = element.querySelector('[data-type="include"]');
|
||||||
includeElement.classList.add("toolbar__icon--active");
|
includeElement.classList.add("toolbar__icon--active");
|
||||||
if (enableIncludeChild) {
|
if (enableIncludeChild) {
|
||||||
|
|
@ -217,28 +344,28 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
} else {
|
} else {
|
||||||
includeElement.setAttribute("disabled", "disabled");
|
includeElement.setAttribute("disabled", "disabled");
|
||||||
}
|
}
|
||||||
toolbarSearchTimeout = updateSearchResult(config);
|
updateSearchResult(config, element);
|
||||||
});
|
});
|
||||||
}, [], undefined, window.siyuan.languages.specifyPath);
|
}, [], undefined, window.siyuan.languages.specifyPath);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "searchInclude") {
|
} else if (type === "include") {
|
||||||
target.classList.toggle("b3-button--cancel");
|
target.classList.toggle("toolbar__icon--active");
|
||||||
if (target.classList.contains("b3-button--cancel")) {
|
if (target.classList.contains("toolbar__icon--active")) {
|
||||||
config.idPath.forEach((item, index) => {
|
|
||||||
if (!item.endsWith(".sy") && item.split("/").length > 1) {
|
|
||||||
config.idPath[index] = item + ".sy";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
config.idPath.forEach((item, index) => {
|
config.idPath.forEach((item, index) => {
|
||||||
if (item.endsWith(".sy")) {
|
if (item.endsWith(".sy")) {
|
||||||
config.idPath[index] = item.replace(".sy", "");
|
config.idPath[index] = item.replace(".sy", "");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
config.idPath.forEach((item, index) => {
|
||||||
|
if (!item.endsWith(".sy") && item.split("/").length > 1) {
|
||||||
|
config.idPath[index] = item + ".sy";
|
||||||
}
|
}
|
||||||
// inputTimeout = inputEvent(element, config, inputTimeout, edit);
|
});
|
||||||
|
}
|
||||||
|
updateSearchResult(config, element);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
|
|
@ -251,7 +378,7 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
break;
|
break;
|
||||||
} else if (type === "more") {
|
} else if (type === "more") {
|
||||||
moreMenu(config, criteriaData, element, () => {
|
moreMenu(config, criteriaData, element, () => {
|
||||||
updateSearchResult(config);
|
updateSearchResult(config, element);
|
||||||
}, () => {
|
}, () => {
|
||||||
updateConfig(element, {
|
updateConfig(element, {
|
||||||
removed: true,
|
removed: true,
|
||||||
|
|
@ -286,27 +413,27 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
break;
|
break;
|
||||||
} else if (type === "filter") {
|
} else if (type === "filter") {
|
||||||
filterMenu(config, () => {
|
filterMenu(config, () => {
|
||||||
updateSearchResult(config)
|
updateSearchResult(config, element)
|
||||||
});
|
});
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
} else if (type === "query") {
|
} else if (type === "query") {
|
||||||
queryMenu(config, () => {
|
queryMenu(config, () => {
|
||||||
updateSearchResult(config)
|
updateSearchResult(config, element)
|
||||||
});
|
});
|
||||||
window.siyuan.menus.menu.element.style.zIndex = "220";
|
window.siyuan.menus.menu.element.style.zIndex = "220";
|
||||||
window.siyuan.menus.menu.fullscreen();
|
window.siyuan.menus.menu.fullscreen();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "replaceAllBtn") {
|
} else if (type === "replace-all") {
|
||||||
// replace(element, config, edit, true);
|
replace(element, config, true);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "replaceBtn") {
|
} else if (type === "replace") {
|
||||||
// replace(element, config, edit, false);
|
replace(element, config, false);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
|
|
@ -317,15 +444,10 @@ const initSearchEvent = (element: Element, config: ISearchOption) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
} else if (target.classList.contains("b3-list-item")) {
|
} else if (target.classList.contains("b3-list-item")) {
|
||||||
if (target.parentElement.id === "searchHistoryList") {
|
if (target.getAttribute("data-type") === "search-new") {
|
||||||
searchInputElement.value = target.textContent;
|
newFileByName(searchInputElement.value);
|
||||||
// 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") {
|
} else if (target.getAttribute("data-type") === "search-item") {
|
||||||
const id = target.getAttribute("data-id");
|
const id = target.getAttribute("data-node-id");
|
||||||
if (window.siyuan.mobile.editor.protyle) {
|
if (window.siyuan.mobile.editor.protyle) {
|
||||||
preventScroll(window.siyuan.mobile.editor.protyle);
|
preventScroll(window.siyuan.mobile.editor.protyle);
|
||||||
}
|
}
|
||||||
|
|
@ -365,14 +487,16 @@ export const popSearch = (config = window.siyuan.storage[Constants.LOCAL_SEARCHD
|
||||||
<div class="toolbar toolbar--border${config.hasReplace ? "" : " fn__none"}">
|
<div class="toolbar toolbar--border${config.hasReplace ? "" : " fn__none"}">
|
||||||
<svg class="toolbar__icon"><use xlink:href="#iconReplace"></use></svg>
|
<svg class="toolbar__icon"><use xlink:href="#iconReplace"></use></svg>
|
||||||
<input id="toolbarReplace" class="b3-text-field fn__flex-1">
|
<input id="toolbarReplace" class="b3-text-field fn__flex-1">
|
||||||
|
<svg class="fn__rotate fn__none toolbar__icon"><use xlink:href="#iconRefresh"></use></svg>
|
||||||
<div class="fn__space"></div>
|
<div class="fn__space"></div>
|
||||||
<button class="b3-button b3-button--outline fn__flex-center">${window.siyuan.languages.replaceAll}</button>
|
<button data-type="replace-all" class="b3-button b3-button--outline fn__flex-center">${window.siyuan.languages.replaceAll}</button>
|
||||||
<div class="fn__space"></div>
|
<div class="fn__space"></div>
|
||||||
<button class="b3-button b3-button--outline fn__flex-center">${window.siyuan.languages.replace}</button>
|
<button data-type="replace" class="b3-button b3-button--outline fn__flex-center">${window.siyuan.languages.replace}</button>
|
||||||
<div class="fn__space"></div>
|
<div class="fn__space"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="criteria" style="background-color: var(--b3-theme-background);" class="b3-chips"></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 style="background-color: var(--b3-theme-background);"></div>
|
||||||
|
<div id="searchList" style="overflow:auto;" class="fn__flex-1 b3-list b3-list--background"></div>
|
||||||
<div id="searchPath" class="b3-chips${config.hPath ? "" : " fn__none"}" style="background-color: var(--b3-theme-background);">
|
<div id="searchPath" class="b3-chips${config.hPath ? "" : " fn__none"}" style="background-color: var(--b3-theme-background);">
|
||||||
<div class="b3-chip b3-chip--middle">
|
<div class="b3-chip b3-chip--middle">
|
||||||
${escapeHtml(config.hPath)}
|
${escapeHtml(config.hPath)}
|
||||||
|
|
@ -391,10 +515,11 @@ export const popSearch = (config = window.siyuan.storage[Constants.LOCAL_SEARCHD
|
||||||
<svg data-type="more" class="toolbar__icon"><use xlink:href="#iconMore"></use></svg>
|
<svg data-type="more" class="toolbar__icon"><use xlink:href="#iconMore"></use></svg>
|
||||||
<span class="fn__flex-1"></span>
|
<span class="fn__flex-1"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="fn__loading fn__loading--top"><img width="120px" src="/stage/loading-pure.svg"></div>
|
||||||
</div>`,
|
</div>`,
|
||||||
bindEvent(element) {
|
bindEvent(element) {
|
||||||
initSearchEvent(element.firstElementChild, config);
|
initSearchEvent(element.firstElementChild, config);
|
||||||
toolbarSearchTimeout = updateSearchResult(config);
|
updateSearchResult(config, element);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -371,3 +371,11 @@ export const initCriteriaMenu = (element: HTMLElement, data: ISearchOption[]) =>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getKeyByLiElement = (element: HTMLElement) => {
|
||||||
|
const keys: string[] = [];
|
||||||
|
element.querySelectorAll("mark").forEach(item => {
|
||||||
|
keys.push(item.textContent);
|
||||||
|
});
|
||||||
|
return [...new Set(keys)].join(" ");
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,11 @@ import {disabledProtyle, onGet} from "../protyle/util/onGet";
|
||||||
import {addLoading, setPadding} from "../protyle/ui/initUI";
|
import {addLoading, setPadding} from "../protyle/ui/initUI";
|
||||||
import {getIconByType} from "../editor/getIcon";
|
import {getIconByType} from "../editor/getIcon";
|
||||||
import {unicode2Emoji} from "../emoji";
|
import {unicode2Emoji} from "../emoji";
|
||||||
import {Dialog} from "../dialog";
|
|
||||||
import {hasClosestByClassName} from "../protyle/util/hasClosest";
|
import {hasClosestByClassName} from "../protyle/util/hasClosest";
|
||||||
import {setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility";
|
import {setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility";
|
||||||
import {replaceFileName} from "../editor/rename";
|
import {newFileByName} from "../util/newFile";
|
||||||
import {hideElements} from "../protyle/ui/hideElements";
|
|
||||||
import {getNewFilePath} from "../util/newFile";
|
|
||||||
import {matchHotKey} from "../protyle/util/hotKey";
|
import {matchHotKey} from "../protyle/util/hotKey";
|
||||||
import {filterMenu, initCriteriaMenu, moreMenu, queryMenu} from "./menu";
|
import {filterMenu, getKeyByLiElement, initCriteriaMenu, moreMenu, queryMenu} from "./menu";
|
||||||
|
|
||||||
const saveKeyList = (type: "keys" | "replaceKeys", value: string) => {
|
const saveKeyList = (type: "keys" | "replaceKeys", value: string) => {
|
||||||
let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type];
|
let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type];
|
||||||
|
|
@ -82,23 +79,6 @@ export const openGlobalSearch = (text: string, replace: boolean) => {
|
||||||
setPanelFocus(tab.panelElement);
|
setPanelFocus(tab.panelElement);
|
||||||
};
|
};
|
||||||
|
|
||||||
const newEmptyFileByInput = (value: string) => {
|
|
||||||
const newData = getNewFilePath(true);
|
|
||||||
fetchPost("/api/filetree/getHPathByPath", {
|
|
||||||
notebook: newData.notebookId,
|
|
||||||
path: newData.currentPath,
|
|
||||||
}, (responsePath) => {
|
|
||||||
fetchPost("/api/filetree/createDocWithMd", {
|
|
||||||
notebook: newData.notebookId,
|
|
||||||
path: pathPosix().join(responsePath.data, replaceFileName(value.trim()) || "Untitled"),
|
|
||||||
markdown: ""
|
|
||||||
}, response => {
|
|
||||||
hideElements(["dialog"]);
|
|
||||||
openFileById({id: response.data, action: [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT]});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// closeCB 不存在为页签搜索
|
// closeCB 不存在为页签搜索
|
||||||
export const genSearch = (config: ISearchOption, element: Element, closeCB?: () => void) => {
|
export const genSearch = (config: ISearchOption, element: Element, closeCB?: () => void) => {
|
||||||
let methodText = window.siyuan.languages.keyword;
|
let methodText = window.siyuan.languages.keyword;
|
||||||
|
|
@ -621,7 +601,7 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
|
||||||
replaceInputElement.value = target.textContent;
|
replaceInputElement.value = target.textContent;
|
||||||
replaceHistoryElement.classList.add("fn__none");
|
replaceHistoryElement.classList.add("fn__none");
|
||||||
} else if (target.getAttribute("data-type") === "search-new") {
|
} else if (target.getAttribute("data-type") === "search-new") {
|
||||||
newEmptyFileByInput(searchInputElement.value);
|
newFileByName(searchInputElement.value);
|
||||||
} else if (target.getAttribute("data-type") === "search-item") {
|
} else if (target.getAttribute("data-type") === "search-item") {
|
||||||
if (event.detail === 1) {
|
if (event.detail === 1) {
|
||||||
clickTimeout = window.setTimeout(() => {
|
clickTimeout = window.setTimeout(() => {
|
||||||
|
|
@ -644,7 +624,7 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
|
||||||
getArticle({
|
getArticle({
|
||||||
edit,
|
edit,
|
||||||
id: target.getAttribute("data-node-id"),
|
id: target.getAttribute("data-node-id"),
|
||||||
k: getKey(target)
|
k: getKeyByLiElement(target)
|
||||||
});
|
});
|
||||||
searchInputElement.focus();
|
searchInputElement.focus();
|
||||||
} else if (target.classList.contains("b3-list-item--focus")) {
|
} else if (target.classList.contains("b3-list-item--focus")) {
|
||||||
|
|
@ -706,14 +686,14 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
|
||||||
}
|
}
|
||||||
const focusIsNew = currentList.getAttribute("data-type") === "search-new";
|
const focusIsNew = currentList.getAttribute("data-type") === "search-new";
|
||||||
if (focusIsNew && matchHotKey(window.siyuan.config.keymap.general.newFile.custom, event)) {
|
if (focusIsNew && matchHotKey(window.siyuan.config.keymap.general.newFile.custom, event)) {
|
||||||
newEmptyFileByInput(searchInputElement.value);
|
newFileByName(searchInputElement.value);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
if (focusIsNew) {
|
if (focusIsNew) {
|
||||||
newEmptyFileByInput(searchInputElement.value);
|
newFileByName(searchInputElement.value);
|
||||||
} else {
|
} else {
|
||||||
const id = currentList.getAttribute("data-node-id");
|
const id = currentList.getAttribute("data-node-id");
|
||||||
fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
|
fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
|
||||||
|
|
@ -755,7 +735,7 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
|
||||||
}
|
}
|
||||||
getArticle({
|
getArticle({
|
||||||
id: currentList.getAttribute("data-node-id"),
|
id: currentList.getAttribute("data-node-id"),
|
||||||
k: getKey(currentList),
|
k: getKeyByLiElement(currentList),
|
||||||
edit
|
edit
|
||||||
});
|
});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -781,7 +761,7 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
|
||||||
}
|
}
|
||||||
getArticle({
|
getArticle({
|
||||||
id: currentList.getAttribute("data-node-id"),
|
id: currentList.getAttribute("data-node-id"),
|
||||||
k: getKey(currentList),
|
k: getKeyByLiElement(currentList),
|
||||||
edit
|
edit
|
||||||
});
|
});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -877,14 +857,6 @@ const updateConfig = (element: Element, item: ISearchOption, config: ISearchOpti
|
||||||
window.siyuan.menus.menu.remove();
|
window.siyuan.menus.menu.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getKey = (element: HTMLElement) => {
|
|
||||||
const keys: string[] = [];
|
|
||||||
element.querySelectorAll("mark").forEach(item => {
|
|
||||||
keys.push(item.textContent);
|
|
||||||
});
|
|
||||||
return [...new Set(keys)].join(" ");
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderNextSearchMark = (options: {
|
const renderNextSearchMark = (options: {
|
||||||
id: string,
|
id: string,
|
||||||
edit: Protyle,
|
edit: Protyle,
|
||||||
|
|
@ -973,7 +945,7 @@ const replace = (element: Element, config: ISearchOption, edit: Protyle, isAll:
|
||||||
rootIds = [currentList.getAttribute("data-root-id")];
|
rootIds = [currentList.getAttribute("data-root-id")];
|
||||||
}
|
}
|
||||||
fetchPost("/api/search/findReplace", {
|
fetchPost("/api/search/findReplace", {
|
||||||
k: config.method === 0 ? getKey(currentList) : (element.querySelector("#searchInput") as HTMLInputElement).value,
|
k: config.method === 0 ? getKeyByLiElement(currentList) : (element.querySelector("#searchInput") as HTMLInputElement).value,
|
||||||
r: replaceInputElement.value,
|
r: replaceInputElement.value,
|
||||||
ids,
|
ids,
|
||||||
types: config.types,
|
types: config.types,
|
||||||
|
|
@ -1027,7 +999,7 @@ const replace = (element: Element, config: ISearchOption, edit: Protyle, isAll:
|
||||||
getArticle({
|
getArticle({
|
||||||
edit,
|
edit,
|
||||||
id: currentList.getAttribute("data-node-id"),
|
id: currentList.getAttribute("data-node-id"),
|
||||||
k: getKey(currentList)
|
k: getKeyByLiElement(currentList)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -1106,14 +1078,14 @@ ${unicode2Emoji(item.ial.icon, false, "b3-list-item__graphic", true)}
|
||||||
getArticle({
|
getArticle({
|
||||||
edit,
|
edit,
|
||||||
id: data[0].children[0].id,
|
id: data[0].children[0].id,
|
||||||
k: getKey(contentElement),
|
k: getKeyByLiElement(contentElement),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
contentElement.innerHTML = data[0].content;
|
contentElement.innerHTML = data[0].content;
|
||||||
getArticle({
|
getArticle({
|
||||||
edit,
|
edit,
|
||||||
id: data[0].id,
|
id: data[0].id,
|
||||||
k: getKey(contentElement),
|
k: getKeyByLiElement(contentElement),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ import {openFileById} from "../editor/util";
|
||||||
import {fetchPost} from "./fetch";
|
import {fetchPost} from "./fetch";
|
||||||
import {getDisplayName, getOpenNotebookCount, pathPosix} from "./pathName";
|
import {getDisplayName, getOpenNotebookCount, pathPosix} from "./pathName";
|
||||||
import {Constants} from "../constants";
|
import {Constants} from "../constants";
|
||||||
import {validateName} from "../editor/rename";
|
import {replaceFileName, validateName} from "../editor/rename";
|
||||||
|
import {hideElements} from "../protyle/ui/hideElements";
|
||||||
|
import {isMobile} from "./functions";
|
||||||
|
import {openMobileFileById} from "../mobile/editor";
|
||||||
|
|
||||||
export const getNewFilePath = (useSavePath: boolean) => {
|
export const getNewFilePath = (useSavePath: boolean) => {
|
||||||
let notebookId = "";
|
let notebookId = "";
|
||||||
|
|
@ -149,3 +152,24 @@ export const getSavePath = (pathString: string, notebookId: string, cb: (p: stri
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const newFileByName = (value: string) => {
|
||||||
|
const newData = getNewFilePath(true);
|
||||||
|
fetchPost("/api/filetree/getHPathByPath", {
|
||||||
|
notebook: newData.notebookId,
|
||||||
|
path: newData.currentPath,
|
||||||
|
}, (responsePath) => {
|
||||||
|
fetchPost("/api/filetree/createDocWithMd", {
|
||||||
|
notebook: newData.notebookId,
|
||||||
|
path: pathPosix().join(responsePath.data, replaceFileName(value.trim()) || "Untitled"),
|
||||||
|
markdown: ""
|
||||||
|
}, response => {
|
||||||
|
hideElements(["dialog"]);
|
||||||
|
if (isMobile()) {
|
||||||
|
openMobileFileById(response.data, [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT]);
|
||||||
|
} else {
|
||||||
|
openFileById({id: response.data, action: [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT]});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue