From 3c4ec7fe1a020a8b2a6c21fe83123d26453f4079 Mon Sep 17 00:00:00 2001 From: zadam Date: Tue, 19 Nov 2019 23:02:54 +0100 Subject: [PATCH] keyboard shortcuts WIP --- .../javascripts/services/entrypoints.js | 148 ++++++++++-------- src/public/javascripts/services/sidebar.js | 2 +- src/public/javascripts/services/utils.js | 5 +- src/routes/routes.js | 2 +- src/services/keyboard_actions.js | 35 ++++- src/services/options_init.js | 2 +- 6 files changed, 119 insertions(+), 75 deletions(-) diff --git a/src/public/javascripts/services/entrypoints.js b/src/public/javascripts/services/entrypoints.js index e4cd13471..0a7bda731 100644 --- a/src/public/javascripts/services/entrypoints.js +++ b/src/public/javascripts/services/entrypoints.js @@ -27,89 +27,99 @@ function registerEntrypoints() { jQuery.hotkeys.options.filterContentEditable = false; jQuery.hotkeys.options.filterTextInputs = false; - utils.bindGlobalShortcut('ctrl+l', () => import(ADD_LINK).then(d => d.showDialog())); - utils.bindGlobalShortcut('ctrl+shift+l', () => import(ADD_LINK).then(d => d.showDialogForClone())); + setActionHandler("AddLinkToText", () => import(ADD_LINK).then(d => d.showDialog())); - $("#jump-to-note-dialog-button").on('click', () => import(JUMP_TO_NOTE).then(d => d.showDialog())); - utils.bindGlobalShortcut('ctrl+j', () => import(JUMP_TO_NOTE).then(d => d.showDialog())); + const showJumpToNoteDialog = () => import(JUMP_TO_NOTE).then(d => d.showDialog()); + $("#jump-to-note-dialog-button").on('click', showJumpToNoteDialog); + setActionHandler("JumpToNote", showJumpToNoteDialog); - $("#recent-changes-button").on('click', () => import(RECENT_CHANGES).then(d => d.showDialog())); + const showRecentChanges = () => import(RECENT_CHANGES).then(d => d.showDialog()); + $("#recent-changes-button").on('click', showRecentChanges); + setActionHandler("ShowRecentChanges", showRecentChanges); $("#enter-protected-session-button").on('click', protectedSessionService.enterProtectedSession); $("#leave-protected-session-button").on('click', protectedSessionService.leaveProtectedSession); $("#toggle-search-button").on('click', searchNotesService.toggleSearch); - utils.bindGlobalShortcut('ctrl+s', searchNotesService.toggleSearch); + setActionHandler('SearchNotes', searchNotesService.toggleSearch); const $noteTabContainer = $("#note-tab-container"); - $noteTabContainer.on("click", ".show-attributes-button", () => import(ATTRIBUTES).then(d => d.showDialog())); - utils.bindGlobalShortcut('alt+a', () => import(ATTRIBUTES).then(d => d.showDialog())); - $noteTabContainer.on("click", ".show-note-info-button", () => import(NOTE_INFO).then(d => d.showDialog())); + const showAttributesDialog = () => import(ATTRIBUTES).then(d => d.showDialog()); + $noteTabContainer.on("click", ".show-attributes-button", showAttributesDialog); + setActionHandler("ShowAttributes", showAttributesDialog); - $noteTabContainer.on("click", ".show-note-revisions-button", function() { + const showNoteInfoDialog = () => import(NOTE_INFO).then(d => d.showDialog()); + $noteTabContainer.on("click", ".show-note-info-button", showNoteInfoDialog); + setActionHandler("ShowNoteInfo", showNoteInfoDialog); + + const showNoteRevisionsDialog = function() { if ($(this).hasClass("disabled")) { return; } import(NOTE_REVISIONS).then(d => d.showCurrentNoteRevisions()); - }); + }; - $noteTabContainer.on("click", ".show-source-button", function() { + $noteTabContainer.on("click", ".show-note-revisions-button", showNoteRevisionsDialog); + setActionHandler("ShowNoteRevisions", showNoteRevisionsDialog); + + const showNoteSourceDialog = function() { if ($(this).hasClass("disabled")) { return; } import(NOTE_SOURCE).then(d => d.showDialog()); - }); + }; - $noteTabContainer.on("click", ".show-link-map-button", function() { - import(LINK_MAP).then(d => d.showDialog()); - }); + $noteTabContainer.on("click", ".show-source-button", showNoteSourceDialog); + setActionHandler("ShowNoteSource", showNoteSourceDialog); - $("#options-button").on('click', () => import(OPTIONS).then(d => d.showDialog())); + const showLinkMapDialog = () => import(LINK_MAP).then(d => d.showDialog()); + $noteTabContainer.on("click", ".show-link-map-button", showLinkMapDialog); + setActionHandler("ShowLinkMap", showLinkMapDialog); - $("#show-help-button").on('click', () => import(HELP).then(d => d.showDialog())); - utils.bindGlobalShortcut('f1', () => import(HELP).then(d => d.showDialog())); + const showOptionsDialog = () => import(OPTIONS).then(d => d.showDialog()); + $("#options-button").on('click', showOptionsDialog); + setActionHandler("ShowOptions", showOptionsDialog); - $("#open-sql-console-button").on('click', () => import(SQL_CONSOLE).then(d => d.showDialog())); - utils.bindGlobalShortcut('alt+o', () => import(SQL_CONSOLE).then(d => d.showDialog())); + const showHelpDialog = () => import(HELP).then(d => d.showDialog()); + $("#show-help-button").on('click', showHelpDialog); + setActionHandler("ShowHelp", showHelpDialog); + + const showSqlConsoleDialog = () => import(SQL_CONSOLE).then(d => d.showDialog()); + $("#open-sql-console-button").on('click', showSqlConsoleDialog); + setActionHandler("ShowSQLConsole", showSqlConsoleDialog); $("#show-about-dialog-button").on('click', () => import(ABOUT).then(d => d.showDialog())); if (utils.isElectron()) { $("#history-navigation").show(); $("#history-back-button").on('click', window.history.back); - $("#history-forward-button").on('click', window.history.forward); + setActionHandler("BackInNoteHistory", window.history.back); - if (utils.isMac()) { - // Mac has a different history navigation shortcuts - https://github.com/zadam/trilium/issues/376 - utils.bindGlobalShortcut('meta+left', window.history.back); - utils.bindGlobalShortcut('meta+right', window.history.forward); - } - else { - utils.bindGlobalShortcut('alt+left', window.history.back); - utils.bindGlobalShortcut('alt+right', window.history.forward); - } + $("#history-forward-button").on('click', window.history.forward); + setActionHandler("ForwardInNoteHistory", window.history.forward); } // hide (toggle) everything except for the note content for zen mode - utils.bindGlobalShortcut('alt+m', e => { + const toggleZenMode = () => { $(".hide-in-zen-mode").toggle(); $("#container").toggleClass("zen-mode"); - }); + }; - utils.bindGlobalShortcut('alt+t', e => { + utils.bindGlobalShortcut('alt+m', toggleZenMode); + setActionHandler("ToggleZenMode", toggleZenMode); + + setActionHandler("InsertDateTime", () => { const date = new Date(); const dateString = utils.formatDateTime(date); linkService.addTextToEditor(dateString); }); - utils.bindGlobalShortcut('f5', utils.reloadApp); - $("#reload-frontend-button").on('click', utils.reloadApp); - utils.bindGlobalShortcut('ctrl+r', utils.reloadApp); + setActionHandler("ReloadApp", utils.reloadApp); $("#open-dev-tools-button").toggle(utils.isElectron()); @@ -120,8 +130,8 @@ function registerEntrypoints() { return false; }; - utils.bindGlobalShortcut('ctrl+shift+i', openDevTools); $("#open-dev-tools-button").on('click', openDevTools); + setActionHandler("OpenDevTools", openDevTools); } let findInPage; @@ -142,18 +152,12 @@ function registerEntrypoints() { textHoverBgColor: '#555', caseSelectedColor: 'var(--main-border-color)' }); + + setActionHandler("FindInText", () => findInPage.openFindWindow()); } if (utils.isElectron()) { - utils.bindGlobalShortcut('ctrl+f', () => { - findInPage.openFindWindow(); - - return false; - }); - } - - if (utils.isElectron()) { - const toggleFullscreen = function() { + const toggleFullscreen = () => { const win = require('electron').remote.getCurrentWindow(); if (win.isFullScreenable()) { @@ -165,7 +169,7 @@ function registerEntrypoints() { $("#toggle-fullscreen-button").on('click', toggleFullscreen); - utils.bindGlobalShortcut('f11', toggleFullscreen); + setActionHandler("ToggleFullscreen", toggleFullscreen); } else { // outside of electron this is handled by the browser @@ -173,8 +177,8 @@ function registerEntrypoints() { } if (utils.isElectron()) { - utils.bindGlobalShortcut('ctrl+-', zoomService.decreaseZoomFactor); - utils.bindGlobalShortcut('ctrl+=', zoomService.increaseZoomFactor); + setActionHandler("ZoomOut", zoomService.decreaseZoomFactor); + setActionHandler("ZoomIn", zoomService.increaseZoomFactor); } $(document).on('click', "a[data-action='note-revision']", async event => { @@ -189,7 +193,7 @@ function registerEntrypoints() { return false; }); - utils.bindGlobalShortcut('ctrl+shift+c', () => import(CLONE_TO).then(d => { + setActionHandler("CloneNotesTo", () => import(CLONE_TO).then(d => { const activeNode = treeService.getActiveNode(); const selectedOrActiveNodes = treeService.getSelectedOrActiveNodes(activeNode); @@ -199,53 +203,63 @@ function registerEntrypoints() { d.showDialog(noteIds); })); - utils.bindGlobalShortcut('ctrl+shift+x', () => import(MOVE_TO).then(d => { + setActionHandler("MoveNotesTo", () => import(MOVE_TO).then(d => { const activeNode = treeService.getActiveNode(); const selectedOrActiveNodes = treeService.getSelectedOrActiveNodes(activeNode); d.showDialog(selectedOrActiveNodes); })); - } class KeyboardAction { constructor(params) { /** @property {string} */ - this.optionName = params.optionName; + this.actionName = params.actionName; /** @property {string[]} */ - this.defaultShortcuts = Array.isArray(params.defaultShortcuts) ? params.defaultShortcuts : [params.defaultShortcuts]; + this.defaultShortcuts = params.defaultShortcuts; /** @property {string[]} */ - this.activeShortcuts = this.defaultShortcuts.slice(); + this.effectiveShortcuts = params.effectiveShortcuts; /** @property {string} */ this.description = params.description; } addShortcut(shortcut) { - this.activeShortcuts.push(shortcut); + this.effectiveShortcuts.push(shortcut); } /** * @param {string|string[]} shortcuts */ replaceShortcuts(shortcuts) { - this.activeShortcuts = Array.isArray(shortcuts) ? shortcuts : [shortcuts]; - } - - /** @return {KeyboardAction[]} */ - static get allActions() { - return Object.keys(KeyboardAction) - .map(key => KeyboardAction[key]) - .filter(obj => obj instanceof KeyboardAction); + this.effectiveShortcuts = Array.isArray(shortcuts) ? shortcuts : [shortcuts]; } } -server.get('keyboard-actions').then(actions => { - for (const action of actions) { +const keyboardActionRepo = {}; +const keyboardActionsLoaded = server.get('keyboard-actions').then(actions => { + for (const action of actions) { + keyboardActionRepo[action.actionName] = new KeyboardAction(action); } }); +function setActionHandler(actionName, handler) { + keyboardActionsLoaded.then(() => { + const action = keyboardActionRepo[actionName]; + + if (!action) { + throw new Error(`Cannot find keyboard action '${actionName}'`); + } + + action.handler = handler; + + for (const shortcut of action.effectiveShortcuts) { + utils.bindGlobalShortcut(shortcut, handler); + } + }); +} + export default { registerEntrypoints } \ No newline at end of file diff --git a/src/public/javascripts/services/sidebar.js b/src/public/javascripts/services/sidebar.js index 5dbbf8f4d..29a84f7d8 100644 --- a/src/public/javascripts/services/sidebar.js +++ b/src/public/javascripts/services/sidebar.js @@ -58,7 +58,7 @@ class Sidebar { import("../widgets/note_revisions.js"), import("../widgets/attributes.js"), import("../widgets/what_links_here.js"), - import("../widgets/similar-notes.js"), + import("../widgets/similar_notes.js"), import("../widgets/edited_notes.js"), import("../widgets/calendar.js") ])).map(m => m.default); diff --git a/src/public/javascripts/services/utils.js b/src/public/javascripts/services/utils.js index 1f1560d74..0d4e439d9 100644 --- a/src/public/javascripts/services/utils.js +++ b/src/public/javascripts/services/utils.js @@ -137,10 +137,7 @@ function bindGlobalShortcut(keyboardShortcut, handler) { function bindElShortcut($el, keyboardShortcut, handler) { if (isDesktop()) { - if (isMac()) { - // use CMD (meta) instead of CTRL for all shortcuts - keyboardShortcut = keyboardShortcut.replace("ctrl", "meta"); - } + keyboardShortcut = keyboardShortcut.replace("mod", isMac() ? "meta" : "ctrl"); $el.bind('keydown', keyboardShortcut, e => { handler(e); diff --git a/src/routes/routes.js b/src/routes/routes.js index fb33589d0..2e3926678 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -33,7 +33,7 @@ const searchRoute = require('./api/search'); const dateNotesRoute = require('./api/date_notes'); const linkMapRoute = require('./api/link_map'); const clipperRoute = require('./api/clipper'); -const similarNotesRoute = require('./api/similar-notes'); +const similarNotesRoute = require('./api/similar_notes'); const keysRoute = require('./api/keys'); const log = require('../services/log'); diff --git a/src/services/keyboard_actions.js b/src/services/keyboard_actions.js index 08e5d63fc..f2741eea1 100644 --- a/src/services/keyboard_actions.js +++ b/src/services/keyboard_actions.js @@ -1,6 +1,7 @@ "use strict"; const optionService = require('./options'); +const utils = require('./utils'); const log = require('./log'); const ELECTRON = "electron"; @@ -107,12 +108,36 @@ const DEFAULT_KEYBOARD_ACTIONS = [ actionName: "ShowAttributes", defaultShortcuts: ["alt+a"] }, + { + actionName: "ShowNoteInfo", + defaultShortcuts: [] + }, + { + actionName: "ShowNoteSource", + defaultShortcuts: [] + }, + { + actionName: "ShowLinkMap", + defaultShortcuts: [] + }, + { + actionName: "ShowOptions", + defaultShortcuts: [] + }, + { + actionName: "ShowNoteRevisions", + defaultShortcuts: [] + }, + { + actionName: "ShowRecentChanges", + defaultShortcuts: [] + }, { actionName: "ShowHelp", defaultShortcuts: ["f1"] }, { - actionName: "OpenSQLConsole", + actionName: "ShowSQLConsole", defaultShortcuts: ["alt+o"] }, { @@ -157,6 +182,12 @@ const DEFAULT_KEYBOARD_ACTIONS = [ } ]; +if (process.platform === "darwin") { + // Mac has a different history navigation shortcuts - https://github.com/zadam/trilium/issues/376 + DEFAULT_KEYBOARD_ACTIONS.find(ka => ka.actionName === 'BackInNoteHistory').defaultShortcuts = ["meta+left"]; + DEFAULT_KEYBOARD_ACTIONS.find(ka => ka.actionName === 'ForwardInNoteHistory').defaultShortcuts = ["meta+right"]; +} + async function getKeyboardActions() { const actions = JSON.parse(JSON.stringify(DEFAULT_KEYBOARD_ACTIONS)); @@ -183,6 +214,8 @@ async function getKeyboardActions() { } } } + + return actions; } module.exports = { diff --git a/src/services/options_init.js b/src/services/options_init.js index 0e8c54860..7f921b972 100644 --- a/src/services/options_init.js +++ b/src/services/options_init.js @@ -102,7 +102,7 @@ async function initStartupOptions() { function getKeyboardDefaultOptions() { return keyboardActions.DEFAULT_KEYBOARD_ACTIONS.map(ka => { return { - name: "keyboardShortcuts" + ka.optionName, + name: "keyboardShortcuts" + ka.actionName, value: JSON.stringify(ka.defaultShortcuts), isSynced: false };