Ajout de la gestion des permissions photos et configuration native Android/iOS
This commit is contained in:
@@ -1,6 +1,11 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
|
<!-- Pour Android 12 et inférieur -->
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||||
|
|
||||||
|
<!-- Pour Android 13 et supérieur -->
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
<application
|
<application
|
||||||
android:label="bully"
|
android:label="bully"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
|||||||
@@ -2,8 +2,13 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSCameraUsageDescription</key>
|
<dict>
|
||||||
<string>This app needs camera access to scan documents</string>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>Bully a besoin d'accéder à vos photos pour analyser vos cibles enregistrées.</string>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>Bully a besoin d'utiliser l'appareil photo pour scanner vos cibles en temps réel.</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>Bully a besoin d'accéder au micro (requis par certains services de caméra même si non utilisé).</string>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
/// Écran de capture - Première étape du workflow d'analyse.
|
|
||||||
///
|
|
||||||
/// Permet de sélectionner le type de cible (concentrique ou silhouette)
|
|
||||||
/// et la source d'image (caméra ou galerie). Affiche un aperçu de l'image
|
|
||||||
/// sélectionnée avant de lancer l'analyse.
|
|
||||||
library;
|
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:google_mlkit_document_scanner/google_mlkit_document_scanner.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
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 '../../core/constants/app_constants.dart';
|
import '../../core/constants/app_constants.dart';
|
||||||
import '../../core/theme/app_theme.dart';
|
import '../../core/theme/app_theme.dart';
|
||||||
import '../../data/models/target_type.dart';
|
import '../../data/models/target_type.dart';
|
||||||
@@ -28,6 +24,61 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
String? _selectedImagePath;
|
String? _selectedImagePath;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
|
||||||
|
/// Gère la demande de permission et la sélection d'image
|
||||||
|
Future<void> _handleGallerySelection() async {
|
||||||
|
PermissionStatus status;
|
||||||
|
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
final deviceInfo = DeviceInfoPlugin();
|
||||||
|
final androidInfo = await deviceInfo.androidInfo;
|
||||||
|
|
||||||
|
// Android 13+ (SDK 33) utilise .photos, les versions précédentes utilisent .storage
|
||||||
|
if (androidInfo.version.sdkInt >= 33) {
|
||||||
|
status = await Permission.photos.request();
|
||||||
|
} else {
|
||||||
|
status = await Permission.storage.request();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = await Permission.photos.request();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.isGranted) {
|
||||||
|
_captureImage(ImageSource.gallery);
|
||||||
|
} else if (status.isPermanentlyDenied) {
|
||||||
|
_showSettingsDialog();
|
||||||
|
} else {
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Accès à la galerie requis pour continuer'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showSettingsDialog() {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Text('Permission requise'),
|
||||||
|
content: const Text(
|
||||||
|
'L\'accès aux photos est nécessaire. Veuillez l\'activer dans les paramètres.',
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: const Text('Annuler'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => openAppSettings(),
|
||||||
|
child: const Text('Paramètres'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -39,7 +90,6 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: AppConstants.largePadding),
|
const SizedBox(height: AppConstants.largePadding),
|
||||||
|
|
||||||
// Image source selection
|
|
||||||
_buildSectionTitle('Source de l\'Image'),
|
_buildSectionTitle('Source de l\'Image'),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Row(
|
Row(
|
||||||
@@ -58,14 +108,13 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
label: 'Galerie',
|
label: 'Galerie',
|
||||||
onPressed: _isLoading
|
onPressed: _isLoading
|
||||||
? null
|
? null
|
||||||
: () => _captureImage(ImageSource.gallery),
|
: _handleGallerySelection, // Appelle la nouvelle fonction
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: AppConstants.largePadding),
|
const SizedBox(height: AppConstants.largePadding),
|
||||||
|
|
||||||
// Image preview
|
|
||||||
if (_isLoading)
|
if (_isLoading)
|
||||||
const Center(
|
const Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -74,10 +123,9 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
else if (_selectedImagePath != null)
|
else if (_selectedImagePath != null)
|
||||||
_buildImagePreview(),
|
_buildImagePreview()
|
||||||
|
else
|
||||||
// Guide text
|
_buildGuide(),
|
||||||
if (_selectedImagePath == null && !_isLoading) _buildGuide(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -91,6 +139,8 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tes widgets _buildSectionTitle, _buildImagePreview, _buildFramingHints restent identiques
|
||||||
|
|
||||||
Widget _buildSectionTitle(String title) {
|
Widget _buildSectionTitle(String title) {
|
||||||
return Text(
|
return Text(
|
||||||
title,
|
title,
|
||||||
@@ -103,7 +153,7 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
Widget _buildImagePreview() {
|
Widget _buildImagePreview() {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
_buildSectionTitle('Apercu'),
|
_buildSectionTitle('Aperçu'),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(AppConstants.borderRadius),
|
borderRadius: BorderRadius.circular(AppConstants.borderRadius),
|
||||||
@@ -119,9 +169,7 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
right: 8,
|
right: 8,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
onPressed: () {
|
onPressed: () => setState(() => _selectedImagePath = null),
|
||||||
setState(() => _selectedImagePath = null);
|
|
||||||
},
|
|
||||||
style: IconButton.styleFrom(
|
style: IconButton.styleFrom(
|
||||||
backgroundColor: Colors.black54,
|
backgroundColor: Colors.black54,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
@@ -139,7 +187,7 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
|
|
||||||
Widget _buildFramingHints() {
|
Widget _buildFramingHints() {
|
||||||
return Card(
|
return Card(
|
||||||
color: AppTheme.warningColor.withValues(alpha: 0.1),
|
color: AppTheme.warningColor.withOpacity(0.1),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -148,10 +196,8 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Assurez-vous que la cible est bien centree et visible.',
|
'Assurez-vous que la cible est bien centrée et visible.',
|
||||||
style: TextStyle(
|
style: TextStyle(color: AppTheme.warningColor.withOpacity(0.8)),
|
||||||
color: AppTheme.warningColor.withValues(alpha: 0.8),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -177,11 +223,11 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
_buildGuideItem(
|
_buildGuideItem(
|
||||||
Icons.crop_free,
|
Icons.crop_free,
|
||||||
'Cadrez la cible entiere dans l\'image',
|
'Cadrez la cible entière dans l\'image',
|
||||||
),
|
),
|
||||||
_buildGuideItem(Icons.wb_sunny, 'Utilisez un bon eclairage'),
|
_buildGuideItem(Icons.wb_sunny, 'Utilisez un bon éclairage'),
|
||||||
_buildGuideItem(Icons.straighten, 'Prenez la photo de face'),
|
_buildGuideItem(Icons.straighten, 'Prenez la photo de face'),
|
||||||
_buildGuideItem(Icons.blur_off, 'Evitez les images floues'),
|
_buildGuideItem(Icons.blur_off, 'Évitez les images floues'),
|
||||||
_buildGuideItem(
|
_buildGuideItem(
|
||||||
Icons.cleaning_services,
|
Icons.cleaning_services,
|
||||||
'Nettoyer votre objectif avec une chiffonnette pour lunette si nécessaire',
|
'Nettoyer votre objectif avec une chiffonnette pour lunette si nécessaire',
|
||||||
@@ -205,9 +251,10 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- LOGIQUE DE CAPTURE ---
|
||||||
|
|
||||||
Future<void> _scanDocument() async {
|
Future<void> _scanDocument() async {
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final options = DocumentScannerOptions(
|
final options = DocumentScannerOptions(
|
||||||
documentFormat: DocumentFormat.jpeg,
|
documentFormat: DocumentFormat.jpeg,
|
||||||
@@ -215,32 +262,20 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
pageLimit: 1,
|
pageLimit: 1,
|
||||||
isGalleryImport: false,
|
isGalleryImport: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
final scanner = DocumentScanner(options: options);
|
final scanner = DocumentScanner(options: options);
|
||||||
final documents = await scanner.scanDocument();
|
final documents = await scanner.scanDocument();
|
||||||
|
|
||||||
if (documents.images.isNotEmpty) {
|
if (documents.images.isNotEmpty) {
|
||||||
setState(() => _selectedImagePath = documents.images.first);
|
setState(() => _selectedImagePath = documents.images.first);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
debugPrint('Erreur scan: $e');
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text('Erreur lors du scan: $e'),
|
|
||||||
backgroundColor: AppTheme.errorColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
if (mounted) {
|
if (mounted) setState(() => _isLoading = false);
|
||||||
setState(() => _isLoading = false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _captureImage(ImageSource source) async {
|
Future<void> _captureImage(ImageSource source) async {
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final XFile? image = await _picker.pickImage(
|
final XFile? image = await _picker.pickImage(
|
||||||
source: source,
|
source: source,
|
||||||
@@ -248,29 +283,18 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
maxHeight: 2048,
|
maxHeight: 2048,
|
||||||
imageQuality: 90,
|
imageQuality: 90,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
setState(() => _selectedImagePath = image.path);
|
setState(() => _selectedImagePath = image.path);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
debugPrint('Erreur capture: $e');
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text('Erreur lors de la capture: $e'),
|
|
||||||
backgroundColor: AppTheme.errorColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
if (mounted) {
|
if (mounted) setState(() => _isLoading = false);
|
||||||
setState(() => _isLoading = false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _analyzeImage() {
|
void _analyzeImage() {
|
||||||
if (_selectedImagePath == null) return;
|
if (_selectedImagePath == null) return;
|
||||||
|
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
|
|||||||
@@ -5,11 +5,13 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import device_info_plus
|
||||||
import file_selector_macos
|
import file_selector_macos
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import sqflite_darwin
|
import sqflite_darwin
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
|
|||||||
92
pubspec.lock
92
pubspec.lock
@@ -97,6 +97,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1+1"
|
version: "2.2.1+1"
|
||||||
|
device_info_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: device_info_plus
|
||||||
|
sha256: "6a642e1daa10190af89ba6cb6386c0df7d071a3592080bfe1e44faa63ae1df65"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "13.1.0"
|
||||||
|
device_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: device_info_plus_platform_interface
|
||||||
|
sha256: "04b173a92e2d9161dfead145667037c8d834db725ce2e7b942bfe18fd2f45a46"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.1.0"
|
||||||
equatable:
|
equatable:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -117,10 +133,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c
|
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.5"
|
version: "2.2.0"
|
||||||
|
ffi_leak_tracker:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi_leak_tracker
|
||||||
|
sha256: "4093d4ef9ca06ffe2786e73bfb25e22aa92112b9bb4ec941f11e3e6b61489a97"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -493,6 +517,54 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
|
permission_handler:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: permission_handler
|
||||||
|
sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "12.0.1"
|
||||||
|
permission_handler_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_android
|
||||||
|
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "13.0.1"
|
||||||
|
permission_handler_apple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_apple
|
||||||
|
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "9.4.7"
|
||||||
|
permission_handler_html:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_html
|
||||||
|
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3+5"
|
||||||
|
permission_handler_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_platform_interface
|
||||||
|
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.3.0"
|
||||||
|
permission_handler_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_windows
|
||||||
|
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -698,6 +770,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: ba7d5750e3441caa1bbe31d9e516348fcf8dfcb32aa29ef87a844a59f4d1f1d0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.0"
|
||||||
|
win32_registry:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32_registry
|
||||||
|
sha256: "73b1d78920a9d6e03f8b4e43e612b87bf3152a0e5c5e5150267762b7c4116904"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.3"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ dependencies:
|
|||||||
|
|
||||||
# Image processing for impact detection
|
# Image processing for impact detection
|
||||||
image: ^4.1.7
|
image: ^4.1.7
|
||||||
|
permission_handler: ^12.0.1
|
||||||
|
device_info_plus: ^13.1.0
|
||||||
|
|
||||||
# Machine Learning for YOLOv8
|
# Machine Learning for YOLOv8
|
||||||
# tflite_flutter: ^0.11.0
|
# tflite_flutter: ^0.11.0
|
||||||
|
|||||||
@@ -7,8 +7,11 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <file_selector_windows/file_selector_windows.h>
|
#include <file_selector_windows/file_selector_windows.h>
|
||||||
|
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
FileSelectorWindowsRegisterWithRegistrar(
|
FileSelectorWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||||
|
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
file_selector_windows
|
file_selector_windows
|
||||||
|
permission_handler_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
Reference in New Issue
Block a user