diff --git a/README.md b/README.md index 0bdd912..626b868 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,10 @@ The AUR package automatically handles installation, desktop integration, and sys Image Generation +### Seemless SillyTavern integration + +SillyTavern integration + diff --git a/package.json b/package.json index 5e994b2..454fe6a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gerbil", "productName": "Gerbil", - "version": "0.9.4", + "version": "0.9.5", "description": "Run Large Language Models locally", "main": "out/main/index.js", "homepage": "./", diff --git a/screenshots/download.png b/screenshots/download.png index 2f0fd1c..f33b8d6 100644 Binary files a/screenshots/download.png and b/screenshots/download.png differ diff --git a/screenshots/gen-img.png b/screenshots/gen-img.png index 2a0dd63..c4d7604 100644 Binary files a/screenshots/gen-img.png and b/screenshots/gen-img.png differ diff --git a/screenshots/launch.png b/screenshots/launch.png index 9e11d8a..4770470 100644 Binary files a/screenshots/launch.png and b/screenshots/launch.png differ diff --git a/screenshots/sillytavern.png b/screenshots/sillytavern.png new file mode 100644 index 0000000..62f56f0 Binary files /dev/null and b/screenshots/sillytavern.png differ diff --git a/screenshots/terminal.png b/screenshots/terminal.png index 23def94..33ff266 100644 Binary files a/screenshots/terminal.png and b/screenshots/terminal.png differ diff --git a/screenshots/text-story.png b/screenshots/text-story.png index c879a7f..a2b5e25 100644 Binary files a/screenshots/text-story.png and b/screenshots/text-story.png differ diff --git a/src/App.tsx b/src/App.tsx index 434aac8..b1ea04f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,7 +22,6 @@ export const App = () => { const [hasInitialized, setHasInitialized] = useState(false); const [activeInterfaceTab, setActiveInterfaceTab] = useState('terminal'); - const [isImageGenerationMode, setIsImageGenerationMode] = useState(false); const [frontendPreference, setFrontendPreference] = useState('koboldcpp'); @@ -159,6 +158,7 @@ export const App = () => { onTabChange={setActiveInterfaceTab} onEject={handleEject} onOpenSettings={() => setModalOpen('settings', true)} + frontendPreference={frontendPreference} /> @@ -191,10 +191,7 @@ export const App = () => { isActive={currentScreen === 'launch'} shouldAnimate={hasInitialized} > - + { )} - {showUpdateModal && binaryUpdateInfo && ( - - )} + - {arg.flag} + + {arg.flag} + {arg.aliases && arg.aliases.map((alias) => ( - + {alias} ))} diff --git a/src/components/ScreenTransition.tsx b/src/components/ScreenTransition.tsx index 3c67c71..1a508cc 100644 --- a/src/components/ScreenTransition.tsx +++ b/src/components/ScreenTransition.tsx @@ -22,11 +22,6 @@ export const ScreenTransition = ({
{children} diff --git a/src/components/TitleBar.tsx b/src/components/TitleBar.tsx index 106f406..6e78ee8 100644 --- a/src/components/TitleBar.tsx +++ b/src/components/TitleBar.tsx @@ -19,9 +19,10 @@ import { useState } from 'react'; import { soundAssets, playSound, initializeAudio } from '@/utils/sounds'; import { useAppUpdateChecker } from '@/hooks/useAppUpdateChecker'; import { useModalStore } from '@/stores/modal'; +import { useLaunchConfigStore } from '@/stores/launchConfig'; import iconUrl from '/icon.png'; -import { PRODUCT_NAME, TITLEBAR_HEIGHT } from '@/constants'; -import type { InterfaceTab, Screen } from '@/types'; +import { FRONTENDS, PRODUCT_NAME, TITLEBAR_HEIGHT } from '@/constants'; +import type { FrontendPreference, InterfaceTab, Screen } from '@/types'; interface TitleBarProps { currentScreen: Screen; @@ -29,6 +30,7 @@ interface TitleBarProps { onTabChange?: (tab: InterfaceTab) => void; onEject?: () => void; onOpenSettings?: () => void; + frontendPreference?: FrontendPreference; } export const TitleBar = ({ @@ -37,16 +39,19 @@ export const TitleBar = ({ onTabChange, onEject, onOpenSettings, + frontendPreference, }: TitleBarProps) => { const computedColorScheme = useComputedColorScheme('light', { getInitialValueInEffect: false, }); const { hasUpdate, openReleasePage } = useAppUpdateChecker(); const { isAnyModalOpen } = useModalStore(); + const { isImageGenerationMode } = useLaunchConfigStore(); const [logoClickCount, setLogoClickCount] = useState(0); const [isElephantMode, setIsElephantMode] = useState(false); const [isMouseSqueaking, setIsMouseSqueaking] = useState(false); const [isMaximized, setIsMaximized] = useState(false); + const [isSelectOpen, setIsSelectOpen] = useState(false); const handleMinimize = () => { window.electronAPI.app.minimizeWindow(); @@ -101,7 +106,8 @@ export const TitleBar = ({ ? 'var(--mantine-color-dark-7)' : 'var(--mantine-color-gray-0)', borderBottom: '1px solid var(--mantine-color-default-border)', - WebkitAppRegion: isAnyModalOpen() ? 'no-drag' : 'drag', + WebkitAppRegion: + isAnyModalOpen() || isSelectOpen ? 'no-drag' : 'drag', userSelect: 'none', position: 'relative', }} @@ -154,10 +160,17 @@ export const TitleBar = ({ onTabChange?.(value as InterfaceTab); } }} + onDropdownOpen={() => setIsSelectOpen(true)} + onDropdownClose={() => setIsSelectOpen(false)} data={[ { value: 'chat', - label: 'Chat', + label: + frontendPreference === 'sillytavern' + ? FRONTENDS.SILLYTAVERN + : isImageGenerationMode + ? FRONTENDS.STABLE_UI + : FRONTENDS.KOBOLDAI_LITE, }, { value: 'terminal', label: 'Terminal' }, { value: 'eject', label: 'Eject' }, @@ -167,7 +180,7 @@ export const TitleBar = ({ size="sm" style={{ textAlign: 'center', - minWidth: '120px', + minWidth: '7.5rem', }} styles={{ input: { diff --git a/src/components/UpdateAvailableModal.tsx b/src/components/UpdateAvailableModal.tsx index a8dac56..cfac1e5 100644 --- a/src/components/UpdateAvailableModal.tsx +++ b/src/components/UpdateAvailableModal.tsx @@ -19,8 +19,8 @@ import { safeExecute } from '@/utils/logger'; interface UpdateAvailableModalProps { opened: boolean; onClose: () => void; - currentVersion: InstalledVersion; - availableUpdate: DownloadItem; + currentVersion?: InstalledVersion; + availableUpdate?: DownloadItem; onUpdate: (download: DownloadItem) => Promise; isDownloading?: boolean; downloadProgress?: number; @@ -38,11 +38,13 @@ export const UpdateAvailableModal = ({ const [isUpdating, setIsUpdating] = useState(false); const handleUpdate = async () => { - setIsUpdating(true); - await safeExecute(async () => { - await onUpdate(availableUpdate); - onClose(); - }, 'Failed to update:'); + if (availableUpdate) { + setIsUpdating(true); + await safeExecute(async () => { + await onUpdate(availableUpdate); + onClose(); + }, 'Failed to update:'); + } setIsUpdating(false); }; @@ -65,7 +67,7 @@ export const UpdateAvailableModal = ({ Current Version - {currentVersion.version} + {currentVersion?.version}
@@ -78,14 +80,16 @@ export const UpdateAvailableModal = ({ Available Version - {availableUpdate.version} + {availableUpdate?.version}
- - Binary: {getDisplayNameFromPath(currentVersion)} - + {currentVersion && ( + + Binary: {getDisplayNameFromPath(currentVersion)} + + )} @@ -93,17 +97,17 @@ export const UpdateAvailableModal = ({ window.electronAPI.app.openExternal( - `https://github.com/${GITHUB_API.KOBOLDCPP_REPO}/releases/tag/v${availableUpdate.version}` + `https://github.com/${GITHUB_API.KOBOLDCPP_REPO}/releases/tag/v${availableUpdate?.version}` ) } > - v{availableUpdate.version} + v{availableUpdate?.version} diff --git a/src/components/screens/Download.tsx b/src/components/screens/Download.tsx index 0b8e4ec..fe86dce 100644 --- a/src/components/screens/Download.tsx +++ b/src/components/screens/Download.tsx @@ -65,7 +65,7 @@ export const DownloadScreen = ({ onDownloadComplete }: DownloadScreenProps) => { }, [downloading]); return ( - + diff --git a/src/components/screens/Interface/ServerTab.tsx b/src/components/screens/Interface/ServerTab.tsx index 56df6ea..cafafae 100644 --- a/src/components/screens/Interface/ServerTab.tsx +++ b/src/components/screens/Interface/ServerTab.tsx @@ -1,22 +1,20 @@ -import { useRef } from 'react'; import { Box, Text, Stack } from '@mantine/core'; -import { SILLYTAVERN, FRONTENDS } from '@/constants'; -import type { ServerTabMode, FrontendPreference } from '@/types'; +import { SILLYTAVERN, FRONTENDS, TITLEBAR_HEIGHT } from '@/constants'; +import { useLaunchConfigStore } from '@/stores/launchConfig'; +import type { FrontendPreference } from '@/types'; interface ServerTabProps { serverUrl?: string; isServerReady?: boolean; - mode: ServerTabMode; frontendPreference?: FrontendPreference; } export const ServerTab = ({ serverUrl, isServerReady, - mode, frontendPreference = 'koboldcpp', }: ServerTabProps) => { - const iframeRef = useRef(null); + const { isImageGenerationMode } = useLaunchConfigStore(); if (!isServerReady || !serverUrl) { return ( @@ -34,8 +32,8 @@ export const ServerTab = ({ Waiting for the KoboldCpp server to start... - The {mode === 'chat' ? 'chat' : 'image generation'} interface will - load automatically when ready + The {isImageGenerationMode ? 'image generation' : 'chat'} interface + will load automatically when ready @@ -49,23 +47,21 @@ export const ServerTab = ({ iframeUrl = SILLYTAVERN.PROXY_URL; title = FRONTENDS.SILLYTAVERN; } else { - iframeUrl = mode === 'image-generation' ? `${serverUrl}/sdui` : serverUrl; - title = - mode === 'image-generation' - ? FRONTENDS.STABLE_UI - : FRONTENDS.KOBOLDAI_LITE; + iframeUrl = isImageGenerationMode ? `${serverUrl}/sdui` : serverUrl; + title = isImageGenerationMode + ? FRONTENDS.STABLE_UI + : FRONTENDS.KOBOLDAI_LITE; } return (