This commit is contained in:
parent
52c9b5fbca
commit
4b02a8a846
11 changed files with 197 additions and 22 deletions
|
@ -265,7 +265,7 @@
|
|||
"importDataTip": "Import the exported zip archive, overwriting the <code class='fn__code'>workspace/data/</code> folder by path",
|
||||
"includeChildDoc": "Include child documents",
|
||||
"text": "Text",
|
||||
"lastUsed": "Apariencia usada recientemente",
|
||||
"lastUsed": "Recently used appearance",
|
||||
"removedNotebook": "Removed notebook",
|
||||
"querySyntax": "Query Syntax",
|
||||
"rollback": "Rollback",
|
||||
|
|
|
@ -265,7 +265,7 @@
|
|||
"importDataTip": "Importar el archivo zip exportado, sobrescribiendo la carpeta <code class='fn__code'>workspace/data/</code> por la ruta",
|
||||
"includeChildDoc": "Incluir los documentos de los niños",
|
||||
"text": "Texto",
|
||||
"lastUsed": "Fuentes utilizadas apariencia",
|
||||
"lastUsed": "Apariencia usada recientemente",
|
||||
"removedNotebook": "Cuaderno de notas eliminado",
|
||||
"querySyntax": "Sintaxis de consulta",
|
||||
"rollback": "Rollback",
|
||||
|
|
|
@ -265,7 +265,7 @@
|
|||
"importDataTip": "将导出的 zip 压缩包导入,按路径覆盖 <code class='fn__code'>工作空间/data/</code> 文件夹",
|
||||
"includeChildDoc": "包含子文档",
|
||||
"text": "文本",
|
||||
"lastUsed": "Recently used appearance",
|
||||
"lastUsed": "最近使用的外观",
|
||||
"removedNotebook": "已删除的笔记本",
|
||||
"querySyntax": "查询语法",
|
||||
"rollback": "回滚",
|
||||
|
|
|
@ -802,10 +802,29 @@ export const globalShortcut = (app: App) => {
|
|||
}
|
||||
|
||||
// 面板的操作
|
||||
if (!isTabWindow && panelTreeKeydown(event)) {
|
||||
if (!isTabWindow && panelTreeKeydown(app, event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let matchCommand = false;
|
||||
app.plugins.find(item => {
|
||||
item.commands.find(command => {
|
||||
if (command.callback &&
|
||||
!command.fileTreeCallback && !command.editorCallback&& !command.dockCallback
|
||||
&& matchHotKey(command.customHotkey, event)) {
|
||||
matchCommand = true;
|
||||
command.callback();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let searchKey = "";
|
||||
if (matchHotKey(window.siyuan.config.keymap.general.replace.custom, event)) {
|
||||
searchKey = window.siyuan.config.keymap.general.replace.custom;
|
||||
|
@ -1112,6 +1131,24 @@ const fileTreeKeydown = (app: App, event: KeyboardEvent) => {
|
|||
return false;
|
||||
}
|
||||
const files = dockFile.data.file as Files;
|
||||
|
||||
let matchCommand = false;
|
||||
app.plugins.find(item => {
|
||||
item.commands.find(command => {
|
||||
if (command.fileTreeCallback && matchHotKey(command.customHotkey, event)) {
|
||||
matchCommand = true;
|
||||
command.fileTreeCallback(files);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matchHotKey(window.siyuan.config.keymap.general.selectOpen1.custom, event)) {
|
||||
event.preventDefault();
|
||||
const element = document.querySelector(".layout__wnd--active > .fn__flex > .layout-tab-bar > .item--focus") ||
|
||||
|
@ -1402,7 +1439,7 @@ const fileTreeKeydown = (app: App, event: KeyboardEvent) => {
|
|||
}
|
||||
};
|
||||
|
||||
const panelTreeKeydown = (event: KeyboardEvent) => {
|
||||
const panelTreeKeydown = (app: App, event: KeyboardEvent) => {
|
||||
// 面板折叠展开操作
|
||||
const target = event.target as HTMLElement;
|
||||
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" ||
|
||||
|
@ -1451,6 +1488,23 @@ const panelTreeKeydown = (event: KeyboardEvent) => {
|
|||
activePanelElement.classList.contains("sy__graph")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let matchCommand = false;
|
||||
app.plugins.find(item => {
|
||||
item.commands.find(command => {
|
||||
if (command.dockCallback && matchHotKey(command.customHotkey, event)) {
|
||||
matchCommand = true;
|
||||
command.dockCallback(activePanelElement as HTMLElement);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
const model = (getInstanceById(activePanelElement.getAttribute("data-id"), window.siyuan.layout.layout) as Tab)?.model;
|
||||
if (!model) {
|
||||
return false;
|
||||
|
|
|
@ -85,6 +85,38 @@ const hasKeymap = (keymap: Record<string, IKeymapItem>, key1: "general" | "edito
|
|||
return match;
|
||||
};
|
||||
|
||||
const mergePluginHotkey = (app: App) => {
|
||||
if (!window.siyuan.config.keymap.plugin) {
|
||||
window.siyuan.config.keymap.plugin = {};
|
||||
}
|
||||
app.plugins.forEach(plugin => {
|
||||
plugin.commands.forEach(command => {
|
||||
if (!window.siyuan.config.keymap.plugin[plugin.name]) {
|
||||
command.customHotkey = command.hotkey;
|
||||
window.siyuan.config.keymap.plugin[plugin.name] = {
|
||||
[command.langKey]: {
|
||||
default: command.hotkey,
|
||||
custom: command.hotkey,
|
||||
}
|
||||
};
|
||||
return
|
||||
}
|
||||
if (!window.siyuan.config.keymap.plugin[plugin.name][command.langKey]) {
|
||||
command.customHotkey = command.hotkey;
|
||||
window.siyuan.config.keymap.plugin[plugin.name][command.langKey] = {
|
||||
default: command.hotkey,
|
||||
custom: command.hotkey,
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (window.siyuan.config.keymap.plugin[plugin.name][command.langKey]) {
|
||||
command.customHotkey = window.siyuan.config.keymap.plugin[plugin.name][command.langKey].custom || command.hotkey;
|
||||
window.siyuan.config.keymap.plugin[plugin.name][command.langKey]["default"] = command.hotkey
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const onGetConfig = (isStart: boolean, app: App) => {
|
||||
const matchKeymap1 = matchKeymap(Constants.SIYUAN_KEYMAP.general, "general");
|
||||
const matchKeymap2 = matchKeymap(Constants.SIYUAN_KEYMAP.editor.general, "editor", "general");
|
||||
|
@ -99,6 +131,7 @@ export const onGetConfig = (isStart: boolean, app: App) => {
|
|||
const hasKeymap4 = hasKeymap(Constants.SIYUAN_KEYMAP.editor.heading, "editor", "heading");
|
||||
const hasKeymap5 = hasKeymap(Constants.SIYUAN_KEYMAP.editor.list, "editor", "list");
|
||||
const hasKeymap6 = hasKeymap(Constants.SIYUAN_KEYMAP.editor.table, "editor", "table");
|
||||
mergePluginHotkey(app);
|
||||
if (!window.siyuan.config.readonly &&
|
||||
(!matchKeymap1 || !matchKeymap2 || !matchKeymap3 || !matchKeymap4 || !matchKeymap5 || !matchKeymap6 ||
|
||||
!hasKeymap1 || !hasKeymap2 || !hasKeymap3 || !hasKeymap4 || !hasKeymap5 || !hasKeymap6)) {
|
||||
|
|
|
@ -48,7 +48,7 @@ export const genItemPanel = (type: string, containerElement: Element, app: App)
|
|||
appearance.bindEvent();
|
||||
break;
|
||||
case "keymap":
|
||||
containerElement.innerHTML = keymap.genHTML();
|
||||
containerElement.innerHTML = keymap.genHTML(app);
|
||||
keymap.element = containerElement;
|
||||
keymap.bindEvent();
|
||||
break;
|
||||
|
|
|
@ -8,6 +8,7 @@ import {getCurrentWindow} from "@electron/remote";
|
|||
import {ipcRenderer} from "electron";
|
||||
/// #endif
|
||||
import {confirmDialog} from "../dialog/confirmDialog";
|
||||
import {App} from "../index";
|
||||
|
||||
export const keymap = {
|
||||
element: undefined as Element,
|
||||
|
@ -25,13 +26,55 @@ export const keymap = {
|
|||
<svg><use xlink:href="#iconTrashcan"></use></svg>
|
||||
</span>
|
||||
<span data-type="update" class="config-keymap__key">${keyValue}</span>
|
||||
<input data-key="${keys + Constants.ZWSP + key}" data-value="${keymap[key].custom}" data-default="${keymap[key].default}" class="b3-text-field fn__none" value="${updateHotkeyTip(keymap[key].custom)}" spellcheck="false">
|
||||
<input data-key="${keys + Constants.ZWSP + key}" data-value="${keymap[key].custom}" data-default="${keymap[key].default}" class="b3-text-field fn__none" value="${keyValue}" spellcheck="false">
|
||||
</label>`;
|
||||
}
|
||||
});
|
||||
return html;
|
||||
},
|
||||
genHTML() {
|
||||
genHTML(app: App) {
|
||||
let pluginHtml = ''
|
||||
app.plugins.forEach(item => {
|
||||
let commandHTML = ''
|
||||
item.commands.forEach(command => {
|
||||
const keyValue = updateHotkeyTip(command.customHotkey);
|
||||
commandHTML += `<label class="b3-list-item b3-list-item--narrow b3-list-item--hide-action">
|
||||
<span class="b3-list-item__text">${item.i18n[command.langKey]}</span>
|
||||
<span data-type="reset" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.reset}">
|
||||
<svg><use xlink:href="#iconUndo"></use></svg>
|
||||
</span>
|
||||
<span data-type="clear" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.remove}">
|
||||
<svg><use xlink:href="#iconTrashcan"></use></svg>
|
||||
</span>
|
||||
<span data-type="update" class="config-keymap__key">${keyValue}</span>
|
||||
<input data-key="plugin${Constants.ZWSP}${item.name}${Constants.ZWSP}${command.langKey}" data-value="${command.customHotkey}" data-default="${command.hotkey}" class="b3-text-field fn__none" value="${keyValue}" spellcheck="false">
|
||||
</label>`;
|
||||
});
|
||||
if (commandHTML) {
|
||||
pluginHtml += `<div class="b3-list__panel">
|
||||
<div class="b3-list-item b3-list-item--narrow toggle">
|
||||
<span class="b3-list-item__toggle b3-list-item__toggle--hl">
|
||||
<svg class="b3-list-item__arrow"><use xlink:href="#iconRight"></use></svg>
|
||||
</span>
|
||||
<span class="b3-list-item__text ft__on-surface">${item.name}</span>
|
||||
</div>
|
||||
<div class="fn__none b3-list__panel">
|
||||
${commandHTML}
|
||||
</div>
|
||||
</div>`
|
||||
}
|
||||
})
|
||||
if (pluginHtml) {
|
||||
pluginHtml = `<div class="b3-list b3-list--border b3-list--background">
|
||||
<div class="b3-list-item b3-list-item--narrow toggle">
|
||||
<span class="b3-list-item__toggle b3-list-item__toggle--hl">
|
||||
<svg class="b3-list-item__arrow b3-list-item__arrow--open"><use xlink:href="#iconRight"></use></svg>
|
||||
</span>
|
||||
<span class="b3-list-item__text ft__on-surface">${window.siyuan.languages.plugin}</span>
|
||||
</div>
|
||||
${pluginHtml}
|
||||
</div>`
|
||||
}
|
||||
return `<label class="fn__flex b3-label config__item">
|
||||
<span class="fn__flex-center">${window.siyuan.languages.keymapTip}</span>
|
||||
<span class="fn__flex-1"></span>
|
||||
|
@ -119,13 +162,17 @@ export const keymap = {
|
|||
<div class="fn__none b3-list__panel">${keymap._genItem(window.siyuan.config.keymap.editor.table, "editor" + Constants.ZWSP + "table")}</div>
|
||||
</div>
|
||||
</div>
|
||||
${pluginHtml}
|
||||
</div>`;
|
||||
},
|
||||
_setkeymap() {
|
||||
const data: IKeymap = JSON.parse(JSON.stringify(Constants.SIYUAN_KEYMAP));
|
||||
keymap.element.querySelectorAll("label.b3-list-item input").forEach((item) => {
|
||||
const keys = item.getAttribute("data-key").split(Constants.ZWSP);
|
||||
if (keys[0] === "general") {
|
||||
if (keys[0] === "plugin") {
|
||||
window.siyuan.config.keymap.plugin[keys[1]][keys[2]].custom = item.getAttribute("data-value");
|
||||
data.plugin = window.siyuan.config.keymap.plugin;
|
||||
} else if (keys[0] === "general") {
|
||||
data[keys[0]][keys[1]].custom = item.getAttribute("data-value");
|
||||
} else if (keys[0] === "editor" && (keys[1] === "general" || keys[1] === "insert" || keys[1] === "heading" || keys[1] === "list" || keys[1] === "table")) {
|
||||
data[keys[0]][keys[1]][keys[2]].custom = item.getAttribute("data-value");
|
||||
|
@ -194,6 +241,17 @@ export const keymap = {
|
|||
editorKeymapElement.firstElementChild.classList.remove("fn__none");
|
||||
}
|
||||
},
|
||||
_getTip(element: HTMLElement) {
|
||||
const thirdElement = element.parentElement;
|
||||
let tip = thirdElement.querySelector(".b3-list-item__text").textContent.trim()
|
||||
const secondElement = thirdElement.parentElement.previousElementSibling;
|
||||
tip = secondElement.textContent.trim() + "-" + tip;
|
||||
const firstElement = secondElement.parentElement.previousElementSibling;
|
||||
if (firstElement.classList.contains("b3-list-item")) {
|
||||
tip = firstElement.textContent.trim() + "-" + tip;
|
||||
}
|
||||
return tip
|
||||
},
|
||||
bindEvent() {
|
||||
keymap.element.querySelector("#keymapRefreshBtn").addEventListener("click", () => {
|
||||
exportLayout({
|
||||
|
@ -309,14 +367,9 @@ export const keymap = {
|
|||
if (keys[1] === "heading") {
|
||||
keys[1] = "headings";
|
||||
}
|
||||
let tip = `${window.siyuan.languages.keymap} [${window.siyuan.languages[keys[0]]}-${window.siyuan.languages[keys[1]]}`;
|
||||
if (keys[2]) {
|
||||
tip += `-${window.siyuan.languages[keys[2]]}`;
|
||||
}
|
||||
|
||||
if (["⌘", "⇧", "⌥", "⌃"].includes(keymapStr.substr(keymapStr.length - 1, 1)) ||
|
||||
["⌘A", "⌘X", "⌘C", "⌘V", "⌘-", "⌘=", "⌘0", "⇧⌘V", "⌘/", "⇧↑", "⇧↓", "⇧→", "⇧←", "⇧⇥", "⇧⌘⇥", "⌃⇥", "⌘⇥", "⌃⌘⇥", "⇧⌘→", "⇧⌘←", "⌘Home", "⌘End", "⇧↩", "↩", "PageUp", "PageDown", "⌫", "⌦"].includes(keymapStr)) {
|
||||
showMessage(tip + "] " + window.siyuan.languages.invalid);
|
||||
showMessage(`${window.siyuan.languages.keymap} [${keymap._getTip(this)}] ${window.siyuan.languages.invalid}`);
|
||||
return;
|
||||
}
|
||||
const hasConflict = Array.from(keymap.element.querySelectorAll("label.b3-list-item input")).find(inputItem => {
|
||||
|
@ -328,11 +381,7 @@ export const keymap = {
|
|||
if (inputValueList[1] === "heading") {
|
||||
inputValueList[1] = "headings";
|
||||
}
|
||||
let conflictTip = `${window.siyuan.languages[inputValueList[0]]}-${window.siyuan.languages[inputValueList[1]]}`;
|
||||
if (inputValueList[2]) {
|
||||
conflictTip += `-${window.siyuan.languages[inputValueList[2]]}`;
|
||||
}
|
||||
showMessage(`${tip}] [${conflictTip}] ${window.siyuan.languages.conflict}`);
|
||||
showMessage(`${window.siyuan.languages.keymap} [${keymap._getTip(this)}] [${keymap._getTip(inputItem)}] ${window.siyuan.languages.conflict}`);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -243,7 +243,8 @@ export abstract class Constants {
|
|||
"delete-row": {default: "⌘-", custom: "⌘-"},
|
||||
"delete-column": {default: "⇧⌘_", custom: "⇧⌘_"}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugin: {},
|
||||
};
|
||||
|
||||
public static readonly SIYUAN_EMPTY_LAYOUT: Record<string, unknown> = {
|
||||
|
|
|
@ -18,6 +18,7 @@ export class Plugin {
|
|||
public data: any = {};
|
||||
public name: string;
|
||||
public topBarIcons: Element[] = [];
|
||||
public commands: ICommand[] = [];
|
||||
public models: {
|
||||
/// #if !MOBILE
|
||||
[key: string]: (options: { tab: Tab, data: any }) => Custom
|
||||
|
@ -55,6 +56,10 @@ export class Plugin {
|
|||
// 布局加载完成
|
||||
}
|
||||
|
||||
public addCommand(command: ICommand) {
|
||||
this.commands.push(command);
|
||||
}
|
||||
|
||||
public addIcons(svg: string) {
|
||||
document.body.insertAdjacentHTML("afterbegin", `<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>${svg}</defs></svg>`);
|
||||
|
|
|
@ -39,8 +39,9 @@ export const commonHotkey = (app: App, protyle: IProtyle, event: KeyboardEvent)
|
|||
netImg2LocalAssets(protyle);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matchHotKey(window.siyuan.config.keymap.editor.general.spaceRepetition.custom, event) ||
|
||||
matchHotKey(window.siyuan.config.keymap.general.dailyNote.custom, event)) {
|
||||
// 阻止输入 https://ld246.com/article/1679618995926
|
||||
|
@ -71,6 +72,23 @@ export const commonHotkey = (app: App, protyle: IProtyle, event: KeyboardEvent)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
let matchCommand = false;
|
||||
app.plugins.find(item => {
|
||||
item.commands.find(command => {
|
||||
if (command.editorCallback && matchHotKey(command.customHotkey, event)) {
|
||||
matchCommand = true;
|
||||
command.editorCallback(protyle);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (matchCommand) {
|
||||
return true;
|
||||
}
|
||||
/// #endif
|
||||
};
|
||||
|
||||
|
|
15
app/src/types/index.d.ts
vendored
15
app/src/types/index.d.ts
vendored
|
@ -301,6 +301,16 @@ declare interface IDockTab {
|
|||
hotkeyLangId?: string // 常量中无法存变量
|
||||
}
|
||||
|
||||
declare interface ICommand {
|
||||
langKey: string, // 多语言 key
|
||||
hotkey: string,
|
||||
customHotkey?: string,
|
||||
callback?: () => void
|
||||
fileTreeCallback?: (file: import("../layout/dock/Files").Files) => void
|
||||
editorCallback?: (protyle: IProtyle) => void
|
||||
dockCallback?: (element: HTMLElement) => void
|
||||
}
|
||||
|
||||
declare interface IPluginData {
|
||||
name: string,
|
||||
js: string,
|
||||
|
@ -635,6 +645,11 @@ declare interface IGraph {
|
|||
}
|
||||
|
||||
declare interface IKeymap {
|
||||
plugin: {
|
||||
[key: string]: {
|
||||
[key: string]: IKeymapItem
|
||||
}
|
||||
}
|
||||
general: { [key: string]: IKeymapItem }
|
||||
editor: {
|
||||
general: { [key: string]: IKeymapItem }
|
||||
|
|
Loading…
Add table
Reference in a new issue