Skip to content

Commit c39a03f

Browse files
authored
[Hotfix] Cherry-pick desktop dialogs framework to core/1.27 (#5634)
## Summary Cherry-picked PR #5605 (Add desktop dialogs framework) to core/1.27 branch for hotfix release. ## Cherry-picked commits - 09e7d10: Add desktop dialogs framework (#5605) ## Changes - Data-driven dialog structure in `desktopDialogs.ts` - Dynamic dialog view component with i18n support - Button action types: openUrl, close, cancel - Button severity levels for styling (primary, secondary, danger, warn) - Fallback invalid dialog for error handling - i18n collection script updated for dialog strings ## Testing - Typecheck passed ✓ - Cherry-pick applied cleanly without conflicts ## Impact This adds the desktop dialog framework feature to the stable 1.27 branch, allowing desktop applications to display standardized dialogs. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5634-Hotfix-Cherry-pick-desktop-dialogs-framework-to-core-1-27-2726d73d3650811188e7f7e58766d52f) by [Unito](https://www.unito.io)
1 parent 045232a commit c39a03f

File tree

5 files changed

+177
-1
lines changed

5 files changed

+177
-1
lines changed

scripts/collect-i18n-general.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as fs from 'fs'
22

33
import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage'
44
import { CORE_MENU_COMMANDS } from '../src/constants/coreMenuCommands'
5+
import { DESKTOP_DIALOGS } from '../src/constants/desktopDialogs'
56
import { SERVER_CONFIG_ITEMS } from '../src/constants/serverConfig'
67
import type { FormItem, SettingParams } from '../src/platform/settings/types'
78
import type { ComfyCommandImpl } from '../src/stores/commandStore'
@@ -131,6 +132,23 @@ test('collect-i18n-general', async ({ comfyPage }) => {
131132
])
132133
)
133134

135+
// Desktop Dialogs
136+
const allDesktopDialogsLocale = Object.fromEntries(
137+
Object.values(DESKTOP_DIALOGS).map((dialog) => [
138+
normalizeI18nKey(dialog.id),
139+
{
140+
title: dialog.title,
141+
message: dialog.message,
142+
buttons: Object.fromEntries(
143+
dialog.buttons.map((button) => [
144+
normalizeI18nKey(button.label),
145+
button.label
146+
])
147+
)
148+
}
149+
])
150+
)
151+
134152
fs.writeFileSync(
135153
localePath,
136154
JSON.stringify(
@@ -144,7 +162,8 @@ test('collect-i18n-general', async ({ comfyPage }) => {
144162
...allSettingCategoriesLocale
145163
},
146164
serverConfigItems: allServerConfigsLocale,
147-
serverConfigCategories: allServerConfigCategoriesLocale
165+
serverConfigCategories: allServerConfigCategoriesLocale,
166+
desktopDialogs: allDesktopDialogsLocale
148167
},
149168
null,
150169
2

src/assets/css/style.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
--color-charcoal-700: #202121;
6767
--color-charcoal-800: #171718;
6868

69+
--color-neutral-550: #636363;
70+
6971
--color-stone-100: #444444;
7072
--color-stone-200: #828282;
7173
--color-stone-300: #bbbbbb;
@@ -103,6 +105,10 @@
103105
--color-danger-100: #c02323;
104106
--color-danger-200: #d62952;
105107

108+
--color-coral-red-600: #973a40;
109+
--color-coral-red-500: #c53f49;
110+
--color-coral-red-400: #dd424e;
111+
106112
--color-bypass: #6a246a;
107113
--color-error: #962a2a;
108114

src/constants/desktopDialogs.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
export interface DialogAction {
2+
readonly label: string
3+
readonly action: 'openUrl' | 'close' | 'cancel'
4+
readonly url?: string
5+
readonly severity?: 'danger' | 'primary' | 'secondary' | 'warn'
6+
readonly returnValue: string
7+
}
8+
9+
interface DesktopDialog {
10+
readonly title: string
11+
readonly message: string
12+
readonly buttons: DialogAction[]
13+
}
14+
15+
export const DESKTOP_DIALOGS = {
16+
/** Shown when a corrupt venv is detected. */
17+
reinstallVenv: {
18+
title: 'Reinstall ComfyUI (Fresh Start)?',
19+
message: `Sorry, we can't launch ComfyUI because some installed packages aren't compatible.
20+
21+
Click Reinstall to restore ComfyUI and get back up and running.
22+
23+
Please note: if you've added custom nodes, you'll need to reinstall them after this process.`,
24+
buttons: [
25+
{
26+
label: 'Learn More',
27+
action: 'openUrl',
28+
url: 'https://docs.comfy.org',
29+
returnValue: 'openDocs'
30+
},
31+
{
32+
label: 'Reinstall',
33+
action: 'close',
34+
severity: 'danger',
35+
returnValue: 'resetVenv'
36+
}
37+
]
38+
},
39+
/** A dialog that is shown when an invalid dialog ID is provided. */
40+
invalidDialog: {
41+
title: 'Invalid Dialog',
42+
message: `Invalid dialog ID was provided.`,
43+
buttons: [
44+
{
45+
label: 'Close',
46+
action: 'cancel',
47+
returnValue: 'cancel'
48+
}
49+
]
50+
}
51+
} as const satisfies { [K: string]: DesktopDialog }
52+
53+
/** The ID of a desktop dialog. */
54+
type DesktopDialogId = keyof typeof DESKTOP_DIALOGS
55+
56+
/**
57+
* Checks if {@link id} is a valid dialog ID.
58+
* @param id The string to check
59+
* @returns `true` if the ID is a valid dialog ID, otherwise `false`
60+
*/
61+
function isDialogId(id: unknown): id is DesktopDialogId {
62+
return typeof id === 'string' && id in DESKTOP_DIALOGS
63+
}
64+
65+
/**
66+
* Gets the dialog with the given ID.
67+
* @param dialogId The ID of the dialog to get
68+
* @returns The dialog with the given ID
69+
*/
70+
export function getDialog(
71+
dialogId: string | string[]
72+
): DesktopDialog & { id: DesktopDialogId } {
73+
const id = isDialogId(dialogId) ? dialogId : 'invalidDialog'
74+
return { id, ...structuredClone(DESKTOP_DIALOGS[id]) }
75+
}

src/router.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ const router = createRouter({
116116
name: 'DesktopUpdateView',
117117
component: () => import('@/views/DesktopUpdateView.vue'),
118118
beforeEnter: guardElectronAccess
119+
},
120+
{
121+
path: 'desktop-dialog/:dialogId',
122+
name: 'DesktopDialogView',
123+
component: () => import('@/views/DesktopDialogView.vue'),
124+
beforeEnter: guardElectronAccess
119125
}
120126
]
121127
}

src/views/DesktopDialogView.vue

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<template>
2+
<div class="w-full h-full flex flex-col rounded-lg p-6 justify-between">
3+
<h1 class="font-inter font-semibold text-xl m-0 italic">
4+
{{ t(`desktopDialogs.${id}.title`, title) }}
5+
</h1>
6+
<p class="whitespace-pre-wrap">
7+
{{ t(`desktopDialogs.${id}.message`, message) }}
8+
</p>
9+
<div class="flex w-full gap-2">
10+
<Button
11+
v-for="button in buttons"
12+
:key="button.label"
13+
class="rounded-lg first:mr-auto"
14+
:label="
15+
t(
16+
`desktopDialogs.${id}.buttons.${normalizeI18nKey(button.label)}`,
17+
button.label
18+
)
19+
"
20+
:severity="button.severity ?? 'secondary'"
21+
@click="handleButtonClick(button)"
22+
/>
23+
</div>
24+
</div>
25+
</template>
26+
27+
<script setup lang="ts">
28+
import Button from 'primevue/button'
29+
import { useRoute } from 'vue-router'
30+
31+
import { type DialogAction, getDialog } from '@/constants/desktopDialogs'
32+
import { t } from '@/i18n'
33+
import { electronAPI } from '@/utils/envUtil'
34+
import { normalizeI18nKey } from '@/utils/formatUtil'
35+
36+
const route = useRoute()
37+
const { id, title, message, buttons } = getDialog(route.params.dialogId)
38+
39+
const handleButtonClick = async (button: DialogAction) => {
40+
await electronAPI().Dialog.clickButton(button.returnValue)
41+
}
42+
</script>
43+
44+
<style scoped>
45+
@reference '../assets/css/style.css';
46+
47+
.p-button-secondary {
48+
@apply text-white border-none bg-neutral-600;
49+
}
50+
51+
.p-button-secondary:hover {
52+
@apply bg-neutral-550;
53+
}
54+
55+
.p-button-secondary:active {
56+
@apply bg-neutral-500;
57+
}
58+
59+
.p-button-danger {
60+
@apply bg-coral-red-600;
61+
}
62+
63+
.p-button-danger:hover {
64+
@apply bg-coral-red-500;
65+
}
66+
67+
.p-button-danger:active {
68+
@apply bg-coral-red-400;
69+
}
70+
</style>

0 commit comments

Comments
 (0)