fix(player): a fullscreen button the browser cannot honour is not shown
Brave on iPadOS switches element fullscreen off, patches requestFullscreen with a video-only stand-in and fakes fullscreenEnabled, so the Plex fullscreen button and the YouTube docked bar's did nothing. Support is now read off Element.prototype and the buttons are left out without it (owner). A stand-in that returns a boolean no longer throws. A test's bare matchMedia stub no longer outlives its describe.
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
||||
|
||||
// The browser's Fullscreen API, WebKit included.
|
||||
//
|
||||
// Safari and iPadOS still ship only the prefixed spelling: no `fullscreenchange`, no
|
||||
// Safari and iPadOS before 16.4 ship only the prefixed spelling: no `fullscreenchange`, no
|
||||
// `fullscreenElement`, no `requestFullscreen` on a plain element. Reading only the unprefixed names
|
||||
// there means the page believes it is NEVER fullscreen — which silently breaks whatever the
|
||||
// fullscreen state drives (an overlay that must yield, a focus reclaim, an Esc branch that would
|
||||
@@ -29,11 +29,26 @@ export function fullscreenElement(): Element | null {
|
||||
return d.fullscreenElement ?? d.webkitFullscreenElement ?? null;
|
||||
}
|
||||
|
||||
/** Can this browser put a plain element in fullscreen at all? Read off `Element.prototype`, never
|
||||
* `document.fullscreenEnabled`: Brave on iPadOS switches element fullscreen off in its web view, then
|
||||
* patches `HTMLElement.prototype.requestFullscreen` with a stand-in that only fullscreens a <video>
|
||||
* and forces `fullscreenEnabled` to true — both claim a support that is not there, and the players'
|
||||
* fullscreen buttons did nothing. A button that cannot work is not shown (owner). */
|
||||
export function canFullscreenElements(): boolean {
|
||||
if (typeof Element === "undefined") return false;
|
||||
const proto = Element.prototype as Partial<WebkitElement>;
|
||||
return (
|
||||
typeof proto.requestFullscreen === "function" ||
|
||||
typeof proto.webkitRequestFullscreen === "function"
|
||||
);
|
||||
}
|
||||
|
||||
/** Ask for fullscreen on `el`. Errors are swallowed on purpose: a refused request (no user
|
||||
* activation, an iOS device that only fullscreens <video>) is not something a caller can fix. */
|
||||
export function requestFullscreen(el: HTMLElement): void {
|
||||
const e = el as WebkitElement;
|
||||
if (e.requestFullscreen) void e.requestFullscreen().catch(() => {});
|
||||
// Wrapped: a patched stand-in (Brave's, above) may return a boolean, not a promise.
|
||||
if (e.requestFullscreen) void Promise.resolve(e.requestFullscreen()).catch(() => {});
|
||||
else e.webkitRequestFullscreen?.();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user