Browse Source

- 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

maziggy 4 months ago
parent
commit
079e9fc2cc

+ 59 - 0
frontend/src/pages/CameraPage.tsx

@@ -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
frontend/src/pages/PrintersPage.tsx

@@ -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 it is too large
+ 0 - 0
static/assets/index-3umWYOC3.js


+ 1 - 1
static/index.html

@@ -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>

Some files were not shown because too many files changed in this diff