fix(frontend): immediate viewer chrome and correct f fullscreen

- remove all hide timers in Viewer; top/bottom bars and arrows now show/hide immediately
- arrows reveal only within the viewer bounds (no longer stay visible when the pointer is over the left/right panels)
- f (and the viewer button) toggle the viewer's own fullscreen via nested fullscreen, so f works inside app-level fullscreen without turning it off
This commit is contained in:
iu
2026-10-10 21:26:46 +03:00
parent 1b4906648d
commit 642e3bcf8a
+7 -77
View File
@@ -37,12 +37,7 @@
let showBottom = $state(false); let showBottom = $state(false);
let showLeft = $state(false); let showLeft = $state(false);
let showRight = $state(false); let showRight = $state(false);
const EDGE = 8; const EDGE = 8;
let hideTopTimer: ReturnType<typeof setTimeout> | undefined;
let hideBottomTimer: ReturnType<typeof setTimeout> | undefined;
let hideLeftTimer: ReturnType<typeof setTimeout> | undefined;
let hideRightTimer: ReturnType<typeof setTimeout> | undefined;
let dragging = false; let dragging = false;
let startX = 0; let startX = 0;
@@ -99,13 +94,7 @@
resetBars(); resetBars();
}; };
document.addEventListener('fullscreenchange', onFs); document.addEventListener('fullscreenchange', onFs);
return () => { return () => document.removeEventListener('fullscreenchange', onFs);
document.removeEventListener('fullscreenchange', onFs);
clearTimeout(hideTopTimer);
clearTimeout(hideBottomTimer);
clearTimeout(hideLeftTimer);
clearTimeout(hideRightTimer);
};
}); });
const topClass = $derived( const topClass = $derived(
@@ -132,14 +121,6 @@
); );
function resetBars() { function resetBars() {
clearTimeout(hideTopTimer);
clearTimeout(hideBottomTimer);
clearTimeout(hideLeftTimer);
clearTimeout(hideRightTimer);
hideTopTimer = undefined;
hideBottomTimer = undefined;
hideLeftTimer = undefined;
hideRightTimer = undefined;
showTop = false; showTop = false;
showBottom = false; showBottom = false;
showLeft = false; showLeft = false;
@@ -152,70 +133,19 @@
return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom; return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
} }
function scheduleTop(shouldShow: boolean) {
if (shouldShow) {
clearTimeout(hideTopTimer);
hideTopTimer = undefined;
showTop = true;
} else if (showTop && !hideTopTimer) {
hideTopTimer = setTimeout(() => {
showTop = false;
hideTopTimer = undefined;
}, 1000);
}
}
function scheduleBottom(shouldShow: boolean) {
if (shouldShow) {
clearTimeout(hideBottomTimer);
hideBottomTimer = undefined;
showBottom = true;
} else if (showBottom && !hideBottomTimer) {
hideBottomTimer = setTimeout(() => {
showBottom = false;
hideBottomTimer = undefined;
}, 1000);
}
}
function scheduleLeft(shouldShow: boolean) {
if (shouldShow) {
clearTimeout(hideLeftTimer);
hideLeftTimer = undefined;
showLeft = true;
} else if (showLeft && !hideLeftTimer) {
hideLeftTimer = setTimeout(() => {
showLeft = false;
hideLeftTimer = undefined;
}, 300);
}
}
function scheduleRight(shouldShow: boolean) {
if (shouldShow) {
clearTimeout(hideRightTimer);
hideRightTimer = undefined;
showRight = true;
} else if (showRight && !hideRightTimer) {
hideRightTimer = setTimeout(() => {
showRight = false;
hideRightTimer = undefined;
}, 300);
}
}
function onWinMouseMove(e: MouseEvent) { function onWinMouseMove(e: MouseEvent) {
const r = viewerEl?.getBoundingClientRect(); const r = viewerEl?.getBoundingClientRect();
if (r) { if (r) {
const zoneX = r.width / 6; const zoneX = r.width / 6;
scheduleLeft(!zoomed && e.clientX <= r.left + zoneX); const insideY = e.clientY >= r.top && e.clientY <= r.bottom;
scheduleRight(!zoomed && e.clientX >= r.right - zoneX); showLeft = !zoomed && insideY && e.clientX >= r.left && e.clientX <= r.left + zoneX;
showRight = !zoomed && insideY && e.clientX <= r.right && e.clientX >= r.right - zoneX;
} }
if (!isFullscreen) return; if (!isFullscreen) return;
const nearTop = e.clientY <= EDGE; const nearTop = e.clientY <= EDGE;
const nearBottom = e.clientY >= window.innerHeight - EDGE; const nearBottom = e.clientY >= window.innerHeight - EDGE;
scheduleTop(nearTop || inRect(topEl, e.clientX, e.clientY)); showTop = nearTop || inRect(topEl, e.clientX, e.clientY);
scheduleBottom(nearBottom || inRect(bottomEl, e.clientX, e.clientY)); showBottom = nearBottom || inRect(bottomEl, e.clientX, e.clientY);
} }
function baseWidth(): number { function baseWidth(): number {
@@ -313,7 +243,7 @@
async function toggleViewerFullscreen() { async function toggleViewerFullscreen() {
if (!viewerEl) return; if (!viewerEl) return;
try { try {
if (document.fullscreenElement) await document.exitFullscreen(); if (document.fullscreenElement === viewerEl) await document.exitFullscreen();
else await viewerEl.requestFullscreen(); else await viewerEl.requestFullscreen();
} catch { } catch {
/* недоступно */ /* недоступно */