fix(client): keyboard shortcuts offset in tree menu

This commit is contained in:
Elian Doran
2025-09-18 07:47:10 +03:00
parent b9055c6810
commit d657303f2f
13 changed files with 59 additions and 30 deletions

View File

@@ -1,4 +1,5 @@
import keyboardActionService from "../services/keyboard_actions.js"; import { KeyboardActionNames } from "@triliumnext/commons";
import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js";
import note_tooltip from "../services/note_tooltip.js"; import note_tooltip from "../services/note_tooltip.js";
import utils from "../services/utils.js"; import utils from "../services/utils.js";
@@ -38,6 +39,7 @@ export interface MenuCommandItem<T> {
handler?: MenuHandler<T>; handler?: MenuHandler<T>;
items?: MenuItem<T>[] | null; items?: MenuItem<T>[] | null;
shortcut?: string; shortcut?: string;
keyboardShortcut?: KeyboardActionNames;
spellingSuggestion?: string; spellingSuggestion?: string;
checked?: boolean; checked?: boolean;
columns?: number; columns?: number;
@@ -185,7 +187,23 @@ class ContextMenu {
} }
} }
if ("shortcut" in item && item.shortcut) { if ("keyboardShortcut" in item && item.keyboardShortcut) {
const shortcuts = getActionSync(item.keyboardShortcut).effectiveShortcuts;
if (shortcuts) {
const allShortcuts: string[] = [];
for (const effectiveShortcut of shortcuts) {
allShortcuts.push(effectiveShortcut.split("+")
.map(key => `<kbd>${key}</kbd>`)
.join("+"));
}
if (allShortcuts.length) {
const container = $("<span>").addClass("keyboard-shortcut");
container.append($(allShortcuts.join(",")));
$link.append(container);
}
}
} else if ("shortcut" in item && item.shortcut) {
$link.append($("<kbd>").text(item.shortcut)); $link.append($("<kbd>").text(item.shortcut));
} }

View File

@@ -76,27 +76,29 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch; const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
const items: (MenuItem<TreeCommandNames> | null)[] = [ const items: (MenuItem<TreeCommandNames> | null)[] = [
{ title: `${t("tree-context-menu.open-in-a-new-tab")}`, command: "openInTab", uiIcon: "bx bx-link-external", enabled: noSelectedNotes }, { title: t("tree-context-menu.open-in-a-new-tab"), command: "openInTab", shortcut: "Ctrl+Click", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes }, { title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit", enabled: noSelectedNotes }, { title: t("tree-context-menu.open-in-popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit", enabled: noSelectedNotes },
isHoisted isHoisted
? null ? null
: { : {
title: `${t("tree-context-menu.hoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, title: `${t("tree-context-menu.hoist-note")}`,
command: "toggleNoteHoisting", command: "toggleNoteHoisting",
keyboardShortcut: "toggleNoteHoisting",
uiIcon: "bx bxs-chevrons-up", uiIcon: "bx bxs-chevrons-up",
enabled: noSelectedNotes && notSearch enabled: noSelectedNotes && notSearch
}, },
!isHoisted || !isNotRoot !isHoisted || !isNotRoot
? null ? null
: { title: `${t("tree-context-menu.unhoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" }, : { title: t("tree-context-menu.unhoist-note"), command: "toggleNoteHoisting", keyboardShortcut: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: "----" }, { title: "----" },
{ {
title: `${t("tree-context-menu.insert-note-after")}<kbd data-command="createNoteAfter"></kbd>`, title: t("tree-context-menu.insert-note-after"),
command: "insertNoteAfter", command: "insertNoteAfter",
keyboardShortcut: "createNoteAfter",
uiIcon: "bx bx-plus", uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null, items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes && notOptionsOrHelp, enabled: insertNoteAfterEnabled && noSelectedNotes && notOptionsOrHelp,
@@ -104,8 +106,9 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
}, },
{ {
title: `${t("tree-context-menu.insert-child-note")}<kbd data-command="createNoteInto"></kbd>`, title: t("tree-context-menu.insert-child-note"),
command: "insertChildNote", command: "insertChildNote",
keyboardShortcut: "createNoteInto",
uiIcon: "bx bx-plus", uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null, items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes && notOptionsOrHelp, enabled: notSearch && noSelectedNotes && notOptionsOrHelp,
@@ -130,8 +133,9 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
{ title: "----" }, { title: "----" },
{ {
title: `${t("tree-context-menu.edit-branch-prefix")} <kbd data-command="editBranchPrefix"></kbd>`, title: t("tree-context-menu.edit-branch-prefix"),
command: "editBranchPrefix", command: "editBranchPrefix",
keyboardShortcut: "editBranchPrefix",
uiIcon: "bx bx-rename", uiIcon: "bx bx-rename",
enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptionsOrHelp enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptionsOrHelp
}, },
@@ -139,11 +143,12 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
{ title: "----" }, { title: "----" },
{ title: `${t("tree-context-menu.expand-subtree")} <kbd data-command="expandSubtree"></kbd>`, command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes }, { title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.collapse-subtree")} <kbd data-command="collapseSubtree"></kbd>`, command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes }, { title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ {
title: `${t("tree-context-menu.sort-by")} <kbd data-command="sortChildNotes"></kbd>`, title: t("tree-context-menu.sort-by"),
command: "sortChildNotes", command: "sortChildNotes",
keyboardShortcut: "sortChildNotes",
uiIcon: "bx bx-sort-down", uiIcon: "bx bx-sort-down",
enabled: noSelectedNotes && notSearch enabled: noSelectedNotes && notSearch
}, },
@@ -158,17 +163,19 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
{ title: "----" }, { title: "----" },
{ {
title: `${t("tree-context-menu.cut")} <kbd data-command="cutNotesToClipboard"></kbd>`, title: t("tree-context-menu.cut"),
command: "cutNotesToClipboard", command: "cutNotesToClipboard",
keyboardShortcut: "cutNotesToClipboard",
uiIcon: "bx bx-cut", uiIcon: "bx bx-cut",
enabled: isNotRoot && !isHoisted && parentNotSearch enabled: isNotRoot && !isHoisted && parentNotSearch
}, },
{ title: `${t("tree-context-menu.copy-clone")} <kbd data-command="copyNotesToClipboard"></kbd>`, command: "copyNotesToClipboard", uiIcon: "bx bx-copy", enabled: isNotRoot && !isHoisted }, { title: t("tree-context-menu.copy-clone"), command: "copyNotesToClipboard", keyboardShortcut: "copyNotesToClipboard", uiIcon: "bx bx-copy", enabled: isNotRoot && !isHoisted },
{ {
title: `${t("tree-context-menu.paste-into")} <kbd data-command="pasteNotesFromClipboard"></kbd>`, title: t("tree-context-menu.paste-into"),
command: "pasteNotesFromClipboard", command: "pasteNotesFromClipboard",
keyboardShortcut: "pasteNotesFromClipboard",
uiIcon: "bx bx-paste", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes
}, },
@@ -181,17 +188,19 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
}, },
{ {
title: `${t("tree-context-menu.move-to")} <kbd data-command="moveNotesTo"></kbd>`, title: t("tree-context-menu.move-to"),
command: "moveNotesTo", command: "moveNotesTo",
keyboardShortcut: "moveNotesTo",
uiIcon: "bx bx-transfer", uiIcon: "bx bx-transfer",
enabled: isNotRoot && !isHoisted && parentNotSearch enabled: isNotRoot && !isHoisted && parentNotSearch
}, },
{ title: `${t("tree-context-menu.clone-to")} <kbd data-command="cloneNotesTo"></kbd>`, command: "cloneNotesTo", uiIcon: "bx bx-duplicate", enabled: isNotRoot && !isHoisted }, { title: t("tree-context-menu.clone-to"), command: "cloneNotesTo", keyboardShortcut: "cloneNotesTo", uiIcon: "bx bx-duplicate", enabled: isNotRoot && !isHoisted },
{ {
title: `${t("tree-context-menu.duplicate")} <kbd data-command="duplicateSubtree">`, title: t("tree-context-menu.duplicate"),
command: "duplicateSubtree", command: "duplicateSubtree",
keyboardShortcut: "duplicateSubtree",
uiIcon: "bx bx-outline", uiIcon: "bx bx-outline",
enabled: parentNotSearch && isNotRoot && !isHoisted && notOptionsOrHelp enabled: parentNotSearch && isNotRoot && !isHoisted && notOptionsOrHelp
}, },
@@ -225,8 +234,9 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
} }
}, },
{ {
title: `${t("tree-context-menu.delete")} <kbd data-command="deleteNotes"></kbd>`, title: t("tree-context-menu.delete"),
command: "deleteNotes", command: "deleteNotes",
keyboardShortcut: "deleteNotes",
uiIcon: "bx bx-trash destructive-action-icon", uiIcon: "bx bx-trash destructive-action-icon",
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptionsOrHelp enabled: isNotRoot && !isHoisted && parentNotSearch && notOptionsOrHelp
}, },
@@ -240,8 +250,9 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
{ title: "----" }, { title: "----" },
{ {
title: `${t("tree-context-menu.search-in-subtree")} <kbd data-command="searchInSubtree"></kbd>`, title: t("tree-context-menu.search-in-subtree"),
command: "searchInSubtree", command: "searchInSubtree",
keyboardShortcut: "searchInSubtree",
uiIcon: "bx bx-search", uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes enabled: notSearch && noSelectedNotes
} }

View File

@@ -1426,7 +1426,7 @@
"button-tree-map": "树形地图" "button-tree-map": "树形地图"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "在新标签页中打开 <kbd>Ctrl+Click</kbd>", "open-in-a-new-tab": "在新标签页中打开",
"open-in-a-new-split": "在新分栏中打开", "open-in-a-new-split": "在新分栏中打开",
"insert-note-after": "在后面插入笔记", "insert-note-after": "在后面插入笔记",
"insert-child-note": "插入子笔记", "insert-child-note": "插入子笔记",

View File

@@ -1376,7 +1376,7 @@
"button-tree-map": "Baumkarte" "button-tree-map": "Baumkarte"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "In neuem Tab öffnen <kbd>Strg+Klick</kbd>", "open-in-a-new-tab": "In neuem Tab öffnen",
"open-in-a-new-split": "In neuem Split öffnen", "open-in-a-new-split": "In neuem Split öffnen",
"insert-note-after": "Notiz dahinter einfügen", "insert-note-after": "Notiz dahinter einfügen",
"insert-child-note": "Unternotiz einfügen", "insert-child-note": "Unternotiz einfügen",

View File

@@ -1590,7 +1590,7 @@
"button-tree-map": "Tree map" "button-tree-map": "Tree map"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "Open in a new tab <kbd>Ctrl+Click</kbd>", "open-in-a-new-tab": "Open in a new tab",
"open-in-a-new-split": "Open in a new split", "open-in-a-new-split": "Open in a new split",
"insert-note-after": "Insert note after", "insert-note-after": "Insert note after",
"insert-child-note": "Insert child note", "insert-child-note": "Insert child note",

View File

@@ -1563,7 +1563,7 @@
"button-tree-map": "Mapa de Árbol" "button-tree-map": "Mapa de Árbol"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "Abrir en nueva pestaña <kbd>Ctrl+Click</kbd>", "open-in-a-new-tab": "Abrir en nueva pestaña",
"open-in-a-new-split": "Abrir en nueva división", "open-in-a-new-split": "Abrir en nueva división",
"insert-note-after": "Insertar nota después de", "insert-note-after": "Insertar nota después de",
"insert-child-note": "Insertar subnota", "insert-child-note": "Insertar subnota",

View File

@@ -1357,7 +1357,7 @@
"button-tree-map": "Carte de l'arborescence" "button-tree-map": "Carte de l'arborescence"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "Ouvrir dans un nouvel onglet <kbd>Ctrl+Clic</kbd>", "open-in-a-new-tab": "Ouvrir dans un nouvel onglet",
"open-in-a-new-split": "Ouvrir dans une nouvelle division", "open-in-a-new-split": "Ouvrir dans une nouvelle division",
"insert-note-after": "Insérer une note après", "insert-note-after": "Insérer une note après",
"insert-child-note": "Insérer une note enfant", "insert-child-note": "Insérer une note enfant",

View File

@@ -365,7 +365,7 @@
}, },
"tree-context-menu": { "tree-context-menu": {
"advanced": "高度", "advanced": "高度",
"open-in-a-new-tab": "新しいタブで開く <kbd>Ctrl+Click</kbd>", "open-in-a-new-tab": "新しいタブで開く",
"open-in-a-new-split": "新しく分割して開く", "open-in-a-new-split": "新しく分割して開く",
"insert-note-after": "ノートを後ろに挿入", "insert-note-after": "ノートを後ろに挿入",
"insert-child-note": "子ノートを挿入", "insert-child-note": "子ノートを挿入",

View File

@@ -744,7 +744,7 @@
"button-tree-map": "Mapa em Árvore" "button-tree-map": "Mapa em Árvore"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "Abrir em uma nova aba <kbd>Ctrl+Click</kbd>", "open-in-a-new-tab": "Abrir em uma nova aba",
"open-in-a-new-split": "Abrir em um novo painel dividido", "open-in-a-new-split": "Abrir em um novo painel dividido",
"insert-note-after": "Inserir nota após", "insert-note-after": "Inserir nota após",
"insert-child-note": "Inserir nota filha", "insert-child-note": "Inserir nota filha",

View File

@@ -1377,7 +1377,7 @@
"insert-note-after": "Inserează după notiță", "insert-note-after": "Inserează după notiță",
"move-to": "Mutare la...", "move-to": "Mutare la...",
"open-in-a-new-split": "Deschide în lateral", "open-in-a-new-split": "Deschide în lateral",
"open-in-a-new-tab": "Deschide în tab nou <kbd>Ctrl+Clic</kbd>", "open-in-a-new-tab": "Deschide în tab nou",
"paste-after": "Lipește după notiță", "paste-after": "Lipește după notiță",
"paste-into": "Lipește în notiță", "paste-into": "Lipește în notiță",
"protect-subtree": "Protejează ierarhia", "protect-subtree": "Protejează ierarhia",

View File

@@ -809,7 +809,7 @@
"cut": "Вырезать", "cut": "Вырезать",
"duplicate": "Создать дубликат", "duplicate": "Создать дубликат",
"export": "Экспорт", "export": "Экспорт",
"open-in-a-new-tab": "Открыть в новой вкладке <kbd>Ctrl+Click</kbd>", "open-in-a-new-tab": "Открыть в новой вкладке",
"open-in-a-new-split": "Открыть в новой панели", "open-in-a-new-split": "Открыть в новой панели",
"unhoist-note": "Отрепить заметку", "unhoist-note": "Отрепить заметку",
"hoist-note": "Закрепить заметку", "hoist-note": "Закрепить заметку",

View File

@@ -1385,7 +1385,7 @@
"button-tree-map": "樹狀地圖" "button-tree-map": "樹狀地圖"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "在新分頁中打開 <kbd>Ctrl+Click</kbd>", "open-in-a-new-tab": "在新分頁中打開",
"open-in-a-new-split": "在新頁面分割中打開", "open-in-a-new-split": "在新頁面分割中打開",
"insert-note-after": "在後面插入筆記", "insert-note-after": "在後面插入筆記",
"insert-child-note": "插入子筆記", "insert-child-note": "插入子筆記",

View File

@@ -1897,7 +1897,7 @@
"button-tree-map": "Карта дерева" "button-tree-map": "Карта дерева"
}, },
"tree-context-menu": { "tree-context-menu": {
"open-in-a-new-tab": "Відкрити в новій вкладці <kbd>Ctrl+Клік</kbd>", "open-in-a-new-tab": "Відкрити в новій вкладці",
"open-in-a-new-split": "Відкрити в новому розділі", "open-in-a-new-split": "Відкрити в новому розділі",
"insert-note-after": "Вставити нотатку після", "insert-note-after": "Вставити нотатку після",
"insert-child-note": "Вставити дочірню нотатку", "insert-child-note": "Вставити дочірню нотатку",