- Camera popup window:

- Auto-resize to fit video resolution on first open
  - Persist window size and position to localStorage
  - Restore saved window state for subsequent opens
This commit is contained in:
maziggy
2026-01-01 12:29:25 +01:00
parent d3686a1b60
commit 079e9fc2cc
4 changed files with 73 additions and 8 deletions
+59
View File
@@ -100,6 +100,43 @@ export function CameraPage() {
return () => document.removeEventListener('fullscreenchange', handleFullscreenChange);
}, []);
// Save window size and position when user resizes or moves (only for popup windows)
useEffect(() => {
if (!window.opener) return;
let saveTimeout: NodeJS.Timeout;
const saveWindowState = () => {
// Debounce to avoid saving during drag
clearTimeout(saveTimeout);
saveTimeout = setTimeout(() => {
localStorage.setItem('cameraWindowState', JSON.stringify({
width: window.outerWidth,
height: window.outerHeight,
left: window.screenX,
top: window.screenY,
}));
}, 500);
};
window.addEventListener('resize', saveWindowState);
// Use interval to detect position changes (no native 'move' event)
const positionInterval = setInterval(() => {
const saved = localStorage.getItem('cameraWindowState');
if (saved) {
const state = JSON.parse(saved);
if (state.left !== window.screenX || state.top !== window.screenY) {
saveWindowState();
}
}
}, 1000);
return () => {
clearTimeout(saveTimeout);
clearInterval(positionInterval);
window.removeEventListener('resize', saveWindowState);
};
}, []);
// Clean up reconnect timers on unmount
useEffect(() => {
return () => {
@@ -178,6 +215,28 @@ export function CameraPage() {
if (countdownIntervalRef.current) {
clearInterval(countdownIntervalRef.current);
}
// Auto-resize popup window to fit video content (only if no saved preference)
if (window.opener && imgRef.current && !localStorage.getItem('cameraWindowState')) {
const img = imgRef.current;
const videoWidth = img.naturalWidth;
const videoHeight = img.naturalHeight;
if (videoWidth > 0 && videoHeight > 0) {
// Add space for header bar (~45px) and some padding
const headerHeight = 45;
const padding = 16;
// Calculate window size (outer size includes chrome)
const chromeWidth = window.outerWidth - window.innerWidth;
const chromeHeight = window.outerHeight - window.innerHeight;
const targetWidth = videoWidth + padding + chromeWidth;
const targetHeight = videoHeight + headerHeight + padding + chromeHeight;
window.resizeTo(targetWidth, targetHeight);
}
}
};
const stopStream = () => {
+11 -5
View File
@@ -1666,11 +1666,17 @@ function PrinterCard({
variant="secondary"
size="sm"
onClick={() => {
window.open(
`/camera/${printer.id}`,
`camera-${printer.id}`,
'width=640,height=400,menubar=no,toolbar=no,location=no,status=no'
);
// Use saved window state or defaults
const saved = localStorage.getItem('cameraWindowState');
const state = saved ? JSON.parse(saved) : { width: 640, height: 400 };
const features = [
`width=${state.width}`,
`height=${state.height}`,
state.left !== undefined ? `left=${state.left}` : '',
state.top !== undefined ? `top=${state.top}` : '',
'menubar=no,toolbar=no,location=no,status=no',
].filter(Boolean).join(',');
window.open(`/camera/${printer.id}`, `camera-${printer.id}`, features);
}}
disabled={!status?.connected}
title="Open camera in new window"
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -23,7 +23,7 @@
<!-- Splash screens for iOS -->
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
<script type="module" crossorigin src="/assets/index-DhHo5MXv.js"></script>
<script type="module" crossorigin src="/assets/index-3umWYOC3.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CCbBv2VC.css">
</head>
<body>