player: fullscreen button (scales with the window)

'⛶ full' in the controls: native requestFullscreen on the video (it fills
the viewport and rescales on window resize for free), with the iOS
webkitEnterFullscreen fallback where the Fullscreen API doesn't exist.
Click again to exit. Live browser test: enter + exit via the button.
This commit is contained in:
jozamudi committed 2026-09-19 00:11:45 +00:00
1 parent 379f591180
commit cea04a20f6
2 files changed
+44

No files matched your search

+16
View File
@@ -446,6 +446,22 @@ async function showAnime(slug_id, opts = {}) {
anB.classList.toggle("on", autoNext); anB.classList.toggle("on", autoNext);
}; };
const ctl = [langBtn, spd, prevB, nextB, fillB, jump, anB]; const ctl = [langBtn, spd, prevB, nextB, fillB, jump, anB];
const fsB = el("button", "tiny", "\u26f6 full");
fsB.title = "fullscreen";
fsB.onclick = () => {
const v = document.querySelector("#player video");
if (!v) return;
if (document.fullscreenElement || document.webkitFullscreenElement) {
(document.exitFullscreen || document.webkitExitFullscreen).call(document);
return;
}
// native Fullscreen API: the video fills the window (and scales with it);
// iOS Safari has no element fullscreen, so fall back to its in-player one
if (v.requestFullscreen) v.requestFullscreen();
else if (v.webkitEnterFullscreen) v.webkitEnterFullscreen();
else if (v.webkitRequestFullscreen) v.webkitRequestFullscreen();
};
ctl.push(fsB);
if (document.pictureInPictureEnabled) { if (document.pictureInPictureEnabled) {
const pipB = el("button", "tiny", "\u29c9 PiP"); const pipB = el("button", "tiny", "\u29c9 PiP");
pipB.title = "picture-in-picture"; pipB.title = "picture-in-picture";
+28
View File
@@ -490,3 +490,31 @@ async def _stale_history_remap_board():
"location.search.includes('q=')", timeout=15000, polling=POLL) "location.search.includes('q=')", timeout=15000, polling=POLL)
assert not errors, errors assert not errors, errors
await browser.close() await browser.close()
def test_fullscreen_toggle():
asyncio.run(_fullscreen_toggle())
async def _fullscreen_toggle():
# the player controls get a fullscreen button; in headless chromium the
# native API works, so exercise enter + exit.
async with async_playwright() as p:
browser = await p.chromium.launch(args=LAUNCH_ARGS)
page = await (await browser.new_context()).new_page()
errors = []
page.on("pageerror", lambda e: errors.append(str(e)))
await _login(page, "admin", "adminpw12345")
await page.goto(BASE + "/?anime=chainsaw-man-922")
btn = page.locator("button:has-text('full')")
await btn.wait_for(timeout=30000)
assert await page.evaluate(
"() => typeof document.querySelector('#player video').requestFullscreen === 'function'")
await btn.click(force=True)
await page.wait_for_function(
"() => !!document.fullscreenElement", timeout=15000, polling=POLL)
await btn.click(force=True)
await page.wait_for_function(
"() => !document.fullscreenElement", timeout=15000, polling=POLL)
assert not errors, errors
await browser.close()