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:
@@ -46,7 +46,7 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
? _buildEmptyState()
|
||||
: _buildWeaponList(),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => _showAddWeaponDialog(context),
|
||||
onPressed: _showAddWeaponDialog,
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
);
|
||||
@@ -62,7 +62,7 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
const Text('Aucune arme enregistrée'),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: () => _showAddWeaponDialog(context),
|
||||
onPressed: _showAddWeaponDialog,
|
||||
child: const Text('Ajouter ma première arme'),
|
||||
),
|
||||
],
|
||||
@@ -88,7 +88,7 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
);
|
||||
_loadWeapons(); // Reload in case it was edited or maintenance was added
|
||||
},
|
||||
onLongPress: () => _confirmDelete(context, weapon),
|
||||
onLongPress: () => _confirmDelete(weapon),
|
||||
child: Padding(
|
||||
// La hauteur du cadre s'adapte automatiquement à la liste d'accessoires.
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
@@ -179,7 +179,9 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
}).toList();
|
||||
}
|
||||
|
||||
void _showAddWeaponDialog(BuildContext context) async {
|
||||
void _showAddWeaponDialog() async {
|
||||
// Capturé AVANT l'await : plus aucun usage du context après le dialogue.
|
||||
final repository = context.read<SessionRepository>();
|
||||
final nameController = TextEditingController();
|
||||
final caliberController = TextEditingController();
|
||||
final magCountController = TextEditingController(text: '2');
|
||||
@@ -200,7 +202,7 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
decoration: const InputDecoration(labelText: 'Nom de l\'arme', hintText: 'ex: Glock 17'),
|
||||
),
|
||||
DropdownButtonFormField<WeaponType>(
|
||||
value: selectedType,
|
||||
initialValue: selectedType,
|
||||
decoration: const InputDecoration(labelText: 'Type'),
|
||||
items: WeaponType.values.map((t) => DropdownMenuItem(value: t, child: Text(t.displayName))).toList(),
|
||||
onChanged: (v) => setState(() => selectedType = v!),
|
||||
@@ -240,7 +242,6 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
);
|
||||
|
||||
if (result == true && nameController.text.isNotEmpty) {
|
||||
final repository = context.read<SessionRepository>();
|
||||
await repository.addWeapon(
|
||||
name: nameController.text,
|
||||
type: selectedType,
|
||||
@@ -248,11 +249,14 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
magazineCount: int.tryParse(magCountController.text) ?? 1,
|
||||
magazineCapacity: int.tryParse(magCapController.text) ?? 10,
|
||||
);
|
||||
if (!mounted) return;
|
||||
_loadWeapons();
|
||||
}
|
||||
}
|
||||
|
||||
void _confirmDelete(BuildContext context, Weapon weapon) async {
|
||||
void _confirmDelete(Weapon weapon) async {
|
||||
// Capturé AVANT l'await : plus aucun usage du context après le dialogue.
|
||||
final repository = context.read<SessionRepository>();
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
@@ -269,8 +273,8 @@ class _WeaponListScreenState extends State<WeaponListScreen> {
|
||||
);
|
||||
|
||||
if (confirmed == true) {
|
||||
final repository = context.read<SessionRepository>();
|
||||
await repository.deleteWeapon(weapon.id);
|
||||
if (!mounted) return;
|
||||
_loadWeapons();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user