revert(player): drop the experimental HD-unlock fullscreen flash
User-tested on prod: the flash fires (fullscreen → back to small) but the source stays 360p — YouTube doesn't switch quality within the flash window and we can't set it via the (dead) API, so the unlock has no effect. Give up on forcing windowed HD. Restore PlayerModal to its 0.36.2 state (native-menu-yield + scroll-anywhere volume kept). Also prune the failed HD-quality attempts from the release notes (the flash and the transform-revert notes, plus the hollow 'higher quality' claim in 0.36.0) so there's no user-facing trace of an effort that yielded nothing.
This commit is contained in:
parent
5d3dce6214
commit
f76b80a946
3 changed files with 12 additions and 81 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.36.3
|
||||
0.36.4
|
||||
|
|
@ -20,14 +20,6 @@ import { useBackToClose } from "../lib/history";
|
|||
// How close to the end (seconds) counts as "finished" → auto-mark watched.
|
||||
const FINISH_MARGIN = 10;
|
||||
|
||||
// One-time HD-unlock (see attemptHdUnlock). YouTube hard-caps a windowed embed to ~360p and only a
|
||||
// real fullscreen lifts the cap; the lift then persists for the whole page session. So on the first
|
||||
// video opened we briefly flash the player to fullscreen and back to coax YouTube past the cap once.
|
||||
// Cap the flash at this many ms, but exit as soon as we see the quality actually rise.
|
||||
const HD_UNLOCK_MAX_MS = 2500;
|
||||
// Module-scoped so the flash happens only ONCE per page session (the unlock persists afterwards).
|
||||
let hdUnlockDone = false;
|
||||
|
||||
// Persistent playback settings (stored in users.preferences). Auto-advance = what plays when a
|
||||
// video ends; loop = whether it repeats the current video ("one"), wraps the list at its ends
|
||||
// ("all"), or neither ("off"). Both apply to any queued player (feed or playlist).
|
||||
|
|
@ -132,9 +124,6 @@ export default function PlayerModal({
|
|||
// modal adjusts volume (not just the small player area).
|
||||
const dialogRef = useRef<HTMLDivElement | null>(null);
|
||||
const volTimerRef = useRef<number | undefined>(undefined);
|
||||
// HD-unlock flash bookkeeping (see attemptHdUnlock / finishHdUnlock).
|
||||
const unlockTimerRef = useRef<number | undefined>(undefined);
|
||||
const unlockingRef = useRef(false);
|
||||
// Volume level to flash in the on-player overlay (null = hidden). Auto-fades after a moment.
|
||||
const [volumeUi, setVolumeUi] = useState<number | null>(null);
|
||||
// When the user interacts with YouTube's own controls (gear/seek/CC), focus moves into the
|
||||
|
|
@ -157,32 +146,6 @@ export default function PlayerModal({
|
|||
if (document.fullscreenElement) document.exitFullscreen?.();
|
||||
else el.requestFullscreen?.();
|
||||
};
|
||||
// End the HD-unlock flash: exit fullscreen (if we're still in it) and mark the session unlocked so
|
||||
// it never flashes again. Called either when YouTube's quality is seen to rise or on the max timeout.
|
||||
const finishHdUnlock = () => {
|
||||
if (!unlockingRef.current) return;
|
||||
unlockingRef.current = false;
|
||||
window.clearTimeout(unlockTimerRef.current);
|
||||
hdUnlockDone = true;
|
||||
if (document.fullscreenElement) document.exitFullscreen?.().catch(() => {});
|
||||
};
|
||||
// Coax YouTube past its windowed 360p cap: on the first opened video, briefly enter fullscreen so
|
||||
// YouTube lifts the cap (which then persists for the session), then exit back to the small player.
|
||||
// Needs live user activation (the modal-open click) — silently retried on the next click if it's
|
||||
// already expired, and a no-op once the session is unlocked. Best-effort; can't be forced further.
|
||||
const attemptHdUnlock = () => {
|
||||
if (hdUnlockDone || unlockingRef.current) return;
|
||||
const el = stageRef.current;
|
||||
if (!el || !el.requestFullscreen || document.fullscreenElement) return;
|
||||
el.requestFullscreen()
|
||||
.then(() => {
|
||||
unlockingRef.current = true;
|
||||
unlockTimerRef.current = window.setTimeout(finishHdUnlock, HD_UNLOCK_MAX_MS);
|
||||
})
|
||||
.catch(() => {
|
||||
/* no user activation yet / fullscreen blocked — leave hdUnlockDone false to retry on a click */
|
||||
});
|
||||
};
|
||||
const flashVolume = (level: number) => {
|
||||
setVolumeUi(level);
|
||||
window.clearTimeout(volTimerRef.current);
|
||||
|
|
@ -525,24 +488,18 @@ export default function PlayerModal({
|
|||
playsinline: 1,
|
||||
// Best-effort HD hint. The IFrame API's setPlaybackQuality/suggestedQuality are hard no-ops
|
||||
// now (YouTube removed them), and the undocumented `vq` URL param is only occasionally
|
||||
// honoured — kept because it's harmless. YouTube hard-caps an embed's max quality by the
|
||||
// player's on-screen size; a windowed embed is stuck ~360p and only true fullscreen lifts
|
||||
// the cap (then it persists for the session). A CSS transform-scale trick does NOT fool it;
|
||||
// we instead do a one-time fullscreen flash on open (see attemptHdUnlock) to lift the cap.
|
||||
// honoured — kept because it's harmless. NOTE: YouTube hard-caps an embed's max quality by
|
||||
// the player's on-screen size; a windowed embed is stuck ~360p and only true fullscreen
|
||||
// lifts the cap (after which the higher pick persists for the session). We can't beat that
|
||||
// programmatically — a CSS transform-scale trick was tried and does NOT fool the cap.
|
||||
vq: "hd1080",
|
||||
},
|
||||
events: {
|
||||
// Keep keyboard focus on the modal, not the iframe, so shortcuts work right away, and try
|
||||
// the one-time HD-unlock flash while the modal-open click is still a live user activation.
|
||||
onReady: () => {
|
||||
focusModal();
|
||||
attemptHdUnlock();
|
||||
},
|
||||
// Keep keyboard focus on the modal, not the iframe, so shortcuts work right away.
|
||||
onReady: () => focusModal(),
|
||||
onStateChange: (e: any) => {
|
||||
// 1 === playing → sync the navigated-to video's title/author for display, and retry the
|
||||
// HD-unlock (a second chance at the flash right as playback begins).
|
||||
// 1 === playing → sync the navigated-to video's title/author for display.
|
||||
if (e?.data === 1) {
|
||||
attemptHdUnlock();
|
||||
const p = playerRef.current;
|
||||
const d = p && typeof p.getVideoData === "function" ? p.getVideoData() : null;
|
||||
if (d) setLiveData({ title: d.title, author: d.author });
|
||||
|
|
@ -556,15 +513,6 @@ export default function PlayerModal({
|
|||
advanceOnEnd();
|
||||
}
|
||||
},
|
||||
// While the HD-unlock flash is running, exit fullscreen as soon as YouTube's quality is
|
||||
// seen to rise (no need to hold the flash the full timeout). onPlaybackQualityChange is one
|
||||
// of the few still-live quality signals; e.data is a label ("hd1080"/"hd720"/"large"/…).
|
||||
onPlaybackQualityChange: (e: any) => {
|
||||
const q = String(e?.data || "");
|
||||
if (unlockingRef.current && (q === "hd1080" || q === "hd720" || q === "large" || q === "highres")) {
|
||||
finishHdUnlock();
|
||||
}
|
||||
},
|
||||
// The embed couldn't play this video (embedding disabled, removed, private…).
|
||||
// Surface our own message + an "Open on YouTube" escape hatch.
|
||||
onError: (e: any) => setPlayerError(typeof e?.data === "number" ? e.data : -1),
|
||||
|
|
@ -578,12 +526,6 @@ export default function PlayerModal({
|
|||
return () => {
|
||||
cancelled = true;
|
||||
window.clearInterval(timer);
|
||||
// If the modal closes / advances mid-flash, don't leave the player stuck in fullscreen.
|
||||
window.clearTimeout(unlockTimerRef.current);
|
||||
if (unlockingRef.current) {
|
||||
unlockingRef.current = false;
|
||||
if (document.fullscreenElement) document.exitFullscreen?.().catch(() => {});
|
||||
}
|
||||
// Final flush, then refresh the feed + playlists so resume bars reflect this session.
|
||||
Promise.resolve(persist()).finally(() => {
|
||||
qc.invalidateQueries({ queryKey: ["feed"] });
|
||||
|
|
@ -651,7 +593,6 @@ export default function PlayerModal({
|
|||
<div
|
||||
onClick={() => {
|
||||
focusModal();
|
||||
attemptHdUnlock(); // fallback: a real click is a fresh user activation for the flash
|
||||
togglePlay();
|
||||
}}
|
||||
title={t("player.shortcutsHint")}
|
||||
|
|
|
|||
|
|
@ -15,19 +15,10 @@ export interface ReleaseEntry {
|
|||
|
||||
export const RELEASE_NOTES: ReleaseEntry[] = [
|
||||
{
|
||||
version: "0.36.3",
|
||||
version: "0.36.4",
|
||||
date: "2026-07-10",
|
||||
summary: "Experimental: the player tries to unlock higher video quality automatically.",
|
||||
features: [
|
||||
"The in-app player now tries to lift YouTube's windowed quality limit for you. YouTube caps a small embedded player to a low resolution and only real fullscreen unlocks HD — so on the first video you open in a session, the player briefly flashes to fullscreen and back to trigger that unlock, which then sticks for the rest of the session. You may notice a short flash on that first video; later videos won't flash. (It's still bandwidth-dependent, and can be reverted if it doesn't help on your setup.)",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "0.36.2",
|
||||
date: "2026-07-10",
|
||||
summary: "Player's YouTube controls back to normal size (a quality experiment was reverted).",
|
||||
fixes: [
|
||||
"Reverted an experiment that tried to raise video quality in the small (windowed) player: it only shrank YouTube's on-screen controls without actually improving quality, because YouTube caps an embedded player's quality by its on-screen size. Tip for the sharpest picture: switch the player to fullscreen once — YouTube then keeps the higher quality even after you return to the small player.",
|
||||
chores: [
|
||||
"Internal in-app player cleanup.",
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -41,9 +32,8 @@ export const RELEASE_NOTES: ReleaseEntry[] = [
|
|||
{
|
||||
version: "0.36.0",
|
||||
date: "2026-07-10",
|
||||
summary: "Sharper in-app playback and full access to YouTube's own player menu.",
|
||||
summary: "Full access to YouTube's own player menu in the in-app player.",
|
||||
features: [
|
||||
"The in-app player is now larger and asks YouTube for higher quality, so videos look sharper than the old low-resolution default. (For the maximum your connection allows, go fullscreen.)",
|
||||
"You can now open and navigate YouTube's own player menu — Quality, Speed, Captions and More options — all the way down. When you use YouTube's built-in controls, the app's click-to-play and scroll-for-volume shortcuts briefly step aside (a small badge shows this), and they return the moment you move the pointer off the video.",
|
||||
],
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue