/// Avertissement du programme d'entraînement IA - Consentement partagé. /// /// Même texte pour les deux points d'entrée : le switch « Participer à /// l'entraînement IA » des Paramètres et le switch « Contribuer à l'IA » de la /// popup de fin de session. La fonction ne persiste rien : elle renvoie /// simplement `true` si l'utilisateur accepte les règles, à charge de l'appelant /// d'enregistrer ce choix. library; import 'package:flutter/material.dart'; import '../theme/app_theme.dart'; /// Affiche l'avertissement IA et renvoie `true` si les règles sont acceptées. Future showAiConsentDialog(BuildContext context) async { final isDark = Theme.of(context).brightness == Brightness.dark; final primary = Theme.of(context).colorScheme.primary; final accepted = await showDialog( context: context, barrierDismissible: false, builder: (context) => AlertDialog( backgroundColor: isDark ? AppTheme.darkSurface : AppTheme.lightSurface, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), title: const Text('Participer à l\'entraînement IA', textAlign: TextAlign.center), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: primary.withValues(alpha: 0.15), shape: BoxShape.circle, ), child: Icon(Icons.psychology, size: 40, color: primary), ), ), const SizedBox(height: 16), const Text( 'En activant cette option, vous acceptez d\'envoyer vos photos de cibles au serveur d\'entraînement IA.', style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), const SizedBox(height: 14), const Text( '📤 Ce qui est envoyé : la photo de la cible, la position des ' 'impacts que vous avez placés, la distance de tir, le calibre et ' 'le nombre de coups prévus.', style: TextStyle(fontSize: 13), ), const SizedBox(height: 10), const Text( '🚫 Ce qui ne l\'est pas : la géolocalisation de la photo (retirée ' 'avant l\'envoi), le nom de votre arme, et le modèle de votre appareil.', style: TextStyle(fontSize: 13), ), const SizedBox(height: 10), const Text( '🔒 Pseudonymat : votre identité est remplacée par un hash ' 'cryptographique. Il reste le même d\'un envoi à l\'autre, afin de ' 'rattacher vos contributions à votre compte (récompenses, ' 'modération, suppression sur demande).', style: TextStyle(fontSize: 13), ), const SizedBox(height: 10), const Text( '🎁 Récompenses : Vos contributions sont enregistrées pour vous donner accès à des fonctionnalités exclusives.', style: TextStyle(fontSize: 13), ), const SizedBox(height: 14), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppTheme.errorColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10), border: Border.all(color: AppTheme.errorColor.withValues(alpha: 0.4)), ), child: const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.warning_amber_rounded, color: AppTheme.errorColor, size: 20), SizedBox(width: 8), Text( 'Règles strictes & Bannissement', style: TextStyle( color: AppTheme.errorColor, fontWeight: FontWeight.bold, fontSize: 13, ), ), ], ), SizedBox(height: 6), Text( 'Vous vous engagez à n\'envoyer que de réelles cibles de tir conformes. ' 'Tout envoi de photos non conformes, fausses cibles, images floues ou contenu inapproprié ' 'entraînera le bannissement immédiat et définitif de votre compte. ' 'L\'application perdra définitivement la possibilité d\'envoyer des photos.', style: TextStyle(fontSize: 12, height: 1.4), ), ], ), ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Refuser', style: TextStyle(color: Colors.grey)), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: primary, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ), onPressed: () => Navigator.pop(context, true), child: const Text('J\'accepte les règles'), ), ], ), ); return accepted ?? false; }