feat: subtitles, delete-all, auto refresh, and menu cleanup
Subtitles: a language preference in Settings drives what is shown and what is downloaded. yt-dlp saves WebVTT sidecars next to each download, including YouTube's auto-generated track, and the player attaches them as <track> elements so they work offline. Sidecars are removed with their video, and by Delete all. WebVTT rather than muxed subtitle streams because WebKit reads a <track> reliably and largely ignores subtitle tracks inside an MP4. Downloads in progress now appear under the downloaded-only filter, so a download you just started does not vanish from the list you are watching it in. That view also gains a Delete all, behind a confirmation naming what goes. The feed refreshes on launch and whenever the player closes, so the Refresh button is only for staleness. Player: Delete moved to the footer and shortened, Open on YouTube is now an external-link icon. Removes the Edit and Help menus. Cut/Copy/Paste move to the app menu, without which their shortcuts would stop working in the search field. The webview context menu is suppressed outside text fields — its Reload and Back items act on a page the app does not present as one. Settings now warns that 4K AV1 plays back with artefacts: the files decode cleanly in ffmpeg, so it is the built-in decoder, not the download.
This commit is contained in:
@@ -21,6 +21,8 @@ interface Props {
|
||||
onView: (v: ViewMode) => void;
|
||||
sidebarHidden: boolean;
|
||||
onShowSidebar: () => void;
|
||||
/** Present only when there is something to delete. */
|
||||
onDeleteAll?: () => void;
|
||||
/** Matches the sidebar's inset so the two headers share a baseline. */
|
||||
titleBarInset: boolean;
|
||||
}
|
||||
@@ -58,7 +60,7 @@ export default function TopBar({
|
||||
search, onSearch, downloadedOnly, onDownloadedOnly, hideShorts, onHideShorts,
|
||||
online, reachable, forcedOffline, onToggleForcedOffline,
|
||||
onRefresh, refreshing, refreshProgress, resultCount, view, onView,
|
||||
sidebarHidden, onShowSidebar, titleBarInset,
|
||||
sidebarHidden, onShowSidebar, onDeleteAll, titleBarInset,
|
||||
}: Props) {
|
||||
const pct = refreshProgress && refreshProgress.total > 0
|
||||
? (refreshProgress.done / refreshProgress.total) * 100
|
||||
@@ -105,6 +107,20 @@ export default function TopBar({
|
||||
Downloaded only
|
||||
</Toggle>
|
||||
|
||||
{downloadedOnly && onDeleteAll && (
|
||||
<button
|
||||
onClick={onDeleteAll}
|
||||
title="Delete every download"
|
||||
className={`inline-flex ${CONTROL_H} cursor-pointer items-center whitespace-nowrap
|
||||
rounded-lg border border-slate-300 px-2.5 text-[12px] font-medium
|
||||
text-slate-500 hover:border-red-500 hover:text-red-600
|
||||
dark:border-slate-700 dark:text-slate-400 dark:hover:border-red-500
|
||||
dark:hover:text-red-400`}
|
||||
>
|
||||
Delete all
|
||||
</button>
|
||||
)}
|
||||
|
||||
<Toggle active={hideShorts} onClick={() => onHideShorts(!hideShorts)}
|
||||
title="Hide Shorts from the feed">
|
||||
Hide Shorts
|
||||
|
||||
Reference in New Issue
Block a user