| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- import 'dart:async';
- import 'package:flutter/material.dart';
- import 'package:geolocator/geolocator.dart';
- import 'package:latlong2/latlong.dart';
- import 'package:physigo/navigation/models/directions.dart';
- import '../services/directions_service.dart';
- import 'directions_instruction.dart';
- import 'navigation_map.dart';
- /// Time in seconds before two consecutive calls to the api
- const throttleCallApis = 30;
- /// Displays map with directions instruction to go from current position
- /// to [destination]
- class Navigation extends StatefulWidget {
- final LatLng destination;
- const Navigation({required this.destination, Key? key}) : super(key: key);
- @override
- State<Navigation> createState() => _NavigationState();
- }
- class _NavigationState extends State<Navigation> {
- final StreamController<int> _currentWaypointIndexController = StreamController.broadcast();
- final StreamController<Directions> _directionsController = StreamController.broadcast();
- late DateTime _lastDirectionsCalculation;
- Stream<LatLng> get _currentPositionStream {
- final currentPositionStream = Geolocator.getPositionStream();
- return currentPositionStream.map((position) => LatLng(position.latitude, position.longitude));
- }
- @override
- void initState() {
- _lastDirectionsCalculation = DateTime.now();
- Geolocator.getCurrentPosition().then((position) {
- final currentPosition = LatLng(position.latitude, position.longitude);
- _getDirections(currentPosition);
- });
- super.initState();
- }
- /// Applies a throttle before getting new directions from [currentPosition] to [widget.destination]
- /// to prevent spam
- ///
- /// If new directions are calculated, returns true
- bool _recalculateDirections(LatLng currentPosition) {
- if (DateTime.now().difference(_lastDirectionsCalculation).inSeconds > throttleCallApis) {
- _getDirections(currentPosition);
- setState(() {
- _lastDirectionsCalculation = DateTime.now();
- });
- return true;
- }
- return false;
- }
- Future<void> _getDirections(LatLng currentPosition) async {
- final directions = await DirectionsService.getDirections(currentPosition, widget.destination);
- _directionsController.add(directions);
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: Column(
- children: [
- NavigationMap(
- waypointsCoordinates: _directionsController.stream.map((directions) => directions.waypointsCoordinates),
- currentWaypointIndexStream: _currentWaypointIndexController.stream,
- ),
- StreamBuilder<Directions>(
- stream: _directionsController.stream,
- builder: (context, snapshot) {
- if (snapshot.hasData) {
- return DirectionsInstruction(
- directions: snapshot.data!,
- currentPositionStream: _currentPositionStream,
- currentWaypointIndexController: _currentWaypointIndexController,
- recalculateDirections: _recalculateDirections,
- );
- }
- return const CircularProgressIndicator();
- }),
- ],
- ),
- );
- }
- @override
- void dispose() {
- _currentWaypointIndexController.close();
- _directionsController.close();
- super.dispose();
- }
- }
|