diff --git a/frontend/src/components/floating-menus/DialogModal.svelte b/frontend/src/components/floating-menus/DialogModal.svelte index 29e2aedc..9a13fab7 100644 --- a/frontend/src/components/floating-menus/DialogModal.svelte +++ b/frontend/src/components/floating-menus/DialogModal.svelte @@ -13,12 +13,8 @@ let self: FloatingMenu | undefined; - export function dismiss() { - dialog.dismissDialog(); - } - onMount(() => { - // Focus the first button in the popup + // Focus the button which is marked as emphasized, or otherwise the first button, in the popup const emphasizedOrFirstButton = (self?.div()?.querySelector("[data-emphasized]") || self?.div()?.querySelector("[data-text-button]") || undefined) as HTMLButtonElement | undefined; emphasizedOrFirstButton?.focus(); }); @@ -34,9 +30,9 @@ {#if $dialog.widgets.layout.length > 0} {/if} - {#if ($dialog.jsCallbackBasedButtons?.length || NaN) > 0} + {#if ($dialog.crashDialogButtons?.length || NaN) > 0} - {#each $dialog.jsCallbackBasedButtons || [] as button, index (index)} + {#each $dialog.crashDialogButtons || [] as button, index (index)} button.callback?.()} {...button.props} /> {/each} diff --git a/frontend/src/io-managers/panic.ts b/frontend/src/io-managers/panic.ts index a2b147d4..60a2f350 100644 --- a/frontend/src/io-managers/panic.ts +++ b/frontend/src/io-managers/panic.ts @@ -19,12 +19,12 @@ export function createPanicManager(editor: Editor, dialogState: DialogState): vo // eslint-disable-next-line no-console console.error(panicDetails); - const panicDialog = preparePanicDialog(displayDialogPanic.header, displayDialogPanic.description, panicDetails); - dialogState.createPanicDialog(...panicDialog); + const crashDialog = prepareCrashDialog(displayDialogPanic.header, displayDialogPanic.description, panicDetails); + dialogState.createCrashDialog(...crashDialog); }); } -function preparePanicDialog(header: string, details: string, panicDetails: string): [IconName, WidgetLayout, TextButtonWidget[]] { +function prepareCrashDialog(header: string, details: string, panicDetails: string): [IconName, WidgetLayout, TextButtonWidget[]] { const headerLabel: TextLabel = { kind: "TextLabel", value: header, disabled: false, bold: true, italic: false, tableAlign: false, minWidth: 0, multiline: false, tooltip: "" }; const detailsLabel: TextLabel = { kind: "TextLabel", value: details, disabled: false, bold: false, italic: false, tableAlign: false, minWidth: 0, multiline: true, tooltip: "" }; @@ -52,9 +52,9 @@ function preparePanicDialog(header: string, details: string, panicDetails: strin }, props: { kind: "TextButton", label: "Clear Saved Data", emphasized: false, minWidth: 96 }, }; - const jsCallbackBasedButtons = [reloadButton, copyErrorLogButton, reportOnGithubButton, clearPersistedDataButton]; + const crashDialogButtons = [reloadButton, copyErrorLogButton, reportOnGithubButton, clearPersistedDataButton]; - return ["Warning", widgets, jsCallbackBasedButtons]; + return ["Warning", widgets, crashDialogButtons]; } function githubUrl(panicDetails: string): string { diff --git a/frontend/src/state-providers/dialog.ts b/frontend/src/state-providers/dialog.ts index 137c9fd1..d4de921d 100644 --- a/frontend/src/state-providers/dialog.ts +++ b/frontend/src/state-providers/dialog.ts @@ -11,24 +11,27 @@ export function createDialogState(editor: Editor) { icon: "" as IconName, widgets: defaultWidgetLayout(), // Special case for the crash dialog because we cannot handle button widget callbacks from Rust once the editor instance has panicked - jsCallbackBasedButtons: undefined as undefined | TextButtonWidget[], + crashDialogButtons: undefined as undefined | TextButtonWidget[], }); function dismissDialog(): void { + update((state) => { - state.visible = false; + // Disallow dismissing the crash dialog since it can confuse users why the app stopped responding if they dismiss it without realizing what it means + if (!state.crashDialogButtons) state.visible = false; + return state; }); } - // Creates a panic dialog from JS. + // Creates a crash dialog from JS once the editor has panicked. // Normal dialogs are created in the Rust backend, but for the crash dialog, the editor instance has panicked so it cannot respond to widget callbacks. - function createPanicDialog(icon: IconName, widgets: WidgetLayout, jsCallbackBasedButtons: TextButtonWidget[]): void { + function createCrashDialog(icon: IconName, widgets: WidgetLayout, crashDialogButtons: TextButtonWidget[]): void { update((state) => { state.visible = true; state.icon = icon; state.widgets = widgets; - state.jsCallbackBasedButtons = jsCallbackBasedButtons; + state.crashDialogButtons = crashDialogButtons; return state; }); } @@ -45,7 +48,7 @@ export function createDialogState(editor: Editor) { update((state) => { patchWidgetLayout(state.widgets, updateDialogDetails); - state.jsCallbackBasedButtons = undefined; + state.crashDialogButtons = undefined; return state; }); }); @@ -54,7 +57,7 @@ export function createDialogState(editor: Editor) { return { subscribe, dismissDialog, - createPanicDialog, + createCrashDialog: createCrashDialog, }; } export type DialogState = ReturnType;