import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:eagletracker/class/BLEProvider.dart'; import 'package:eagletracker/class/devicesSaved.dart' as DevicesSaved; import 'package:eagletracker/class/preferenceSaved.dart' as PreferenceSaved; import 'package:eagletracker/deviceAdvertizinScan.dart'; import 'package:eagletracker/deviceFlowMap.dart'; import 'package:provider/provider.dart'; class DeviceSelection extends StatefulWidget { const DeviceSelection({super.key}); @override State createState() => _DeviceSelectionState(); } class _DeviceSelectionState extends State { List scanResults = []; TextEditingController tecSearch = TextEditingController(); bool isScanning = false; List devicesSaved = []; PreferenceSaved.PreferenceSaved preferenceSaved = PreferenceSaved.PreferenceSaved.empty(); TextEditingController tecTimeTakingPointSecond = TextEditingController(); // Initialize Bluetooth scanning and subscription in initState @override void initState() { super.initState(); isScanning = true; PreferenceSaved.restoreLocal().then((value) { setState(() { preferenceSaved = value; tecTimeTakingPointSecond.text = preferenceSaved.timeTakingPointSecond.toString(); }); }); DevicesSaved.restoreLocal().then((value) { setState(() { devicesSaved = value; }); }); FlutterBluePlus.isSupported.then((isSupported) { if (!isSupported) { showDialog( context: context, builder: (context) { return AlertDialog( title: const Text("Bluetooth non activé"), content: const Text( "Le Bluetooth n'est pas activé sur cet appareil. Veillez l'activer pour continuer."), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text("OK"), ), ], ); }, ); } }); } @override Widget build(BuildContext context) { final bleProvider = Provider.of(context); scanResults = bleProvider.scanResults; // Filtered list of devices List filteredDevices = scanResults .where((result) => result.device.platformName .toLowerCase() .contains(tecSearch.text.toLowerCase())) .toList(); //Saved devices list is connected ? for (var element in devicesSaved) { element.connected = scanResults .where((result) => result.device.remoteId.str == element.remoteId) .isNotEmpty; } return Scaffold( appBar: AppBar( actions: [ IconButton( icon: const Icon(Icons.settings, color: Colors.white), onPressed: () { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('Paramètres'), content: SizedBox( height: 100, child: Column(children: [ const Text('Capture des points (secondes)'), TextField( controller: tecTimeTakingPointSecond, keyboardType: TextInputType.number, ), ]), ), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('Annuler'), ), TextButton( onPressed: () { Navigator.of(context).pop(); preferenceSaved.timeTakingPointSecond = int.parse(tecTimeTakingPointSecond.text); PreferenceSaved.saveLocal(preferenceSaved); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Paramètres enregistrés'), ), ); }, child: const Text('Enregistrer'), ), ], ); }, ); }) ], backgroundColor: Colors.blue, title: const Text("Eagle Tr@cker", style: TextStyle(color: Colors.white)), ), body: Column( children: [ devicesSaved.isNotEmpty ? Column( children: [ const Padding( padding: EdgeInsets.all(16.0), child: Text('Appareils sauvegardés', style: TextStyle( fontSize: 18.0, fontWeight: FontWeight.bold)), ), ListView.builder( shrinkWrap: true, itemCount: devicesSaved.length, itemBuilder: (context, index) { DevicesSaved.DevicesSaved device = devicesSaved[index]; return Container( margin: const EdgeInsets.only(left: 10, right: 10.0), child: Card( child: ListTile( title: Row(children: [ Icon(Icons.circle, color: devicesSaved[index].connected ? Colors.green : Colors.orange, size: 10.0), Text(device.deviceName) ]), subtitle: Text(device.deviceAddress), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ GestureDetector( onTap: () async { devicesSaved.removeAt(index); await DevicesSaved.saveLocal( devicesSaved); setState(() { devicesSaved = devicesSaved; }); }, child: const Icon(Icons.delete)), GestureDetector( onTap: () { if (checkIsScanning( context, isScanning)) { Navigator.push( context, MaterialPageRoute( builder: (context) => DeviceAdvertizinScan( deviceName: device.deviceName, deviceAddress: device.deviceAddress, remoteId: device.remoteId, )), ); } }, child: const Icon(Icons.info_outline), ), GestureDetector( onTap: () { if (checkIsScanning( context, isScanning)) { Navigator.push( context, MaterialPageRoute( builder: (context) => DeviceFlowMap( deviceName: device.deviceName, deviceAddress: device.deviceAddress, ), ), ); } }, child: const Icon(Icons.map_outlined), ), ], ), ))); }, ), ], ) : Container(), const Padding( padding: EdgeInsets.all(16.0), child: Text('Recherche d\' appareils BLE', style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold)), ), Padding( padding: const EdgeInsets.all(16.0), child: TextFormField( controller: tecSearch, decoration: const InputDecoration( hintText: 'Rechercher un appareil par nom', prefixIcon: Icon(Icons.search), ), onChanged: (value) { setState(() {}); }, ), ), const SizedBox(height: 16.0), Expanded( child: ListView.builder( itemCount: filteredDevices.length, itemBuilder: (context, index) { ScanResult result = filteredDevices[index]; return ListTile( trailing: Row( mainAxisSize: MainAxisSize.min, children: [ GestureDetector( onTap: () async { if (devicesSaved .where((element) => element.deviceAddress == result.device.remoteId.str) .isNotEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Cet appareil est déjà sauvegardé'), ), ); return; } devicesSaved.add(DevicesSaved.DevicesSaved( deviceName: result.device.platformName, deviceAddress: result.device.remoteId.str, remoteId: result.device.remoteId.str, )); await DevicesSaved.saveLocal(devicesSaved); setState(() { devicesSaved = devicesSaved; }); ; }, child: const Icon(Icons.add), ), GestureDetector( onTap: () { if (checkIsScanning(context, isScanning)) { Navigator.push( context, MaterialPageRoute( builder: (context) => DeviceAdvertizinScan( deviceName: result.device.platformName, deviceAddress: result.device.remoteId.str, remoteId: result.device.remoteId.str, ), ), ); } }, child: const Icon(Icons.info_outline), ), GestureDetector( onTap: () { if (checkIsScanning(context, isScanning)) return; Navigator.push( context, MaterialPageRoute( builder: (context) => DeviceFlowMap( deviceName: result.device.platformName, deviceAddress: result.device.remoteId.str, ), ), ); }, child: const Icon(Icons.map_outlined), ), ], ), title: Row(children: [ const Icon(Icons.circle, color: Colors.green, size: 10.0), Text(result.device.platformName) ]), subtitle: Text(result.device.remoteId.str), ); }, ), ), ], ), floatingActionButton: FloatingActionButton( backgroundColor: Colors.blue, onPressed: () { setState(() { isScanning = !isScanning; if (isScanning) { bleProvider.startScan(); } else { bleProvider.stopScan(); } }); }, child: Icon(isScanning ? Icons.stop : Icons.play_arrow, color: Colors.white), ), ); } } bool checkIsScanning(BuildContext context, bool isScanning) { if (!isScanning) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Vous devez activer le scan pour continuer'), ), ); return false; } else { return true; } }