fix(player): first-class maximise/fullscreen view (UAT round)
UAT feedback on the F-maximise view — three fixes: - Own control bar in the big views (maximise + our fullscreen): previous/next + N/M, auto-advance, loop, add-to-playlist, download, mark-watched, exit, and a true-fullscreen toggle. Auto-hides on idle. Add/download are hidden in true fullscreen (their popovers portal to <body>, outside the fullscreen element). - Wheel volume works in the big views again: the centre interaction overlay is now armed in maximise/fullscreen (it only yields to YouTube's own settings menu), so the wheel bubbles to our handler instead of the bare iframe. F also offers true fullscreen that WE own (Fullscreen API on the stage), so wheel/ arrow volume and our controls work inside it too — YouTube's own fullscreen button, which we never surface, is not involved. - Back (mouse/browser) steps out one level at a time via nested history layers (useBackToExit): fullscreen -> maximise -> the modal -> closed, instead of closing the whole player at once. Verified in Chrome: wheel volume in maximise + fullscreen, the control bar, and the full Back ladder (fullscreen -> maximise -> modal -> closed).
This commit is contained in:
@@ -114,3 +114,26 @@ export function useBackToClose(onClose: () => void): void {
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
|
||||
/** A Back-closable layer that exists only WHILE `active`. Stacks on top of `useBackToClose` and any
|
||||
* other active `useBackToExit` (LIFO) so nested views peel off one Back at a time — e.g. a player's
|
||||
* fullscreen sits above its maximise, which sits above the player itself: Back exits fullscreen,
|
||||
* then maximise, then closes the player. Leaving a layer by its own control (button/Esc) flips
|
||||
* `active` false, whose cleanup drops the entry and its history state on the next tick — exactly the
|
||||
* useBackToClose lifecycle, just gated on a flag. `onExit` runs on a genuine Back while active. */
|
||||
export function useBackToExit(active: boolean, onExit: () => void): void {
|
||||
const cb = useRef(onExit);
|
||||
cb.current = onExit;
|
||||
useEffect(() => {
|
||||
if (!active) return;
|
||||
ensureOverlayListener();
|
||||
const entry: Overlay = { token: ++overlayCounter, cb: () => cb.current() };
|
||||
overlayStack.push(entry);
|
||||
scheduleReconcile();
|
||||
return () => {
|
||||
const idx = overlayStack.indexOf(entry);
|
||||
if (idx !== -1) overlayStack.splice(idx, 1);
|
||||
scheduleReconcile();
|
||||
};
|
||||
}, [active]);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ export const RELEASE_NOTES: ReleaseEntry[] = [
|
||||
summary:
|
||||
"A sturdier player — press F to go big, arrow-key volume that's remembered — plus downloads and subscription sync that hold up when something goes wrong.",
|
||||
features: [
|
||||
"Player: press F to maximise the video to a full-window view, and use the ↑/↓ arrow keys to change the volume — your level is now remembered per account. Ctrl+scroll zooms the page as usual again instead of being captured by the player.",
|
||||
"The maximised view no longer blocks YouTube's own fullscreen button or on-video controls, keyboard shortcuts keep working after you click into the video, and exiting the view returns keyboard focus to the app. Both the YouTube and the local/Plex player behave the same way.",
|
||||
"Player: press F to maximise the video to a full-window view — now with its own control bar (previous/next, auto-advance, loop, add-to-playlist, download, mark watched) that auto-hides while you watch, plus a button for true fullscreen. Scroll-wheel and ↑/↓ volume work in every mode (the full window and fullscreen too), and your volume is remembered per account.",
|
||||
"Volume: Ctrl+scroll zooms the page as usual again instead of being captured by the player. Keyboard shortcuts keep working after you click into the video, and the mouse/browser Back button now steps out one level at a time (fullscreen → full window → the normal player → closed) instead of closing the whole player at once.",
|
||||
],
|
||||
fixes: [
|
||||
"Downloads: fixed a class of downloads that could fail with an internal error (a produced file the downloader couldn't locate), and mp4 downloads are no longer needlessly re-encoded — they finish faster and keep their original quality.",
|
||||
|
||||
Reference in New Issue
Block a user