import { Card, Container, Stack, Tabs, Group, Button } from '@mantine/core'; import { useState, useEffect, useCallback } from 'react'; import { useLaunchConfig } from '@/hooks/useLaunchConfig'; import { useLaunchLogic } from '@/hooks/useLaunchLogic'; import { useWarnings } from '@/hooks/useWarnings'; import { GeneralTab } from '@/components/screens/Launch/GeneralTab/index'; import { AdvancedTab } from '@/components/screens/Launch/AdvancedTab'; import { NetworkTab } from '@/components/screens/Launch/NetworkTab'; import { ImageGenerationTab } from '@/components/screens/Launch/ImageGenerationTab'; import { WarningDisplay } from '@/components/WarningDisplay'; import { ConfigFileManager } from '@/components/ConfigFileManager'; import type { ConfigFile } from '@/types'; interface LaunchScreenProps { onLaunch: () => void; onLaunchModeChange?: (isImageMode: boolean) => void; } export const LaunchScreen = ({ onLaunch, onLaunchModeChange, }: LaunchScreenProps) => { const [configFiles, setConfigFiles] = useState([]); const [selectedFile, setSelectedFile] = useState(null); const [, setInstallDir] = useState(''); const [activeTab, setActiveTab] = useState('general'); const [warnings, setWarnings] = useState< Array<{ type: 'warning' | 'info'; message: string }> >([]); const { gpuLayers, autoGpuLayers, contextSize, modelPath, additionalArguments, port, host, multiuser, multiplayer, remotetunnel, nocertify, websearch, noshift, flashattention, noavx2, failsafe, lowvram, quantmatmul, backend, gpuDevice, gpuPlatform, sdmodel, sdt5xxl, sdclipl, sdclipg, sdphotomaker, sdvae, sdlora, parseAndApplyConfigFile, loadConfigFromFile, } = useLaunchConfig(); const { isLaunching, handleLaunch } = useLaunchLogic({ modelPath, sdmodel, onLaunch, onLaunchModeChange, }); const combinedWarnings = useWarnings({ modelPath, sdmodel, warnings }); const loadConfigFiles = useCallback(async () => { const [files, currentDir, savedConfig] = await Promise.all([ window.electronAPI.kobold.getConfigFiles(), window.electronAPI.kobold.getCurrentInstallDir(), window.electronAPI.kobold.getSelectedConfig(), ]); setConfigFiles(files); setInstallDir(currentDir); if (savedConfig && files.some((f) => f.name === savedConfig)) { setSelectedFile(savedConfig); } else if (files.length > 0 && !selectedFile) { setSelectedFile(files[0].name); } const loadedConfigFileName = await loadConfigFromFile(files, savedConfig); if (loadedConfigFileName && !selectedFile) { setSelectedFile(loadedConfigFileName); } }, [selectedFile, loadConfigFromFile]); const handleFileSelection = async (fileName: string) => { setSelectedFile(fileName); await window.electronAPI.kobold.setSelectedConfig(fileName); const selectedConfig = configFiles.find((f) => f.name === fileName); if (selectedConfig) { await parseAndApplyConfigFile(selectedConfig.path); } }; const buildConfigData = () => { let useclblastValue: [number, number] | false = false; if (backend === 'clblast') { useclblastValue = [gpuDevice, gpuPlatform]; } return { gpulayers: gpuLayers, contextsize: contextSize, model: modelPath, port, host, multiuser: multiuser ? 1 : 0, multiplayer, remotetunnel, nocertify, websearch, noshift, flashattention, noavx2, failsafe, usecuda: backend === 'cuda' || backend === 'rocm', usevulkan: backend === 'vulkan', useclblast: useclblastValue, sdmodel, sdt5xxl, sdclipl, sdclipg, sdphotomaker, sdvae, }; }; const handleCreateNewConfig = async (configName: string) => { try { const success = await window.electronAPI.kobold.saveConfigFile( configName, buildConfigData() ); if (success) { await loadConfigFiles(); const newFileName = `${configName}.kcpps`; setSelectedFile(newFileName); await window.electronAPI.kobold.setSelectedConfig(newFileName); } else { window.electronAPI.logs.logError( 'Failed to create new configuration', new Error('Save operation failed') ); } } catch (error) { window.electronAPI.logs.logError( 'Failed to create new configuration:', error as Error ); } }; const handleSaveConfig = async () => { if (!selectedFile) { window.electronAPI.logs.logError( 'No configuration file selected for saving', new Error('Selected file is null') ); return; } try { const configName = selectedFile.replace('.kcpps', ''); const success = await window.electronAPI.kobold.saveConfigFile( configName, buildConfigData() ); if (!success) { window.electronAPI.logs.logError( 'Failed to save configuration', new Error('Save operation failed') ); } } catch (error) { window.electronAPI.logs.logError( 'Failed to save configuration:', error as Error ); } }; useEffect(() => { void loadConfigFiles(); const handleInstallDirChange = () => { void loadConfigFiles(); }; const cleanup = window.electronAPI.kobold.onInstallDirChanged( handleInstallDirChange ); return cleanup; }, [loadConfigFiles]); const handleLaunchClick = () => { handleLaunch({ autoGpuLayers, gpuLayers, contextSize, port: port ?? 5001, host, multiuser, multiplayer, remotetunnel, nocertify, websearch, noshift, flashattention, backend, lowvram, gpuDevice, quantmatmul, additionalArguments, sdt5xxl, sdclipl, sdclipg, sdphotomaker, sdvae, sdlora, }); }; return ( General Image Generation Network Advanced
); };