Simplify CC dropdown: downloaded langs at top, YouTube langs below
Single CC chip shows downloaded langs inline. One click opens a dropdown with optgroups — already-on-disk at top, YouTube-available below loading async. No re-download needed to select an already-downloaded lang. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -671,8 +671,8 @@ export default function Watch() {
|
||||
const { data: subtitleFiles = [] } = useQuery({
|
||||
queryKey: ["subtitle-files", youtubeVideoId],
|
||||
queryFn: () => getSubtitleFiles(youtubeVideoId).then(r => r.data),
|
||||
enabled: fileReady,
|
||||
staleTime: Infinity,
|
||||
enabled: !!youtubeVideoId,
|
||||
staleTime: 60_000,
|
||||
});
|
||||
|
||||
const { data: dlStatus } = useQuery({
|
||||
@@ -995,41 +995,22 @@ export default function Watch() {
|
||||
)}
|
||||
|
||||
{(() => {
|
||||
// Subs already on disk → show langs + "+" to add more
|
||||
if (subtitleFiles.length > 0 && !subsRequested) return (
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="px-3 py-1.5 rounded-full bg-zinc-800 text-zinc-400 text-xs font-mono">
|
||||
CC: {subtitleFiles.map(s => s.lang).join(", ")}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setSubsRequested(true)}
|
||||
className="px-2.5 py-1.5 rounded-full text-xs bg-zinc-800 text-zinc-500 hover:bg-zinc-700 transition-colors"
|
||||
title="Add subtitle language"
|
||||
>+</button>
|
||||
</div>
|
||||
);
|
||||
// Not yet asked → show CC chip
|
||||
const onDisk = subtitleFiles.map(s => s.lang);
|
||||
const onDiskSet = new Set(onDisk);
|
||||
|
||||
if (!subsRequested) return (
|
||||
<button
|
||||
onClick={() => setSubsRequested(true)}
|
||||
className="flex items-center gap-1 px-3 py-1.5 rounded-full text-xs font-medium bg-zinc-800 text-zinc-400 hover:bg-zinc-700 transition-colors"
|
||||
title="Check available subtitles on YouTube"
|
||||
>
|
||||
CC
|
||||
CC{onDisk.length > 0 ? ` · ${onDisk.join(", ")}` : ""}
|
||||
</button>
|
||||
);
|
||||
// Loading YouTube subtitle list
|
||||
if (subsLoading) return (
|
||||
<span className="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-zinc-800 text-zinc-500 text-xs">
|
||||
<span className="w-3 h-3 border border-zinc-600 border-t-transparent rounded-full animate-spin inline-block" />
|
||||
CC
|
||||
</span>
|
||||
);
|
||||
const manual = new Set(availableSubs?.manual ?? []);
|
||||
const auto = (availableSubs?.auto ?? []).filter(l => !manual.has(l));
|
||||
if (!manual.size && !auto.length) return (
|
||||
<span className="px-3 py-1.5 rounded-full bg-zinc-800 text-zinc-600 text-xs">No CC</span>
|
||||
);
|
||||
|
||||
const ytManual = (availableSubs?.manual ?? []).filter(l => !onDiskSet.has(l));
|
||||
const ytAuto = (availableSubs?.auto ?? []).filter(l => !onDiskSet.has(l) && !ytManual.includes(l));
|
||||
const needsDownload = selectedSubLang && !onDiskSet.has(selectedSubLang);
|
||||
|
||||
return (
|
||||
<>
|
||||
<select
|
||||
@@ -1038,18 +1019,25 @@ export default function Watch() {
|
||||
className="bg-zinc-800 text-zinc-300 text-xs rounded-full px-3 py-2 border border-zinc-700 focus:outline-none focus:border-accent"
|
||||
>
|
||||
<option value="">No subtitles</option>
|
||||
{[...manual].map(l => <option key={l} value={l}>{l}</option>)}
|
||||
{auto.map(l => <option key={l} value={l}>{l} (auto)</option>)}
|
||||
{onDisk.length > 0 && (
|
||||
<optgroup label="— Downloaded —">
|
||||
{onDisk.map(l => <option key={l} value={l}>{l}</option>)}
|
||||
</optgroup>
|
||||
)}
|
||||
{(subsLoading || ytManual.length > 0 || ytAuto.length > 0) && (
|
||||
<optgroup label={subsLoading ? "— Loading YouTube… —" : "— Available on YouTube —"}>
|
||||
{ytManual.map(l => <option key={l} value={l}>{l}</option>)}
|
||||
{ytAuto.map(l => <option key={l} value={l}>{l} (auto)</option>)}
|
||||
</optgroup>
|
||||
)}
|
||||
</select>
|
||||
{dlComplete && selectedSubLang && (
|
||||
{dlComplete && needsDownload && (
|
||||
<button
|
||||
onClick={() => addSubsMut.mutate()}
|
||||
disabled={addSubsMut.isPending}
|
||||
className="flex items-center gap-1 px-3 py-1.5 rounded-full text-xs font-medium bg-accent text-black hover:bg-yellow-300 transition-colors disabled:opacity-50"
|
||||
>
|
||||
{addSubsMut.isPending ? (
|
||||
<span className="w-3 h-3 border-2 border-black/40 border-t-transparent rounded-full animate-spin inline-block" />
|
||||
) : null}
|
||||
{addSubsMut.isPending && <span className="w-3 h-3 border-2 border-black/40 border-t-transparent rounded-full animate-spin inline-block" />}
|
||||
{addSubsMut.isPending ? "Fetching…" : "Add subtitles"}
|
||||
</button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user