diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index 09b411011..b4c3bf0e2 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -17,7 +17,7 @@ import { t, initLocale } from "../services/i18n.js"; import NoteDetailWidget from "../widgets/note_detail.js"; import { ResolveOptions } from "../widgets/dialogs/delete_notes.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 { getRootWidget: (appContext: AppContext) => RootWidget; @@ -31,63 +31,76 @@ interface BeforeUploadListener extends Component { beforeUnloadEvent(): boolean; } -interface ApiLogMessagesData { - noteId?: string; - noteIds?: string[]; - messages?: unknown[]; +interface CommandData { + ntxId?: string; } -interface FocusOnDetailData { +interface ApiLogMessagesData extends CommandData { + +} + +interface FocusOnDetailData extends CommandData { ntxId: string; } -interface SearchNotesData { +interface SearchNotesData extends CommandData { searchString: string | undefined; } -interface ShowDeleteNotesDialogData { +interface ShowDeleteNotesDialogData extends CommandData { branchIdsToDelete: string[]; callback: (value: ResolveOptions) => void; forceDeleteAllClones: boolean; } -interface OpenedFileUpdatedData { +interface OpenedFileUpdatedData extends CommandData { entityType: string; entityId: string; lastModifiedMs: number; filePath: string; } -interface FocusAndSelectTitleData { +interface FocusAndSelectTitleData extends CommandData { isNewNote: boolean; } -interface OpenNewNoteSplitData { +interface OpenNewNoteSplitData extends CommandData { ntxId: string; notePath: string; } -interface ExecuteInActiveNoteDetailWidgetData { +interface ExecuteInActiveNoteDetailWidgetData extends CommandData { callback: (value: NoteDetailWidget | PromiseLike) => void } -interface AddTextToActiveEditorData { +interface AddTextToActiveEditorData extends CommandData { text: string; } -export type TriggerData = - ApiLogMessagesData // For "api-log-messages" - | FocusOnDetailData // For "focusOnDetail" - | SearchNotesData // For "searchNotes" - | ShowDeleteNotesDialogData // For "showDeleteNotesDialog" - | OpenedFileUpdatedData // For "openedFileUpdated" - | FocusAndSelectTitleData // For "focusAndSelectTitle" - | PromptDialogOptions // For "showPromptDialog" - | ConfirmWithMessageOptions // For "showConfirmDialog" - | OpenNewNoteSplitData // For "openNewNoteSplit" - | ExecuteInActiveNoteDetailWidgetData // For "executeInActiveNoteDetailWidget" - | AddTextToActiveEditorData // For "addTextToActiveEditor" -; +interface NoData extends CommandData { } + +type CommandMappings = { + "api-log-messages": ApiLogMessagesData; + focusOnDetail: FocusOnDetailData; + searchNotes: SearchNotesData; + showDeleteNotesDialog: ShowDeleteNotesDialogData; + showConfirmDeleteNoteBoxWithNoteDialog: ConfirmWithTitleOptions; + openedFileUpdated: OpenedFileUpdatedData; + focusAndSelectTitle: FocusAndSelectTitleData; + showPromptDialog: PromptDialogOptions; + 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 { @@ -182,11 +195,14 @@ class AppContext extends Component { 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); } - triggerCommand(name: string, data: TriggerData = {}) { + // TODO: Remove ignore once all commands are mapped out. + //@ts-ignore + triggerCommand(name: K, data: CommandMappings[K] = {}) { for (const executor of this.components) { const fun = (executor as any)[`${name}Command`]; diff --git a/src/public/app/services/frontend_script_api.ts b/src/public/app/services/frontend_script_api.ts index 6a3c61c49..1cbab4a0f 100644 --- a/src/public/app/services/frontend_script_api.ts +++ b/src/public/app/services/frontend_script_api.ts @@ -9,7 +9,7 @@ import dateNotesService from './date_notes.js'; import searchService from './search.js'; import RightPanelWidget from '../widgets/right_panel_widget.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 BasicWidget from "../widgets/basic_widget.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. */ - 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. */ - triggerEvent(name: string, data: TriggerData): void; + triggerEvent: typeof appContext.triggerEvent; /** * Create a note link (jQuery object) for given note. diff --git a/src/public/app/services/keyboard_actions.ts b/src/public/app/services/keyboard_actions.ts index 786cf2605..630ec03a9 100644 --- a/src/public/app/services/keyboard_actions.ts +++ b/src/public/app/services/keyboard_actions.ts @@ -1,5 +1,5 @@ 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 Component from "../components/component.js"; @@ -7,7 +7,7 @@ const keyboardActionRepo: Record = {}; // TODO: Deduplicate with server. interface Action { - actionName: string; + actionName: CommandNames; effectiveShortcuts: string[]; scope: string; } diff --git a/src/public/app/widgets/dialogs/confirm.ts b/src/public/app/widgets/dialogs/confirm.ts index 5054eb70d..9ccda11ee 100644 --- a/src/public/app/widgets/dialogs/confirm.ts +++ b/src/public/app/widgets/dialogs/confirm.ts @@ -41,7 +41,7 @@ export interface ConfirmWithMessageOptions { callback: ConfirmDialogCallback; } -interface ConfirmWithTitleOptions { +export interface ConfirmWithTitleOptions { title: string; callback: ConfirmDialogCallback; } diff --git a/src/public/app/widgets/dialogs/prompt.ts b/src/public/app/widgets/dialogs/prompt.ts index 8a470860c..7bdc23956 100644 --- a/src/public/app/widgets/dialogs/prompt.ts +++ b/src/public/app/widgets/dialogs/prompt.ts @@ -32,7 +32,7 @@ export interface PromptDialogOptions { message?: string; defaultValue?: string; shown: PromptShownDialogCallback; - callback: () => void; + callback: (value: unknown) => void; } export type PromptShownDialogCallback = ((callback: ShownCallbackData) => void) | null;