mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
remove the double try/catch cases on the frontend side for cleaner code
This commit is contained in:
parent
3eb97f5683
commit
0b905a7f67
22 changed files with 250 additions and 364 deletions
|
|
@ -12,7 +12,6 @@ import { StatusBar } from '@/components/StatusBar';
|
||||||
import { ErrorBoundary } from '@/components/ErrorBoundary';
|
import { ErrorBoundary } from '@/components/ErrorBoundary';
|
||||||
import { useUpdateChecker } from '@/hooks/useUpdateChecker';
|
import { useUpdateChecker } from '@/hooks/useUpdateChecker';
|
||||||
import { useKoboldVersions } from '@/hooks/useKoboldVersions';
|
import { useKoboldVersions } from '@/hooks/useKoboldVersions';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
import { STATUSBAR_HEIGHT, TITLEBAR_HEIGHT } from '@/constants';
|
import { STATUSBAR_HEIGHT, TITLEBAR_HEIGHT } from '@/constants';
|
||||||
import type { DownloadItem } from '@/types/electron';
|
import type { DownloadItem } from '@/types/electron';
|
||||||
import type { InterfaceTab, Screen } from '@/types';
|
import type { InterfaceTab, Screen } from '@/types';
|
||||||
|
|
@ -40,7 +39,6 @@ export const App = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkInstallation = async () => {
|
const checkInstallation = async () => {
|
||||||
await safeExecute(async () => {
|
|
||||||
const [currentVersion, hasSeenWelcome] = await Promise.all([
|
const [currentVersion, hasSeenWelcome] = await Promise.all([
|
||||||
window.electronAPI.kobold.getCurrentVersion(),
|
window.electronAPI.kobold.getCurrentVersion(),
|
||||||
window.electronAPI.config.get('hasSeenWelcome') as Promise<boolean>,
|
window.electronAPI.config.get('hasSeenWelcome') as Promise<boolean>,
|
||||||
|
|
@ -59,7 +57,6 @@ export const App = () => {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
}, 'Error checking installation:');
|
|
||||||
|
|
||||||
setHasInitialized(true);
|
setHasInitialized(true);
|
||||||
};
|
};
|
||||||
|
|
@ -69,7 +66,6 @@ export const App = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleBinaryUpdate = async (download: DownloadItem) => {
|
const handleBinaryUpdate = async (download: DownloadItem) => {
|
||||||
await safeExecute(async () => {
|
|
||||||
const success = await sharedHandleDownload({
|
const success = await sharedHandleDownload({
|
||||||
item: download,
|
item: download,
|
||||||
isUpdate: true,
|
isUpdate: true,
|
||||||
|
|
@ -79,13 +75,10 @@ export const App = () => {
|
||||||
if (success) {
|
if (success) {
|
||||||
dismissUpdate();
|
dismissUpdate();
|
||||||
}
|
}
|
||||||
}, 'Failed to update binary:');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDownloadComplete = async () => {
|
const handleDownloadComplete = async () => {
|
||||||
await safeExecute(async () => {
|
|
||||||
await window.electronAPI.kobold.getCurrentVersion();
|
await window.electronAPI.kobold.getCurrentVersion();
|
||||||
}, 'Error refreshing versions after download:');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setCurrentScreen('launch');
|
setCurrentScreen('launch');
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { ReactNode } from 'react';
|
||||||
import { Center, Stack, Text, Button, Alert, rem } from '@mantine/core';
|
import { Center, Stack, Text, Button, Alert, rem } from '@mantine/core';
|
||||||
import { AlertTriangle, FolderOpen } from 'lucide-react';
|
import { AlertTriangle, FolderOpen } from 'lucide-react';
|
||||||
import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary';
|
import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
|
|
||||||
interface ErrorBoundaryProps {
|
interface ErrorBoundaryProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
@ -39,12 +38,7 @@ const ErrorFallback = ({
|
||||||
leftSection={
|
leftSection={
|
||||||
<FolderOpen style={{ width: rem(16), height: rem(16) }} />
|
<FolderOpen style={{ width: rem(16), height: rem(16) }} />
|
||||||
}
|
}
|
||||||
onClick={async () => {
|
onClick={() => window.electronAPI.app.showLogsFolder()}
|
||||||
await safeExecute(
|
|
||||||
() => window.electronAPI.app.showLogsFolder(),
|
|
||||||
'Failed to open logs folder'
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Show Logs Folder
|
Show Logs Folder
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { Badge, Tooltip } from '@mantine/core';
|
import { Badge, Tooltip } from '@mantine/core';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
|
|
||||||
interface PerformanceBadgeProps {
|
interface PerformanceBadgeProps {
|
||||||
label: string;
|
label: string;
|
||||||
|
|
@ -16,12 +15,9 @@ export const PerformanceBadge = ({
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
|
||||||
const handlePerformanceClick = async () => {
|
const handlePerformanceClick = async () => {
|
||||||
const result = await safeExecute(
|
const result = await window.electronAPI.app.openPerformanceManager();
|
||||||
() => window.electronAPI.app.openPerformanceManager(),
|
|
||||||
'Failed to open performance manager'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result && !result.success) {
|
if (!result.success) {
|
||||||
window.electronAPI.logs.logError(
|
window.electronAPI.logs.logError(
|
||||||
`Failed to open performance manager: ${result.error}`
|
`Failed to open performance manager: ${result.error}`
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import { useState, useCallback, useEffect, useRef } from 'react';
|
import { useState, useCallback, useRef, useEffect } from 'react';
|
||||||
import { Card, Text, Title, Loader, Stack, Container } from '@mantine/core';
|
import { Card, Text, Title, Loader, Stack, Container } from '@mantine/core';
|
||||||
import { DownloadCard } from '@/components/DownloadCard';
|
import { DownloadCard } from '@/components/DownloadCard';
|
||||||
import { getPlatformDisplayName } from '@/utils/platform';
|
import { getPlatformDisplayName } from '@/utils/platform';
|
||||||
import { formatDownloadSize } from '@/utils/format';
|
import { formatDownloadSize } from '@/utils/format';
|
||||||
import { getAssetDescription } from '@/utils/assets';
|
import { getAssetDescription } from '@/utils/assets';
|
||||||
import { useKoboldVersions } from '@/hooks/useKoboldVersions';
|
import { useKoboldVersions } from '@/hooks/useKoboldVersions';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
import type { DownloadItem } from '@/types/electron';
|
import type { DownloadItem } from '@/types/electron';
|
||||||
|
|
||||||
interface DownloadScreenProps {
|
interface DownloadScreenProps {
|
||||||
|
|
@ -32,7 +31,6 @@ export const DownloadScreen = ({ onDownloadComplete }: DownloadScreenProps) => {
|
||||||
async (download: DownloadItem) => {
|
async (download: DownloadItem) => {
|
||||||
setDownloadingAsset(download.name);
|
setDownloadingAsset(download.name);
|
||||||
|
|
||||||
await safeExecute(async () => {
|
|
||||||
const success = await sharedHandleDownload({
|
const success = await sharedHandleDownload({
|
||||||
item: download,
|
item: download,
|
||||||
isUpdate: false,
|
isUpdate: false,
|
||||||
|
|
@ -46,7 +44,6 @@ export const DownloadScreen = ({ onDownloadComplete }: DownloadScreenProps) => {
|
||||||
setDownloadingAsset(null);
|
setDownloadingAsset(null);
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
}, `Failed to download ${download.name}:`);
|
|
||||||
|
|
||||||
setDownloadingAsset(null);
|
setDownloadingAsset(null);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import { InfoTooltip } from '@/components/InfoTooltip';
|
||||||
import { CheckboxWithTooltip } from '@/components/CheckboxWithTooltip';
|
import { CheckboxWithTooltip } from '@/components/CheckboxWithTooltip';
|
||||||
import { CommandLineArgumentsModal } from '@/components/CommandLineArgumentsModal';
|
import { CommandLineArgumentsModal } from '@/components/CommandLineArgumentsModal';
|
||||||
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
|
|
||||||
export const AdvancedTab = () => {
|
export const AdvancedTab = () => {
|
||||||
const {
|
const {
|
||||||
|
|
@ -56,10 +55,7 @@ export const AdvancedTab = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const detectBackendSupport = async () => {
|
const detectBackendSupport = async () => {
|
||||||
const support = await safeExecute(
|
const support = await window.electronAPI.kobold.detectBackendSupport();
|
||||||
() => window.electronAPI.kobold.detectBackendSupport(),
|
|
||||||
'Failed to detect backend support:'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (support) {
|
if (support) {
|
||||||
setBackendSupport({
|
setBackendSupport({
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import { InfoTooltip } from '@/components/InfoTooltip';
|
||||||
import { BackendSelectItem } from '@/components/screens/Launch/GeneralTab/BackendSelectItem';
|
import { BackendSelectItem } from '@/components/screens/Launch/GeneralTab/BackendSelectItem';
|
||||||
import { GpuDeviceSelector } from '@/components/screens/Launch/GeneralTab/GpuDeviceSelector';
|
import { GpuDeviceSelector } from '@/components/screens/Launch/GeneralTab/GpuDeviceSelector';
|
||||||
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
import type { BackendOption } from '@/types';
|
import type { BackendOption } from '@/types';
|
||||||
|
|
||||||
export const BackendSelector = () => {
|
export const BackendSelector = () => {
|
||||||
|
|
@ -26,10 +25,8 @@ export const BackendSelector = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadBackends = async () => {
|
const loadBackends = async () => {
|
||||||
setIsLoadingBackends(true);
|
setIsLoadingBackends(true);
|
||||||
const backends = await safeExecute(
|
const backends =
|
||||||
() => window.electronAPI.kobold.getAvailableBackends(true),
|
await window.electronAPI.kobold.getAvailableBackends(true);
|
||||||
'Failed to detect available backends:'
|
|
||||||
);
|
|
||||||
setAvailableBackends(backends || []);
|
setAvailableBackends(backends || []);
|
||||||
setIsLoadingBackends(false);
|
setIsLoadingBackends(false);
|
||||||
hasInitialized.current = true;
|
hasInitialized.current = true;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Card, Container, Stack, Tabs, Group, Button } from '@mantine/core';
|
import { Card, Container, Stack, Tabs, Group, Button } from '@mantine/core';
|
||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||||
import { logError, safeExecute } from '@/utils/logger';
|
import { logError } from '@/utils/logger';
|
||||||
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
||||||
import { useLaunchLogic } from '@/hooks/useLaunchLogic';
|
import { useLaunchLogic } from '@/hooks/useLaunchLogic';
|
||||||
import { useWarnings } from '@/hooks/useWarnings';
|
import { useWarnings } from '@/hooks/useWarnings';
|
||||||
|
|
@ -81,10 +81,7 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const setHappyDefaults = useCallback(async () => {
|
const setHappyDefaults = useCallback(async () => {
|
||||||
const backends = await safeExecute(
|
const backends = await window.electronAPI.kobold.getAvailableBackends();
|
||||||
() => window.electronAPI.kobold.getAvailableBackends(),
|
|
||||||
'Failed to set defaults:'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!backend && backends && backends.length > 0) {
|
if (!backend && backends && backends.length > 0) {
|
||||||
handleBackendChange(backends[0].value);
|
handleBackendChange(backends[0].value);
|
||||||
|
|
@ -183,7 +180,6 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCreateNewConfig = async (configName: string) => {
|
const handleCreateNewConfig = async (configName: string) => {
|
||||||
await safeExecute(async () => {
|
|
||||||
const fullConfigName = `${configName}.json`;
|
const fullConfigName = `${configName}.json`;
|
||||||
const saveSuccess = await window.electronAPI.kobold.saveConfigFile(
|
const saveSuccess = await window.electronAPI.kobold.saveConfigFile(
|
||||||
fullConfigName,
|
fullConfigName,
|
||||||
|
|
@ -200,7 +196,6 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
new Error('Save operation failed')
|
new Error('Save operation failed')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, 'Failed to create new configuration:');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveConfig = async () => {
|
const handleSaveConfig = async () => {
|
||||||
|
|
@ -212,7 +207,6 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const success = await safeExecute(async () => {
|
|
||||||
const saveSuccess = await window.electronAPI.kobold.saveConfigFile(
|
const saveSuccess = await window.electronAPI.kobold.saveConfigFile(
|
||||||
selectedFile,
|
selectedFile,
|
||||||
buildConfigData()
|
buildConfigData()
|
||||||
|
|
@ -227,9 +221,6 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, 'Failed to save configuration:');
|
|
||||||
|
|
||||||
return success ?? false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,7 @@ export const AboutTab = () => {
|
||||||
const { handleLogoClick, getLogoStyles } = useLogoClickSounds();
|
const { handleLogoClick, getLogoStyles } = useLogoClickSounds();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadVersionInfo = async () => {
|
const loadVersionInfo = async () => {
|
||||||
const info = await safeExecute(
|
const info = await window.electronAPI.app.getVersionInfo();
|
||||||
() => window.electronAPI.app.getVersionInfo(),
|
|
||||||
'Failed to load version info'
|
|
||||||
);
|
|
||||||
if (info) {
|
if (info) {
|
||||||
setVersionInfo(info);
|
setVersionInfo(info);
|
||||||
}
|
}
|
||||||
|
|
@ -48,9 +45,7 @@ export const AboutTab = () => {
|
||||||
{ label: 'Electron', value: versionInfo.electronVersion },
|
{ label: 'Electron', value: versionInfo.electronVersion },
|
||||||
{
|
{
|
||||||
label: 'Node.js',
|
label: 'Node.js',
|
||||||
value:
|
value: versionInfo.nodeJsSystemVersion
|
||||||
versionInfo.nodeJsSystemVersion &&
|
|
||||||
versionInfo.nodeJsSystemVersion !== versionInfo.nodeVersion
|
|
||||||
? `${versionInfo.nodeVersion} (System: ${versionInfo.nodeJsSystemVersion})`
|
? `${versionInfo.nodeVersion} (System: ${versionInfo.nodeJsSystemVersion})`
|
||||||
: versionInfo.nodeVersion,
|
: versionInfo.nodeVersion,
|
||||||
},
|
},
|
||||||
|
|
@ -66,21 +61,9 @@ export const AboutTab = () => {
|
||||||
];
|
];
|
||||||
|
|
||||||
const copyVersionInfo = async () => {
|
const copyVersionInfo = async () => {
|
||||||
const nodeJsInfo =
|
const info = versionItems
|
||||||
versionInfo.nodeJsSystemVersion &&
|
.map((item) => `${item.label}: ${item.value}`)
|
||||||
versionInfo.nodeJsSystemVersion !== versionInfo.nodeVersion
|
.join('\n');
|
||||||
? `${versionInfo.nodeVersion} (system: ${versionInfo.nodeJsSystemVersion})`
|
|
||||||
: versionInfo.nodeVersion;
|
|
||||||
|
|
||||||
const info = [
|
|
||||||
`${PRODUCT_NAME}: ${versionInfo.appVersion}`,
|
|
||||||
`Electron: ${versionInfo.electronVersion}`,
|
|
||||||
`Node.js: ${nodeJsInfo}`,
|
|
||||||
`Chromium: ${versionInfo.chromeVersion}`,
|
|
||||||
`V8: ${versionInfo.v8Version}`,
|
|
||||||
`OS: ${versionInfo.platform} ${versionInfo.arch} (${versionInfo.osVersion})`,
|
|
||||||
...(versionInfo.uvVersion ? [`uv: ${versionInfo.uvVersion}`] : []),
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
await safeExecute(
|
await safeExecute(
|
||||||
() => navigator.clipboard.writeText(info),
|
() => navigator.clipboard.writeText(info),
|
||||||
|
|
@ -128,15 +111,11 @@ export const AboutTab = () => {
|
||||||
leftSection={
|
leftSection={
|
||||||
<Github style={{ width: rem(16), height: rem(16) }} />
|
<Github style={{ width: rem(16), height: rem(16) }} />
|
||||||
}
|
}
|
||||||
onClick={async () => {
|
onClick={() =>
|
||||||
await safeExecute(
|
|
||||||
() =>
|
|
||||||
window.electronAPI.app.openExternal(
|
window.electronAPI.app.openExternal(
|
||||||
'https://github.com/lone-cloud/gerbil'
|
'https://github.com/lone-cloud/gerbil'
|
||||||
),
|
)
|
||||||
'Failed to open GitHub link'
|
}
|
||||||
);
|
|
||||||
}}
|
|
||||||
style={{ textDecoration: 'none' }}
|
style={{ textDecoration: 'none' }}
|
||||||
>
|
>
|
||||||
GitHub
|
GitHub
|
||||||
|
|
@ -148,12 +127,7 @@ export const AboutTab = () => {
|
||||||
leftSection={
|
leftSection={
|
||||||
<FolderOpen style={{ width: rem(16), height: rem(16) }} />
|
<FolderOpen style={{ width: rem(16), height: rem(16) }} />
|
||||||
}
|
}
|
||||||
onClick={async () => {
|
onClick={() => window.electronAPI.app.showLogsFolder()}
|
||||||
await safeExecute(
|
|
||||||
() => window.electronAPI.app.showLogsFolder(),
|
|
||||||
'Failed to open logs folder'
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Show Logs
|
Show Logs
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import {
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Sun, Moon, Monitor } from 'lucide-react';
|
import { Sun, Moon, Monitor } from 'lucide-react';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
import { useAppColorScheme } from '@/hooks/useAppColorScheme';
|
import { useAppColorScheme } from '@/hooks/useAppColorScheme';
|
||||||
import {
|
import {
|
||||||
zoomLevelToPercentage,
|
zoomLevelToPercentage,
|
||||||
|
|
@ -33,14 +32,8 @@ export const AppearanceTab = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadSettings = async () => {
|
const loadSettings = async () => {
|
||||||
const [currentZoom, savedColorScheme] = await Promise.all([
|
const [currentZoom, savedColorScheme] = await Promise.all([
|
||||||
safeExecute(
|
window.electronAPI.app.getZoomLevel(),
|
||||||
() => window.electronAPI.app.getZoomLevel(),
|
window.electronAPI.app.getColorScheme(),
|
||||||
'Failed to load zoom level:'
|
|
||||||
),
|
|
||||||
safeExecute(
|
|
||||||
() => window.electronAPI.app.getColorScheme(),
|
|
||||||
'Failed to load color scheme:'
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (typeof currentZoom === 'number') {
|
if (typeof currentZoom === 'number') {
|
||||||
|
|
@ -56,38 +49,29 @@ export const AppearanceTab = () => {
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleColorSchemeChange = async (value: string) => {
|
const handleColorSchemeChange = (value: string) => {
|
||||||
const newColorScheme = value as MantineColorScheme;
|
const newColorScheme = value as MantineColorScheme;
|
||||||
setRawColorScheme(newColorScheme);
|
setRawColorScheme(newColorScheme);
|
||||||
|
|
||||||
await safeExecute(
|
void window.electronAPI.app.setColorScheme(newColorScheme);
|
||||||
() => window.electronAPI.app.setColorScheme(newColorScheme),
|
|
||||||
'Failed to save color scheme:'
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleZoomChange = async (newZoomLevel: number) => {
|
const handleZoomChange = (newZoomLevel: number) => {
|
||||||
setZoomLevel(newZoomLevel);
|
setZoomLevel(newZoomLevel);
|
||||||
const percentage = zoomLevelToPercentage(newZoomLevel);
|
const percentage = zoomLevelToPercentage(newZoomLevel);
|
||||||
setZoomPercentage(percentage.toString());
|
setZoomPercentage(percentage.toString());
|
||||||
|
|
||||||
await safeExecute(
|
void window.electronAPI.app.setZoomLevel(newZoomLevel);
|
||||||
() => window.electronAPI.app.setZoomLevel(newZoomLevel),
|
|
||||||
'Failed to set zoom level:'
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleZoomPercentageChange = async (value: string) => {
|
const handleZoomPercentageChange = (value: string) => {
|
||||||
setZoomPercentage(value);
|
setZoomPercentage(value);
|
||||||
const numValue = Number(value);
|
const numValue = Number(value);
|
||||||
if (!isNaN(numValue) && isValidZoomPercentage(numValue)) {
|
if (!isNaN(numValue) && isValidZoomPercentage(numValue)) {
|
||||||
const newZoomLevel = percentageToZoomLevel(numValue);
|
const newZoomLevel = percentageToZoomLevel(numValue);
|
||||||
setZoomLevel(newZoomLevel);
|
setZoomLevel(newZoomLevel);
|
||||||
|
|
||||||
await safeExecute(
|
void window.electronAPI.app.setZoomLevel(newZoomLevel);
|
||||||
() => window.electronAPI.app.setZoomLevel(newZoomLevel),
|
|
||||||
'Failed to set zoom level:'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useState, useEffect, useCallback, useMemo } from 'react';
|
import { useState, useEffect, useCallback, useMemo } from 'react';
|
||||||
import { tryExecute, safeExecute } from '@/utils/logger';
|
import { tryExecute } from '@/utils/logger';
|
||||||
import {
|
import {
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
|
|
@ -99,11 +99,8 @@ export const GeneralTab = ({
|
||||||
|
|
||||||
for (const config of frontendConfigs) {
|
for (const config of frontendConfigs) {
|
||||||
if (config.requirementCheck) {
|
if (config.requirementCheck) {
|
||||||
const isAvailable = await safeExecute(
|
const isAvailable = await config.requirementCheck();
|
||||||
config.requirementCheck,
|
requirementResults.set(config.value, isAvailable);
|
||||||
`Failed to check requirements for ${config.label}:`
|
|
||||||
);
|
|
||||||
requirementResults.set(config.value, isAvailable ?? false);
|
|
||||||
} else {
|
} else {
|
||||||
requirementResults.set(config.value, true);
|
requirementResults.set(config.value, true);
|
||||||
}
|
}
|
||||||
|
|
@ -163,20 +160,15 @@ export const GeneralTab = ({
|
||||||
}, [FrontendPreference, checkAllFrontendRequirements]);
|
}, [FrontendPreference, checkAllFrontendRequirements]);
|
||||||
|
|
||||||
const loadCurrentInstallDir = async () => {
|
const loadCurrentInstallDir = async () => {
|
||||||
const currentDir = await safeExecute(
|
const currentDir = await window.electronAPI.kobold.getCurrentInstallDir();
|
||||||
() => window.electronAPI.kobold.getCurrentInstallDir(),
|
|
||||||
'Failed to load install directory:'
|
|
||||||
);
|
|
||||||
if (currentDir) {
|
if (currentDir) {
|
||||||
setInstallDir(currentDir);
|
setInstallDir(currentDir);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadFrontendPreference = async () => {
|
const loadFrontendPreference = async () => {
|
||||||
const frontendPreference = await safeExecute(
|
const frontendPreference =
|
||||||
() => window.electronAPI.config.get('frontendPreference'),
|
await window.electronAPI.config.get('frontendPreference');
|
||||||
'Failed to load frontend preference:'
|
|
||||||
);
|
|
||||||
if (frontendPreference) {
|
if (frontendPreference) {
|
||||||
setFrontendPreference(
|
setFrontendPreference(
|
||||||
(frontendPreference as FrontendPreference) || 'koboldcpp'
|
(frontendPreference as FrontendPreference) || 'koboldcpp'
|
||||||
|
|
@ -185,10 +177,8 @@ export const GeneralTab = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectInstallDir = async () => {
|
const handleSelectInstallDir = async () => {
|
||||||
const selectedDir = await safeExecute(
|
const selectedDir =
|
||||||
() => window.electronAPI.kobold.selectInstallDirectory(),
|
await window.electronAPI.kobold.selectInstallDirectory();
|
||||||
'Failed to select install directory:'
|
|
||||||
);
|
|
||||||
if (selectedDir) {
|
if (selectedDir) {
|
||||||
setInstallDir(selectedDir);
|
setInstallDir(selectedDir);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import {
|
||||||
stripAssetExtensions,
|
stripAssetExtensions,
|
||||||
compareVersions,
|
compareVersions,
|
||||||
} from '@/utils/version';
|
} from '@/utils/version';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
import { formatDownloadSize } from '@/utils/format';
|
import { formatDownloadSize } from '@/utils/format';
|
||||||
|
|
||||||
import { useKoboldVersions } from '@/hooks/useKoboldVersions';
|
import { useKoboldVersions } from '@/hooks/useKoboldVersions';
|
||||||
|
|
@ -60,7 +59,6 @@ export const VersionsTab = () => {
|
||||||
const loadInstalledVersions = useCallback(async () => {
|
const loadInstalledVersions = useCallback(async () => {
|
||||||
setLoadingInstalled(true);
|
setLoadingInstalled(true);
|
||||||
|
|
||||||
await safeExecute(async () => {
|
|
||||||
const [versions, currentVersion] = await Promise.all([
|
const [versions, currentVersion] = await Promise.all([
|
||||||
window.electronAPI.kobold.getInstalledVersions(),
|
window.electronAPI.kobold.getInstalledVersions(),
|
||||||
window.electronAPI.kobold.getCurrentVersion(),
|
window.electronAPI.kobold.getCurrentVersion(),
|
||||||
|
|
@ -68,16 +66,12 @@ export const VersionsTab = () => {
|
||||||
|
|
||||||
setInstalledVersions(versions);
|
setInstalledVersions(versions);
|
||||||
setCurrentVersion(currentVersion);
|
setCurrentVersion(currentVersion);
|
||||||
}, 'Failed to load installed versions:');
|
|
||||||
|
|
||||||
setLoadingInstalled(false);
|
setLoadingInstalled(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const loadLatestRelease = useCallback(async () => {
|
const loadLatestRelease = useCallback(async () => {
|
||||||
const release = await safeExecute(
|
const release = await getLatestReleaseWithDownloadStatus();
|
||||||
() => getLatestReleaseWithDownloadStatus(),
|
|
||||||
'Failed to load latest release:'
|
|
||||||
);
|
|
||||||
if (release) {
|
if (release) {
|
||||||
setLatestRelease(release);
|
setLatestRelease(release);
|
||||||
}
|
}
|
||||||
|
|
@ -174,11 +168,8 @@ export const VersionsTab = () => {
|
||||||
}, [downloading]);
|
}, [downloading]);
|
||||||
|
|
||||||
const handleDownload = async (version: VersionInfo) => {
|
const handleDownload = async (version: VersionInfo) => {
|
||||||
await safeExecute(async () => {
|
|
||||||
const download = availableDownloads.find((d) => d.name === version.name);
|
const download = availableDownloads.find((d) => d.name === version.name);
|
||||||
if (!download) {
|
if (!download) return;
|
||||||
throw new Error('Download not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const success = await sharedHandleDownload({
|
const success = await sharedHandleDownload({
|
||||||
item: download,
|
item: download,
|
||||||
|
|
@ -189,15 +180,11 @@ export const VersionsTab = () => {
|
||||||
if (success) {
|
if (success) {
|
||||||
await loadInstalledVersions();
|
await loadInstalledVersions();
|
||||||
}
|
}
|
||||||
}, 'Failed to download:');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdate = async (version: VersionInfo) => {
|
const handleUpdate = async (version: VersionInfo) => {
|
||||||
await safeExecute(async () => {
|
|
||||||
const download = availableDownloads.find((d) => d.name === version.name);
|
const download = availableDownloads.find((d) => d.name === version.name);
|
||||||
if (!download) {
|
if (!download) return;
|
||||||
throw new Error('Download not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const success = await sharedHandleDownload({
|
const success = await sharedHandleDownload({
|
||||||
item: download,
|
item: download,
|
||||||
|
|
@ -208,21 +195,18 @@ export const VersionsTab = () => {
|
||||||
if (success) {
|
if (success) {
|
||||||
await loadInstalledVersions();
|
await loadInstalledVersions();
|
||||||
}
|
}
|
||||||
}, 'Failed to update:');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeCurrent = async (version: VersionInfo) => {
|
const makeCurrent = async (version: VersionInfo) => {
|
||||||
if (!version.installedPath) return;
|
if (!version.installedPath) return;
|
||||||
|
|
||||||
await safeExecute(async () => {
|
|
||||||
const success = await window.electronAPI.kobold.setCurrentVersion(
|
const success = await window.electronAPI.kobold.setCurrentVersion(
|
||||||
version.installedPath!
|
version.installedPath
|
||||||
);
|
);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
await loadInstalledVersions();
|
await loadInstalledVersions();
|
||||||
}
|
}
|
||||||
}, 'Failed to set current version:');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loadingInstalled || loadingPlatform || loadingRemote) {
|
if (loadingInstalled || loadingPlatform || loadingRemote) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useMantineColorScheme } from '@mantine/core';
|
import { useMantineColorScheme } from '@mantine/core';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
|
|
||||||
type ColorScheme = 'light' | 'dark';
|
type ColorScheme = 'light' | 'dark';
|
||||||
|
|
||||||
|
|
@ -10,10 +9,7 @@ export const useAppColorScheme = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadColorScheme = async () => {
|
const loadColorScheme = async () => {
|
||||||
const rawScheme = await safeExecute(
|
const rawScheme = await window.electronAPI.app.getColorScheme();
|
||||||
() => window.electronAPI.app.getColorScheme(),
|
|
||||||
'Failed to get app color scheme'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (rawScheme) {
|
if (rawScheme) {
|
||||||
let resolvedScheme: ColorScheme;
|
let resolvedScheme: ColorScheme;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useState, useCallback, useEffect } from 'react';
|
import { useState, useCallback, useEffect } from 'react';
|
||||||
import { safeExecute, tryExecute } from '@/utils/logger';
|
import { tryExecute } from '@/utils/logger';
|
||||||
import { compareVersions } from '@/utils/version';
|
import { compareVersions } from '@/utils/version';
|
||||||
import { GITHUB_API } from '@/constants';
|
import { GITHUB_API } from '@/constants';
|
||||||
|
|
||||||
|
|
@ -19,18 +19,12 @@ export const useAppUpdateChecker = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeUpdater = async () => {
|
const initializeUpdater = async () => {
|
||||||
const [canUpdate, isDownloaded] = await Promise.all([
|
const [canUpdate, isDownloaded] = await Promise.all([
|
||||||
safeExecute(
|
window.electronAPI.updater.canAutoUpdate(),
|
||||||
() => window.electronAPI.updater.canAutoUpdate(),
|
window.electronAPI.updater.isUpdateDownloaded(),
|
||||||
'Failed to check auto-update capability'
|
|
||||||
),
|
|
||||||
safeExecute(
|
|
||||||
() => window.electronAPI.updater.isUpdateDownloaded(),
|
|
||||||
'Failed to check update download status'
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (canUpdate !== null) setCanAutoUpdate(canUpdate);
|
setCanAutoUpdate(canUpdate);
|
||||||
if (isDownloaded !== null) setIsUpdateDownloaded(isDownloaded);
|
setIsUpdateDownloaded(isDownloaded);
|
||||||
};
|
};
|
||||||
|
|
||||||
void initializeUpdater();
|
void initializeUpdater();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useState, useCallback, useEffect } from 'react';
|
import { useState, useCallback, useEffect } from 'react';
|
||||||
import { tryExecute, safeExecute } from '@/utils/logger';
|
import { tryExecute } from '@/utils/logger';
|
||||||
import {
|
import {
|
||||||
getDisplayNameFromPath,
|
getDisplayNameFromPath,
|
||||||
compareVersions,
|
compareVersions,
|
||||||
|
|
@ -27,13 +27,9 @@ export const useUpdateChecker = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadDismissedUpdates = async () => {
|
const loadDismissedUpdates = async () => {
|
||||||
const dismissed = await safeExecute(
|
const dismissed = (await window.electronAPI.config.get(
|
||||||
async () =>
|
'dismissedUpdates'
|
||||||
(await window.electronAPI.config.get('dismissedUpdates')) as
|
)) as string[] | undefined;
|
||||||
| string[]
|
|
||||||
| undefined,
|
|
||||||
'Failed to load dismissed updates'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dismissed) {
|
if (dismissed) {
|
||||||
setDismissedUpdates(new Set(dismissed));
|
setDismissedUpdates(new Set(dismissed));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useEffect, useState, useCallback, useMemo } from 'react';
|
import { useEffect, useState, useCallback, useMemo } from 'react';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
import type { BackendOption, BackendSupport } from '@/types';
|
import type { BackendOption, BackendSupport } from '@/types';
|
||||||
|
|
||||||
export interface Warning {
|
export interface Warning {
|
||||||
|
|
@ -105,10 +104,7 @@ const checkVramWarnings = async (backend: string): Promise<Warning[]> => {
|
||||||
const isGpuBackend = ['cuda', 'rocm', 'vulkan', 'clblast'].includes(backend);
|
const isGpuBackend = ['cuda', 'rocm', 'vulkan', 'clblast'].includes(backend);
|
||||||
|
|
||||||
if (isGpuBackend) {
|
if (isGpuBackend) {
|
||||||
const gpuMemoryInfo = await safeExecute(
|
const gpuMemoryInfo = await window.electronAPI.kobold.detectGPUMemory();
|
||||||
() => window.electronAPI.kobold.detectGPUMemory(),
|
|
||||||
'Failed to detect GPU memory:'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (gpuMemoryInfo) {
|
if (gpuMemoryInfo) {
|
||||||
const lowVramThreshold = 8;
|
const lowVramThreshold = 8;
|
||||||
|
|
@ -189,7 +185,6 @@ const checkBackendWarnings = async (params?: {
|
||||||
}): Promise<Warning[]> => {
|
}): Promise<Warning[]> => {
|
||||||
const warnings: Warning[] = [];
|
const warnings: Warning[] = [];
|
||||||
|
|
||||||
const result = await safeExecute(async () => {
|
|
||||||
const [backendSupport, gpuCapabilities, gpuInfo] = await Promise.all([
|
const [backendSupport, gpuCapabilities, gpuInfo] = await Promise.all([
|
||||||
window.electronAPI.kobold.detectBackendSupport(),
|
window.electronAPI.kobold.detectBackendSupport(),
|
||||||
window.electronAPI.kobold.detectGPUCapabilities(),
|
window.electronAPI.kobold.detectGPUCapabilities(),
|
||||||
|
|
@ -227,9 +222,6 @@ const checkBackendWarnings = async (params?: {
|
||||||
}
|
}
|
||||||
|
|
||||||
return warnings;
|
return warnings;
|
||||||
}, 'Failed to check backend warnings:');
|
|
||||||
|
|
||||||
return result || warnings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useWarnings = ({
|
export const useWarnings = ({
|
||||||
|
|
@ -253,7 +245,6 @@ export const useWarnings = ({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await safeExecute(async () => {
|
|
||||||
const [cpuCapabilitiesResult, availableBackends] = await Promise.all([
|
const [cpuCapabilitiesResult, availableBackends] = await Promise.all([
|
||||||
window.electronAPI.kobold.detectCPU(),
|
window.electronAPI.kobold.detectCPU(),
|
||||||
window.electronAPI.kobold.getAvailableBackends(),
|
window.electronAPI.kobold.getAvailableBackends(),
|
||||||
|
|
@ -264,16 +255,15 @@ export const useWarnings = ({
|
||||||
avx2: cpuCapabilitiesResult.avx2,
|
avx2: cpuCapabilitiesResult.avx2,
|
||||||
};
|
};
|
||||||
|
|
||||||
return checkBackendWarnings({
|
const result = await checkBackendWarnings({
|
||||||
backend,
|
backend,
|
||||||
cpuCapabilities,
|
cpuCapabilities,
|
||||||
noavx2,
|
noavx2,
|
||||||
failsafe,
|
failsafe,
|
||||||
availableBackends,
|
availableBackends,
|
||||||
});
|
});
|
||||||
}, 'Failed to check backend warnings:');
|
|
||||||
|
|
||||||
setBackendWarnings(result || []);
|
setBackendWarnings(result);
|
||||||
}, [backend, noavx2, failsafe]);
|
}, [backend, noavx2, failsafe]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ setupAutoUpdater();
|
||||||
|
|
||||||
export const checkForUpdates = async () => {
|
export const checkForUpdates = async () => {
|
||||||
if (isDevelopment) {
|
if (isDevelopment) {
|
||||||
logError('Auto-updater: Cannot check for updates in development mode');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +50,6 @@ export const checkForUpdates = async () => {
|
||||||
|
|
||||||
export const downloadUpdate = async () => {
|
export const downloadUpdate = async () => {
|
||||||
if (isDevelopment) {
|
if (isDevelopment) {
|
||||||
logError('Auto-updater: Cannot download updates in development mode');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,29 @@
|
||||||
import { app } from 'electron';
|
import { app } from 'electron';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { createLogger, format, type Logger } from 'winston';
|
import { mkdir } from 'fs/promises';
|
||||||
|
import { createLogger, format } from 'winston';
|
||||||
import DailyRotateFile from 'winston-daily-rotate-file';
|
import DailyRotateFile from 'winston-daily-rotate-file';
|
||||||
import { isDevelopment } from '@/utils/node/environment';
|
import { isDevelopment } from '@/utils/node/environment';
|
||||||
|
|
||||||
let logger: Logger | null = null;
|
const ensureLogsDirectory = async (logsDir: string) => {
|
||||||
let isInitialized = false;
|
try {
|
||||||
|
await mkdir(logsDir, { recursive: true });
|
||||||
export const initializeLogger = () => {
|
} catch {
|
||||||
if (isInitialized) return;
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createAppLogger = () => {
|
||||||
const logsDir = join(app.getPath('userData'), 'logs');
|
const logsDir = join(app.getPath('userData'), 'logs');
|
||||||
|
|
||||||
logger = createLogger({
|
void ensureLogsDirectory(logsDir);
|
||||||
|
|
||||||
|
return createLogger({
|
||||||
level: isDevelopment ? 'debug' : 'info',
|
level: isDevelopment ? 'debug' : 'info',
|
||||||
format: format.combine(
|
format: format.combine(
|
||||||
format.timestamp(),
|
format.timestamp({
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss.SSS',
|
||||||
|
}),
|
||||||
format.printf(({ timestamp, level, message, error }) => {
|
format.printf(({ timestamp, level, message, error }) => {
|
||||||
let logEntry = `${timestamp} [MAIN] [${level.toUpperCase()}] ${message}`;
|
let logEntry = `${timestamp} [MAIN] [${level.toUpperCase()}] ${message}`;
|
||||||
|
|
||||||
|
|
@ -40,25 +48,17 @@ export const initializeLogger = () => {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
isInitialized = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ensureInitialized = () => {
|
const logger = createAppLogger();
|
||||||
if (!isInitialized) {
|
|
||||||
initializeLogger();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const logError = (message: string, error?: Error) => {
|
export const logError = (message: string, error?: Error) => {
|
||||||
ensureInitialized();
|
logger.error(message, { error });
|
||||||
logger!.error(message, { error });
|
|
||||||
flushLogs();
|
flushLogs();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const flushLogs = () => {
|
export const flushLogs = () => {
|
||||||
ensureInitialized();
|
const fileTransport = logger.transports.find(
|
||||||
const fileTransport = logger!.transports.find(
|
|
||||||
(t) => t.constructor.name === 'DailyRotateFile'
|
(t) => t.constructor.name === 'DailyRotateFile'
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { execa } from 'execa';
|
import { spawn } from 'child_process';
|
||||||
import { platform } from 'process';
|
import { platform } from 'process';
|
||||||
import { safeExecute } from '@/utils/node/logger';
|
import { safeExecute } from '@/utils/node/logger';
|
||||||
|
|
||||||
|
|
@ -12,16 +12,37 @@ const LINUX_PERFORMANCE_APPS = [
|
||||||
];
|
];
|
||||||
|
|
||||||
async function tryLaunchCommand(command: string, args: string[] = []) {
|
async function tryLaunchCommand(command: string, args: string[] = []) {
|
||||||
try {
|
return new Promise((resolve) => {
|
||||||
await execa(command, args, {
|
const child = spawn(command, args, {
|
||||||
detached: true,
|
detached: true,
|
||||||
stdio: 'ignore',
|
stdio: 'ignore',
|
||||||
timeout: 2000,
|
|
||||||
});
|
});
|
||||||
return true;
|
|
||||||
} catch {
|
let hasResolved = false;
|
||||||
return false;
|
|
||||||
|
child.on('error', () => {
|
||||||
|
if (!hasResolved) {
|
||||||
|
hasResolved = true;
|
||||||
|
resolve(false);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('spawn', () => {
|
||||||
|
if (!hasResolved) {
|
||||||
|
hasResolved = true;
|
||||||
|
child.unref();
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!hasResolved) {
|
||||||
|
hasResolved = true;
|
||||||
|
child.kill();
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const openPerformanceManager = async () =>
|
export const openPerformanceManager = async () =>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { safeExecute } from '@/utils/logger';
|
|
||||||
import type { FrontendPreference } from '@/types';
|
import type { FrontendPreference } from '@/types';
|
||||||
|
|
||||||
interface FrontendPreferenceState {
|
interface FrontendPreferenceState {
|
||||||
|
|
@ -15,19 +14,15 @@ export const useFrontendPreferenceStore = create<FrontendPreferenceState>()(
|
||||||
setFrontendPreference: (preference: FrontendPreference) => {
|
setFrontendPreference: (preference: FrontendPreference) => {
|
||||||
set({ frontendPreference: preference });
|
set({ frontendPreference: preference });
|
||||||
|
|
||||||
safeExecute(async () => {
|
window.electronAPI.config.set('frontendPreference', preference);
|
||||||
await window.electronAPI.config.set('frontendPreference', preference);
|
|
||||||
}, 'Error saving frontend preference:');
|
|
||||||
},
|
},
|
||||||
|
|
||||||
loadFromConfig: async () => {
|
loadFromConfig: async () => {
|
||||||
await safeExecute(async () => {
|
|
||||||
const preference = (await window.electronAPI.config.get(
|
const preference = (await window.electronAPI.config.get(
|
||||||
'frontendPreference'
|
'frontendPreference'
|
||||||
)) as FrontendPreference;
|
)) as FrontendPreference;
|
||||||
|
|
||||||
set({ frontendPreference: preference || 'koboldcpp' });
|
set({ frontendPreference: preference || 'koboldcpp' });
|
||||||
}, 'Error loading frontend preference:');
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {
|
||||||
createTryExecute,
|
createTryExecute,
|
||||||
createTryExecuteImmediate,
|
createTryExecuteImmediate,
|
||||||
createSafeTryExecute,
|
createSafeTryExecute,
|
||||||
} from '@/utils/shared/logger-core';
|
} from '@/utils/logger-core';
|
||||||
|
|
||||||
export const logError = (message: string, error: Error) => {
|
export const logError = (message: string, error: Error) => {
|
||||||
window.electronAPI.logs.logError(message, error);
|
window.electronAPI.logs.logError(message, error);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {
|
||||||
createSafeExecute,
|
createSafeExecute,
|
||||||
createTryExecute,
|
createTryExecute,
|
||||||
createSafeTryExecute,
|
createSafeTryExecute,
|
||||||
} from '@/utils/shared/logger-core';
|
} from '@/utils/logger-core';
|
||||||
|
|
||||||
export const safeExecute = createSafeExecute(logError);
|
export const safeExecute = createSafeExecute(logError);
|
||||||
export const tryExecute = createTryExecute(logError);
|
export const tryExecute = createTryExecute(logError);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue