import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart' as mapbox; import 'package:shared_preferences/shared_preferences.dart'; import 'package:geolocator/geolocator.dart' as geo; import '../classes/alert.dart'; import '../variable/globals.dart' as globals; import '../classes/MyDrawer.dart'; import '../classes/auth_service.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:covas_mobile/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import '../locale_provider.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await dotenv.load(fileName: ".env"); // Set the access token globally mapbox.MapboxOptions.setAccessToken(dotenv.env['MAPBOX_ACCESS_TOKEN'] ?? ''); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Directions Example', theme: ThemeData(primarySwatch: Colors.blue), home: const MapboxPages(title: 'Event Location', place: "Flutter"), ); } } class MapboxPages extends StatefulWidget { const MapboxPages({Key? key, required this.title, required this.place}) : super(key: key); final String title; final String place; @override State createState() => _MapboxPagesState(); } class _MapboxPagesState extends State with ShowAlertDialog { final AuthService _authService = AuthService(); mapbox.MapboxMap? mapboxMap; mapbox.PointAnnotationManager? pointAnnotationManager; mapbox.PolylineAnnotationManager? polylineAnnotationManager; double longitude = 0.0; double latitude = 0.0; bool isLoading = true; mapbox.Point? userPosition; bool isUserPositionInitialized = false; String selectedMode = 'driving'; List> routeCoordinates = []; @override void initState() { super.initState(); _authService.checkTokenStatus(context); _getUserLocation(); } Future _getEventInfo() async { SharedPreferences prefs = await SharedPreferences.getInstance(); var accessToken = prefs.getString("access_token") ?? ""; if (accessToken.isNotEmpty) { var urlGet = Uri.parse("${globals.api}/events/${widget.title}"); var responseGet = await http.get(urlGet, headers: {HttpHeaders.cookieHeader: 'access_token=${accessToken}'}); if (responseGet.statusCode == 200) { var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); latitude = events["latitude"]; longitude = events["longitude"]; setState(() => isLoading = false); } else { _handleErrorResponse(responseGet.statusCode); } } else { showAlertDialog(context, "Error", "Invalid cache."); } } void _handleErrorResponse(int statusCode) { final errorMessage = "Error $statusCode fetching event"; showAlertDialog(context, "Error", errorMessage); } Future _getUserLocation() async { try { bool serviceEnabled = await geo.Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) return; geo.LocationPermission permission = await geo.Geolocator.checkPermission(); if (permission == geo.LocationPermission.denied) { permission = await geo.Geolocator.requestPermission(); } if (permission == geo.LocationPermission.deniedForever) return; geo.Position position = await geo.Geolocator.getCurrentPosition(); setState(() { userPosition = mapbox.Point( coordinates: mapbox.Position(position.latitude, position.longitude)); isUserPositionInitialized = true; }); _getEventInfo(); } catch (e) { showAlertDialog(context, "Error", "Failed to get location"); } } Future _fetchRoute( mapbox.Point origin, mapbox.Point destination, String mode) async { final url = Uri.parse( 'https://api.mapbox.com/directions/v5/mapbox/$mode/${origin.coordinates.lng},${origin.coordinates.lat};${destination.coordinates.lng},${destination.coordinates.lat}?geometries=geojson&access_token=${dotenv.env['MAPBOX_ACCESS_TOKEN']}', ); final response = await http.get(url); if (response.statusCode == 200) { final data = jsonDecode(response.body); final geometry = data['routes'][0]['geometry']['coordinates']; setState(() { routeCoordinates = (geometry as List) .map>((coord) => [coord[0], coord[1]]) .toList(); }); } } Future _drawRouteAndMarkers() async { if (mapboxMap == null || !isUserPositionInitialized) return; // Managers pointAnnotationManager ??= await mapboxMap!.annotations.createPointAnnotationManager(); polylineAnnotationManager ??= await mapboxMap!.annotations.createPolylineAnnotationManager(); // Clear old annotations await pointAnnotationManager!.deleteAll(); await polylineAnnotationManager!.deleteAll(); final destination = mapbox.Point(coordinates: mapbox.Position(longitude, latitude)); // Add user marker final userIcon = await _loadMarkerImage('images/marker.png'); await pointAnnotationManager!.create(mapbox.PointAnnotationOptions( geometry: mapbox.Point( coordinates: mapbox.Position( userPosition!.coordinates.lng, userPosition!.coordinates.lat)), image: userIcon, iconSize: 0.4, )); // Add event marker final eventIcon = await _loadMarkerImage('images/marker-red.png'); await pointAnnotationManager!.create(mapbox.PointAnnotationOptions( geometry: mapbox.Point( coordinates: mapbox.Position( destination.coordinates.lng, destination.coordinates.lat)), image: eventIcon, iconSize: 0.4, )); // Fetch and draw route await _fetchRoute(userPosition!, destination, selectedMode); if (routeCoordinates.isNotEmpty) { await polylineAnnotationManager!.create(mapbox.PolylineAnnotationOptions( geometry: mapbox.LineString( coordinates: routeCoordinates.map((c) => mapbox.Position(c[0], c[1])).toList(), ), lineColor: Colors.blue.value, lineWidth: 4.0, )); } } Future _loadMarkerImage(String assetPath) async { final ByteData data = await rootBundle.load(assetPath); return data.buffer.asUint8List(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.place)), drawer: MyDrawer(), body: isLoading ? const Center(child: CircularProgressIndicator()) : mapbox.MapWidget( onMapCreated: (controller) { mapboxMap = controller; }, cameraOptions: mapbox.CameraOptions( center: mapbox.Point( coordinates: mapbox.Position(longitude, latitude)), zoom: 14.0, ), ), floatingActionButton: FloatingActionButton( onPressed: _drawRouteAndMarkers, child: const Icon(Icons.directions), ), ); } }