feat: implement base architecture and core repositories for weapon tracking and target analysis functionality

This commit is contained in:
streaper2
2026-05-08 20:29:18 +02:00
parent 5dd58da51c
commit 774dbfcf40
37 changed files with 3687 additions and 2713 deletions

View File

@@ -5,10 +5,12 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:google_mlkit_document_scanner/google_mlkit_document_scanner.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:provider/provider.dart';
import '../../core/constants/app_constants.dart';
import '../../core/theme/app_theme.dart';
import '../../data/models/target_type.dart';
import '../crop/crop_screen.dart';
import '../session/session_provider.dart';
import 'widgets/image_source_button.dart';
class CaptureScreen extends StatefulWidget {
@@ -80,8 +82,13 @@ class _CaptureScreenState extends State<CaptureScreen> {
@override
Widget build(BuildContext context) {
final sessionProvider = context.watch<SessionProvider>();
final title = sessionProvider.isSessionActive
? 'Cible ${sessionProvider.targetCount + 1}'
: 'Source';
return Scaffold(
appBar: AppBar(title: const Text('Source')),
appBar: AppBar(title: Text(title)),
body: SingleChildScrollView(
padding: const EdgeInsets.all(AppConstants.defaultPadding),
child: Column(
@@ -119,42 +126,8 @@ class _CaptureScreenState extends State<CaptureScreen> {
child: CircularProgressIndicator(),
),
)
else if (_selectedImagePath != null)
_buildImagePreview()
else
_buildGuide(),
// --- NOUVEAU BOUTON VALIDER ---
if (_selectedImagePath != null && !_isLoading) ...[
const SizedBox(height: 24),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF112233), // Ton bleu foncé
foregroundColor: Colors.white,
minimumSize: const Size(double.infinity, 54),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 0,
),
onPressed: _analyzeImage,
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Valider',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
SizedBox(width: 12),
Icon(Icons.arrow_forward, size: 20),
],
),
),
const SizedBox(height: 32),
],
],
),
),
@@ -170,61 +143,9 @@ class _CaptureScreenState extends State<CaptureScreen> {
);
}
Widget _buildImagePreview() {
return Column(
children: [
_buildSectionTitle('Aperçu'),
const SizedBox(height: 12),
ClipRRect(
borderRadius: BorderRadius.circular(AppConstants.borderRadius),
child: Stack(
children: [
Image.file(
File(_selectedImagePath!),
fit: BoxFit.contain,
width: double.infinity,
),
Positioned(
top: 8,
right: 8,
child: IconButton(
icon: const Icon(Icons.close),
onPressed: () => setState(() => _selectedImagePath = null),
style: IconButton.styleFrom(
backgroundColor: Colors.black54,
foregroundColor: Colors.white,
),
),
),
],
),
),
const SizedBox(height: 12),
_buildFramingHints(),
],
);
}
Widget _buildFramingHints() {
return Card(
color: AppTheme.warningColor.withOpacity(0.1),
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Icon(Icons.info_outline, color: AppTheme.warningColor),
const SizedBox(width: 12),
Expanded(
child: Text(
'Assurez-vous que la cible est bien centrée et visible.',
style: TextStyle(color: AppTheme.warningColor.withOpacity(0.8)),
),
),
],
),
),
);
}
Widget _buildGuide() {
return Card(
@@ -283,7 +204,8 @@ class _CaptureScreenState extends State<CaptureScreen> {
final scanner = DocumentScanner(options: options);
final documents = await scanner.scanDocument();
if (documents.images.isNotEmpty) {
setState(() => _selectedImagePath = documents.images.first);
_selectedImagePath = documents.images.first;
_analyzeImage();
}
} catch (e) {
debugPrint('Erreur scan: $e');
@@ -302,7 +224,8 @@ class _CaptureScreenState extends State<CaptureScreen> {
imageQuality: 90,
);
if (image != null) {
setState(() => _selectedImagePath = image.path);
_selectedImagePath = image.path;
_analyzeImage();
}
} catch (e) {
debugPrint('Erreur capture: $e');