feat: uniform control height, chrome auto-hide, streaming quality

Every control in the app now shares one height (CONTROL_H), with width
still growing to fit its label. The player transport is larger, Back is
an icon, and the footer buttons match the prev/next size.

Player chrome — transport and edge arrows — fades after 2.6s of
inactivity and never hides while paused.

The title-bar strip collapses in macOS window fullscreen, where the
traffic lights are gone and it was just a blank white bar.

Streaming quality is now selectable alongside download quality. A cap is
applied by rewriting YouTube's HLS master playlist down to the best
variant at or below the chosen height, keeping its audio group. That
playlist is served from a small loopback HTTP server: Safari's native
HLS is backed by AVFoundation, which cannot read blob: or custom-scheme
URLs, so a Blob URL silently fails to play.

Settings closes with an icon button and its selects match the shared
control height.
This commit is contained in:
vincent
2026-08-29 11:28:05 +02:00
parent 211823f265
commit 9bb7b71225
16 changed files with 503 additions and 92 deletions
+24
View File
@@ -0,0 +1,24 @@
import { getCurrentWindow } from "@tauri-apps/api/window";
import { useEffect, useState } from "react";
/**
* True while the macOS *window* is fullscreen (the green button), as distinct
* from the video being fullscreen. In that state the traffic lights are gone,
* so the title-bar strip the app paints is pure dead space and must collapse.
*/
export function useWindowFullscreen(): boolean {
const [full, setFull] = useState(false);
useEffect(() => {
const win = getCurrentWindow();
let unlisten: (() => void) | undefined;
const check = () => {
win.isFullscreen().then(setFull).catch(() => {});
};
check();
win.onResized(check).then((u) => (unlisten = u));
return () => unlisten?.();
}, []);
return full;
}