refactor: replace captions tab switcher with import action button

This commit is contained in:
Maze Winther 2026-04-14 03:17:23 +02:00
parent d8214916e0
commit 7cb6983294
1 changed files with 60 additions and 93 deletions

View File

@ -7,7 +7,6 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useReducer, useRef, useState } from "react"; import { useReducer, useRef, useState } from "react";
import { extractTimelineAudio } from "@/lib/media/mediabunny"; import { extractTimelineAudio } from "@/lib/media/mediabunny";
import { useEditor } from "@/hooks/use-editor"; import { useEditor } from "@/hooks/use-editor";
@ -32,8 +31,8 @@ import {
SectionField, SectionField,
SectionFields, SectionFields,
} from "@/components/section"; } from "@/components/section";
import { CloudUploadIcon } from "@hugeicons/core-free-icons";
type CaptionsView = "generate" | "import"; import { HugeiconsIcon } from "@hugeicons/react";
type ProcessingState = type ProcessingState =
| { status: "idle"; error: string | null; warnings: string[] } | { status: "idle"; error: string | null; warnings: string[] }
@ -65,7 +64,6 @@ function processingReducer(
} }
export function Captions() { export function Captions() {
const [view, setView] = useState<CaptionsView>("generate");
const [selectedLanguage, setSelectedLanguage] = const [selectedLanguage, setSelectedLanguage] =
useState<TranscriptionLanguage>("auto"); useState<TranscriptionLanguage>("auto");
const [processing, dispatch] = useReducer(processingReducer, IDLE_STATE); const [processing, dispatch] = useReducer(processingReducer, IDLE_STATE);
@ -207,17 +205,20 @@ export function Captions() {
return ( return (
<PanelView <PanelView
title="Captions"
contentClassName="px-0 flex flex-col h-full" contentClassName="px-0 flex flex-col h-full"
actions={ actions={
<Tabs <Button
value={view} type="button"
onValueChange={(value) => setView(value as CaptionsView)} variant="outline"
size="sm"
onClick={handleImportClick}
disabled={isProcessing}
className="items-center justify-center gap-1.5"
> >
<TabsList> <HugeiconsIcon icon={CloudUploadIcon} />
<TabsTrigger value="generate">Generate</TabsTrigger> Import
<TabsTrigger value="import">Import</TabsTrigger> </Button>
</TabsList>
</Tabs>
} }
ref={containerRef} ref={containerRef}
> >
@ -228,88 +229,54 @@ export function Captions() {
className="hidden" className="hidden"
onChange={(event) => void handleFileChange({ event })} onChange={(event) => void handleFileChange({ event })}
/> />
{view === "generate" && ( <Section showTopBorder={false} showBottomBorder={false} className="flex-1">
<Section <SectionContent className="flex flex-col gap-4 h-full pt-1">
showTopBorder={false} <SectionFields>
showBottomBorder={false} <SectionField label="Language">
className="flex-1" <Select
> value={selectedLanguage}
<SectionContent className="flex flex-col gap-4 h-full pt-1"> onValueChange={(value) => handleLanguageChange({ value })}
<SectionFields> >
<SectionField label="Language"> <SelectTrigger>
<Select <SelectValue placeholder="Select a language" />
value={selectedLanguage} </SelectTrigger>
onValueChange={(value) => handleLanguageChange({ value })} <SelectContent>
> <SelectItem value="auto">Auto detect</SelectItem>
<SelectTrigger> {TRANSCRIPTION_LANGUAGES.map((language) => (
<SelectValue placeholder="Select a language" /> <SelectItem key={language.code} value={language.code}>
</SelectTrigger> {language.name}
<SelectContent> </SelectItem>
<SelectItem value="auto">Auto detect</SelectItem>
{TRANSCRIPTION_LANGUAGES.map((language) => (
<SelectItem key={language.code} value={language.code}>
{language.name}
</SelectItem>
))}
</SelectContent>
</Select>
</SectionField>
</SectionFields>
<Button
type="button"
className="mt-auto w-full"
onClick={handleGenerateTranscript}
disabled={isProcessing}
>
{isProcessing && <Spinner className="mr-1" />}
{isProcessing ? processing.step : "Generate transcript"}
</Button>
{error && (
<div className="bg-destructive/10 border-destructive/20 rounded-md border p-3">
<p className="text-destructive text-sm">{error}</p>
</div>
)}
</SectionContent>
</Section>
)}
{view === "import" && (
<Section
showTopBorder={false}
showBottomBorder={false}
className="flex-1"
>
<SectionContent className="flex flex-col gap-4 h-full pt-1">
<p className="text-muted-foreground text-sm">
Import an existing <code>.srt</code> or <code>.ass</code> subtitle
file into the timeline.
</p>
<Button
type="button"
className="mt-auto w-full"
onClick={handleImportClick}
disabled={isProcessing}
>
{isProcessing && <Spinner className="mr-1" />}
{isProcessing ? processing.step : "Import subtitles"}
</Button>
{error && (
<div className="bg-destructive/10 border-destructive/20 rounded-md border p-3">
<p className="text-destructive text-sm">{error}</p>
</div>
)}
{warnings.length > 0 && (
<div className="rounded-md border border-amber-500/20 bg-amber-500/10 p-3">
<ul className="space-y-1 text-sm text-amber-700">
{warnings.map((warning) => (
<li key={warning}>{warning}</li>
))} ))}
</ul> </SelectContent>
</div> </Select>
)} </SectionField>
</SectionContent> </SectionFields>
</Section>
)} <Button
type="button"
className="mt-auto w-full"
onClick={handleGenerateTranscript}
disabled={isProcessing}
>
{isProcessing && <Spinner className="mr-1" />}
{isProcessing ? processing.step : "Generate transcript"}
</Button>
{error && (
<div className="bg-destructive/10 border-destructive/20 rounded-md border p-3">
<p className="text-destructive text-sm">{error}</p>
</div>
)}
{warnings.length > 0 && (
<div className="rounded-md border border-amber-500/20 bg-amber-500/10 p-3">
<ul className="space-y-1 text-sm text-amber-700">
{warnings.map((warning) => (
<li key={warning}>{warning}</li>
))}
</ul>
</div>
)}
</SectionContent>
</Section>
</PanelView> </PanelView>
); );
} }