- 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...
This commit is contained in:
maziggy
2026-01-08 16:48:24 +01:00
parent 50a5f5473b
commit 03f473f7ab
4 changed files with 30 additions and 29 deletions
+20 -21
View File
@@ -36,28 +36,27 @@ function App() {
<ThemeProvider>
<ToastProvider>
<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>
</ToastProvider>
</ThemeProvider>
+8 -6
View File
@@ -197,8 +197,9 @@ export function CameraPage() {
// Stall detection - periodically check if stream is still receiving frames
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) {
clearInterval(stallCheckIntervalRef.current);
stallCheckIntervalRef.current = null;
@@ -212,14 +213,15 @@ export function CameraPage() {
const response = await fetch(`/api/v1/printers/${id}/camera/status`);
if (response.ok) {
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) {
clearInterval(stallCheckIntervalRef.current);
stallCheckIntervalRef.current = null;
}
// Use the same reconnect logic as stream error
setStreamLoading(false);
attemptReconnect();
}
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-yp9aZph0.js"></script>
<script type="module" crossorigin src="/assets/index-BstVVW2U.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DIdbNfsf.css">
</head>
<body>