mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-30 12:13:52 +08: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,58 +11,43 @@ 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; | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
|     openDevToolsListener() { | ||||
|         if (utils.isElectron()) { | ||||
|         const { remote } = require('electron'); | ||||
|         const { FindInPage } = require('electron-find'); | ||||
|             require('electron').remote.getCurrentWindow().toggleDevTools(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|         findInPage = new FindInPage(remote.getCurrentWebContents(), { | ||||
| 
 | ||||
|     findInTextListener() { | ||||
|         if (utils.isElectron()) { | ||||
|             const {remote} = require('electron'); | ||||
|             const {FindInPage} = require('electron-find'); | ||||
| 
 | ||||
|             const findInPage = new FindInPage(remote.getCurrentWebContents(), { | ||||
|                 offsetTop: 10, | ||||
|                 offsetRight: 10, | ||||
|                 boxBgColor: 'var(--main-background-color)', | ||||
| @ -81,25 +66,17 @@ function registerEntrypoints() { | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|     if (utils.isElectron()) { | ||||
|         keyboardActionService.setGlobalActionHandler("ZoomOut", zoomService.decreaseZoomFactor); | ||||
|         keyboardActionService.setGlobalActionHandler("ZoomIn", zoomService.increaseZoomFactor); | ||||
|     } | ||||
| 
 | ||||
|     $(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'); | ||||
|     zoomOutListener() { | ||||
|         zoomService.decreaseZoomFactor(); | ||||
|     } | ||||
| 
 | ||||
|         const attributesDialog = await import("../dialogs/note_revisions.js"); | ||||
|     zoomInListener() { | ||||
|         zoomService.increaseZoomFactor(); | ||||
|     } | ||||
| 
 | ||||
|         attributesDialog.showNoteRevisionsDialog(noteId, noteRevisionId); | ||||
| 
 | ||||
|         return false; | ||||
|     }); | ||||
| 
 | ||||
|     keyboardActionService.setGlobalActionHandler("CreateNoteIntoDayNote", async () => { | ||||
|     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 { | ||||
| <div class="search-box"> | ||||
|     <style> | ||||
|     .search-box { | ||||
|         display: none; | ||||
|         padding: 10px; | ||||
|         margin-top: 10px; | ||||
| } | ||||
|     } | ||||
|      | ||||
| .search-text { | ||||
|     .search-text { | ||||
|         border: 1px solid var(--main-border-color); | ||||
| } | ||||
| </style> | ||||
|     } | ||||
|     </style> | ||||
| 
 | ||||
| <div class="search-box"> | ||||
|     <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
	 zadam
						zadam