fix fulscreen between btns

This commit is contained in:
Dejan R 2026-04-22 10:57:15 +02:00
parent 6e2cf09ce5
commit ea9bdddef4
2 changed files with 92 additions and 8 deletions

View file

@ -36,7 +36,7 @@ import (
//go:embed static //go:embed static
var embeddedStaticFiles embed.FS var embeddedStaticFiles embed.FS
const version = "1.0.5" const version = "1.0.6"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Config structs // Config structs

View file

@ -1,7 +1,17 @@
(function(){ (function(){
const THEME_KEY = 'force-monitor-theme'; const THEME_KEY = 'force-monitor-theme';
const FULLSCREEN_INTENT_KEY = 'force-monitor-fullscreen-intent';
function byId(id){ return id ? document.getElementById(id) : null; } function byId(id){ return id ? document.getElementById(id) : null; }
function getFullscreenIntent(){
try { return sessionStorage.getItem(FULLSCREEN_INTENT_KEY) === '1'; } catch (_) { return false; }
}
function setFullscreenIntent(enabled){
try { sessionStorage.setItem(FULLSCREEN_INTENT_KEY, enabled ? '1' : '0'); } catch (_) {}
}
function setTheme(theme, opts){ function setTheme(theme, opts){
opts = opts || {}; opts = opts || {};
const t = theme === 'light' ? 'light' : 'dark'; const t = theme === 'light' ? 'light' : 'dark';
@ -12,6 +22,7 @@
if (typeof opts.onChange === 'function') opts.onChange(t); if (typeof opts.onChange === 'function') opts.onChange(t);
return t; return t;
} }
function initTheme(opts){ function initTheme(opts){
opts = opts || {}; opts = opts || {};
let theme = 'dark'; let theme = 'dark';
@ -30,21 +41,74 @@
} }
return theme; return theme;
} }
function updateFullscreenButton(buttonId){ function updateFullscreenButton(buttonId){
const btn = byId(buttonId || 'fullscreen-toggle'); const btn = byId(buttonId || 'fullscreen-toggle');
if (btn) btn.textContent = document.fullscreenElement ? 'Exit fullscreen' : 'Enter fullscreen'; if (!btn) return;
if (document.fullscreenElement) {
btn.textContent = 'Exit fullscreen';
return;
}
btn.textContent = getFullscreenIntent() ? 'Restore fullscreen' : 'Enter fullscreen';
} }
async function requestFullscreenSafe(){
if (document.fullscreenElement) return true;
if (!document.fullscreenEnabled) return false;
try {
await document.documentElement.requestFullscreen();
setFullscreenIntent(true);
return true;
} catch (err) {
console.warn('Fullscreen restore/request blocked:', err);
return false;
}
}
async function toggleFullscreen(buttonId){ async function toggleFullscreen(buttonId){
try { try {
if (!document.fullscreenElement) await document.documentElement.requestFullscreen(); if (!document.fullscreenElement) {
else await document.exitFullscreen(); await requestFullscreenSafe();
} else {
setFullscreenIntent(false);
await document.exitFullscreen();
}
} catch (err) { } catch (err) {
console.warn('Fullscreen error:', err); console.warn('Fullscreen error:', err);
} finally { } finally {
updateFullscreenButton(buttonId || 'fullscreen-toggle'); updateFullscreenButton(buttonId || 'fullscreen-toggle');
} }
} }
function initFullscreen(opts){
function bindFullscreenNavPersistence(){
if (document.documentElement.dataset.fsNavBound) return;
document.documentElement.dataset.fsNavBound = '1';
document.addEventListener('click', function(ev){
const link = ev.target && ev.target.closest ? ev.target.closest('a[href]') : null;
if (!link) return;
const href = link.getAttribute('href') || '';
const target = link.getAttribute('target') || '';
if (!href || href.startsWith('#') || target === '_blank' || link.hasAttribute('download')) return;
try {
const url = new URL(link.href, window.location.href);
if (url.origin !== window.location.origin) return;
} catch (_) {
return;
}
if (document.fullscreenElement || getFullscreenIntent()) {
setFullscreenIntent(true);
}
}, true);
window.addEventListener('pageshow', function(){
document.querySelectorAll('#fullscreen-toggle, #fullscreen-btn').forEach(function(el){
updateFullscreenButton(el.id);
});
});
}
async function initFullscreen(opts){
opts = opts || {}; opts = opts || {};
const buttonId = opts.buttonId || 'fullscreen-toggle'; const buttonId = opts.buttonId || 'fullscreen-toggle';
const btn = byId(buttonId); const btn = byId(buttonId);
@ -55,13 +119,23 @@
if (!document.documentElement.dataset.fsListenerBound) { if (!document.documentElement.dataset.fsListenerBound) {
document.documentElement.dataset.fsListenerBound = '1'; document.documentElement.dataset.fsListenerBound = '1';
document.addEventListener('fullscreenchange', function(){ document.addEventListener('fullscreenchange', function(){
setFullscreenIntent(!!document.fullscreenElement);
document.querySelectorAll('#fullscreen-toggle, #fullscreen-btn').forEach(function(el){ document.querySelectorAll('#fullscreen-toggle, #fullscreen-btn').forEach(function(el){
el.textContent = document.fullscreenElement ? 'Exit fullscreen' : 'Enter fullscreen'; updateFullscreenButton(el.id);
}); });
}); });
} }
bindFullscreenNavPersistence();
updateFullscreenButton(buttonId); updateFullscreenButton(buttonId);
if (getFullscreenIntent() && !document.fullscreenElement) {
// Best effort only: some browsers require a fresh user gesture after navigation.
requestAnimationFrame(function(){
requestFullscreenSafe().finally(function(){ updateFullscreenButton(buttonId); });
});
}
} }
async function fetchJson(url, opts){ async function fetchJson(url, opts){
opts = opts || {}; opts = opts || {};
const controller = new AbortController(); const controller = new AbortController();
@ -88,5 +162,15 @@
clearTimeout(timer); clearTimeout(timer);
} }
} }
window.AppUI = { setTheme, initTheme, updateFullscreenButton, toggleFullscreen, initFullscreen, fetchJson };
window.AppUI = {
setTheme,
initTheme,
updateFullscreenButton,
toggleFullscreen,
initFullscreen,
fetchJson,
getFullscreenIntent,
setFullscreenIntent
};
})(); })();