diff --git a/src/components/video-editor/timeline/.codex/plan_timeline_refacto b/src/components/video-editor/timeline/.codex/plan_timeline_refacto deleted file mode 100644 index adda622e..00000000 --- a/src/components/video-editor/timeline/.codex/plan_timeline_refacto +++ /dev/null @@ -1,116 +0,0 @@ -# Refonte Totale de timeline avec Parité Fonctionnelle (Big Bang) - - ## Résumé - - Objectif: remplacer l’implémentation actuelle de TimelineEditor.tsx (2372 lignes) par une - architecture modulaire, lisible et testable, sans perte de fonctionnalités. - Stratégie retenue: big bang sans couche de compatibilité, avec conservation stricte du - contrat externe (TimelineEditor props + TimelineEditorHandle). - - ## Changements d’implémentation - - 1. Nouvelle architecture par dossiers (feature-first) - - - timeline/core/: constantes, types internes, utilitaires temporels (scale, range, format, - rowId, overlap). - - timeline/model/: mapping régions -> items timeline, labels, calculs de spans, sélection. - - timeline/hooks/: hooks métier découplés: - - useTimelineRange - - useTimelineSelection - - useTimelineKeyboardShortcuts - - useTimelineZoomActions - - useTimelineAudioActions - - useTimelineAnnotationsActions - - useTimelineNormalization - - timeline/dnd/: adaptation dnd-timeline (clamp drag/resize, voisinage, row resolve), - extraction de la logique actuelle de TimelineWrapper. - - timeline/components/: - - editor/TimelineEditorShell (orchestration haut niveau) - - toolbar/TimelineToolbar - - viewport/TimelineViewport - - axis/TimelineAxis - - playhead/PlaybackCursor - - rows/{ClipRow,ZoomRow,AnnotationRows,AudioRows} - - overlays/{ClipMarkerOverlay,GhostPlayhead,GhostZoom} - - keyframes/KeyframeMarkers - - timeline/services/: - - audioFilePlacementService (picker + metadata + track fit) - - zoomSuggestionService (wrapping buildInteractionZoomSuggestions) - - 2. Découpage de TimelineEditor.tsx - - - Garder uniquement: - - API publique (TimelineEditorProps, TimelineEditorHandle) - - composition des hooks/composants - - useImperativeHandle - - Déplacer tout le reste: - - handlers clavier/souris - - logique add/delete/select (zoom/clip/annotation/audio/keyframes) - - logique de normalisation spans - - logique pan/zoom range - - logique ghost/hover rows - - logique auto-suggest zooms - - logique audio placement multi-track - - 3. Contrats publics et interfaces - - - Inchangés: - - export default TimelineEditor - - export TimelineEditorHandle - - signature complète des props actuelles - - comportement des callbacks (onZoomAdded, onAudioAdded, onItemSpanChange, etc.) - - Ajouts internes uniquement: - - types internes (TimelineItemViewModel, RowDescriptor, SelectionState, - TimelineActionContext) - - interfaces de services purs pour tests unitaires - - 4. Nettoyage qualité - - - Éliminer duplications (ex: setRange(createInitialRange(totalMs)) présent 2 fois). - - Centraliser constantes magiques (1000, 150, labels clavier, etc.). - - Isoler tous les side-effects (window.addEventListener, electronAPI, toast) dans hooks - dédiés. - - Séparer strictement: - - logique pure (testable sans DOM) - - logique React/UI - - I/O plateforme (Electron/audio) - - ## Plan de tests (parité de features) - - 1. Tests unitaires (logique pure) - - - placement zoom: disponibilité, clip boundaries, overlap rules. - - placement audio: choix de piste, gap computation, fallback track. - - clamping drag/resize + minDuration + voisins. - - normalisation régions au changement de durée totale. - - formatters temps/axis scale/row id resolvers. - - 2. Tests d’intégration React - - - timeline click -> seek. - - drag playhead + snap keyframe. - - drag/resize item par row (zoom/clip/audio). - - ghost playhead + ghost zoom apparition/disparition. - - keyboard shortcuts (A, Z, C, delete, select all timeline blocks). - - cycle annotations Tab/Shift+Tab. - - auto-suggest zooms (cas succès + cas toast d’erreur). - - 3. Scénarios e2e ciblés (smoke) - - - session complète: add zoom, split clip, add annotation, add audio, move/resize/delete, - crop action, aspect ratio custom. - - validation “avant/après refacto” sur jeu de données identique (snapshot d’état timeline et - callbacks attendus). - - 4. Critères d’acceptation - - API publique strictement identique. - - composants/fichiers courts avec responsabilité unique. - - couverture forte sur logique timeline + interactions critiques. - - ## Hypothèses et choix verrouillés - - - Refonte en big bang (pas de couche compatibilité intermédiaire). - - Approche hooks modulaires (pas de reducer global/state machine). - - Niveau de validation: forte couverture + scénarios UI. - - Le périmètre visuel reste aligné au design actuel; priorité à la séparation propre et à la - maintenabilité. \ No newline at end of file diff --git a/src/components/video-editor/timeline/.codex/plan_timeline_refacto_phases.md b/src/components/video-editor/timeline/.codex/plan_timeline_refacto_phases.md deleted file mode 100644 index 49499a3d..00000000 --- a/src/components/video-editor/timeline/.codex/plan_timeline_refacto_phases.md +++ /dev/null @@ -1,403 +0,0 @@ -# Plan de Refacto Timeline - Déclinaison par Phases (Big Bang strict) - -Ce document décline `plan_timeline_refacto` en phases d’exécution explicites pour éviter les changements involontaires. - -Contraintes non négociables: -- Pas de couche de compatibilité -- Pas de fallback -- Big Bang unique en production (cutover final) -- Parité fonctionnelle stricte avec l’existant - -## Plan A (recommandé) - 7 phases avec verrous - -### Phase 1 - Cadrage technique figé -Objectif: -- Geler le contrat public (`TimelineEditorProps`, `TimelineEditorHandle`, exports). -- Établir une matrice de parité feature complète. -- Fixer les conventions d’architecture et de découpage. - -Travaux: -- Inventorier toutes les features actuelles: zoom, clip, annotation, audio, keyframes, shortcuts, toolbar, crop/aspect ratio. -- Écrire les critères observables de parité (entrées/sorties/callbacks). -- Définir les règles de taille et responsabilités par module. - -Definition of Done: -- Contrat API public verrouillé. -- Matrice de parité validée. -- Règles de découpage figées. - ---- - -### Phase 2 - Extraction du noyau pur (`core` + `model`) -Objectif: -- Sortir toute la logique pure hors de `TimelineEditor.tsx`. - -Travaux: -- `timeline/core/`: constantes, temps/range/scale/format, row IDs, overlap. -- `timeline/model/`: mapping régions -> items timeline, labels, spans, sélection. -- Suppression de la logique pure du composant monolithique. - -Definition of Done: -- Modules purs sans dépendance React/DOM/Electron. -- Comportement identique validé par tests unitaires. - ---- - -### Phase 3 - Extraction DnD (`dnd`) -Objectif: -- Isoler toute la logique drag/resize/collision/voisinage. - -Travaux: -- Migrer la logique de `TimelineWrapper` vers `timeline/dnd/`. -- Encapsuler clamp resize/drag, min duration, row resolve. -- Standardiser l’API DnD vers le reste du système. - -Definition of Done: -- DnD autonome et testable. -- Même sémantique d’overlap qu’avant. - ---- - -### Phase 4 - Extraction hooks métier (`hooks`) -Objectif: -- Décomposer la logique d’orchestration en hooks spécialisés. - -Travaux: -- Implémenter: - - `useTimelineRange` - - `useTimelineSelection` - - `useTimelineNormalization` - - `useTimelineZoomActions` - - `useTimelineAudioActions` - - `useTimelineAnnotationsActions` - - `useTimelineKeyboardShortcuts` -- Isoler side-effects (`window`, `electronAPI`, `toast`) dans ces hooks. - -Definition of Done: -- `TimelineEditor` n’héberge plus la logique métier. -- Side-effects regroupés et contrôlés. - ---- - -### Phase 5 - Découpage UI complet (`components`) -Objectif: -- Transformer la vue monolithique en composants de responsabilité unique. - -Travaux: -- Extraire: - - `components/editor/TimelineEditorShell` - - `components/toolbar/TimelineToolbar` - - `components/viewport/TimelineViewport` - - `components/axis/TimelineAxis` - - `components/playhead/PlaybackCursor` - - `components/rows/{ClipRow,ZoomRow,AnnotationRows,AudioRows}` - - `components/overlays/{ClipMarkerOverlay,GhostPlayhead,GhostZoom}` - - `components/keyframes/KeyframeMarkers` -- Rebrancher les props et callbacks sans changer les signatures publiques. - -Definition of Done: -- UI modulaire complète. -- Pas de régression interactionnelle (clic, hover, drag, resize, shortcuts). - ---- - -### Phase 6 - Recomposition finale Big Bang -Objectif: -- Bascule complète vers la nouvelle architecture. - -Travaux: -- Remplacer l’implémentation interne de `TimelineEditor` par la version modulaire. -- Supprimer code legacy et code mort. -- Conserver strictement le même point d’entrée public. - -Definition of Done: -- Aucune branche legacy. -- Aucune couche de compatibilité. -- Nouvelle architecture seule active. - ---- - -### Phase 7 - Validation finale parité + gate release -Objectif: -- Bloquer toute régression avant merge final. - -Travaux: -- Exécuter: - - Tests unitaires logique pure. - - Tests d’intégration React sur interactions clés. - - Smoke e2e sur scénarios d’édition complets. -- Vérifier la matrice de parité feature point par point. - -Definition of Done: -- API publique identique. -- Parité fonctionnelle validée. -- Couverture forte sur logique critique timeline. - ---- - -## Plan B (plus agressif) - 3 macro-phases - -### Phase 1 - Extraction massive moteur -- Extraire d’un coup `core`, `model`, `dnd`, `hooks`. -- Réduire `TimelineEditor` à orchestration. - -### Phase 2 - Reconstruction UI modulaire -- Recomposer la vue avec `components/*`. -- Rebrancher toutes les interactions et actions. - -### Phase 3 - Durcissement et cutover final -- Tests intégration + smoke. -- Suppression définitive du monolithe et de tout reliquat legacy. - ---- - -## Plan C (orienté anti-régression involontaire) - 5 phases - -### Phase 1 - Baseline comportementale -- Capturer états/callbacks attendus sur scénarios clés. - -### Phase 2 - Extraction moteur logique -- Extraire `core/model/dnd` et verrouiller par unit tests. - -### Phase 3 - Extraction actions + side-effects -- Extraire hooks actions/shortcuts/normalization et valider intégration. - -### Phase 4 - Extraction UI modulaire -- Extraire toolbar/viewport/rows/overlays et stabiliser interactions. - -### Phase 5 - Cutover Big Bang -- Basculer complètement. -- Supprimer ancien code. -- Valider parité complète. - ---- - -## Tests minimaux obligatoires (quel que soit le plan choisi) - -Unitaires: -- Placement zoom (disponibilité, overlap, clip boundaries). -- Placement audio (choix de piste, gap computation, fit réel). -- Clamp drag/resize (min duration, voisins, bornes timeline). -- Format/scale/range/row resolvers. - -Intégration: -- Timeline click -> seek. -- Drag playhead + snap keyframe. -- Drag/resize items par row. -- Ghost playhead / ghost zoom. -- Shortcuts: A, Z, C, Delete/Backspace, select-all blocks. -- Tab / Shift+Tab cycle annotations. - -Smoke: -- Session complète: add/move/resize/delete zoom/clip/annotation/audio + crop + aspect ratio custom. - ---- - -## Choix verrouillés -- Big Bang strict. -- Zéro compatibilité. -- Zéro fallback. -- Parité fonctionnelle stricte avant release. - ---- - -## Verrou Phase 1 (figé) - -### Contrat API public verrouillé -- Export public composant: - - `default TimelineEditor` - - `type TimelineEditorHandle` - - `type TimelineEditorProps` -- `TimelineEditorProps` gelé (sans fallback compat): - - Inputs: `videoDuration`, `currentTime`, `playheadTime`, `cursorTelemetry`, `autoSuggestZoomsTrigger`, `disableSuggestedZooms`, `zoomRegions`, `trimRegions`, `clipRegions`, `annotationRegions`, `speedRegions`, `audioRegions`, `aspectRatio`, `isCropped`, `videoPath`, `hideToolbar`. - - Callbacks: `onSeek`, `onAutoSuggestZoomsConsumed`, `onZoomAdded`, `onZoomSuggested`, `onZoomSpanChange`, `onZoomDelete`, `onSelectZoom`, `onTrimAdded`, `onTrimSpanChange`, `onTrimDelete`, `onSelectTrim`, `onClipSplit`, `onClipSpanChange`, `onClipDelete`, `onSelectClip`, `onAnnotationAdded`, `onAnnotationSpanChange`, `onAnnotationDelete`, `onSelectAnnotation`, `onSpeedAdded`, `onSpeedSpanChange`, `onSpeedDelete`, `onSelectSpeed`, `onAudioAdded`, `onAudioSpanChange`, `onAudioDelete`, `onSelectAudio`, `onAspectRatioChange`, `onOpenCropEditor`. -- `TimelineEditorHandle` gelé: - - Méthodes: `addZoom()`, `suggestZooms()`, `splitClip()`, `addAnnotation(trackIndex?)`, `addAudio(trackIndex?)`. - - État exposé: `keyframes: { id: string; time: number }[]`. - -### Matrice de parité feature (critères observables) -- Zoom: - - Entrées: `zoomRegions`, `cursorTelemetry`, `disableSuggestedZooms`. - - Sorties/callbacks: `onZoomAdded`, `onZoomSuggested`, `onZoomSpanChange`, `onZoomDelete`, `onSelectZoom`. - - Observables: ajout manuel, suggestions interaction, drag/resize sans overlap. -- Clip: - - Entrées: `clipRegions`, `currentTime`. - - Sorties/callbacks: `onClipSplit`, `onClipSpanChange`, `onClipDelete`, `onSelectClip`. - - Observables: split au playhead, sélection/resize clip. -- Annotation: - - Entrées: `annotationRegions`, `currentTime`. - - Sorties/callbacks: `onAnnotationAdded`, `onAnnotationSpanChange`, `onAnnotationDelete`, `onSelectAnnotation`. - - Observables: multi-track, Tab/Shift+Tab cycle sur overlaps. -- Audio: - - Entrées: `audioRegions`, `videoPath`, `currentTime`. - - Sorties/callbacks: `onAudioAdded`, `onAudioSpanChange`, `onAudioDelete`, `onSelectAudio`. - - Observables: placement piste libre, clamp durée au gap restant. -- Keyframes: - - Entrées: `currentTime`. - - Sorties: handle `keyframes`; interactions internes `add/move/delete`. - - Observables: snap playhead ±150ms sur keyframe en drag. -- Shortcuts: - - Entrées: focus timeline + keymap contexte shortcuts. - - Sorties: déclenche callbacks de feature ou suppression. - - Observables: `A`, `Z`, `C`, `Delete/Backspace`, `Ctrl/Cmd+A`, `Tab`, `Shift+Tab`. -- Toolbar: - - Entrées: `hideToolbar`, `aspectRatio`, `isCropped`. - - Sorties: actions zoom/annotation/audio/split/crop/aspect. - - Observables: parité boutons et menus. -- Crop / Aspect ratio: - - Entrées: `aspectRatio`, `isCropped`. - - Sorties: `onAspectRatioChange`, `onOpenCropEditor`. - - Observables: presets + custom ratio, indicateur crop actif. - -### Conventions d’architecture / découpage (figées) -- `timeline/core/*`: - - Pur (pas React/DOM/Electron). - - Responsabilités: temps/range/scale/format, rows IDs, overlap, normalisation span. -- `timeline/model/*`: - - Pur (pas React/DOM/Electron). - - Responsabilités: mapping régions -> items timeline, labels, spans DnD, resolve row. -- Contraintes module: - - Taille cible: `< 200` LOC/module pur, `< 300` LOC max exceptionnel. - - Fonctions exportées pures, typées explicitement, testées unitairement. - - Aucune dépendance croisée `model -> React` ou `core -> model UI`. - -## Verrou Phase 2 (extraction core+model) - -### Extraction réalisée -- `timeline/core/`: - - `constants.ts` - - `rows.ts` - - `spans.ts` - - `time.ts` -- `timeline/model/`: - - `timelineModel.ts` -- `TimelineEditor.tsx` rebranché: - - Utilise les fonctions `core`/`model` pour la logique pure extraite. - - Contrat public inchangé côté comportement. - -### Tests unitaires ajoutés -- `timeline/core/time.test.ts` -- `timeline/core/rows.test.ts` -- `timeline/model/timelineModel.test.ts` - -## Verrou Phase 3 (extraction DnD) - -### Extraction réalisée -- Nouveau module DnD pur: `timeline/dnd/engine.ts`. -- Logique migrée hors `TimelineWrapper`: - - clamp resize/drag - - clamp range viewport - - voisinage/siblings par row - - résolution d’overlap en fin de drag/resize -- `TimelineWrapper` devient adaptateur d’événements (`dnd-timeline` -> appels `engine`). - -### API DnD standardisée -- Entrée unifiée `DndEngineConfig`: - - `totalMs`, `minItemDurationMs`, `minVisibleRangeMs`, `allRegionSpans`, `hasOverlap`. -- Fonctions pures exportées: - - `clampSpanToBounds`, `clampRange` - - `clampResizedSpanToNeighbours`, `clampDraggedSpanToNeighbours` - - `resolveResizeEnd`, `resolveDragEnd` - -### Parité sémantique -- Pas de changement de comportement attendu: - - même conservation de durée sur drag - - même logique de clamp voisinage - - même fallback `return` quand overlap persiste après clamp - -## Verrou Phase 4 (extraction hooks métier) - -### Hooks implémentés -- `timeline/hooks/useTimelineRange.ts` -- `timeline/hooks/useTimelineSelection.ts` -- `timeline/hooks/useTimelineNormalization.ts` -- `timeline/hooks/useTimelineZoomActions.ts` -- `timeline/hooks/useTimelineAudioActions.ts` -- `timeline/hooks/useTimelineAnnotationsActions.ts` -- `timeline/hooks/useTimelineKeyboardShortcuts.ts` - -### Side-effects isolés -- `window` (keyboard listeners) -> `useTimelineKeyboardShortcuts` -- `window.electronAPI` + lecture metadata audio -> `useTimelineAudioActions` -- `toast` (zoom/audio/aspect custom) -> hooks métier correspondants - -### Rebranchement `TimelineEditor` -- `TimelineEditor` consomme désormais les hooks pour: - - range/pan/wheel - - sélection/keyframes/delete/select-all - - normalisation spans - - actions zoom/audio/annotation - - shortcuts clavier -- Le composant conserve l’orchestration UI et le wiring des callbacks/props publics. - -## Verrou Phase 5 (découpage UI components) - -### Composants UI extraits -- `timeline/components/toolbar/TimelineToolbar.tsx` -- `timeline/components/viewport/TimelineCanvas.tsx` -- `timeline/components/axis/TimelineAxis.tsx` -- `timeline/components/playhead/PlaybackCursor.tsx` -- `timeline/components/overlays/ClipMarkerOverlay.tsx` - -### Recomposition -- `TimelineEditor` délègue désormais: - - toolbar actions + aspect/crop UI à `TimelineToolbar` - - viewport timeline (rows/items/ghosts/playhead/axis) à `TimelineCanvas` -- `TimelineEditor` conserve l’orchestration props/callbacks publiques + wiring hooks métier. - -### Parité interactionnelle conservée -- Clic timeline -> seek -- Drag playhead + snap keyframes -- Ghost playhead / ghost zoom -- Rendu rows multi-tracks annotation/audio -- Actions toolbar (zoom/suggest/annotation/audio/split/crop/aspect) - -## Verrou Phase 6 (recomposition finale Big Bang) - -### Bascule architecture modulaire -- `TimelineEditor` est désormais une façade API publique + wiring de hooks/composants. -- Extraction finale des blocs monolithiques restants: - - DnD bindings -> `timeline/hooks/useTimelineDndBindings.ts` - - Shell editor/empty state -> `timeline/components/editor/TimelineEditorShell.tsx` - -### Suppression legacy/code mort -- Retrait des implémentations inline restantes de: - - overlap resolver - - routing span-change par type/track - - mapping items/spans DnD - - empty-state inline du monolithe -- Aucune couche de compatibilité/fallback ajoutée. - -### Point d’entrée public inchangé -- `default export TimelineEditor` -- `TimelineEditorProps` et `TimelineEditorHandle` inchangés. - -### Validation -- Typecheck: `npx tsc --noEmit` OK. -- Tests timeline: 31/31 OK (PowerShell Windows). - -## Verrou Phase 7 (validation parité + gate release) - -### Exécution validations -- Typecheck global: - - `npx tsc --noEmit` -> OK. -- Tests timeline ciblés (core/model/dnd/layout/suggestions): - - 31/31 passés. -- Suite de tests projet complète (`npm run test`): - - 542 passés / 2 échoués (échecs hors périmètre timeline refactor): - - `electron/ipc/recording/diagnostics.test.ts` (timeout test) - - `electron/ipc/recording/prune.test.ts` (attente de rejection non satisfaite) - -### Vérification matrice de parité timeline -- API publique inchangée: - - `TimelineEditor` default export - - `TimelineEditorProps` - - `TimelineEditorHandle` -- Features timeline validées par tests + revue wiring: - - zoom, clip, annotation, audio, keyframes, shortcuts, toolbar, crop/aspect ratio. -- Sémantique DnD/overlap conservée (tests dnd + comportement rebranché). - -### Décision gate -- Statut refactor timeline: **PASS** (périmètre feature/API). -- Statut release globale dépôt: **BLOCKED** tant que les 2 tests non-timeline restent rouges. -- Action recommandée: traiter séparément les régressions `electron/ipc/recording/*` avant merge release global.