diff --git a/app/src/components/ServerSettings/ConnectionForm.tsx b/app/src/components/ServerSettings/ConnectionForm.tsx
index cc1e2d1d..84cf9dac 100644
--- a/app/src/components/ServerSettings/ConnectionForm.tsx
+++ b/app/src/components/ServerSettings/ConnectionForm.tsx
@@ -1,6 +1,6 @@
import { zodResolver } from '@hookform/resolvers/zod';
-import { useForm } from 'react-hook-form';
import { useEffect } from 'react';
+import { useForm } from 'react-hook-form';
import * as z from 'zod';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@@ -14,11 +14,10 @@ import {
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
+import { Checkbox } from '@/components/ui/checkbox';
import { useToast } from '@/components/ui/use-toast';
import { useServerStore } from '@/stores/serverStore';
import { setKeepServerRunning } from '@/lib/tauri';
-import { Check } from 'lucide-react';
-import { cn } from '@/lib/utils/cn';
const connectionSchema = z.object({
serverUrl: z.string().url('Please enter a valid URL'),
@@ -84,41 +83,36 @@ export function ConnectionForm() {
-
{
- const newValue = !keepServerRunningOnClose;
- setKeepServerRunningOnClose(newValue);
- setKeepServerRunning(newValue).catch((error) => {
- console.error('Failed to sync setting to Rust:', error);
- });
- toast({
- title: 'Setting updated',
- description: newValue
- ? 'Server will continue running when app closes'
- : 'Server will stop when app closes',
- });
- }}
- className="flex items-start gap-3 text-left w-full"
- >
-
- {keepServerRunningOnClose && }
-
+
+
{
+ setKeepServerRunningOnClose(checked);
+ setKeepServerRunning(checked).catch((error) => {
+ console.error('Failed to sync setting to Rust:', error);
+ });
+ toast({
+ title: 'Setting updated',
+ description: checked
+ ? 'Server will continue running when app closes'
+ : 'Server will stop when app closes',
+ });
+ }}
+ />
-
+
Keep server running when app closes
-
+
When enabled, the server will continue running in the background after closing the
app. Disabled by default.
-
+
diff --git a/app/src/components/ServerSettings/ModelManagement.tsx b/app/src/components/ServerSettings/ModelManagement.tsx
index 776d5077..4d3975e5 100644
--- a/app/src/components/ServerSettings/ModelManagement.tsx
+++ b/app/src/components/ServerSettings/ModelManagement.tsx
@@ -1,4 +1,4 @@
-import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Download, Loader2, Trash2 } from 'lucide-react';
import { useState } from 'react';
import {
diff --git a/app/src/components/ServerSettings/ModelProgress.tsx b/app/src/components/ServerSettings/ModelProgress.tsx
index 4f651a7f..ae882c1a 100644
--- a/app/src/components/ServerSettings/ModelProgress.tsx
+++ b/app/src/components/ServerSettings/ModelProgress.tsx
@@ -1,9 +1,9 @@
-import { useEffect, useState } from 'react';
-import { Progress } from '@/components/ui/progress';
-import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
-import { useServerStore } from '@/stores/serverStore';
-import type { ModelProgress as ModelProgressType } from '@/lib/api/types';
import { Loader2, XCircle } from 'lucide-react';
+import { useEffect, useState } from 'react';
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
+import { Progress } from '@/components/ui/progress';
+import type { ModelProgress as ModelProgressType } from '@/lib/api/types';
+import { useServerStore } from '@/stores/serverStore';
interface ModelProgressProps {
modelName: string;
@@ -63,7 +63,7 @@ export function ModelProgress({ modelName, displayName }: ModelProgressProps) {
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
- return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
+ return `${(bytes / k ** i).toFixed(1)} ${sizes[i]}`;
};
const getStatusIcon = () => {
diff --git a/app/src/components/ServerSettings/UpdateStatus.tsx b/app/src/components/ServerSettings/UpdateStatus.tsx
index d0d122e4..c946e421 100644
--- a/app/src/components/ServerSettings/UpdateStatus.tsx
+++ b/app/src/components/ServerSettings/UpdateStatus.tsx
@@ -1,11 +1,11 @@
-import { useState, useEffect } from 'react';
+import { getVersion } from '@tauri-apps/api/app';
import { RefreshCw, Download, AlertCircle } from 'lucide-react';
+import { useEffect, useState } from 'react';
+import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
-import { Badge } from '@/components/ui/badge';
import { Progress } from '@/components/ui/progress';
import { useAutoUpdater } from '@/hooks/useAutoUpdater';
-import { getVersion } from '@tauri-apps/api/app';
export function UpdateStatus() {
const { status, checkForUpdates, downloadAndInstall, restartAndInstall } = useAutoUpdater(false);
@@ -77,17 +77,18 @@ export function UpdateStatus() {
Downloading update...
{status.downloadProgress !== undefined && (
-
- {status.downloadProgress}%
-
+ {status.downloadProgress}%
)}
- {status.downloadedBytes !== undefined && status.totalBytes !== undefined && status.totalBytes > 0 && (
-
- {(status.downloadedBytes / 1024 / 1024).toFixed(1)} MB / {(status.totalBytes / 1024 / 1024).toFixed(1)} MB
-
- )}
+ {status.downloadedBytes !== undefined &&
+ status.totalBytes !== undefined &&
+ status.totalBytes > 0 && (
+
+ {(status.downloadedBytes / 1024 / 1024).toFixed(1)} MB /{' '}
+ {(status.totalBytes / 1024 / 1024).toFixed(1)} MB
+
+ )}
)}
@@ -96,11 +97,14 @@ export function UpdateStatus() {
Update Ready to Install
-
Version {status.version} has been downloaded
+
+ Version {status.version} has been downloaded
+
- The app needs to restart to complete the installation. You can do this now or later at your convenience.
+ The app needs to restart to complete the installation. You can do this now or later at
+ your convenience.
diff --git a/app/src/components/ui/checkbox.tsx b/app/src/components/ui/checkbox.tsx
index 6ae7d75b..f423fef0 100644
--- a/app/src/components/ui/checkbox.tsx
+++ b/app/src/components/ui/checkbox.tsx
@@ -1,33 +1,41 @@
import * as React from 'react';
+import { Check } from 'lucide-react';
import { cn } from '@/lib/utils/cn';
-export interface CheckboxProps extends React.InputHTMLAttributes {
+export interface CheckboxProps {
+ checked?: boolean;
onCheckedChange?: (checked: boolean) => void;
+ disabled?: boolean;
+ className?: string;
+ id?: string;
}
-const Checkbox = React.forwardRef(
- ({ className, onCheckedChange, ...props }, ref) => {
- const handleChange = (e: React.ChangeEvent) => {
- if (onCheckedChange) {
- onCheckedChange(e.target.checked);
- }
- // Call original onChange if provided
- if (props.onChange) {
- props.onChange(e);
- }
- };
-
+const Checkbox = React.forwardRef(
+ ({ checked = false, onCheckedChange, disabled = false, className, id, ...props }, ref) => {
return (
- {
+ if (!disabled && onCheckedChange) {
+ onCheckedChange(!checked);
+ }
+ }}
className={cn(
- 'h-4 w-4 rounded border-gray-300 text-primary focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
+ 'h-4 w-4 rounded border-2 flex items-center justify-center shrink-0 transition-colors',
+ checked ? 'bg-accent border-accent' : 'border-muted-foreground/30',
+ disabled && 'opacity-50 cursor-not-allowed',
+ !disabled && 'cursor-pointer',
className,
)}
- ref={ref}
- onChange={handleChange}
{...props}
- />
+ >
+ {checked && }
+
);
},
);