import 'dart:convert'; import 'dart:io'; import 'package:aves/model/gpx/gpx_track.dart'; import 'package:aves/utils/gpx_parser.dart'; import 'package:aves/widgets/gpx/gpx_map_page.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; class GpxFilesPage extends StatefulWidget { static const routeName = '/gpx'; const GpxFilesPage({super.key}); @override State createState() => _GpxFilesPageState(); } class _GpxFilesPageState extends State { final List _tracks = []; Future _pickGpxFile() async { try { final result = await FilePicker.platform.pickFiles( type: FileType.any, withData: true, ); final pickedFile = result?.files.single; if (pickedFile == null) return; final fileName = pickedFile.name.toLowerCase(); if (!fileName.endsWith('.gpx')) { if (!mounted) return; _showMessage('Seleziona un file GPX.'); return; } final xml = await _readPickedFile(pickedFile); final track = GpxParser.parse( xml, fallbackName: pickedFile.name, ); if (track.isEmpty) { if (!mounted) return; _showMessage('Nessuna traccia valida trovata nel file GPX.'); return; } if (!mounted) return; setState(() { _tracks.add(track); }); } catch (e) { if (!mounted) return; _showMessage('Impossibile leggere il file GPX: $e'); } } Future _readPickedFile(PlatformFile pickedFile) async { final bytes = pickedFile.bytes; if (bytes != null) { return utf8.decode(bytes); } final path = pickedFile.path; if (path == null) { throw Exception('percorso file non disponibile'); } return File(path).readAsString(); } void _openTrack(GpxTrack track) { Navigator.of(context).push( MaterialPageRoute( builder: (_) => GpxMapPage(track: track), ), ); } void _showMessage(String message) { ScaffoldMessenger.maybeOf(context)?.showSnackBar( SnackBar( content: Text(message), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('GPX'), actions: [ IconButton( icon: const Icon(Icons.add), tooltip: 'Apri file GPX', onPressed: _pickGpxFile, ), ], ), body: _tracks.isEmpty ? Center( child: TextButton.icon( onPressed: _pickGpxFile, icon: const Icon(Icons.upload_file), label: const Text('Apri file GPX'), ), ) : ListView.builder( itemCount: _tracks.length, itemBuilder: (context, index) { final track = _tracks[index]; return ListTile( leading: const Icon(Icons.route), title: Text(track.name), subtitle: Text('${track.pointCount} punti'), onTap: () => _openTrack(track), ); }, ), ); } }