Files
mobile-flutter/covas_mobile_new/lib/pages/MapboxPages.dart
2025-09-01 22:14:08 +02:00

231 lines
7.3 KiB
Dart

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<MapboxPages> createState() => _MapboxPagesState();
}
class _MapboxPagesState extends State<MapboxPages> 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<List<double>> routeCoordinates = [];
@override
void initState() {
super.initState();
_authService.checkTokenStatus(context);
_getUserLocation();
}
Future<void> _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<void> _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<void> _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<List<double>>((coord) => [coord[0], coord[1]])
.toList();
});
}
}
Future<void> _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<Uint8List> _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),
),
);
}
}