feat: 4K downloads, watch progress, player controls, new icon

Window chrome: titleBarStyle Overlay (Transparent left the native bar in
place, white in dark mode, with a dead strip beneath it). The app now
paints that strip itself, so it matches the page background.

Player: prev/next through the feed, a full-screen button, a spinner
while a stream resolves, Open on YouTube on downloaded videos too, and
the description collapsed behind a disclosure.

Downloads default to Best, which reaches real 4K — above 1080p YouTube
serves VP9/AV1, verified to play natively in WKWebView here. Audio stays
pinned to AAC because Opus in MP4 would be silent. A Compatible setting
keeps the old 1080p H.264 behaviour. Files are now named
'<ISO date> - <title> [<id>].mp4'.

Watch progress is recorded and drawn under thumbnails like YouTube's,
and reopening a video resumes where it left off.

Tiles clamp every text line to a fixed height so they share a baseline,
and the search field no longer clips its placeholder.

Fixes a Picture-in-Picture leak: WebKit kept a detached video playing
after the player closed, so a second video could play over the first
with no way to stop it. Every exit path now tears the element down.
This commit is contained in:
vincent
2026-08-29 04:03:45 +02:00
parent d0bad64d7c
commit 5b09acd28d
69 changed files with 582 additions and 89 deletions
+3 -1
View File
@@ -2,6 +2,7 @@ import { thumbSrc } from "../api";
import type { LiveDownload } from "../hooks/useDownloads";
import type { FeedItem } from "../types";
import DownloadButton from "./DownloadButton";
import WatchBar from "./WatchBar";
import { compactViews, relativeTime } from "./format";
interface Props {
@@ -48,12 +49,13 @@ export default function VideoRow({
)}
{downloaded && (
<span
className="absolute bottom-1 right-1 rounded bg-sky-500 px-1 py-0.5 text-[9px]
className="absolute bottom-1.5 right-1 rounded bg-sky-500 px-1 py-0.5 text-[9px]
font-bold uppercase tracking-widest leading-none text-white"
>
Offline
</span>
)}
<WatchBar item={item} />
</button>
<div className="min-w-0 flex-1">