refactor: perf getAllSessions, zéro warning analyze, docs à jour

- getAllSessions : élimine le N+1 (une requête par session + par analyse)
  au profit de 3 requêtes groupées (sessions, analyses IN, shots IN),
  découpées en paquets de 500 pour rester sous la limite SQLite. Assemblage
  en mémoire via maps — accueil/historique/stats ne ralentiront plus au fil
  des mois
- flutter analyze : 28 -> 0 problème. APIs dépréciées migrées (withOpacity
  -> withValues, scale -> scaleByDouble, DropdownButtonFormField.value ->
  initialValue, dialogBackgroundColor -> dialogTheme, activeColor ->
  activeThumbColor), use_build_context_synchronously corrigés dans
  l'armurerie (repository capturé avant await + gardes mounted), print ->
  debugPrint, identifiants TopLeft/... -> lowerCamelCase, blocs if, champ final
- _showShotDetails dédupliqué : bottom sheet extraite dans le widget partagé
  shot_details_sheet.dart, utilisée par l'écran d'analyse et l'éditeur d'impacts
- CLAUDE.md : sections Features réécrites (retrait détection auto/références,
  ajout capture/plotting manuel) ; description pubspec renseignée

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
qguillaume
2026-07-04 10:40:25 +02:00
parent 8d5641c0a3
commit cec9838e9b
14 changed files with 229 additions and 229 deletions

View File

@@ -305,7 +305,9 @@ class _CaptureScreenState extends State<CaptureScreen>
final now = DateTime.now();
// Cadence ~1 s : assez réactif pour suivre la cible sans saturer le CPU.
if (lastAnalysis != null &&
now.difference(lastAnalysis!).inMilliseconds < 1000) return;
now.difference(lastAnalysis!).inMilliseconds < 1000) {
return;
}
lastAnalysis = now;
_isAnalyzingFrame = true;
@@ -514,10 +516,10 @@ class _CaptureScreenState extends State<CaptureScreen>
height: MediaQuery.of(context).size.width * 0.85,
child: Stack(
children: [
_buildCameraCorner(TopLeft: true, color: frameColor),
_buildCameraCorner(TopRight: true, color: frameColor),
_buildCameraCorner(BottomLeft: true, color: frameColor),
_buildCameraCorner(BottomRight: true, color: frameColor),
_buildCameraCorner(topLeft: true, color: frameColor),
_buildCameraCorner(topRight: true, color: frameColor),
_buildCameraCorner(bottomLeft: true, color: frameColor),
_buildCameraCorner(bottomRight: true, color: frameColor),
Center(
child: Container(
width: 24,
@@ -824,32 +826,32 @@ class _CaptureScreenState extends State<CaptureScreen>
// Coins du cadre (inchangés)
// ─────────────────────────────────────────────────────────────────────────
Widget _buildCameraCorner({
bool TopLeft = false,
bool TopRight = false,
bool BottomLeft = false,
bool BottomRight = false,
bool topLeft = false,
bool topRight = false,
bool bottomLeft = false,
bool bottomRight = false,
Color color = const Color(0xFF00FF00),
}) {
return Positioned(
top: (TopLeft || TopRight) ? 10 : null,
bottom: (BottomLeft || BottomRight) ? 10 : null,
left: (TopLeft || BottomLeft) ? 10 : null,
right: (TopRight || BottomRight) ? 10 : null,
top: (topLeft || topRight) ? 10 : null,
bottom: (bottomLeft || bottomRight) ? 10 : null,
left: (topLeft || bottomLeft) ? 10 : null,
right: (topRight || bottomRight) ? 10 : null,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
border: Border(
top: (TopLeft || TopRight)
top: (topLeft || topRight)
? BorderSide(color: color, width: 4)
: BorderSide.none,
bottom: (BottomLeft || BottomRight)
bottom: (bottomLeft || bottomRight)
? BorderSide(color: color, width: 4)
: BorderSide.none,
left: (TopLeft || BottomLeft)
left: (topLeft || bottomLeft)
? BorderSide(color: color, width: 4)
: BorderSide.none,
right: (TopRight || BottomRight)
right: (topRight || bottomRight)
? BorderSide(color: color, width: 4)
: BorderSide.none,
),