From d1e019589d782bbe967c402d231191bcfdd155c7 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Sun, 10 Nov 2024 19:56:01 -0500 Subject: [PATCH] [Electron] ComfyUI Desktop install wizard (#1503) * Basic prototype * Welcome screen animation * nit * Refactor structure * Fix mocking * Add tooltips * i18n * Add next button * nit * Stepper navigate * Extract * More i18n * More i18n * Polish MigrationPicker * Polish settings step * Add more i18n * nit * nit --- .../install/DesktopSettingsConfiguration.vue | 112 +++++++++++++++ .../install/InstallLocationPicker.vue | 115 +++++++++++++++ src/components/install/MigrationPicker.vue | 136 ++++++++++++++++++ src/components/install/WelcomeScreen.vue | 47 ------ src/i18n.ts | 45 ++++++ src/router.ts | 39 ++--- src/views/InstallView.vue | 113 ++++++++++++++- src/views/WelcomeView.vue | 69 +++++++++ vite.electron.config.mts | 46 ++++-- 9 files changed, 644 insertions(+), 78 deletions(-) create mode 100644 src/components/install/DesktopSettingsConfiguration.vue create mode 100644 src/components/install/InstallLocationPicker.vue create mode 100644 src/components/install/MigrationPicker.vue delete mode 100644 src/components/install/WelcomeScreen.vue create mode 100644 src/views/WelcomeView.vue diff --git a/src/components/install/DesktopSettingsConfiguration.vue b/src/components/install/DesktopSettingsConfiguration.vue new file mode 100644 index 000000000..48f792dbd --- /dev/null +++ b/src/components/install/DesktopSettingsConfiguration.vue @@ -0,0 +1,112 @@ + + + diff --git a/src/components/install/InstallLocationPicker.vue b/src/components/install/InstallLocationPicker.vue new file mode 100644 index 000000000..2a8402714 --- /dev/null +++ b/src/components/install/InstallLocationPicker.vue @@ -0,0 +1,115 @@ + + + diff --git a/src/components/install/MigrationPicker.vue b/src/components/install/MigrationPicker.vue new file mode 100644 index 000000000..609de6a48 --- /dev/null +++ b/src/components/install/MigrationPicker.vue @@ -0,0 +1,136 @@ + + + diff --git a/src/components/install/WelcomeScreen.vue b/src/components/install/WelcomeScreen.vue deleted file mode 100644 index 08a0f637d..000000000 --- a/src/components/install/WelcomeScreen.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/src/i18n.ts b/src/i18n.ts index 6f281bb7c..0b1fe9dd0 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -2,6 +2,51 @@ import { createI18n } from 'vue-i18n' const messages = { en: { + install: { + installLocation: 'Install Location', + migration: 'Migration', + desktopSettings: 'Desktop Settings', + chooseInstallationLocation: 'Choose Installation Location', + systemLocations: 'System Locations', + failedToSelectDirectory: 'Failed to select directory', + pathValidationFailed: 'Failed to validate path', + installLocationDescription: + "Select the directory for ComfyUI's user data. A python environment will be installed to the selected location. Please make sure the selected disk has enough space (~5GB) left.", + installLocationTooltip: + "ComfyUI's user data directory. Stores:\n- Python Environment\n- Models\n- Custom nodes\n", + appDataLocationTooltip: + "ComfyUI's app data directory. Stores:\n- Logs\n- Server configs", + appPathLocationTooltip: + "ComfyUI's app asset directory. Stores the ComfyUI code and assets", + migrateFromExistingInstallation: 'Migrate from Existing Installation', + migrationSourcePathDescription: + 'If you have an existing ComfyUI installation, we can copy/link your existing user files and models to the new installation.', + selectItemsToMigrate: 'Select Items to Migrate', + migrationOptional: + "Migration is optional. If you don't have an existing installation, you can skip this step.", + desktopAppSettings: 'Desktop App Settings', + desktopAppSettingsDescription: + 'Configure how ComfyUI behaves on your desktop. You can change these settings later.', + settings: { + autoUpdate: 'Automatic Updates', + allowMetrics: 'Usage Analytics', + autoUpdateDescription: + "Automatically download and install updates when they become available. You'll always be notified before updates are installed.", + allowMetricsDescription: + 'Help improve ComfyUI by sending anonymous usage data. No personal information or workflow content will be collected.', + learnMoreAboutData: 'Learn more about data collection', + dataCollectionDialog: { + title: 'About Data Collection', + whatWeCollect: 'What we collect:', + whatWeDoNotCollect: "What we don't collect:", + errorReports: 'Error reports', + systemInfo: 'Operating system and app version', + personalInformation: 'Personal information', + workflowContent: 'Workflow content', + fileSystemInformation: 'File system information' + } + } + }, download: 'Download', loadAllFolders: 'Load All Folders', refresh: 'Refresh', diff --git a/src/router.ts b/src/router.ts index cfbde0b03..52868c4ab 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,12 +1,25 @@ import { createRouter, createWebHashHistory, - createWebHistory + createWebHistory, + NavigationGuardNext, + RouteLocationNormalized } from 'vue-router' import LayoutDefault from '@/views/layouts/LayoutDefault.vue' import { isElectron } from './utils/envUtil' const isFileProtocol = () => window.location.protocol === 'file:' +const guardElectronAccess = ( + to: RouteLocationNormalized, + from: RouteLocationNormalized, + next: NavigationGuardNext +) => { + if (isElectron()) { + next() + } else { + next('/') + } +} const router = createRouter({ history: isFileProtocol() ? createWebHashHistory() : createWebHistory(), @@ -24,27 +37,19 @@ const router = createRouter({ path: 'server-start', name: 'ServerStartView', component: () => import('@/views/ServerStartView.vue'), - beforeEnter: async (to, from, next) => { - // Only allow access to this page in electron environment - if (isElectron()) { - next() - } else { - next('/') - } - } + beforeEnter: guardElectronAccess }, { path: 'install', name: 'InstallView', component: () => import('@/views/InstallView.vue'), - beforeEnter: async (to, from, next) => { - // Only allow access to this page in electron environment - if (isElectron()) { - next() - } else { - next('/') - } - } + beforeEnter: guardElectronAccess + }, + { + path: 'welcome', + name: 'WelcomeView', + component: () => import('@/views/WelcomeView.vue'), + beforeEnter: guardElectronAccess } ] } diff --git a/src/views/InstallView.vue b/src/views/InstallView.vue index 03b0df275..5d70d846e 100644 --- a/src/views/InstallView.vue +++ b/src/views/InstallView.vue @@ -1,11 +1,118 @@ + + diff --git a/src/views/WelcomeView.vue b/src/views/WelcomeView.vue new file mode 100644 index 000000000..793fbb828 --- /dev/null +++ b/src/views/WelcomeView.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/vite.electron.config.mts b/vite.electron.config.mts index f8a64dc29..f97dc383f 100644 --- a/vite.electron.config.mts +++ b/vite.electron.config.mts @@ -2,16 +2,6 @@ import { defineConfig, Plugin } from 'vite' import { mergeConfig } from 'vite' import type { UserConfig } from 'vitest/config' import baseConfig from './vite.config.mts' -import type { ElectronAPI } from '@comfyorg/comfyui-electron-types' - -const electronAPIMock: Partial = { - sendReady: () => {}, - onShowSelectDirectory: () => {}, - onFirstTimeSetupComplete: () => {}, - onProgressUpdate: () => {}, - onLogMessage: () => {}, - isFirstTimeSetup: () => Promise.resolve(true) -} const mockElectronAPI: Plugin = { name: 'mock-electron-api', @@ -19,7 +9,41 @@ const mockElectronAPI: Plugin = { return [ { tag: 'script', - children: `window.electronAPI = ${JSON.stringify(electronAPIMock)};` + children: `window.electronAPI = { + sendReady: () => {}, + onShowSelectDirectory: () => {}, + onFirstTimeSetupComplete: () => {}, + onProgressUpdate: () => {}, + onLogMessage: () => {}, + isFirstTimeSetup: () => Promise.resolve(true), + getSystemPaths: () => + Promise.resolve({ + appData: 'C:/Users/username/AppData/Roaming', + appPath: 'C:/Program Files/comfyui-electron/resources/app', + defaultInstallPath: 'C:/Users/username/comfyui-electron' + }), + validateInstallPath: (path) => { + if (path === 'bad') { + return { isValid: false, error: 'Bad path!' } + } + return { isValid: true } + }, + migrationItems: () => + Promise.resolve([ + { + id: 'user_files', + label: 'User Files', + description: 'Settings and user-created workflows' + } + ]), + validateComfyUISource: (path) => { + if (path === 'bad') { + return { isValid: false, error: 'Bad path!' } + } + return { isValid: true } + }, + showDirectoryPicker: () => Promise.resolve('C:/Users/username/comfyui-electron/1') + };` } ] }