Refactor ProfileForm for improved readability and maintainability

- Reorganized import statements for clarity.
- Enhanced conditional checks for restoring saved files with improved formatting.
- Streamlined draft saving logic by consolidating variable declarations.
- Updated UI components for better structure and readability in the form layout.
This commit is contained in:
Jamie Pine
2026-01-29 18:56:22 -08:00
parent 7b5e73cfa8
commit ef3c3a7f8c
+229 -219
View File
@@ -43,7 +43,7 @@ import { useSystemAudioCapture } from '@/lib/hooks/useSystemAudioCapture';
import { useTranscription } from '@/lib/hooks/useTranscription'; import { useTranscription } from '@/lib/hooks/useTranscription';
import { isTauri } from '@/lib/tauri'; import { isTauri } from '@/lib/tauri';
import { formatAudioDuration, getAudioDuration } from '@/lib/utils/audio'; import { formatAudioDuration, getAudioDuration } from '@/lib/utils/audio';
import { useUIStore, type ProfileFormDraft } from '@/stores/uiStore'; import { type ProfileFormDraft, useUIStore } from '@/stores/uiStore';
import { AudioSampleRecording } from './AudioSampleRecording'; import { AudioSampleRecording } from './AudioSampleRecording';
import { AudioSampleSystem } from './AudioSampleSystem'; import { AudioSampleSystem } from './AudioSampleSystem';
import { AudioSampleUpload } from './AudioSampleUpload'; import { AudioSampleUpload } from './AudioSampleUpload';
@@ -265,11 +265,15 @@ export function ProfileForm() {
}); });
setSampleMode(profileFormDraft.sampleMode); setSampleMode(profileFormDraft.sampleMode);
// Restore the file if we have it saved // Restore the file if we have it saved
if (profileFormDraft.sampleFileData && profileFormDraft.sampleFileName && profileFormDraft.sampleFileType) { if (
profileFormDraft.sampleFileData &&
profileFormDraft.sampleFileName &&
profileFormDraft.sampleFileType
) {
const file = base64ToFile( const file = base64ToFile(
profileFormDraft.sampleFileData, profileFormDraft.sampleFileData,
profileFormDraft.sampleFileName, profileFormDraft.sampleFileName,
profileFormDraft.sampleFileType profileFormDraft.sampleFileType,
); );
form.setValue('sampleFile', file); form.setValue('sampleFile', file);
} }
@@ -446,7 +450,8 @@ export function ProfileForm() {
if (!newOpen && isCreating) { if (!newOpen && isCreating) {
// Save draft when closing the create modal // Save draft when closing the create modal
const values = form.getValues(); const values = form.getValues();
const hasContent = values.name || values.description || values.referenceText || values.sampleFile; const hasContent =
values.name || values.description || values.referenceText || values.sampleFile;
if (hasContent) { if (hasContent) {
const draft: ProfileFormDraft = { const draft: ProfileFormDraft = {
@@ -491,135 +496,116 @@ export function ProfileForm() {
<DialogContent className="max-w-none w-screen h-screen left-0 top-0 translate-x-0 translate-y-0 rounded-none p-6 overflow-y-auto"> <DialogContent className="max-w-none w-screen h-screen left-0 top-0 translate-x-0 translate-y-0 rounded-none p-6 overflow-y-auto">
<div className="max-w-5xl max-h-[85vh] mx-auto my-auto w-full flex flex-col"> <div className="max-w-5xl max-h-[85vh] mx-auto my-auto w-full flex flex-col">
<DialogHeader> <DialogHeader>
<DialogTitle className="text-2xl">{editingProfileId ? 'Edit Voice' : 'Clone voice'}</DialogTitle> <DialogTitle className="text-2xl">
<DialogDescription> {editingProfileId ? 'Edit Voice' : 'Clone voice'}
{editingProfileId </DialogTitle>
? 'Update your voice profile details and manage samples.' <DialogDescription>
: 'Create a new voice profile with an audio sample to clone the voice.'} {editingProfileId
</DialogDescription> ? 'Update your voice profile details and manage samples.'
{isCreating && profileFormDraft && ( : 'Create a new voice profile with an audio sample to clone the voice.'}
<div className="flex items-center gap-2 pt-2"> </DialogDescription>
<span className="text-xs text-muted-foreground">Draft restored</span> {isCreating && profileFormDraft && (
<Button <div className="flex items-center gap-2 pt-2">
type="button" <span className="text-xs text-muted-foreground">Draft restored</span>
variant="ghost" <Button
size="sm" type="button"
className="h-6 px-2 text-xs text-muted-foreground" variant="ghost"
onClick={() => { size="sm"
setProfileFormDraft(null); className="h-6 px-2 text-xs text-muted-foreground"
form.reset({ onClick={() => {
name: '', setProfileFormDraft(null);
description: '', form.reset({
language: 'en', name: '',
sampleFile: undefined, description: '',
referenceText: '', language: 'en',
}); sampleFile: undefined,
setSampleMode('record'); referenceText: '',
}} });
> setSampleMode('record');
<X className="h-3 w-3 mr-1" /> }}
Discard >
</Button> <X className="h-3 w-3 mr-1" />
</div> Discard
)} </Button>
</DialogHeader> </div>
)}
</DialogHeader>
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex-1 min-h-0 flex flex-col"> <form onSubmit={form.handleSubmit(onSubmit)} className="flex-1 min-h-0 flex flex-col">
<div className="grid gap-6 grid-cols-2 flex-1 overflow-y-auto min-h-0"> <div className="grid gap-6 grid-cols-2 flex-1 overflow-y-auto min-h-0">
{/* Left column: Sample management */} {/* Left column: Sample management */}
<div className="space-y-4 border-r pr-6"> <div className="space-y-4 border-r pr-6">
{isCreating ? ( {isCreating ? (
<> <>
<Tabs <Tabs
className="pt-4" className="pt-4"
value={sampleMode} value={sampleMode}
onValueChange={(v) => { onValueChange={(v) => {
const newMode = v as 'upload' | 'record' | 'system'; const newMode = v as 'upload' | 'record' | 'system';
// Cancel any active recordings when switching modes // Cancel any active recordings when switching modes
if (isRecording && newMode !== 'record') { if (isRecording && newMode !== 'record') {
cancelRecording(); cancelRecording();
} }
if (isSystemRecording && newMode !== 'system') { if (isSystemRecording && newMode !== 'system') {
cancelSystemRecording(); cancelSystemRecording();
} }
setSampleMode(newMode); setSampleMode(newMode);
}} }}
>
<TabsList
className={`grid w-full ${isTauri() && isSystemAudioSupported ? 'grid-cols-3' : 'grid-cols-2'}`}
> >
<TabsTrigger value="upload" className="flex items-center gap-2"> <TabsList
<Upload className="h-4 w-4 shrink-0" /> className={`grid w-full ${isTauri() && isSystemAudioSupported ? 'grid-cols-3' : 'grid-cols-2'}`}
Upload >
</TabsTrigger> <TabsTrigger value="upload" className="flex items-center gap-2">
<TabsTrigger value="record" className="flex items-center gap-2"> <Upload className="h-4 w-4 shrink-0" />
<Mic className="h-4 w-4 shrink-0" /> Upload
Record
</TabsTrigger>
{isTauri() && isSystemAudioSupported && (
<TabsTrigger value="system" className="flex items-center gap-2">
<Monitor className="h-4 w-4 shrink-0" />
System Audio
</TabsTrigger> </TabsTrigger>
)} <TabsTrigger value="record" className="flex items-center gap-2">
</TabsList> <Mic className="h-4 w-4 shrink-0" />
Record
<TabsContent value="upload" className="space-y-4"> </TabsTrigger>
<FormField {isTauri() && isSystemAudioSupported && (
control={form.control} <TabsTrigger value="system" className="flex items-center gap-2">
name="sampleFile" <Monitor className="h-4 w-4 shrink-0" />
render={({ field: { onChange, name } }) => ( System Audio
<AudioSampleUpload </TabsTrigger>
file={selectedFile}
onFileChange={onChange}
onTranscribe={handleTranscribe}
onPlayPause={handlePlayPause}
isPlaying={isPlaying}
isValidating={isValidatingAudio}
isTranscribing={transcribe.isPending}
isDisabled={
audioDuration !== null && audioDuration > MAX_AUDIO_DURATION_SECONDS
}
fieldName={name}
/>
)} )}
/> </TabsList>
</TabsContent>
<TabsContent value="record" className="space-y-4"> <TabsContent value="upload" className="space-y-4">
<FormField <FormField
control={form.control} control={form.control}
name="sampleFile" name="sampleFile"
render={() => ( render={({ field: { onChange, name } }) => (
<AudioSampleRecording <AudioSampleUpload
file={selectedFile} file={selectedFile}
isRecording={isRecording} onFileChange={onChange}
duration={duration} onTranscribe={handleTranscribe}
onStart={startRecording} onPlayPause={handlePlayPause}
onStop={stopRecording} isPlaying={isPlaying}
onCancel={handleCancelRecording} isValidating={isValidatingAudio}
onTranscribe={handleTranscribe} isTranscribing={transcribe.isPending}
onPlayPause={handlePlayPause} isDisabled={
isPlaying={isPlaying} audioDuration !== null &&
isTranscribing={transcribe.isPending} audioDuration > MAX_AUDIO_DURATION_SECONDS
/> }
)} fieldName={name}
/> />
</TabsContent> )}
/>
</TabsContent>
{isTauri() && isSystemAudioSupported && ( <TabsContent value="record" className="space-y-4">
<TabsContent value="system" className="space-y-4">
<FormField <FormField
control={form.control} control={form.control}
name="sampleFile" name="sampleFile"
render={() => ( render={() => (
<AudioSampleSystem <AudioSampleRecording
file={selectedFile} file={selectedFile}
isRecording={isSystemRecording} isRecording={isRecording}
duration={systemDuration} duration={duration}
onStart={startSystemRecording} onStart={startRecording}
onStop={stopSystemRecording} onStop={stopRecording}
onCancel={handleCancelRecording} onCancel={handleCancelRecording}
onTranscribe={handleTranscribe} onTranscribe={handleTranscribe}
onPlayPause={handlePlayPause} onPlayPause={handlePlayPause}
@@ -629,111 +615,135 @@ export function ProfileForm() {
)} )}
/> />
</TabsContent> </TabsContent>
)}
</Tabs>
<FormField {isTauri() && isSystemAudioSupported && (
control={form.control} <TabsContent value="system" className="space-y-4">
name="referenceText" <FormField
render={({ field }) => ( control={form.control}
<FormItem> name="sampleFile"
<FormLabel>Reference Text</FormLabel> render={() => (
<FormControl> <AudioSampleSystem
<Textarea file={selectedFile}
placeholder="Enter the exact text spoken in the audio..." isRecording={isSystemRecording}
className="min-h-[100px]" duration={systemDuration}
{...field} onStart={startSystemRecording}
onStop={stopSystemRecording}
onCancel={handleCancelRecording}
onTranscribe={handleTranscribe}
onPlayPause={handlePlayPause}
isPlaying={isPlaying}
isTranscribing={transcribe.isPending}
/>
)}
/> />
</FormControl> </TabsContent>
<FormMessage /> )}
</FormItem> </Tabs>
)}
/>
</>
) : (
// Show sample list when editing
editingProfileId && (
<div>
<SampleList profileId={editingProfileId} />
</div>
)
)}
</div>
{/* Right column: Profile info */} <FormField
<div className="space-y-4"> control={form.control}
<FormField name="referenceText"
control={form.control} render={({ field }) => (
name="name" <FormItem>
render={({ field }) => ( <FormLabel>Reference Text</FormLabel>
<FormItem> <FormControl>
<FormLabel>Name</FormLabel> <Textarea
<FormControl> placeholder="Enter the exact text spoken in the audio..."
<Input placeholder="My Voice" {...field} /> className="min-h-[100px]"
</FormControl> {...field}
<FormMessage /> />
</FormItem> </FormControl>
<FormMessage />
</FormItem>
)}
/>
</>
) : (
// Show sample list when editing
editingProfileId && (
<div>
<SampleList profileId={editingProfileId} />
</div>
)
)} )}
/> </div>
<FormField {/* Right column: Profile info */}
control={form.control} <div className="space-y-4">
name="description" <FormField
render={({ field }) => ( control={form.control}
<FormItem> name="name"
<FormLabel>Description (Optional)</FormLabel> render={({ field }) => (
<FormControl> <FormItem>
<Textarea placeholder="Describe this voice..." {...field} /> <FormLabel>Name</FormLabel>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="language"
render={({ field }) => (
<FormItem>
<FormLabel>Language</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl> <FormControl>
<SelectTrigger> <Input placeholder="My Voice" {...field} />
<SelectValue />
</SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <FormMessage />
{LANGUAGE_OPTIONS.map((lang) => ( </FormItem>
<SelectItem key={lang.value} value={lang.value}> )}
{lang.label} />
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
<div className="flex gap-2 justify-end mt-6 pt-4 border-t"> <FormField
<Button type="button" variant="outline" onClick={() => handleOpenChange(false)}> control={form.control}
Cancel name="description"
</Button> render={({ field }) => (
<Button <FormItem>
type="submit" <FormLabel>Description (Optional)</FormLabel>
disabled={createProfile.isPending || updateProfile.isPending || addSample.isPending} <FormControl>
> <Textarea placeholder="Describe this voice..." {...field} />
{createProfile.isPending || updateProfile.isPending || addSample.isPending </FormControl>
? 'Saving...' <FormMessage />
: editingProfileId </FormItem>
? 'Save Changes' )}
: 'Create Profile'} />
</Button>
</div> <FormField
</form> control={form.control}
</Form> name="language"
render={({ field }) => (
<FormItem>
<FormLabel>Language</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
</FormControl>
<SelectContent>
{LANGUAGE_OPTIONS.map((lang) => (
<SelectItem key={lang.value} value={lang.value}>
{lang.label}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
<div className="flex gap-2 justify-end mt-6 pt-4 border-t">
<Button type="button" variant="outline" onClick={() => handleOpenChange(false)}>
Cancel
</Button>
<Button
type="submit"
disabled={
createProfile.isPending || updateProfile.isPending || addSample.isPending
}
>
{createProfile.isPending || updateProfile.isPending || addSample.isPending
? 'Saving...'
: editingProfileId
? 'Save Changes'
: 'Create Profile'}
</Button>
</div>
</form>
</Form>
</div> </div>
</DialogContent> </DialogContent>
</Dialog> </Dialog>