Browse Source

- Browser freeze fix
CameraPage no longer receives WebSocket messages - it was creating a second WebSocket connection that would also try to process print_complete events.
- Improved stall detection:
Now continues checking even when in error state.
Also triggers reconnect if the stream process died (!status.active)
Added console logging to help debug: Stream issue detected: stalled=X, active=X, reconnecting...

maziggy 4 months ago
parent
commit
03f473f7ab
4 changed files with 29 additions and 28 deletions
  1. 20 21
      frontend/src/App.tsx
  2. 8 6
      frontend/src/pages/CameraPage.tsx
  3. 0 0
      static/assets/index-BstVVW2U.js
  4. 1 1
      static/index.html

+ 20 - 21
frontend/src/App.tsx

@@ -36,28 +36,27 @@ function App() {
     <ThemeProvider>
     <ThemeProvider>
       <ToastProvider>
       <ToastProvider>
         <QueryClientProvider client={queryClient}>
         <QueryClientProvider client={queryClient}>
-          <WebSocketProvider>
-            <BrowserRouter>
-              <Routes>
-                {/* Camera page - standalone, no layout */}
-                <Route path="/camera/:printerId" element={<CameraPage />} />
+          <BrowserRouter>
+            <Routes>
+              {/* Camera page - standalone, no layout, no WebSocket (doesn't need real-time updates) */}
+              <Route path="/camera/:printerId" element={<CameraPage />} />
 
 
-                <Route path="/" element={<Layout />}>
-                  <Route index element={<PrintersPage />} />
-                  <Route path="archives" element={<ArchivesPage />} />
-                  <Route path="queue" element={<QueuePage />} />
-                  <Route path="stats" element={<StatsPage />} />
-                  <Route path="profiles" element={<ProfilesPage />} />
-                  <Route path="maintenance" element={<MaintenancePage />} />
-                  <Route path="projects" element={<ProjectsPage />} />
-                  <Route path="projects/:id" element={<ProjectDetailPage />} />
-                  <Route path="settings" element={<SettingsPage />} />
-                  <Route path="system" element={<SystemInfoPage />} />
-                  <Route path="external/:id" element={<ExternalLinkPage />} />
-                </Route>
-              </Routes>
-            </BrowserRouter>
-          </WebSocketProvider>
+              {/* Main app with WebSocket for real-time updates */}
+              <Route element={<WebSocketProvider><Layout /></WebSocketProvider>}>
+                <Route index element={<PrintersPage />} />
+                <Route path="archives" element={<ArchivesPage />} />
+                <Route path="queue" element={<QueuePage />} />
+                <Route path="stats" element={<StatsPage />} />
+                <Route path="profiles" element={<ProfilesPage />} />
+                <Route path="maintenance" element={<MaintenancePage />} />
+                <Route path="projects" element={<ProjectsPage />} />
+                <Route path="projects/:id" element={<ProjectDetailPage />} />
+                <Route path="settings" element={<SettingsPage />} />
+                <Route path="system" element={<SystemInfoPage />} />
+                <Route path="external/:id" element={<ExternalLinkPage />} />
+              </Route>
+            </Routes>
+          </BrowserRouter>
         </QueryClientProvider>
         </QueryClientProvider>
       </ToastProvider>
       </ToastProvider>
     </ThemeProvider>
     </ThemeProvider>

+ 8 - 6
frontend/src/pages/CameraPage.tsx

@@ -197,8 +197,9 @@ export function CameraPage() {
 
 
   // Stall detection - periodically check if stream is still receiving frames
   // Stall detection - periodically check if stream is still receiving frames
   useEffect(() => {
   useEffect(() => {
-    if (streamMode !== 'stream' || streamLoading || streamError || isReconnecting || transitioning) {
-      // Clear stall check when not actively streaming
+    // Only skip stall check during initial load, reconnecting, or transitioning
+    // Continue checking even during streamError to detect recovery
+    if (streamMode !== 'stream' || streamLoading || isReconnecting || transitioning) {
       if (stallCheckIntervalRef.current) {
       if (stallCheckIntervalRef.current) {
         clearInterval(stallCheckIntervalRef.current);
         clearInterval(stallCheckIntervalRef.current);
         stallCheckIntervalRef.current = null;
         stallCheckIntervalRef.current = null;
@@ -212,14 +213,15 @@ export function CameraPage() {
         const response = await fetch(`/api/v1/printers/${id}/camera/status`);
         const response = await fetch(`/api/v1/printers/${id}/camera/status`);
         if (response.ok) {
         if (response.ok) {
           const status = await response.json();
           const status = await response.json();
-          if (status.stalled) {
-            console.log('Stream stall detected, auto-reconnecting...');
-            // Trigger reconnect
+          // Trigger reconnect if:
+          // 1. Backend reports stall (no frames for 10+ seconds)
+          // 2. OR stream is not active anymore (process died)
+          if (status.stalled || (!status.active && !streamError)) {
+            console.log(`Stream issue detected: stalled=${status.stalled}, active=${status.active}, reconnecting...`);
             if (stallCheckIntervalRef.current) {
             if (stallCheckIntervalRef.current) {
               clearInterval(stallCheckIntervalRef.current);
               clearInterval(stallCheckIntervalRef.current);
               stallCheckIntervalRef.current = null;
               stallCheckIntervalRef.current = null;
             }
             }
-            // Use the same reconnect logic as stream error
             setStreamLoading(false);
             setStreamLoading(false);
             attemptReconnect();
             attemptReconnect();
           }
           }

File diff suppressed because it is too large
+ 0 - 0
static/assets/index-BstVVW2U.js


+ 1 - 1
static/index.html

@@ -23,7 +23,7 @@
 
 
     <!-- Splash screens for iOS -->
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-yp9aZph0.js"></script>
+    <script type="module" crossorigin src="/assets/index-BstVVW2U.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-DIdbNfsf.css">
     <link rel="stylesheet" crossorigin href="/assets/index-DIdbNfsf.css">
   </head>
   </head>
   <body>
   <body>

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