mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	refactor(client/ts): use discriminated unions for triggering commands
This commit is contained in:
		| @@ -17,7 +17,7 @@ import { t, initLocale } from "../services/i18n.js"; | |||||||
| import NoteDetailWidget from "../widgets/note_detail.js"; | import NoteDetailWidget from "../widgets/note_detail.js"; | ||||||
| import { ResolveOptions } from "../widgets/dialogs/delete_notes.js"; | import { ResolveOptions } from "../widgets/dialogs/delete_notes.js"; | ||||||
| import { PromptDialogOptions } from "../widgets/dialogs/prompt.js"; | import { PromptDialogOptions } from "../widgets/dialogs/prompt.js"; | ||||||
| import { ConfirmWithMessageOptions } from "../widgets/dialogs/confirm.js"; | import { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js"; | ||||||
|  |  | ||||||
| interface Layout { | interface Layout { | ||||||
|     getRootWidget: (appContext: AppContext) => RootWidget; |     getRootWidget: (appContext: AppContext) => RootWidget; | ||||||
| @@ -31,63 +31,76 @@ interface BeforeUploadListener extends Component { | |||||||
|     beforeUnloadEvent(): boolean; |     beforeUnloadEvent(): boolean; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface ApiLogMessagesData { | interface CommandData { | ||||||
|     noteId?: string; |     ntxId?: string; | ||||||
|     noteIds?: string[]; |  | ||||||
|     messages?: unknown[];     |  | ||||||
| } | } | ||||||
|  |  | ||||||
| interface FocusOnDetailData { | interface ApiLogMessagesData extends CommandData { | ||||||
|  |        | ||||||
|  | } | ||||||
|  |  | ||||||
|  | interface FocusOnDetailData extends CommandData { | ||||||
|     ntxId: string; |     ntxId: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface SearchNotesData {     | interface SearchNotesData extends CommandData {     | ||||||
|     searchString: string | undefined; |     searchString: string | undefined; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface ShowDeleteNotesDialogData {     | interface ShowDeleteNotesDialogData extends CommandData {     | ||||||
|     branchIdsToDelete: string[]; |     branchIdsToDelete: string[]; | ||||||
|     callback: (value: ResolveOptions) => void; |     callback: (value: ResolveOptions) => void; | ||||||
|     forceDeleteAllClones: boolean; |     forceDeleteAllClones: boolean; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface OpenedFileUpdatedData { | interface OpenedFileUpdatedData extends CommandData { | ||||||
|     entityType: string; |     entityType: string; | ||||||
|     entityId: string; |     entityId: string; | ||||||
|     lastModifiedMs: number; |     lastModifiedMs: number; | ||||||
|     filePath: string; |     filePath: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface FocusAndSelectTitleData { | interface FocusAndSelectTitleData extends CommandData { | ||||||
|     isNewNote: boolean; |     isNewNote: boolean; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface OpenNewNoteSplitData { | interface OpenNewNoteSplitData extends CommandData { | ||||||
|     ntxId: string; |     ntxId: string; | ||||||
|     notePath: string; |     notePath: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface ExecuteInActiveNoteDetailWidgetData { | interface ExecuteInActiveNoteDetailWidgetData extends CommandData { | ||||||
|     callback: (value: NoteDetailWidget | PromiseLike<NoteDetailWidget>) => void |     callback: (value: NoteDetailWidget | PromiseLike<NoteDetailWidget>) => void | ||||||
| } | } | ||||||
|  |  | ||||||
| interface AddTextToActiveEditorData { | interface AddTextToActiveEditorData extends CommandData { | ||||||
|     text: string;    |     text: string;    | ||||||
| } | } | ||||||
|  |  | ||||||
| export type TriggerData = | interface NoData extends CommandData { } | ||||||
|       ApiLogMessagesData        // For "api-log-messages" |  | ||||||
|     | FocusOnDetailData         // For "focusOnDetail" | type CommandMappings = { | ||||||
|     | SearchNotesData           // For "searchNotes" |     "api-log-messages": ApiLogMessagesData; | ||||||
|     | ShowDeleteNotesDialogData // For "showDeleteNotesDialog" |     focusOnDetail: FocusOnDetailData; | ||||||
|     | OpenedFileUpdatedData     // For "openedFileUpdated" |     searchNotes: SearchNotesData; | ||||||
|     | FocusAndSelectTitleData   // For "focusAndSelectTitle" |     showDeleteNotesDialog: ShowDeleteNotesDialogData; | ||||||
|     | PromptDialogOptions       // For "showPromptDialog" |     showConfirmDeleteNoteBoxWithNoteDialog: ConfirmWithTitleOptions; | ||||||
|     | ConfirmWithMessageOptions // For "showConfirmDialog" |     openedFileUpdated: OpenedFileUpdatedData; | ||||||
|     | OpenNewNoteSplitData      // For "openNewNoteSplit" |     focusAndSelectTitle: FocusAndSelectTitleData; | ||||||
|     | ExecuteInActiveNoteDetailWidgetData   // For "executeInActiveNoteDetailWidget" |     showPromptDialog: PromptDialogOptions; | ||||||
|     | AddTextToActiveEditorData // For "addTextToActiveEditor" |     showInfoDialog: ConfirmWithMessageOptions; | ||||||
| ; |     showConfirmDialog: ConfirmWithMessageOptions; | ||||||
|  |     openNewNoteSplit: OpenNewNoteSplitData; | ||||||
|  |     executeInActiveNoteDetailWidget: ExecuteInActiveNoteDetailWidgetData; | ||||||
|  |     addTextToActiveEditor: AddTextToActiveEditorData; | ||||||
|  |      | ||||||
|  |     importMarkdownInline: NoData; | ||||||
|  |     showPasswordNotSet: NoData; | ||||||
|  |     showProtectedSessionPasswordDialog: NoData; | ||||||
|  |     closeProtectedSessionPasswordDialog: NoData; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export type CommandNames = keyof CommandMappings; | ||||||
|  |  | ||||||
| class AppContext extends Component { | class AppContext extends Component { | ||||||
|  |  | ||||||
| @@ -182,11 +195,14 @@ class AppContext extends Component { | |||||||
|         this.triggerEvent('initialRenderComplete'); |         this.triggerEvent('initialRenderComplete'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     triggerEvent(name: string, data: TriggerData = {}) { |     // TODO: Update signature once all client code is updated, to use a map similar to triggerCommand. | ||||||
|  |     triggerEvent(name: string, data: unknown = {}) { | ||||||
|         return this.handleEvent(name, data); |         return this.handleEvent(name, data); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     triggerCommand(name: string, data: TriggerData = {}) { |     // TODO: Remove ignore once all commands are mapped out. | ||||||
|  |     //@ts-ignore | ||||||
|  |     triggerCommand<K extends CommandNames>(name: K, data: CommandMappings[K] = {}) { | ||||||
|         for (const executor of this.components) { |         for (const executor of this.components) { | ||||||
|             const fun = (executor as any)[`${name}Command`]; |             const fun = (executor as any)[`${name}Command`]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import dateNotesService from './date_notes.js'; | |||||||
| import searchService from './search.js'; | import searchService from './search.js'; | ||||||
| import RightPanelWidget from '../widgets/right_panel_widget.js'; | import RightPanelWidget from '../widgets/right_panel_widget.js'; | ||||||
| import ws from "./ws.js"; | import ws from "./ws.js"; | ||||||
| import appContext, { TriggerData } from "../components/app_context.js"; | import appContext from "../components/app_context.js"; | ||||||
| import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js"; | import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js"; | ||||||
| import BasicWidget from "../widgets/basic_widget.js"; | import BasicWidget from "../widgets/basic_widget.js"; | ||||||
| import SpacedUpdate from "./spaced_update.js"; | import SpacedUpdate from "./spaced_update.js"; | ||||||
| @@ -241,12 +241,12 @@ interface Api { | |||||||
|     /** |     /** | ||||||
|      * Trigger command. This is a very low-level API which should be avoided if possible. |      * Trigger command. This is a very low-level API which should be avoided if possible. | ||||||
|      */ |      */ | ||||||
|     triggerCommand(name: string, data: TriggerData): void; |     triggerCommand: typeof appContext.triggerCommand; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Trigger event. This is a very low-level API which should be avoided if possible. |      * Trigger event. This is a very low-level API which should be avoided if possible. | ||||||
|      */ |      */ | ||||||
|     triggerEvent(name: string, data: TriggerData): void; |     triggerEvent: typeof appContext.triggerEvent; | ||||||
|  |  | ||||||
|      /** |      /** | ||||||
|      * Create a note link (jQuery object) for given note. |      * Create a note link (jQuery object) for given note. | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import server from "./server.js"; | import server from "./server.js"; | ||||||
| import appContext from "../components/app_context.js"; | import appContext, { CommandNames } from "../components/app_context.js"; | ||||||
| import shortcutService from "./shortcuts.js"; | import shortcutService from "./shortcuts.js"; | ||||||
| import Component from "../components/component.js"; | import Component from "../components/component.js"; | ||||||
|  |  | ||||||
| @@ -7,7 +7,7 @@ const keyboardActionRepo: Record<string, Action> = {}; | |||||||
|  |  | ||||||
| // TODO: Deduplicate with server. | // TODO: Deduplicate with server. | ||||||
| interface Action { | interface Action { | ||||||
| 	actionName: string; | 	actionName: CommandNames; | ||||||
| 	effectiveShortcuts: string[]; | 	effectiveShortcuts: string[]; | ||||||
| 	scope: string; | 	scope: string; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ export interface ConfirmWithMessageOptions { | |||||||
|     callback: ConfirmDialogCallback; |     callback: ConfirmDialogCallback; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface ConfirmWithTitleOptions { | export interface ConfirmWithTitleOptions { | ||||||
|     title: string; |     title: string; | ||||||
|     callback: ConfirmDialogCallback;        |     callback: ConfirmDialogCallback;        | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ export interface PromptDialogOptions { | |||||||
|     message?: string; |     message?: string; | ||||||
|     defaultValue?: string; |     defaultValue?: string; | ||||||
|     shown: PromptShownDialogCallback; |     shown: PromptShownDialogCallback; | ||||||
|     callback: () => void; |     callback: (value: unknown) => void; | ||||||
| } | } | ||||||
|  |  | ||||||
| export type PromptShownDialogCallback = ((callback: ShownCallbackData) => void) | null; | export type PromptShownDialogCallback = ((callback: ShownCallbackData) => void) | null; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user