From 8b67faf96d89de745b22840a217ed6d81ef668e6 Mon Sep 17 00:00:00 2001 From: Jamie Pine Date: Mon, 26 Jan 2026 19:22:43 -0800 Subject: [PATCH 01/16] Enhance update status display and audio sample components - Improved the UpdateStatus component to show download progress and total bytes downloaded during updates. - Refactored AudioSampleRecording and AudioSampleSystem components for cleaner button rendering and consistent layout. - Updated import order in SampleUpload component for better organization. --- .../ServerSettings/UpdateStatus.tsx | 20 +++++++-- .../VoiceProfiles/AudioSampleRecording.tsx | 20 ++------- .../VoiceProfiles/AudioSampleSystem.tsx | 20 ++------- .../components/VoiceProfiles/SampleUpload.tsx | 4 +- app/src/hooks/useAutoUpdater.ts | 41 +++++++++++++++---- 5 files changed, 60 insertions(+), 45 deletions(-) diff --git a/app/src/components/ServerSettings/UpdateStatus.tsx b/app/src/components/ServerSettings/UpdateStatus.tsx index 7e1e160d..31e4640b 100644 --- a/app/src/components/ServerSettings/UpdateStatus.tsx +++ b/app/src/components/ServerSettings/UpdateStatus.tsx @@ -71,11 +71,23 @@ export function UpdateStatus() { {status.downloading && (
-
- - Downloading update... +
+
+ + Downloading update... +
+ {status.downloadProgress !== undefined && ( + + {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 +
+ )}
)} diff --git a/app/src/components/VoiceProfiles/AudioSampleRecording.tsx b/app/src/components/VoiceProfiles/AudioSampleRecording.tsx index 34c3c372..9c7c9b62 100644 --- a/app/src/components/VoiceProfiles/AudioSampleRecording.tsx +++ b/app/src/components/VoiceProfiles/AudioSampleRecording.tsx @@ -1,4 +1,4 @@ -import { Mic, Square, Play, Pause } from 'lucide-react'; +import { Mic, Pause, Play, Square } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { FormControl, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; import { formatAudioDuration } from '@/lib/utils/audio'; @@ -35,12 +35,7 @@ export function AudioSampleRecording({
{!isRecording && !file && (
- @@ -81,16 +76,9 @@ export function AudioSampleRecording({ Recording complete
-

- File: {file.name} -

+

File: {file.name}

- @@ -81,16 +76,9 @@ export function AudioSampleSystem({ Capture complete
-

- File: {file.name} -

+

File: {file.name}

-
- { - e.stopPropagation(); - setDetailOpen(true); - }} - aria-label="View details" - /> - - diff --git a/app/src/components/VoiceProfiles/ProfileDetail.tsx b/app/src/components/VoiceProfiles/ProfileDetail.tsx deleted file mode 100644 index 60527aa3..00000000 --- a/app/src/components/VoiceProfiles/ProfileDetail.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { Badge } from '@/components/ui/badge'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog'; -import { useProfile } from '@/lib/hooks/useProfiles'; -import { formatDate } from '@/lib/utils/format'; -import { SampleList } from './SampleList'; - -interface ProfileDetailProps { - profileId: string; - open: boolean; - onOpenChange: (open: boolean) => void; -} - -export function ProfileDetail({ profileId, open, onOpenChange }: ProfileDetailProps) { - const { data: profile, isLoading } = useProfile(profileId); - - if (isLoading) { - return ( - - -
Loading profile...
-
-
- ); - } - - if (!profile) { - return null; - } - - return ( - - - - {profile.name} - Manage samples and view profile details - - -
- {profile.description && ( -
-

Description

-

{profile.description}

-
- )} - -
- {profile.language} - - Created {formatDate(profile.created_at)} - -
- -
- -
-
-
-
- ); -} diff --git a/app/src/components/VoiceProfiles/ProfileForm.tsx b/app/src/components/VoiceProfiles/ProfileForm.tsx index f10798f9..19e6c13a 100644 --- a/app/src/components/VoiceProfiles/ProfileForm.tsx +++ b/app/src/components/VoiceProfiles/ProfileForm.tsx @@ -47,6 +47,7 @@ import { useUIStore } from '@/stores/uiStore'; import { AudioSampleRecording } from './AudioSampleRecording'; import { AudioSampleSystem } from './AudioSampleSystem'; import { AudioSampleUpload } from './AudioSampleUpload'; +import { SampleList } from './SampleList'; // Helper function to get audio duration from File async function getAudioDuration(file: File & { recordedDuration?: number }): Promise { @@ -325,7 +326,7 @@ export function ProfileForm() { }, }); toast({ - title: 'Profile updated', + title: 'Voice updated', description: `"${data.name}" has been updated successfully.`, }); } else { @@ -446,17 +447,17 @@ export function ProfileForm() { - {editingProfileId ? 'Edit Profile' : 'Create Voice Profile'} + {editingProfileId ? 'Edit Voice' : 'Create Voice Profile'} {editingProfileId - ? 'Update your voice profile details.' + ? 'Update your voice profile details and manage samples.' : 'Create a new voice profile with an audio sample to clone the voice.'}
-
+
{/* Left column: Profile info */}
- {/* Right column: Sample upload section - only show when creating */} - {isCreating && ( -
-
-

Add Sample

-

- Provide an audio sample to clone the voice. You can add more samples later. -

-
+ {/* Right column: Sample management */} +
+ {isCreating ? ( + <> +
+

Add Sample

+

+ Provide an audio sample to clone the voice. You can add more samples later. +

+
- ( - - Reference Text - -