Skip to content

Commit 7d59b97

Browse files
bidahclaude
andcommitted
feat(screenshots): retry once if first attempt fails after 120s
After the initial 60s attempt, if screenshots fail, schedule a retry 120s later. Before retrying, check the public project endpoint to see if screenshots were already saved (e.g. by a concurrent trigger). Only retries once. Cleans up both timeouts on unmount. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0cec61c commit 7d59b97

1 file changed

Lines changed: 39 additions & 11 deletions

File tree

‎apps/web/components/preview-panel.tsx‎

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export function PreviewPanel({
109109
)
110110
const [hasTriggeredScreenshots, setHasTriggeredScreenshots] = useState(false)
111111
const screenshotTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
112+
const screenshotRetryRef = useRef<ReturnType<typeof setTimeout> | null>(null)
112113
const { Canvas } = useQRCode()
113114

114115
// Track if user has seen Expo Go modal
@@ -393,36 +394,59 @@ export function PreviewPanel({
393394
const projectId = currentProject.id
394395
const currentUserId = userId
395396

396-
screenshotTimeoutRef.current = setTimeout(async () => {
397+
const triggerScreenshots = async () => {
397398
console.log('[PreviewPanel] Triggering automatic screenshot capture for project:', projectId)
398399

399400
try {
400401
const response = await fetch(`/api/projects/${projectId}/screenshots`, {
401402
method: 'POST',
402-
headers: {
403-
'Content-Type': 'application/json',
404-
},
405-
body: JSON.stringify({
406-
userID: currentUserId,
407-
}),
403+
headers: { 'Content-Type': 'application/json' },
404+
body: JSON.stringify({ userID: currentUserId }),
408405
})
409406

410407
if (response.ok) {
411408
const data = await response.json()
412409
console.log('[PreviewPanel] Screenshots captured successfully:', data.screenshots)
413-
414-
// Update current project with new screenshot URLs
415410
if (data.project && onProjectUpdate) {
416411
onProjectUpdate(data.project)
417412
}
413+
return true
418414
} else {
419415
const error = await response.json()
420416
console.error('[PreviewPanel] Failed to capture screenshots:', error)
417+
return false
421418
}
422419
} catch (error) {
423420
console.error('[PreviewPanel] Error triggering screenshots:', error)
424-
} finally {
425-
screenshotTimeoutRef.current = null
421+
return false
422+
}
423+
}
424+
425+
screenshotTimeoutRef.current = setTimeout(async () => {
426+
const success = await triggerScreenshots()
427+
screenshotTimeoutRef.current = null
428+
429+
if (!success) {
430+
// Schedule a retry in 120 seconds: first check DB, only retry if still missing
431+
console.log('[PreviewPanel] Screenshot failed, scheduling retry in 120 seconds...')
432+
screenshotRetryRef.current = setTimeout(async () => {
433+
screenshotRetryRef.current = null
434+
try {
435+
const check = await fetch(`/api/projects/${projectId}/public`)
436+
if (check.ok) {
437+
const data = await check.json()
438+
if (data.screenshotMobile && data.screenshotDesktop) {
439+
console.log('[PreviewPanel] Screenshots already saved, skipping retry')
440+
if (onProjectUpdate) onProjectUpdate(data)
441+
return
442+
}
443+
}
444+
} catch {
445+
// If check fails, attempt the retry anyway
446+
}
447+
console.log('[PreviewPanel] Screenshots still missing, retrying...')
448+
await triggerScreenshots()
449+
}, 120000)
426450
}
427451
}, 60000) // 60 seconds - wait for app to fully initialize
428452
}
@@ -435,6 +459,10 @@ export function PreviewPanel({
435459
clearTimeout(screenshotTimeoutRef.current)
436460
screenshotTimeoutRef.current = null
437461
}
462+
if (screenshotRetryRef.current) {
463+
clearTimeout(screenshotRetryRef.current)
464+
screenshotRetryRef.current = null
465+
}
438466
}
439467
}, [])
440468

0 commit comments

Comments
 (0)