From 81320e2c7290e665cebfd18dddfb00e3bfdc35ee Mon Sep 17 00:00:00 2001 From: Robin Huang Date: Thu, 5 Dec 2024 13:20:45 -0800 Subject: [PATCH] Revert "Settings store (#362)" (#440) This reverts commit 54f1a96cc714ff8441a6f4f52981fa0c8a441fa9. --- scripts/resetInstall.js | 54 ++++---------- src/install/installationValidator.ts | 58 --------------- src/main-process/appWindow.ts | 8 +-- src/main-process/comfyDesktopApp.ts | 54 +++----------- src/main.ts | 17 +---- src/store/desktopConfig.ts | 104 --------------------------- src/store/index.ts | 14 +--- 7 files changed, 27 insertions(+), 282 deletions(-) delete mode 100644 src/install/installationValidator.ts delete mode 100644 src/store/desktopConfig.ts diff --git a/scripts/resetInstall.js b/scripts/resetInstall.js index 4d82b0e3..4d25605c 100644 --- a/scripts/resetInstall.js +++ b/scripts/resetInstall.js @@ -6,16 +6,15 @@ const readline = require('readline'); /** * Get the path to the extra_models_config.yaml file based on the platform. - * @param {string} filename The name of the file to find in the user data folder * @returns The path to the extra_models_config.yaml file. */ -function getConfigPath(filename) { +function getConfigPath() { switch (process.platform) { case 'darwin': // macOS - return path.join(os.homedir(), 'Library', 'Application Support', 'ComfyUI', filename); + return path.join(os.homedir(), 'Library', 'Application Support', 'ComfyUI', 'extra_models_config.yaml'); case 'win32': // Windows - return path.join(process.env.APPDATA, 'ComfyUI', filename); + return path.join(process.env.APPDATA, 'ComfyUI', 'extra_models_config.yaml'); default: console.log('Platform not supported for this operation'); process.exit(1); @@ -38,54 +37,27 @@ async function askForConfirmation(question) { async function main() { try { - const configPath = getConfigPath('config.json'); - const windowStorePath = getConfigPath('window.json'); - const modelsConfigPath = getConfigPath('extra_models_config.yaml'); - let desktopBasePath = null; + const configPath = getConfigPath(); let basePath = null; - // Read basePath from desktop config + // Read base_path before deleting the config file if (fs.existsSync(configPath)) { const configContent = fs.readFileSync(configPath, 'utf8'); - const parsed = JSON.parse(configContent); - desktopBasePath = parsed?.basePath; - } - - // Read base_path before deleting the config file - if (fs.existsSync(modelsConfigPath)) { - const configContent = fs.readFileSync(modelsConfigPath, 'utf8'); const config = yaml.parse(configContent); basePath = config?.comfyui?.base_path; + + // Delete config file + fs.unlinkSync(configPath); + console.log(`Successfully removed ${configPath}`); } else { console.log('Config file not found, nothing to remove'); } - // Delete all config files - for (const file of [configPath, windowStorePath, modelsConfigPath]) { - if (fs.existsSync(file)) { - fs.unlinkSync(file); - console.log(`Successfully removed ${file}`); - } - } - - // If config.json basePath exists, ask user if they want to delete it - if (desktopBasePath && fs.existsSync(desktopBasePath)) { - console.log(`Found ComfyUI installation directory at: ${desktopBasePath}`); - const shouldDelete = await askForConfirmation('Would you like to delete this directory as well?'); - - if (shouldDelete) { - fs.rmSync(desktopBasePath, { recursive: true, force: true }); - console.log(`Successfully removed ComfyUI directory at ${desktopBasePath}`); - } else { - console.log('Skipping ComfyUI directory deletion'); - } - } - - // If base_path exists and does not match basePath, ask user if they want to delete it - if (basePath && basePath !== desktopBasePath && fs.existsSync(basePath)) { - console.log(`Found ComfyUI models directory at: ${basePath}`); + // If base_path exists, ask user if they want to delete it + if (basePath && fs.existsSync(basePath)) { + console.log(`Found ComfyUI installation directory at: ${basePath}`); const shouldDelete = await askForConfirmation('Would you like to delete this directory as well?'); - + if (shouldDelete) { fs.rmSync(basePath, { recursive: true, force: true }); console.log(`Successfully removed ComfyUI directory at ${basePath}`); diff --git a/src/install/installationValidator.ts b/src/install/installationValidator.ts deleted file mode 100644 index b92ebabb..00000000 --- a/src/install/installationValidator.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { app, dialog, shell } from 'electron'; -import fs from 'fs/promises'; -import log from 'electron-log/main'; -import path from 'node:path'; - -export class InstallationValidator { - /** - * Shows a dialog box with an option to open the problematic file in the native shell file viewer. - * @param options The options paramter of {@link dialog.showMessageBox}, filled with defaults for invalid config - * @returns - */ - static async showInvalidFileAndQuit(file: string, options: Electron.MessageBoxOptions): Promise { - const defaults: Electron.MessageBoxOptions = { - // Message must be set by caller. - message: `Was unable to read the file shown below. It could be missing, inaccessible, or corrupt.\n\n${file}`, - title: 'Invalid file', - type: 'error', - buttons: ['Locate the &file (then quit)', '&Quit'], - defaultId: 0, - cancelId: 1, - normalizeAccessKeys: true, - }; - const opt = Object.assign(defaults, options); - - const result = await dialog.showMessageBox(opt); - - // Try show the file in file manager - if (result.response === 0) { - try { - const parsed = path.parse(file); - log.debug(`Attempting to open containing directory: ${parsed.dir}`); - await fs.access(file); - shell.showItemInFolder(file); - } catch (error) { - log.warn(`Could not access file whilst attempting to exit gracefully after a critical error.`, file); - try { - // Failed - try the parent dir - const parsed = path.parse(file); - await fs.access(parsed.dir); - shell.openPath(parsed.dir); - } catch (error) { - // Nothing works. Log, notify, quit. - log.error( - `Could not read directory containing file, whilst attempting to exit gracefully after a critical error.` - ); - dialog.showErrorBox( - 'Unable to fine file', - `Unable to find the file. Please navigate to it manually:\n\n${file}` - ); - } - } - } - - app.quit(); - // Wait patiently for graceful termination. - await new Promise(() => {}); - } -} diff --git a/src/main-process/appWindow.ts b/src/main-process/appWindow.ts index 2d1089bc..380d33d5 100644 --- a/src/main-process/appWindow.ts +++ b/src/main-process/appWindow.ts @@ -1,7 +1,7 @@ import { BrowserWindow, screen, app, shell, ipcMain, Tray, Menu, dialog, MenuItem } from 'electron'; import path from 'node:path'; import Store from 'electron-store'; -import { AppWindowSettings } from '../store'; +import { StoreType } from '../store'; import log from 'electron-log/main'; import { IPC_CHANNELS, ProgressStatus, ServerArgs } from '../constants'; import { getAppResourcesPath } from '../install/resourcePaths'; @@ -12,7 +12,7 @@ import { getAppResourcesPath } from '../install/resourcePaths'; */ export class AppWindow { private window: BrowserWindow; - private store: Store; + private store: Store; private messageQueue: Array<{ channel: string; data: any }> = []; private rendererReady: boolean = false; @@ -142,10 +142,10 @@ export class AppWindow { * There are edge cases where this might not be a catastrophic failure, but inability * to write to our own datastore may result in unexpected user data loss. */ - private loadWindowStore(): Store { + private loadWindowStore(): Store { try { // Separate file for non-critical convenience settings - just resets itself if invalid - return new Store({ + return new Store({ clearInvalidConfig: true, name: 'window', }); diff --git a/src/main-process/comfyDesktopApp.ts b/src/main-process/comfyDesktopApp.ts index dda44ac9..adf00c16 100644 --- a/src/main-process/comfyDesktopApp.ts +++ b/src/main-process/comfyDesktopApp.ts @@ -16,10 +16,8 @@ import { DownloadManager } from '../models/DownloadManager'; import { VirtualEnvironment } from '../virtualEnvironment'; import { InstallWizard } from '../install/installWizard'; import { Terminal } from '../terminal'; -import { DesktopConfig } from '../store/desktopConfig'; -import { InstallationValidator } from '../install/installationValidator'; import { restoreCustomNodes } from '../services/backup'; - +import Store from 'electron-store'; export class ComfyDesktopApp { public comfyServer: ComfyServer | null = null; private terminal: Terminal | null = null; // Only created after server starts. @@ -147,11 +145,7 @@ export class ComfyDesktopApp { return new Promise((resolve) => { ipcMain.on(IPC_CHANNELS.INSTALL_COMFYUI, async (event, installOptions: InstallOptions) => { const installWizard = new InstallWizard(installOptions); - const { store } = DesktopConfig; - store.set('basePath', installWizard.basePath); - await installWizard.install(); - store.set('installState', 'installed'); resolve(installWizard.basePath); }); }); @@ -188,7 +182,7 @@ export class ComfyDesktopApp { this.appWindow.send(IPC_CHANNELS.LOG_MESSAGE, data); }, }); - const { store } = DesktopConfig; + const store = new Store(); if (!store.get('Comfy-Desktop.RestoredCustomNodes', false)) { try { await restoreCustomNodes(virtualEnvironment, this.appWindow); @@ -206,48 +200,16 @@ export class ComfyDesktopApp { } static async create(appWindow: AppWindow): Promise { - const { store } = DesktopConfig; - // Migrate settings from old version if required - const installState = store.get('installState') ?? (await ComfyDesktopApp.migrateInstallState()); - - // Fresh install - const basePath = - installState === undefined ? await ComfyDesktopApp.install(appWindow) : await ComfyDesktopApp.loadBasePath(); + const basePath = ComfyServerConfig.exists() + ? await ComfyServerConfig.readBasePathFromConfig(ComfyServerConfig.configPath) + : await this.install(appWindow); + if (!basePath) { + throw new Error(`Base path not found! ${ComfyServerConfig.configPath} is probably corrupted.`); + } return new ComfyDesktopApp(basePath, new ComfySettings(basePath), appWindow); } - /** - * Sets the ugpraded state if this is a version upgrade from <= 0.3.18 - * @returns 'upgraded' if this install has just been upgraded, or undefined for a fresh install - */ - static async migrateInstallState(): Promise { - // Fresh install - if (!ComfyServerConfig.exists()) return undefined; - - // Upgrade - const basePath = await ComfyDesktopApp.loadBasePath(); - - // Migrate config - const { store } = DesktopConfig; - const upgraded = 'upgraded'; - store.set('installState', upgraded); - store.set('basePath', basePath); - return upgraded; - } - - /** Loads the base_path value from the YAML config. Quits in the event of failure. */ - static async loadBasePath(): Promise { - const basePath = await ComfyServerConfig.readBasePathFromConfig(ComfyServerConfig.configPath); - if (basePath) return basePath; - - log.error(`Base path not found! ${ComfyServerConfig.configPath} is probably corrupted.`); - await InstallationValidator.showInvalidFileAndQuit(ComfyServerConfig.configPath, { - message: `Base path not found! This file is probably corrupt:\n\n${ComfyServerConfig.configPath}`, - }); - throw new Error(/* Unreachable. */); - } - uninstall(): void { fs.rmSync(ComfyServerConfig.configPath); } diff --git a/src/main.ts b/src/main.ts index 9c186198..fc5d8cea 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,7 +9,6 @@ import { AppInfoHandlers } from './handlers/appInfoHandlers'; import { ComfyDesktopApp } from './main-process/comfyDesktopApp'; import { LevelOption } from 'electron-log'; import SentryLogging from './services/sentry'; -import { DesktopConfig } from './store/desktopConfig'; dotenv.config(); log.initialize(); @@ -41,17 +40,6 @@ if (!gotTheLock) { app.on('ready', async () => { log.debug('App ready'); - const store = await DesktopConfig.load(); - if (store) { - startApp(); - } else { - app.exit(20); - } - }); -} - -async function startApp() { - try { const appWindow = new AppWindow(); appWindow.onClose(() => { log.info('App window closed. Quitting application.'); @@ -91,8 +79,5 @@ async function startApp() { appWindow.sendServerStartProgress(ProgressStatus.ERROR); appWindow.send(IPC_CHANNELS.LOG_MESSAGE, error); } - } catch (error) { - log.error('Fatal error occurred during app startup.', error); - app.exit(2024); - } + }); } diff --git a/src/store/desktopConfig.ts b/src/store/desktopConfig.ts deleted file mode 100644 index 51ca9e2d..00000000 --- a/src/store/desktopConfig.ts +++ /dev/null @@ -1,104 +0,0 @@ -import log from 'electron-log/main'; -import ElectronStore from 'electron-store'; -import { app, dialog, shell } from 'electron'; -import path from 'node:path'; -import fs from 'fs/promises'; -import type { DesktopSettings } from '.'; - -/** Handles loading of electron-store config, pre-window errors, and provides a non-null interface for the store. */ -export class DesktopConfig { - static #store: ElectronStore | undefined; - static get store(): ElectronStore { - const store = this.#store; - if (!store) throw new Error('Cannot access store before initialization.'); - return store; - } - - static async load( - options?: ConstructorParameters>[0] - ): Promise | undefined> { - try { - DesktopConfig.#store = new ElectronStore(options); - - return DesktopConfig.#store; - } catch (error) { - const configFilePath = path.join(getUserDataOrQuit(), `${options?.name ?? 'config'}.json`); - - if (error instanceof SyntaxError) { - // The .json file is invalid. Prompt user to reset. - const { response } = await showResetPrompt(configFilePath); - - if (response === 1) { - // Open dir with file selected - shell.showItemInFolder(configFilePath); - } else if (response === 0) { - // Reset - you sure? - const { response } = await showConfirmReset(configFilePath); - - if (response === 0) { - // Open dir with file selected - shell.showItemInFolder(configFilePath); - } else if (response === 1) { - // Delete all settings - await tryDeleteConfigFile(configFilePath); - - // Causing a stack overflow from this recursion would take immense patience. - return DesktopConfig.load(options); - } - } - - // User chose to exit - app.quit(); - } else { - // Crash: Unknown filesystem error, permission denied on user data folder, etc - log.error(`Unknown error whilst loading configuration file: ${configFilePath}`, error); - dialog.showErrorBox('User Data', `Unknown error whilst writing to user data folder:\n\n${configFilePath}`); - } - } - } -} - -function showResetPrompt(configFilePath: string): Promise { - return dialog.showMessageBox({ - title: 'Invalid configuration file', - type: 'error', - message: `Format of the configuration file below is invalid. It should be a JSON file containing only ComfyUI configuration options.\n\n${configFilePath}`, - buttons: ['&Reset desktop configuration', 'Show the &file (and quit)', '&Quit'], - defaultId: 0, - cancelId: 2, - normalizeAccessKeys: true, - }); -} - -function showConfirmReset(configFilePath: string): Promise { - return dialog.showMessageBox({ - title: 'Confirm reset settings', - type: 'warning', - message: `The configuration file below will be cleared and all settings will be reset. You should back this file up before deleting it.\n\n${configFilePath}`, - buttons: ['Show the &file (and quit)', '&Yes, delete all settings', '&Quit'], - defaultId: 0, - cancelId: 2, - normalizeAccessKeys: true, - }); -} - -async function tryDeleteConfigFile(configFilePath: string) { - try { - await fs.rm(configFilePath); - } catch (error) { - log.error(`Unable to delete configuration file: ${configFilePath}`, error); - dialog.showErrorBox('Delete Failed', `Unknown error whilst attempting to delete config file:\n\n${configFilePath}`); - } -} - -function getUserDataOrQuit() { - try { - return app.getPath('userData'); - } catch (error) { - // Crash: Can't even find the user userData folder - log.error('Cannot find user data folder.', error); - dialog.showErrorBox('User Data', 'Unknown error whilst attempting to determine user data folder.'); - app.quit(); - throw error; - } -} diff --git a/src/store/index.ts b/src/store/index.ts index f0cabae9..64997873 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,19 +1,7 @@ -export type AppWindowSettings = { +export type StoreType = { windowWidth: number; windowHeight: number; windowX: number | undefined; windowY: number | undefined; windowMaximized?: boolean; }; - -export type DesktopSettings = { - basePath?: string; - /** - * The state of the installation. - * - `started`: The installation has started. - * - `installed`: A fresh installation. - * - `upgraded`: An upgrade from a previous version that stores the base path - * in the yaml config. - */ - installState?: 'started' | 'installed' | 'upgraded'; -};