mirror of
				https://github.com/open-webui/desktop
				synced 2025-06-26 18:15:59 +00:00 
			
		
		
		
	refac
This commit is contained in:
		
							parent
							
								
									58edd82696
								
							
						
					
					
						commit
						8f499475fd
					
				| @ -11,7 +11,7 @@ const config: ForgeConfig = { | ||||
| 	packagerConfig: { | ||||
| 		asar: true, | ||||
| 		icon: 'public/assets/icon.png', | ||||
| 		extraResource: ['public/assets', 'resources/python.tar.gz'] | ||||
| 		extraResource: ['public/assets', 'resources'] | ||||
| 	}, | ||||
| 	rebuildConfig: {}, | ||||
| 	makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})], | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| 		"lint": "eslint --ext .ts,.tsx .", | ||||
| 		"format": "prettier --plugin-search-dir --write \"**/*.{js,ts,svelte,css,md,html,json}\"", | ||||
| 		"create:conda-lock": "cd resources && rimraf conda-lock.yml && conda-lock -f environment.yml && cd -", | ||||
| 		"create:python-tar": "rimraf ./resources/python.tar.gz && conda-lock install --prefix ./resources/python ./resources/conda-lock.yml && conda pack -p ./resources/python -o ./resources/python.tar.gz" | ||||
| 		"create:python-tar": "rimraf ./resources/python.tar.gz && conda-lock install --prefix ./resources/python ./resources/conda-lock.yml && conda pack -p ./resources/python -o ./resources/python.tar.gz && rimraf ./resources/python" | ||||
| 	}, | ||||
| 	"devDependencies": { | ||||
| 		"@electron-forge/cli": "^7.6.0", | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| <script lang="ts"> | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import { installStatus, serverStatus } from './lib/stores'; | ||||
| 	import { installStatus, serverStatus, serverStartedAt } from './lib/stores'; | ||||
| 
 | ||||
| 	import Main from './lib/components/Main.svelte'; | ||||
| 
 | ||||
| @ -28,6 +28,9 @@ | ||||
| 						console.log('Server status:', event.data.data); | ||||
| 						serverStatus.set(event.data.data); | ||||
| 
 | ||||
| 						if ($serverStatus) { | ||||
| 							serverStartedAt.set(Date.now()); | ||||
| 						} | ||||
| 						break; | ||||
| 
 | ||||
| 					default: | ||||
|  | ||||
| @ -2,13 +2,15 @@ | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import { fly } from 'svelte/transition'; | ||||
| 
 | ||||
| 	import { installStatus, serverStatus } from '../stores'; | ||||
| 	import { installStatus, serverStatus, serverStartedAt } from '../stores'; | ||||
| 
 | ||||
| 	import Spinner from './common/Spinner.svelte'; | ||||
| 	import ArrowRightCircle from './icons/ArrowRightCircle.svelte'; | ||||
| 
 | ||||
| 	import backgroundImage from '../assets/images/green.jpg'; | ||||
| 
 | ||||
| 	let currentTime = Date.now(); | ||||
| 
 | ||||
| 	let installing = false; | ||||
| 	const continueHandler = async () => { | ||||
| 		if (window?.electronAPI) { | ||||
| @ -16,6 +18,16 @@ | ||||
| 			installing = true; | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	onMount(() => { | ||||
| 		const interval = setInterval(() => { | ||||
| 			currentTime = Date.now(); | ||||
| 		}, 1000); // Update every second | ||||
| 
 | ||||
| 		return () => { | ||||
| 			clearInterval(interval); // Cleanup interval on destroy | ||||
| 		}; | ||||
| 	}); | ||||
| </script> | ||||
| 
 | ||||
| {#if $installStatus === null} | ||||
| @ -107,10 +119,22 @@ | ||||
| 			{:else if $installStatus === true} | ||||
| 				<div class="flex-1 w-full flex justify-center relative"> | ||||
| 					<div class="m-auto"> | ||||
| 						<div class="flex flex-col gap-3"> | ||||
| 						<div class="flex flex-col gap-3 text-center"> | ||||
| 							<Spinner className="size-5" /> | ||||
| 
 | ||||
| 							<div class=" font-secondary">Launching Open WebUI...</div> | ||||
| 
 | ||||
| 							{#if $serverStartedAt} | ||||
| 								{#if currentTime - $serverStartedAt > 10000} | ||||
| 									<div | ||||
| 										class=" font-default text-xs" | ||||
| 										in:fly={{ duration: 500, y: 10 }} | ||||
| 									> | ||||
| 										If it's your first time, it might take a few minutes to | ||||
| 										start. | ||||
| 									</div> | ||||
| 								{/if} | ||||
| 							{/if} | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
|  | ||||
| @ -2,3 +2,5 @@ import { writable } from 'svelte/store'; | ||||
| 
 | ||||
| export const installStatus = writable(null); | ||||
| export const serverStatus = writable(null); | ||||
| 
 | ||||
| export const serverStartedAt = writable(null); | ||||
|  | ||||
| @ -192,8 +192,13 @@ export function createAdHocSignCommand(envPath: string): string { | ||||
| 	return `cd ${envPath} && codesign -s - -o 0x2 -f ${signList.join(' ')} && cd -`; | ||||
| } | ||||
| 
 | ||||
| export async function installOpenWebUI(installationPath: string, version?: string) { | ||||
| export async function installOpenWebUI( | ||||
| 	installationPath: string, | ||||
| 	version?: string | ||||
| ): Promise<boolean> { | ||||
| 	console.log(installationPath); | ||||
| 
 | ||||
| 	// Build the appropriate unpack command based on the platform
 | ||||
| 	let unpackCommand = | ||||
| 		process.platform === 'win32' | ||||
| 			? `${installationPath}\\Scripts\\activate.bat && pip install open-webui${version ? `==${version}` : ' -U'}` | ||||
| @ -204,32 +209,47 @@ export async function installOpenWebUI(installationPath: string, version?: strin | ||||
| 	//     unpackCommand = `${createAdHocSignCommand(installationPath)}\n${unpackCommand}`;
 | ||||
| 	// }
 | ||||
| 
 | ||||
| 	const commandProcess = exec(unpackCommand, { | ||||
| 		shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash' | ||||
| 	}); | ||||
| 	// Wrap the logic in a Promise to properly handle async execution and return a boolean
 | ||||
| 	return new Promise((resolve, reject) => { | ||||
| 		const commandProcess = exec(unpackCommand, { | ||||
| 			shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash' | ||||
| 		}); | ||||
| 
 | ||||
| 	const onLog = (data) => { | ||||
| 		console.log(data); | ||||
| 		logEmitter.emit('log', data); | ||||
| 	}; | ||||
| 		// Function to handle logging output
 | ||||
| 		const onLog = (data: any) => { | ||||
| 			console.log(data); | ||||
| 			logEmitter.emit('log', data); | ||||
| 		}; | ||||
| 
 | ||||
| 	commandProcess.stdout?.on('data', onLog); | ||||
| 	commandProcess.stderr?.on('data', onLog); | ||||
| 		// Listen to stdout and stderr for logging
 | ||||
| 		commandProcess.stdout?.on('data', onLog); | ||||
| 		commandProcess.stderr?.on('data', onLog); | ||||
| 
 | ||||
| 	commandProcess.on('exit', (code) => { | ||||
| 		console.log(`Child exited with code ${code}`); | ||||
| 		logEmitter.emit('log', `Child exited with code ${code}`); | ||||
| 		// Handle the exit event
 | ||||
| 		commandProcess.on('exit', (code) => { | ||||
| 			console.log(`Child exited with code ${code}`); | ||||
| 			logEmitter.emit('log', `Child exited with code ${code}`); | ||||
| 
 | ||||
| 		if (code !== 0) { | ||||
| 			log.error(`Failed to install open-webui: ${code}`); | ||||
| 			logEmitter.emit('log', `Failed to install open-webui: ${code}`); | ||||
| 		} else { | ||||
| 			logEmitter.emit('log', 'open-webui installed successfully'); | ||||
| 		} | ||||
| 			if (code !== 0) { | ||||
| 				log.error(`Failed to install open-webui: ${code}`); | ||||
| 				logEmitter.emit('log', `Failed to install open-webui: ${code}`); | ||||
| 				resolve(false); // Resolve the Promise with `false` if the command fails
 | ||||
| 			} else { | ||||
| 				logEmitter.emit('log', 'open-webui installed successfully'); | ||||
| 				resolve(true); // Resolve the Promise with `true` if the command succeeds
 | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		// Handle errors during execution
 | ||||
| 		commandProcess.on('error', (error) => { | ||||
| 			log.error(`Error occurred while installing open-webui: ${error.message}`); | ||||
| 			logEmitter.emit('log', `Error occurred while installing open-webui: ${error.message}`); | ||||
| 			reject(error); // Reject the Promise if an unexpected error occurs
 | ||||
| 		}); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| export async function installBundledPython(installationPath?: string) { | ||||
| export async function installBundledPython(installationPath?: string): Promise<boolean> { | ||||
| 	installationPath = installationPath || getBundledPythonInstallationPath(); | ||||
| 
 | ||||
| 	const pythonTarPath = getBundledPythonTarPath(); | ||||
| @ -241,7 +261,7 @@ export async function installBundledPython(installationPath?: string) { | ||||
| 	if (!fs.existsSync(pythonTarPath)) { | ||||
| 		log.error('Python tarball not found'); | ||||
| 		logEmitter.emit('log', 'Python tarball not found'); // Emit log
 | ||||
| 		return; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	try { | ||||
| @ -253,6 +273,7 @@ export async function installBundledPython(installationPath?: string) { | ||||
| 	} catch (error) { | ||||
| 		log.error(error); | ||||
| 		logEmitter.emit('log', error); // Emit log
 | ||||
| 		return false; // Return false to indicate failure
 | ||||
| 	} | ||||
| 
 | ||||
| 	// Get the path to the installed Python binary
 | ||||
| @ -261,7 +282,7 @@ export async function installBundledPython(installationPath?: string) { | ||||
| 	if (!fs.existsSync(bundledPythonPath)) { | ||||
| 		log.error('Python binary not found in install path'); | ||||
| 		logEmitter.emit('log', 'Python binary not found in install path'); // Emit log
 | ||||
| 		return; | ||||
| 		return false; // Return false to indicate failure
 | ||||
| 	} | ||||
| 
 | ||||
| 	try { | ||||
| @ -271,12 +292,17 @@ export async function installBundledPython(installationPath?: string) { | ||||
| 		}); | ||||
| 		console.log('Installed Python Version:', pythonVersion.trim()); | ||||
| 		logEmitter.emit('log', `Installed Python Version: ${pythonVersion.trim()}`); // Emit log
 | ||||
| 
 | ||||
| 		return true; // Return true to indicate success
 | ||||
| 	} catch (error) { | ||||
| 		log.error('Failed to execute Python binary', error); | ||||
| 
 | ||||
| 		return false; // Return false to indicate failure
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export async function installPackage(installationPath?: string) { | ||||
| export async function installPackage(installationPath?: string): Promise<boolean> { | ||||
| 	// Resolve the installation path or use the default bundled Python installation path
 | ||||
| 	installationPath = installationPath || getBundledPythonInstallationPath(); | ||||
| 
 | ||||
| 	// if (!isBundledPythonInstalled()) {
 | ||||
| @ -288,24 +314,35 @@ export async function installPackage(installationPath?: string) { | ||||
| 	//     }
 | ||||
| 	// }
 | ||||
| 
 | ||||
| 	console.log('Installing python...'); | ||||
| 	// Log the status for installation steps
 | ||||
| 	console.log('Installing Python...'); | ||||
| 
 | ||||
| 	try { | ||||
| 		await installBundledPython(installationPath); | ||||
| 		// Install the bundled Python
 | ||||
| 		const res = await installBundledPython(installationPath); | ||||
| 		if (!res) { | ||||
| 			throw new Error('Failed to install bundled Python'); | ||||
| 		} | ||||
| 	} catch (error) { | ||||
| 		log.error('Failed to install bundled Python', error); | ||||
| 
 | ||||
| 		throw new Error('Failed to install bundled Python'); | ||||
| 	} | ||||
| 
 | ||||
| 	console.log('Installing open-webui...'); | ||||
| 	try { | ||||
| 		await installOpenWebUI(installationPath); | ||||
| 		// Install the Open-WebUI package
 | ||||
| 		const success = await installOpenWebUI(installationPath); | ||||
| 		if (!success) { | ||||
| 			// Handle a scenario where `installOpenWebUI` returns `false`
 | ||||
| 			log.error('Failed to install open-webui'); | ||||
| 			throw new Error('Failed to install open-webui'); | ||||
| 		} | ||||
| 	} catch (error) { | ||||
| 		// Log and throw an error if the Open-WebUI installation fails
 | ||||
| 		log.error('Failed to install open-webui', error); | ||||
| 		throw new Error('Failed to install open-webui'); | ||||
| 	} | ||||
| 
 | ||||
| 	// Return true if all installations are successful
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user