siyuan/app/src/boot/globalEvent/searchKeydown.ts

319 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// #if !BROWSER
import * as path from "path";
/// #endif
import {matchHotKey} from "../../protyle/util/hotKey";
import {fetchPost} from "../../util/fetch";
import {openFileById} from "../../editor/util";
import {Constants} from "../../constants";
import {newFileByName} from "../../util/newFile";
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 {showFileInFolder} from "../../util/pathName";
import {assetInputEvent, renderPreview, toggleAssetHistory} from "../../search/assets";
import {initSearchMenu} from "../../menus/search";
import {writeText} from "../../protyle/util/compatibility";
import {checkFold} from "../../util/noRelyPCFunction";
import {getUnRefList} from "../../search/unRef";
export const searchKeydown = (app: App, event: KeyboardEvent) => {
if (getSelection().rangeCount === 0) {
return false;
}
const range = getSelection().getRangeAt(0);
if (hasClosestByClassName(range.startContainer, "protyle", true)) {
return false;
}
let element: HTMLElement;
let dialog: Dialog;
let edit;
let unRefEdit;
let config: ISearchOption;
window.siyuan.dialogs.find((item) => {
if (item.element.contains(range.startContainer) && item.element.querySelector("#searchList")) {
element = item.element.querySelector(".b3-dialog__body");
dialog = item;
config = dialog.data;
edit = dialog.editors.edit;
unRefEdit = dialog.editors.unRefEdit;
return true;
}
});
if (!element) {
getAllModels().search.find((item) => {
if (item.element.contains(range.startContainer)) {
element = item.element;
edit = item.editors.edit;
config = item.config;
unRefEdit = item.editors.unRefEdit;
return true;
}
});
}
if (!element) {
return false;
}
const assetsElement = element.querySelector("#searchAssets");
const unRefElement = element.querySelector("#searchUnRefPanel");
const searchType = assetsElement.classList.contains("fn__none") ? (unRefElement.classList.contains("fn__none") ? "doc" : "unRef") : "asset";
const listElement = searchType === "asset" ? assetsElement.querySelector("#searchAssetList") : (searchType === "doc" ? element.querySelector("#searchList") : unRefElement.querySelector("#searchUnRefList"));
const searchInputElement = element.querySelector("#searchInput") as HTMLInputElement;
if (searchType === "doc" && matchHotKey(window.siyuan.config.keymap.general.newFile.custom, event)) {
if (config.method === 0) {
newFileByName(app, searchInputElement.value);
}
return true;
}
const targetId = (event.target as HTMLElement).id;
if (event.key === "ArrowDown" && event.altKey) {
if (searchType === "asset") {
toggleAssetHistory(assetsElement);
} else if (searchType === "doc") {
if (targetId === "replaceInput") {
toggleReplaceHistory(element);
} else {
toggleSearchHistory(element, config, edit);
}
}
return true;
}
const assetLocal = window.siyuan.storage[Constants.LOCAL_SEARCHASSET] as ISearchAssetOption;
if (!window.siyuan.menus.menu.element.classList.contains("fn__none")) {
// 不能返回 true否则历史菜单无法使用快捷键
return false;
}
let currentList: HTMLElement = listElement.querySelector(".b3-list-item--focus");
if (!currentList) {
return false;
}
if (currentList.getAttribute("data-type") === "search-new") {
if (event.key === "Enter" && config.method === 0) {
newFileByName(app, searchInputElement.value);
return true;
}
return false;
}
if (searchType !== "asset") {
if (matchHotKey(window.siyuan.config.keymap.editor.general.insertRight.custom, event)) {
const id = currentList.getAttribute("data-node-id");
checkFold(id, (zoomIn, action) => {
openFileById({
app,
id,
position: "right",
action,
zoomIn
});
if (dialog) {
dialog.destroy({focus: "false"});
}
});
return true;
}
const id = currentList.getAttribute("data-node-id");
if (matchHotKey("⌘/", event)) {
const currentRect = currentList.getBoundingClientRect();
initSearchMenu(id).popup({
x: currentRect.left + 30,
y: currentRect.bottom
});
return true;
}
if (matchHotKey(window.siyuan.config.keymap.editor.general.copyBlockRef.custom, event)) {
fetchPost("/api/block/getRefText", {id}, (response) => {
writeText(`((${id} '${response.data}'))`);
});
return true;
}
if (matchHotKey(window.siyuan.config.keymap.editor.general.copyBlockEmbed.custom, event)) {
writeText(`{{select * from blocks where id='${id}'}}`);
return true;
}
if (matchHotKey(window.siyuan.config.keymap.editor.general.copyProtocol.custom, event)) {
writeText(`siyuan://blocks/${id}`);
return true;
}
if (matchHotKey(window.siyuan.config.keymap.editor.general.copyProtocolInMd.custom, event)) {
fetchPost("/api/block/getRefText", {id}, (response) => {
writeText(`[${response.data}](siyuan://blocks/${id})`);
});
return true;
}
if (matchHotKey(window.siyuan.config.keymap.editor.general.copyHPath.custom, event)) {
fetchPost("/api/filetree/getHPathByID", {
id
}, (response) => {
writeText(response.data);
});
return true;
}
if (matchHotKey(window.siyuan.config.keymap.editor.general.copyID.custom, event)) {
writeText(id);
return true;
}
}
if (Constants.KEYCODELIST[event.keyCode] === "PageUp") {
if (searchType === "asset") {
if (!assetsElement.querySelector('[data-type="assetPrevious"]').getAttribute("disabled")) {
let currentPage = parseInt(assetsElement.querySelector("#searchAssetResult .fn__flex-center").textContent.split("/")[0]);
if (currentPage > 1) {
currentPage--;
assetInputEvent(assetsElement, assetLocal, currentPage);
}
}
} else if (searchType === "doc") {
if (!element.querySelector('[data-type="previous"]').getAttribute("disabled")) {
if (config.page > 1) {
config.page--;
inputEvent(element, config, edit);
}
}
} else if (searchType === "unRef") {
if (!element.querySelector('[data-type="unRefPrevious"]').getAttribute("disabled")) {
let currentPage = parseInt(unRefElement.querySelector("#searchUnRefResult").textContent);
if (currentPage > 1) {
currentPage--;
getUnRefList(unRefElement, unRefEdit, currentPage);
}
}
}
return true;
}
if (Constants.KEYCODELIST[event.keyCode] === "PageDown") {
if (searchType === "asset") {
if (!assetsElement.querySelector('[data-type="assetNext"]').getAttribute("disabled")) {
const assetPages = assetsElement.querySelector("#searchAssetResult .fn__flex-center").textContent.split("/");
let currentPage = parseInt(assetPages[0]);
if (currentPage < parseInt(assetPages[1])) {
currentPage++;
assetInputEvent(assetsElement, assetLocal, currentPage);
}
}
} else if (searchType === "doc") {
const nextElement = element.querySelector('[data-type="next"]');
if (!nextElement.getAttribute("disabled")) {
if (config.page < parseInt(nextElement.parentElement.querySelector("#searchResult").getAttribute("data-pagecount"))) {
config.page++;
inputEvent(element, config, edit);
}
}
} else if (searchType === "unRef") {
if (!element.querySelector('[data-type="unRefNext"]').getAttribute("disabled")) {
let currentPage = parseInt(unRefElement.querySelector("#searchUnRefResult").textContent);
if (currentPage < parseInt(unRefElement.querySelector("#searchUnRefResult").textContent.split("/")[1])) {
currentPage++;
getUnRefList(unRefElement, unRefEdit, currentPage);
}
}
}
return true;
}
if (!window.siyuan.menus.menu.element.classList.contains("fn__none")) {
return false;
}
if (event.key === "Enter") {
if (searchType !== "asset") {
if (targetId === "replaceInput") {
replace(element, config, edit, false);
} else {
const id = currentList.getAttribute("data-node-id");
checkFold(id, (zoomIn, action) => {
openFileById({
app,
id,
action,
zoomIn
});
if (dialog) {
dialog.destroy({focus: "false"});
}
});
}
} else {
/// #if !BROWSER
showFileInFolder(path.join(window.siyuan.config.system.dataDir, currentList.lastElementChild.getAttribute("aria-label")));
/// #endif
}
return true;
}
const lineHeight = 28;
const assetPreviewElement = assetsElement.querySelector("#searchAssetPreview");
if (event.key === "ArrowDown") {
currentList.classList.remove("b3-list-item--focus");
if (!currentList.nextElementSibling) {
if (config.group === 1 && searchType === "doc") {
if (currentList.parentElement.nextElementSibling) {
currentList.parentElement.nextElementSibling.nextElementSibling.firstElementChild.classList.add("b3-list-item--focus");
} else {
listElement.children[1].firstElementChild.classList.add("b3-list-item--focus");
}
} else {
listElement.firstElementChild.classList.add("b3-list-item--focus");
}
} else {
currentList.nextElementSibling.classList.add("b3-list-item--focus");
}
currentList = listElement.querySelector(".b3-list-item--focus");
if (listElement.scrollTop < currentList.offsetTop - listElement.clientHeight + lineHeight ||
listElement.scrollTop > currentList.offsetTop) {
listElement.scrollTop = currentList.offsetTop - listElement.clientHeight + lineHeight;
}
if (searchType === "asset") {
renderPreview(assetPreviewElement, currentList.dataset.id, searchInputElement.value, assetLocal.method);
} else if (searchType === "doc") {
getArticle({
id: currentList.getAttribute("data-node-id"),
config,
value: searchInputElement.value,
edit,
});
} else {
getArticle({
id: currentList.getAttribute("data-node-id"),
edit: unRefEdit,
});
}
return true;
}
if (event.key === "ArrowUp") {
currentList.classList.remove("b3-list-item--focus");
if (!currentList.previousElementSibling) {
if (config.group === 1 && searchType === "doc") {
if (currentList.parentElement.previousElementSibling.previousElementSibling) {
currentList.parentElement.previousElementSibling.previousElementSibling.lastElementChild.classList.add("b3-list-item--focus");
} else {
listElement.lastElementChild.lastElementChild.classList.add("b3-list-item--focus");
}
} else {
listElement.lastElementChild.classList.add("b3-list-item--focus");
}
} else {
currentList.previousElementSibling.classList.add("b3-list-item--focus");
}
currentList = listElement.querySelector(".b3-list-item--focus");
if (listElement.scrollTop < currentList.offsetTop - listElement.clientHeight + lineHeight ||
listElement.scrollTop > currentList.offsetTop - lineHeight * 2) {
listElement.scrollTop = currentList.offsetTop - lineHeight * 2;
}
if (searchType === "asset") {
renderPreview(assetPreviewElement, currentList.dataset.id, searchInputElement.value, assetLocal.method);
} else if (searchType === "doc") {
getArticle({
id: currentList.getAttribute("data-node-id"),
config,
value: searchInputElement.value,
edit,
});
} else if (searchType === "unRef") {
getArticle({
id: currentList.getAttribute("data-node-id"),
edit: unRefEdit,
});
}
return true;
}
return false;
};