// lib/widgets/activity/activity_files_page.dart import 'dart:io'; import 'dart:typed_data'; import 'package:aves/model/activity/activity_track.dart'; import 'package:aves/utils/activity_file_parser.dart'; import 'package:aves/widgets/activity/activity_map_page.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; class ActivityFilesPage extends StatefulWidget { static const routeName = '/activity'; const ActivityFilesPage({super.key}); @override State createState() => _ActivityFilesPageState(); } class _ActivityFilesPageState extends State { final List _activities = []; Future _pickActivityFile() async { try { final result = await FilePicker.platform.pickFiles( type: FileType.any, withData: true, ); final pickedFile = result?.files.single; if (pickedFile == null) return; if (!ActivityFileParser.isSupportedFileName(pickedFile.name)) { if (!mounted) return; _showMessage('Seleziona un file GPX, TCX o FIT.'); return; } final bytes = await _readPickedFileBytes(pickedFile); /* final activity = await ActivityFileParser.parse( bytes, fileName: pickedFile.name, ); if (activity.isEmpty) { if (!mounted) return; _showMessage('Nessuna traccia GPS valida trovata nel file.'); return; } if (!mounted) return; setState(() { _activities.add(activity); }); */ final activity = await ActivityFileParser.parse( bytes, fileName: pickedFile.name, ); // 1) Controllo null if (activity == null) { if (!mounted) return; _showMessage('Impossibile leggere il file attività.'); return; } // 2) Controllo traccia vuota if (activity.isEmpty) { if (!mounted) return; _showMessage('Nessuna traccia GPS valida trovata nel file.'); return; } // 3) Ora activity è NON-null → si può aggiungere if (!mounted) return; setState(() { _activities.add(activity!); }); } catch (e) { if (!mounted) return; _showMessage('Impossibile leggere il file attività: $e'); } } Future _readPickedFileBytes(PlatformFile pickedFile) async { final bytes = pickedFile.bytes; if (bytes != null) return bytes; final path = pickedFile.path; if (path == null) { throw Exception('percorso file non disponibile'); } return File(path).readAsBytes(); } void _openActivity(ActivityTrack activity) { Navigator.of(context).push( MaterialPageRoute( builder: (_) => ActivityMapPage(activity: activity), ), ); } void _showMessage(String message) { ScaffoldMessenger.maybeOf(context)?.showSnackBar( SnackBar( content: Text(message), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Attività'), actions: [ IconButton( icon: const Icon(Icons.add), tooltip: 'Apri file attività', onPressed: _pickActivityFile, ), ], ), body: _activities.isEmpty ? Center( child: TextButton.icon( onPressed: _pickActivityFile, icon: const Icon(Icons.upload_file), label: const Text('Apri file GPX, TCX o FIT'), ), ) : ListView.builder( itemCount: _activities.length, itemBuilder: (context, index) { final activity = _activities[index]; return ListTile( leading: const Icon(Icons.route), title: Text(activity.name), subtitle: Text( [ activity.sportLabel, activity.distanceLabel, activity.elevationGainLabel, activity.durationLabel, '${activity.pointCount} punti', ].join(' · '), ), onTap: () => _openActivity(activity), ); }, ), ); } }