From a67d8961049d84b1be007249fe26ae02008303f0 Mon Sep 17 00:00:00 2001 From: Dom Date: Wed, 29 Apr 2026 21:13:56 +0200 Subject: [PATCH] =?UTF-8?q?fix(vwb):=20biblioth=C3=A8que=20de=20capture=20?= =?UTF-8?q?restait=20vide=20apr=C3=A8s=20'Capturer'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cause racine : le useEffect d'ajout à la bibliothèque écoutait la prop 'capture' venant du parent. Le path 'agent Windows distant' (doSmartCapture quand l'agent V1 répond) faisait setCurrentCapture(state local) mais ne déclenchait jamais la prop parente — donc useEffect [capture] ne tirait pas, donc addCaptureToLibrary jamais appelé. La capture s'affichait, mais rien n'était persisté côté backend. Fix : - Factorisation de l'ajout dans un useCallback addToLibrary(cap) - Appel explicite après setCurrentCapture dans doSmartCapture - Le path fallback local (via prop capture) garde le useEffect [capture] qui appelle aussi addToLibrary Erreurs d'upload (réseau, backend down) avalées silencieusement avec console.warn — la capture locale reste utilisable même si le backend de bibliothèque est indisponible. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/components/CapturePanel.tsx | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/visual_workflow_builder/frontend_v4/src/components/CapturePanel.tsx b/visual_workflow_builder/frontend_v4/src/components/CapturePanel.tsx index 4c35e6652..fbf352005 100644 --- a/visual_workflow_builder/frontend_v4/src/components/CapturePanel.tsx +++ b/visual_workflow_builder/frontend_v4/src/components/CapturePanel.tsx @@ -92,15 +92,12 @@ export default function CapturePanel({ } }, [library, libraryLoaded]); - // Ajouter capture à la bibliothèque (format v2 : PNG HD côté backend, - // thumbnail 640x360 q85 dans le JSON pour la grille). - useEffect(() => { - if (!capture) return; - setCurrentCapture(capture); - let cancelled = false; - (async () => { - const item = await addCaptureToLibrary(capture, { id: `cap_${Date.now()}` }); - if (cancelled) return; + // Helper : ajoute une capture à la bibliothèque (PNG HD upload backend + + // mise à jour de l'état local). Utilisé par le useEffect [capture] et par + // doSmartCapture (capture locale Windows qui ne passe pas par la prop parente). + const addToLibrary = useCallback(async (cap: Capture) => { + try { + const item = await addCaptureToLibrary(cap, { id: `cap_${Date.now()}` }); setLibrary(prev => [ { id: item.id, @@ -113,9 +110,17 @@ export default function CapturePanel({ }, ...prev.slice(0, 19), ]); - })(); - return () => { cancelled = true; }; - }, [capture]); + } catch (e) { + console.warn('[CapturePanel] Échec ajout bibliothèque', e); + } + }, []); + + // Capture venant du parent (path "fallback local" via prop capture) + useEffect(() => { + if (!capture) return; + setCurrentCapture(capture); + void addToLibrary(capture); + }, [capture, addToLibrary]); // Detecter les elements UI quand une capture arrive useEffect(() => { @@ -161,19 +166,24 @@ export default function CapturePanel({ const resp = await fetch('/api/screen-capture/capture-windows', { method: 'POST' }); const data = await resp.json(); if (resp.ok && data.image) { - setCurrentCapture({ + const cap: Capture = { screenshot_base64: data.image, width: data.width, height: data.height, source: data.source || 'windows', - } as any); + } as any; + setCurrentCapture(cap); + // Ajouter à la bibliothèque (le useEffect [capture] ne tire pas + // ici car on ne passe pas par la prop parente) + void addToLibrary(cap); return; } console.warn('Agent Windows indisponible, fallback local:', data.error); } catch (err) { console.warn('Erreur capture Windows, fallback local:', err); } - // Fallback : capture locale (ecran du serveur Linux) + // Fallback : capture locale (ecran du serveur Linux) — passe par la prop + // parente, l'ajout se fera dans le useEffect [capture] onCapture(); };