diff --git a/src/public/app/services/frontend_script_api.js b/src/public/app/services/frontend_script_api.js
index 0b40b0333..c34e0492d 100644
--- a/src/public/app/services/frontend_script_api.js
+++ b/src/public/app/services/frontend_script_api.js
@@ -13,6 +13,7 @@ import appContext from "./app_context.js";
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js";
+import shortcutService from "./shortcuts.js";
/**
* This is the main frontend API interface for scripts. It's published in the local "api" object.
@@ -509,7 +510,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @param {string} keyboardShortcut - e.g. "ctrl+shift+a"
* @param {function} handler
*/
- this.bindGlobalShortcut = utils.bindGlobalShortcut;
+ this.bindGlobalShortcut = shortcutService.bindGlobalShortcut;
/**
* Trilium runs in backend and frontend process, when something is changed on the backend from script,
diff --git a/src/public/app/services/keyboard_actions.js b/src/public/app/services/keyboard_actions.js
index fecebca3f..6c7670092 100644
--- a/src/public/app/services/keyboard_actions.js
+++ b/src/public/app/services/keyboard_actions.js
@@ -1,6 +1,6 @@
import server from "./server.js";
-import utils from "./utils.js";
import appContext from "./app_context.js";
+import shortcutService from "./shortcuts.js";
const keyboardActionRepo = {};
@@ -31,7 +31,7 @@ async function setupActionsForElement(scope, $el, component) {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
- utils.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
+ shortcutService.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
}
}
}
@@ -39,14 +39,14 @@ async function setupActionsForElement(scope, $el, component) {
getActionsForScope("window").then(actions => {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
- utils.bindGlobalShortcut(shortcut, () => appContext.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
+ shortcutService.bindGlobalShortcut(shortcut, () => appContext.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
}
}
});
server.get('keyboard-shortcuts-for-notes').then(shortcutForNotes => {
for (const shortcut in shortcutForNotes) {
- utils.bindGlobalShortcut(shortcut, async () => {
+ shortcutService.bindGlobalShortcut(shortcut, async () => {
appContext.tabManager.getActiveContext().setNote(shortcutForNotes[shortcut]);
});
}
@@ -64,7 +64,7 @@ function setElementActionHandler($el, actionName, handler) {
for (const shortcut of action.effectiveShortcuts) {
if (shortcut) {
- utils.bindElShortcut($el, shortcut, handler);
+ shortcutService.bindElShortcut($el, shortcut, handler);
}
}
});
diff --git a/src/public/app/services/mac_init.js b/src/public/app/services/mac_init.js
index 624c4858f..10fba8cbb 100644
--- a/src/public/app/services/mac_init.js
+++ b/src/public/app/services/mac_init.js
@@ -2,15 +2,16 @@
* Mac specific initialization
*/
import utils from "./utils.js";
+import shortcutService from "./shortcuts.js";
function init() {
if (utils.isElectron() && utils.isMac()) {
- utils.bindGlobalShortcut('meta+c', () => exec("copy"));
- utils.bindGlobalShortcut('meta+v', () => exec('paste'));
- utils.bindGlobalShortcut('meta+x', () => exec('cut'));
- utils.bindGlobalShortcut('meta+a', () => exec('selectAll'));
- utils.bindGlobalShortcut('meta+z', () => exec('undo'));
- utils.bindGlobalShortcut('meta+y', () => exec('redo'));
+ shortcutService.bindGlobalShortcut('meta+c', () => exec("copy"));
+ shortcutService.bindGlobalShortcut('meta+v', () => exec('paste'));
+ shortcutService.bindGlobalShortcut('meta+x', () => exec('cut'));
+ shortcutService.bindGlobalShortcut('meta+a', () => exec('selectAll'));
+ shortcutService.bindGlobalShortcut('meta+z', () => exec('undo'));
+ shortcutService.bindGlobalShortcut('meta+y', () => exec('redo'));
}
}
@@ -22,4 +23,4 @@ function exec(cmd) {
export default {
init
-}
\ No newline at end of file
+}
diff --git a/src/public/app/services/shortcuts.js b/src/public/app/services/shortcuts.js
new file mode 100644
index 000000000..0a617d0bd
--- /dev/null
+++ b/src/public/app/services/shortcuts.js
@@ -0,0 +1,36 @@
+import utils from "./utils.js";
+
+function bindGlobalShortcut(keyboardShortcut, handler) {
+ bindElShortcut($(document), keyboardShortcut, handler);
+}
+
+function bindElShortcut($el, keyboardShortcut, handler) {
+ if (utils.isDesktop()) {
+ keyboardShortcut = normalizeShortcut(keyboardShortcut);
+
+ $el.bind('keydown', keyboardShortcut, e => {
+ handler(e);
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ }
+}
+
+/**
+ * Normalize to the form expected by the jquery.hotkeys.js
+ */
+function normalizeShortcut(shortcut) {
+ return shortcut
+ .toLowerCase()
+ .replace("enter", "return")
+ .replace("delete", "del")
+ .replace("ctrl+alt", "alt+ctrl")
+ .replace("meta+alt", "alt+meta"); // alt needs to be first;
+}
+
+export default {
+ bindGlobalShortcut,
+ bindElShortcut,
+ normalizeShortcut
+}
diff --git a/src/public/app/services/utils.js b/src/public/app/services/utils.js
index 21f79ceb7..6d2fe7c2e 100644
--- a/src/public/app/services/utils.js
+++ b/src/public/app/services/utils.js
@@ -132,35 +132,6 @@ function randomString(len) {
return text;
}
-function bindGlobalShortcut(keyboardShortcut, handler) {
- bindElShortcut($(document), keyboardShortcut, handler);
-}
-
-function bindElShortcut($el, keyboardShortcut, handler) {
- if (isDesktop()) {
- keyboardShortcut = normalizeShortcut(keyboardShortcut);
-
- $el.bind('keydown', keyboardShortcut, e => {
- handler(e);
-
- e.preventDefault();
- e.stopPropagation();
- });
- }
-}
-
-/**
- * Normalize to the form expected by the jquery.hotkeys.js
- */
-function normalizeShortcut(shortcut) {
- return shortcut
- .toLowerCase()
- .replace("enter", "return")
- .replace("delete", "del")
- .replace("ctrl+alt", "alt+ctrl")
- .replace("meta+alt", "alt+meta"); // alt needs to be first;
-}
-
function isMobile() {
return window.device === "mobile"
// window.device is not available in setup
@@ -387,8 +358,6 @@ export default {
formatLabel,
toObject,
randomString,
- bindGlobalShortcut,
- bindElShortcut,
isMobile,
isDesktop,
setCookie,
@@ -402,7 +371,6 @@ export default {
focusSavedElement,
isHtmlEmpty,
clearBrowserCache,
- normalizeShortcut,
copySelectionToClipboard,
dynamicRequire,
timeLimit,
diff --git a/src/public/app/widgets/attribute_widgets/attribute_detail.js b/src/public/app/widgets/attribute_widgets/attribute_detail.js
index 027fa5429..84d0cf057 100644
--- a/src/public/app/widgets/attribute_widgets/attribute_detail.js
+++ b/src/public/app/widgets/attribute_widgets/attribute_detail.js
@@ -8,6 +8,7 @@ import promotedAttributeDefinitionParser from '../../services/promoted_attribute
import NoteContextAwareWidget from "../note_context_aware_widget.js";
import SpacedUpdate from "../../services/spaced_update.js";
import utils from "../../services/utils.js";
+import shortcutService from "../../services/shortcuts.js";
const TPL = `
@@ -271,8 +272,8 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
this.$widget = $(TPL);
- utils.bindElShortcut(this.$widget, 'ctrl+return', () => this.saveAndClose());
- utils.bindElShortcut(this.$widget, 'esc', () => this.cancelAndClose());
+ shortcutService.bindElShortcut(this.$widget, 'ctrl+return', () => this.saveAndClose());
+ shortcutService.bindElShortcut(this.$widget, 'esc', () => this.cancelAndClose());
this.$title = this.$widget.find('.attr-detail-title');
diff --git a/src/public/app/widgets/dialogs/jump_to_note.js b/src/public/app/widgets/dialogs/jump_to_note.js
index 4db606c01..68d2ec2f4 100644
--- a/src/public/app/widgets/dialogs/jump_to_note.js
+++ b/src/public/app/widgets/dialogs/jump_to_note.js
@@ -2,6 +2,7 @@ import noteAutocompleteService from '../../services/note_autocomplete.js';
import utils from "../../services/utils.js";
import appContext from "../../services/app_context.js";
import BasicWidget from "../basic_widget.js";
+import shortcutService from "../../services/shortcuts.js";
const TPL = `
@@ -42,7 +43,7 @@ export default class JumpToNoteDialog extends BasicWidget {
this.$showInFullTextButton = this.$widget.find(".show-in-full-text-button");
this.$showInFullTextButton.on('click', e => this.showInFullText(e));
- utils.bindElShortcut(this.$widget, 'ctrl+return', e => this.showInFullText(e));
+ shortcutService.bindElShortcut(this.$widget, 'ctrl+return', e => this.showInFullText(e));
}
async jumpToNoteEvent() {
diff --git a/src/public/app/widgets/dialogs/markdown_import.js b/src/public/app/widgets/dialogs/markdown_import.js
index bdba6796d..67d74bff6 100644
--- a/src/public/app/widgets/dialogs/markdown_import.js
+++ b/src/public/app/widgets/dialogs/markdown_import.js
@@ -3,6 +3,7 @@ import toastService from "../../services/toast.js";
import utils from "../../services/utils.js";
import appContext from "../../services/app_context.js";
import BasicWidget from "../basic_widget.js";
+import shortcutService from "../../services/shortcuts.js";
const TPL = `
@@ -42,7 +43,7 @@ export default class MarkdownImportDialog extends BasicWidget {
this.$widget.on('shown.bs.modal', () => this.$importTextarea.trigger('focus'));
- utils.bindElShortcut(this.$widget, 'ctrl+return', () => this.sendForm());
+ shortcutService.bindElShortcut(this.$widget, 'ctrl+return', () => this.sendForm());
}
async convertMarkdownToHtml(text) {
diff --git a/src/public/app/widgets/note_title.js b/src/public/app/widgets/note_title.js
index 722e88b7c..9e62b5848 100644
--- a/src/public/app/widgets/note_title.js
+++ b/src/public/app/widgets/note_title.js
@@ -1,10 +1,10 @@
import NoteContextAwareWidget from "./note_context_aware_widget.js";
-import utils from "../services/utils.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import server from "../services/server.js";
import SpacedUpdate from "../services/spaced_update.js";
import appContext from "../services/app_context.js";
import branchService from "../services/branches.js";
+import shortcutService from "../services/shortcuts.js";
const TPL = `
@@ -58,13 +58,13 @@ export default class NoteTitleWidget extends NoteContextAwareWidget {
this.deleteNoteOnEscape = false;
});
- utils.bindElShortcut(this.$noteTitle, 'esc', () => {
+ shortcutService.bindElShortcut(this.$noteTitle, 'esc', () => {
if (this.deleteNoteOnEscape && this.noteContext.isActive()) {
branchService.deleteNotes(Object.values(this.noteContext.note.parentToBranch));
}
});
- utils.bindElShortcut(this.$noteTitle, 'return', () => {
+ shortcutService.bindElShortcut(this.$noteTitle, 'return', () => {
this.triggerCommand('focusOnDetail', {ntxId: this.noteContext.ntxId});
});
}
diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js
index 6475f78b6..e36bc92d0 100644
--- a/src/public/app/widgets/note_tree.js
+++ b/src/public/app/widgets/note_tree.js
@@ -18,6 +18,7 @@ import syncService from "../services/sync.js";
import options from "../services/options.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import dialogService from "../services/dialog.js";
+import shortcutService from "../services/shortcuts.js";
const TPL = `
@@ -1331,7 +1332,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
- hotKeyMap[utils.normalizeShortcut(shortcut)] = node => {
+ hotKeyMap[shortcutService.normalizeShortcut(shortcut)] = node => {
const notePath = treeService.getNotePath(node);
this.triggerCommand(action.actionName, {node, notePath});
diff --git a/src/public/app/widgets/quick_search.js b/src/public/app/widgets/quick_search.js
index 6337f4dd0..e6167f1ce 100644
--- a/src/public/app/widgets/quick_search.js
+++ b/src/public/app/widgets/quick_search.js
@@ -1,10 +1,10 @@
import BasicWidget from "./basic_widget.js";
import server from "../services/server.js";
import linkService from "../services/link.js";
-import dateNotesService from "../services/date_notes.js";
import froca from "../services/froca.js";
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
+import shortcutService from "../services/shortcuts.js";
const TPL = `
@@ -66,7 +66,7 @@ export default class QuickSearchWidget extends BasicWidget {
})
}
- utils.bindElShortcut(this.$searchString, 'return', () => {
+ shortcutService.bindElShortcut(this.$searchString, 'return', () => {
if (this.$dropdownMenu.is(":visible")) {
this.search(); // just update already visible dropdown
} else {
@@ -76,11 +76,11 @@ export default class QuickSearchWidget extends BasicWidget {
this.$searchString.focus();
});
- utils.bindElShortcut(this.$searchString, 'down', () => {
+ shortcutService.bindElShortcut(this.$searchString, 'down', () => {
this.$dropdownMenu.find('.dropdown-item:first').focus();
});
- utils.bindElShortcut(this.$searchString, 'esc', () => {
+ shortcutService.bindElShortcut(this.$searchString, 'esc', () => {
this.$dropdownToggle.dropdown('hide');
});
@@ -120,7 +120,7 @@ export default class QuickSearchWidget extends BasicWidget {
appContext.tabManager.getActiveContext().setNote(note.noteId);
}
});
- utils.bindElShortcut($link, 'return', () => {
+ shortcutService.bindElShortcut($link, 'return', () => {
this.$dropdownToggle.dropdown("hide");
appContext.tabManager.getActiveContext().setNote(note.noteId);
@@ -140,9 +140,9 @@ export default class QuickSearchWidget extends BasicWidget {
$showInFullButton.on('click', () => this.showInFullSearch());
- utils.bindElShortcut($showInFullButton, 'return', () => this.showInFullSearch());
+ shortcutService.bindElShortcut($showInFullButton, 'return', () => this.showInFullSearch());
- utils.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus());
+ shortcutService.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus());
this.$dropdownToggle.dropdown('update');
}
diff --git a/src/public/app/widgets/search_options/search_string.js b/src/public/app/widgets/search_options/search_string.js
index beb4deeed..ebfd03a95 100644
--- a/src/public/app/widgets/search_options/search_string.js
+++ b/src/public/app/widgets/search_options/search_string.js
@@ -1,7 +1,7 @@
import AbstractSearchOption from "./abstract_search_option.js";
-import utils from "../../services/utils.js";
import SpacedUpdate from "../../services/spaced_update.js";
import server from "../../services/server.js";
+import shortcutService from "../../services/shortcuts.js";
const TPL = `
@@ -45,7 +45,7 @@ export default class SearchString extends AbstractSearchOption {
this.$searchString = $option.find('.search-string');
this.$searchString.on('input', () => this.spacedUpdate.scheduleUpdate());
- utils.bindElShortcut(this.$searchString, 'return', async () => {
+ shortcutService.bindElShortcut(this.$searchString, 'return', async () => {
// this also in effect disallows new lines in query string.
// on one hand this makes sense since search string is a label
// on the other hand it could be nice for structuring long search string. It's probably a niche case though.