mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 19:21:33 +02:00
- 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:
@@ -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 = () => {
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user