mirror of
https://github.com/zadam/trilium.git
synced 2025-06-04 08:58:40 +02:00
converted more keyboard actions
This commit is contained in:
parent
af5c623671
commit
c63bb7ce8a
@ -15,7 +15,7 @@ import treeChanges from './services/branches.js';
|
||||
import treeUtils from './services/tree_utils.js';
|
||||
import utils from './services/utils.js';
|
||||
import server from './services/server.js';
|
||||
import entrypoints from './services/entrypoints.js';
|
||||
import Entrypoints from './services/entrypoints.js';
|
||||
import noteTooltipService from './services/note_tooltip.js';
|
||||
import bundle from "./services/bundle.js";
|
||||
import treeCache from "./services/tree_cache.js";
|
||||
@ -133,8 +133,6 @@ searchNotesService.init(); // should be in front of treeService since that one m
|
||||
|
||||
appContext.showWidgets();
|
||||
|
||||
entrypoints.registerEntrypoints();
|
||||
|
||||
noteTooltipService.setupGlobalTooltip();
|
||||
|
||||
noteAutocompleteService.init();
|
||||
|
@ -31,6 +31,7 @@ import NoteActionsWidget from "../widgets/note_actions.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import bundleService from "./bundle.js";
|
||||
import DialogEventComponent from "./dialog_events.js";
|
||||
import Entrypoints from "./entrypoints.js";
|
||||
|
||||
class AppContext {
|
||||
constructor() {
|
||||
@ -112,6 +113,7 @@ class AppContext {
|
||||
}
|
||||
|
||||
this.components = [
|
||||
new Entrypoints(),
|
||||
this.tabRow,
|
||||
new DialogEventComponent(this),
|
||||
...leftPaneWidgets,
|
||||
@ -123,8 +125,8 @@ class AppContext {
|
||||
trigger(name, data, sync = false) {
|
||||
this.eventReceived(name, data);
|
||||
|
||||
for (const tabContext of this.components) {
|
||||
tabContext.eventReceived(name, data, sync);
|
||||
for (const component of this.components) {
|
||||
component.eventReceived(name, data, sync);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,95 +11,72 @@ import hoistedNoteService from "./hoisted_note.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
import server from "./server.js";
|
||||
import appContext from "./app_context.js";
|
||||
import Component from "../widgets/component.js";
|
||||
|
||||
const NOTE_REVISIONS = "../dialogs/note_revisions.js";
|
||||
const OPTIONS = "../dialogs/options.js";
|
||||
const ADD_LINK = "../dialogs/add_link.js";
|
||||
const JUMP_TO_NOTE = "../dialogs/jump_to_note.js";
|
||||
const NOTE_SOURCE = "../dialogs/note_source.js";
|
||||
const RECENT_CHANGES = "../dialogs/recent_changes.js";
|
||||
const SQL_CONSOLE = "../dialogs/sql_console.js";
|
||||
const BACKEND_LOG = "../dialogs/backend_log.js";
|
||||
const ATTRIBUTES = "../dialogs/attributes.js";
|
||||
const HELP = "../dialogs/help.js";
|
||||
const NOTE_INFO = "../dialogs/note_info.js";
|
||||
const ABOUT = "../dialogs/about.js";
|
||||
const LINK_MAP = "../dialogs/link_map.js";
|
||||
const CLONE_TO = "../dialogs/clone_to.js";
|
||||
const MOVE_TO = "../dialogs/move_to.js";
|
||||
export default class Entrypoints extends Component {
|
||||
constructor(appContext) {
|
||||
super(appContext);
|
||||
|
||||
function registerEntrypoints() {
|
||||
// hot keys are active also inside inputs and content editables
|
||||
jQuery.hotkeys.options.filterInputAcceptingElements = false;
|
||||
jQuery.hotkeys.options.filterContentEditable = false;
|
||||
jQuery.hotkeys.options.filterTextInputs = false;
|
||||
// hot keys are active also inside inputs and content editables
|
||||
jQuery.hotkeys.options.filterInputAcceptingElements = false;
|
||||
jQuery.hotkeys.options.filterContentEditable = false;
|
||||
jQuery.hotkeys.options.filterTextInputs = false;
|
||||
|
||||
keyboardActionService.setGlobalActionHandler('SearchNotes', searchNotesService.toggleSearch);
|
||||
$(document).on('click', "a[data-action='note-revision']", async event => {
|
||||
const linkEl = $(event.target);
|
||||
const noteId = linkEl.attr('data-note-path');
|
||||
const noteRevisionId = linkEl.attr('data-note-revision-id');
|
||||
|
||||
const $noteTabContainer = $("#note-tab-container");
|
||||
const attributesDialog = await import("../dialogs/note_revisions.js");
|
||||
|
||||
keyboardActionService.setGlobalActionHandler("InsertDateTimeToText", () => {
|
||||
const date = new Date();
|
||||
const dateString = utils.formatDateTime(date);
|
||||
|
||||
linkService.addTextToEditor(dateString);
|
||||
});
|
||||
|
||||
if (utils.isElectron()) {
|
||||
const openDevTools = () => {
|
||||
require('electron').remote.getCurrentWindow().toggleDevTools();
|
||||
attributesDialog.showNoteRevisionsDialog(noteId, noteRevisionId);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
$("#open-dev-tools-button").on('click', openDevTools);
|
||||
keyboardActionService.setGlobalActionHandler("OpenDevTools", openDevTools);
|
||||
}
|
||||
|
||||
let findInPage;
|
||||
|
||||
if (utils.isElectron()) {
|
||||
const { remote } = require('electron');
|
||||
const { FindInPage } = require('electron-find');
|
||||
|
||||
findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||
offsetTop: 10,
|
||||
offsetRight: 10,
|
||||
boxBgColor: 'var(--main-background-color)',
|
||||
boxShadowColor: '#000',
|
||||
inputColor: 'var(--input-text-color)',
|
||||
inputBgColor: 'var(--input-background-color)',
|
||||
inputFocusColor: '#555',
|
||||
textColor: 'var(--main-text-color)',
|
||||
textHoverBgColor: '#555',
|
||||
caseSelectedColor: 'var(--main-border-color)'
|
||||
});
|
||||
|
||||
keyboardActionService.setGlobalActionHandler("FindInText", () => {
|
||||
if (!glob.activeDialog || !glob.activeDialog.is(":visible")) {
|
||||
findInPage.openFindWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (utils.isElectron()) {
|
||||
keyboardActionService.setGlobalActionHandler("ZoomOut", zoomService.decreaseZoomFactor);
|
||||
keyboardActionService.setGlobalActionHandler("ZoomIn", zoomService.increaseZoomFactor);
|
||||
openDevToolsListener() {
|
||||
if (utils.isElectron()) {
|
||||
require('electron').remote.getCurrentWindow().toggleDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('click', "a[data-action='note-revision']", async event => {
|
||||
const linkEl = $(event.target);
|
||||
const noteId = linkEl.attr('data-note-path');
|
||||
const noteRevisionId = linkEl.attr('data-note-revision-id');
|
||||
|
||||
const attributesDialog = await import("../dialogs/note_revisions.js");
|
||||
findInTextListener() {
|
||||
if (utils.isElectron()) {
|
||||
const {remote} = require('electron');
|
||||
const {FindInPage} = require('electron-find');
|
||||
|
||||
attributesDialog.showNoteRevisionsDialog(noteId, noteRevisionId);
|
||||
const findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||
offsetTop: 10,
|
||||
offsetRight: 10,
|
||||
boxBgColor: 'var(--main-background-color)',
|
||||
boxShadowColor: '#000',
|
||||
inputColor: 'var(--input-text-color)',
|
||||
inputBgColor: 'var(--input-background-color)',
|
||||
inputFocusColor: '#555',
|
||||
textColor: 'var(--main-text-color)',
|
||||
textHoverBgColor: '#555',
|
||||
caseSelectedColor: 'var(--main-border-color)'
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
keyboardActionService.setGlobalActionHandler("FindInText", () => {
|
||||
if (!glob.activeDialog || !glob.activeDialog.is(":visible")) {
|
||||
findInPage.openFindWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
keyboardActionService.setGlobalActionHandler("CreateNoteIntoDayNote", async () => {
|
||||
zoomOutListener() {
|
||||
zoomService.decreaseZoomFactor();
|
||||
}
|
||||
|
||||
zoomInListener() {
|
||||
zoomService.increaseZoomFactor();
|
||||
}
|
||||
|
||||
async createNoteIntoDayNoteListener() {
|
||||
const todayNote = await dateNoteService.getTodayNote();
|
||||
|
||||
const {note} = await server.post(`notes/${todayNote.noteId}/children?target=into`, {
|
||||
@ -114,9 +91,9 @@ function registerEntrypoints() {
|
||||
await noteDetailService.openInTab(note.noteId, true);
|
||||
|
||||
noteDetailService.focusAndSelectTitle();
|
||||
});
|
||||
}
|
||||
|
||||
keyboardActionService.setGlobalActionHandler("ToggleNoteHoisting", async () => {
|
||||
toggleNoteHoistingListener() {
|
||||
const node = appContext.getMainNoteTree().getActiveNode();
|
||||
|
||||
hoistedNoteService.getHoistedNoteId().then(async hoistedNoteId => {
|
||||
@ -131,19 +108,9 @@ function registerEntrypoints() {
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
keyboardActionService.setGlobalActionHandler("SearchInSubtree", () => {
|
||||
const node = appContext.getMainNoteTree().getActiveNode();
|
||||
|
||||
searchNotesService.searchInSubtree(node.data.noteId);
|
||||
});
|
||||
|
||||
keyboardActionService.setGlobalActionHandler('CollapseTree', () => appContext.getMainNoteTree().collapseTree());
|
||||
|
||||
keyboardActionService.setGlobalActionHandler("CopyWithoutFormatting", utils.copySelectionToClipboard);
|
||||
}
|
||||
|
||||
export default {
|
||||
registerEntrypoints
|
||||
copyWithoutFormattingListener() {
|
||||
utils.copySelectionToClipboard();
|
||||
}
|
||||
}
|
@ -12,7 +12,8 @@ const keyboardActionsLoaded = server.get('keyboard-actions').then(actions => {
|
||||
if (shortcut && !shortcut.startsWith("global:")) { // global shortcuts should be handled in the electron code
|
||||
const eventName = action.actionName.charAt(0).toLowerCase() + action.actionName.slice(1);
|
||||
|
||||
utils.bindGlobalShortcut(shortcut, () => appContext.trigger(eventName));
|
||||
// empty object param so that destructuring with optional params work
|
||||
utils.bindGlobalShortcut(shortcut, () => appContext.trigger(eventName, {}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import treeService from './tree.js';
|
||||
import treeUtils from './tree_utils.js';
|
||||
import contextMenuService from "./context_menu.js";
|
||||
import noteDetailService from "./note_detail.js";
|
||||
import appContext from "./app_context.js";
|
||||
|
||||
function getNotePathFromUrl(url) {
|
||||
const notePathMatch = /#(root[A-Za-z0-9/]*)$/.exec(url);
|
||||
@ -98,28 +99,6 @@ function goToLink(e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function addLinkToEditor(linkTitle, linkHref) {
|
||||
const editor = noteDetailService.getActiveEditor();
|
||||
|
||||
if (editor) {
|
||||
editor.model.change(writer => {
|
||||
const insertPosition = editor.model.document.selection.getFirstPosition();
|
||||
writer.insertText(linkTitle, {linkHref: linkHref}, insertPosition);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function addTextToEditor(text) {
|
||||
const editor = noteDetailService.getActiveEditor();
|
||||
|
||||
if (editor) {
|
||||
editor.model.change(writer => {
|
||||
const insertPosition = editor.model.document.selection.getFirstPosition();
|
||||
writer.insertText(text, insertPosition);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function newTabContextMenu(e) {
|
||||
const $link = $(e.target).closest("a");
|
||||
|
||||
@ -188,7 +167,5 @@ $(document).on('contextmenu', ".note-detail-render a", newTabContextMenu);
|
||||
export default {
|
||||
getNotePathFromUrl,
|
||||
createNoteLink,
|
||||
addLinkToEditor,
|
||||
addTextToEditor,
|
||||
goToLink
|
||||
};
|
@ -13,12 +13,6 @@ async function refreshSearch() {
|
||||
toastService.showMessage("Saved search note refreshed.");
|
||||
}
|
||||
|
||||
function searchInSubtree(noteId) {
|
||||
showSearch();
|
||||
|
||||
$searchInput.val(`@in=${noteId} @text*=*`);
|
||||
}
|
||||
|
||||
function init() {
|
||||
const hashValue = document.location.hash ? document.location.hash.substr(1) : ""; // strip initial #
|
||||
|
||||
@ -35,6 +29,5 @@ export default {
|
||||
// doSearch,
|
||||
refreshSearch,
|
||||
init,
|
||||
searchInSubtree,
|
||||
getHelpText: () => helpText
|
||||
};
|
@ -10,6 +10,7 @@ import noteDetailService from './note_detail.js';
|
||||
import clipboard from './clipboard.js';
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import searchNotesService from "./search_notes.js";
|
||||
import appContext from "./app_context.js";
|
||||
|
||||
class TreeContextMenu {
|
||||
/**
|
||||
@ -99,6 +100,7 @@ class TreeContextMenu {
|
||||
}
|
||||
|
||||
async selectContextMenuItem(event, cmd) {
|
||||
const noteId = this.node.data.noteId;
|
||||
const notePath = await treeUtils.getNotePath(this.node);
|
||||
|
||||
if (cmd === 'openInTab') {
|
||||
@ -127,10 +129,10 @@ class TreeContextMenu {
|
||||
branchPrefixDialog.showDialog(this.node);
|
||||
}
|
||||
else if (cmd === "protectSubtree") {
|
||||
protectedSessionService.protectSubtree(this.node.data.noteId, true);
|
||||
protectedSessionService.protectSubtree(noteId, true);
|
||||
}
|
||||
else if (cmd === "unprotectSubtree") {
|
||||
protectedSessionService.protectSubtree(this.node.data.noteId, false);
|
||||
protectedSessionService.protectSubtree(noteId, false);
|
||||
}
|
||||
else if (cmd === "copy") {
|
||||
clipboard.copy(this.getSelectedOrActiveBranchIds());
|
||||
@ -153,7 +155,7 @@ class TreeContextMenu {
|
||||
clipboard.pasteAfter(this.node.data.branchId);
|
||||
}
|
||||
else if (cmd === "pasteInto") {
|
||||
clipboard.pasteInto(this.node.data.noteId);
|
||||
clipboard.pasteInto(noteId);
|
||||
}
|
||||
else if (cmd === "delete") {
|
||||
treeChangesService.deleteNodes(this.getSelectedOrActiveBranchIds());
|
||||
@ -164,19 +166,19 @@ class TreeContextMenu {
|
||||
}
|
||||
else if (cmd === "importIntoNote") {
|
||||
const importDialog = await import('../dialogs/import.js');
|
||||
importDialog.showDialog(this.node.data.noteId);
|
||||
importDialog.showDialog(noteId);
|
||||
}
|
||||
else if (cmd === "collapseSubtree") {
|
||||
this.treeWidget.collapseTree(this.node);
|
||||
}
|
||||
else if (cmd === "forceNoteSync") {
|
||||
syncService.forceNoteSync(this.node.data.noteId);
|
||||
syncService.forceNoteSync(noteId);
|
||||
}
|
||||
else if (cmd === "sortAlphabetically") {
|
||||
treeService.sortAlphabetically(this.node.data.noteId);
|
||||
treeService.sortAlphabetically(noteId);
|
||||
}
|
||||
else if (cmd === "hoist") {
|
||||
hoistedNoteService.setHoistedNoteId(this.node.data.noteId);
|
||||
hoistedNoteService.setHoistedNoteId(noteId);
|
||||
}
|
||||
else if (cmd === "unhoist") {
|
||||
hoistedNoteService.unhoist();
|
||||
@ -184,10 +186,10 @@ class TreeContextMenu {
|
||||
else if (cmd === "duplicateNote") {
|
||||
const branch = treeCache.getBranch(this.node.data.branchId);
|
||||
|
||||
treeService.duplicateNote(this.node.data.noteId, branch.parentNoteId);
|
||||
treeService.duplicateNote(noteId, branch.parentNoteId);
|
||||
}
|
||||
else if (cmd === "searchInSubtree") {
|
||||
searchNotesService.searchInSubtree(this.node.data.noteId);
|
||||
appContext.trigger("searchInSubtree", {noteId});
|
||||
}
|
||||
else {
|
||||
ws.logError("Unknown command: " + cmd);
|
||||
|
@ -20,19 +20,19 @@ const helpText = `
|
||||
</p>`;
|
||||
|
||||
const TPL = `
|
||||
<style>
|
||||
.search-box {
|
||||
display: none;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.search-text {
|
||||
border: 1px solid var(--main-border-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="search-box">
|
||||
<style>
|
||||
.search-box {
|
||||
display: none;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.search-text {
|
||||
border: 1px solid var(--main-border-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input name="search-text" class="search-text form-control"
|
||||
@ -58,14 +58,14 @@ const TPL = `
|
||||
|
||||
export default class SearchBoxWidget extends BasicWidget {
|
||||
doRender() {
|
||||
const $widget = $(TPL);
|
||||
this.$widget = $(TPL);
|
||||
|
||||
this.$searchBox = $widget.find(".search-box");
|
||||
this.$closeSearchButton = $widget.find(".close-search-button");
|
||||
this.$searchInput = $widget.find("input[name='search-text']");
|
||||
this.$resetSearchButton = $widget.find(".reset-search-button");
|
||||
this.$doSearchButton = $widget.find(".do-search-button");
|
||||
this.$saveSearchButton = $widget.find(".save-search-button");
|
||||
this.$searchBox = this.$widget;
|
||||
this.$closeSearchButton = this.$widget.find(".close-search-button");
|
||||
this.$searchInput = this.$widget.find("input[name='search-text']");
|
||||
this.$resetSearchButton = this.$widget.find(".reset-search-button");
|
||||
this.$doSearchButton = this.$widget.find(".do-search-button");
|
||||
this.$saveSearchButton = this.$widget.find(".save-search-button");
|
||||
|
||||
this.$searchInput.on('keyup',e => {
|
||||
const searchText = this.$searchInput.val();
|
||||
@ -87,7 +87,7 @@ export default class SearchBoxWidget extends BasicWidget {
|
||||
|
||||
this.$closeSearchButton.on('click', () => this.hideSearchListener());
|
||||
|
||||
return $widget;
|
||||
return this.$widget;
|
||||
}
|
||||
|
||||
doSearch(searchText) {
|
||||
@ -171,7 +171,19 @@ export default class SearchBoxWidget extends BasicWidget {
|
||||
}
|
||||
}
|
||||
|
||||
searchNotesListener() {
|
||||
this.toggleSearchListener();
|
||||
}
|
||||
|
||||
resetSearchListener() {
|
||||
this.$searchInput.val("");
|
||||
}
|
||||
|
||||
searchInSubtreeListener({noteId}) {
|
||||
noteId = noteId || appContext.getActiveTabNoteId();
|
||||
|
||||
this.toggle(true);
|
||||
|
||||
this.$searchInput.val(`@in=${noteId} @text*=*`);
|
||||
}
|
||||
}
|
@ -2,8 +2,11 @@ import libraryLoader from "../../services/library_loader.js";
|
||||
import treeService from '../../services/tree.js';
|
||||
import noteAutocompleteService from '../../services/note_autocomplete.js';
|
||||
import mimeTypesService from '../../services/mime_types.js';
|
||||
import TabAwareWidget from "../tab_aware_widget.js";
|
||||
import TypeWidget from "./type_widget.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import linkService from "../../services/link.js";
|
||||
import appContext from "../../services/app_context.js";
|
||||
import noteDetailService from "../../services/note_detail.js";
|
||||
|
||||
const ENABLE_INSPECTOR = false;
|
||||
|
||||
@ -189,6 +192,31 @@ class TextTypeWidget extends TypeWidget {
|
||||
scrollToTop() {
|
||||
this.$widget.scrollTop(0);
|
||||
}
|
||||
|
||||
insertDateTimeToTextListener() {
|
||||
const date = new Date();
|
||||
const dateString = utils.formatDateTime(date);
|
||||
|
||||
this.addTextToEditor(dateString);
|
||||
}
|
||||
|
||||
async addLinkToEditor(linkTitle, linkHref) {
|
||||
await this.initialized;
|
||||
|
||||
this.textEditor.model.change(writer => {
|
||||
const insertPosition = this.textEditor.model.document.selection.getFirstPosition();
|
||||
writer.insertText(linkTitle, {linkHref: linkHref}, insertPosition);
|
||||
});
|
||||
}
|
||||
|
||||
async addTextToEditor(text) {
|
||||
await this.initialized;
|
||||
|
||||
this.textEditor.model.change(writer => {
|
||||
const insertPosition = this.textEditor.model.document.selection.getFirstPosition();
|
||||
writer.insertText(text, insertPosition);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default TextTypeWidget;
|
Loading…
x
Reference in New Issue
Block a user