137 lines
3.5 KiB
Dart
137 lines
3.5 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../data/routing_repository.dart';
|
|
|
|
class RoutingState {
|
|
final double? originLat;
|
|
final double? originLon;
|
|
final String originName;
|
|
final double? destLat;
|
|
final double? destLon;
|
|
final String destName;
|
|
final String profile; // driving, walking, cycling
|
|
final List<RouteData> routes;
|
|
final int selectedRouteIndex;
|
|
final bool isLoading;
|
|
final String? error;
|
|
|
|
const RoutingState({
|
|
this.originLat,
|
|
this.originLon,
|
|
this.originName = 'My Location',
|
|
this.destLat,
|
|
this.destLon,
|
|
this.destName = '',
|
|
this.profile = 'driving',
|
|
this.routes = const [],
|
|
this.selectedRouteIndex = 0,
|
|
this.isLoading = false,
|
|
this.error,
|
|
});
|
|
|
|
RoutingState copyWith({
|
|
double? originLat,
|
|
double? originLon,
|
|
String? originName,
|
|
double? destLat,
|
|
double? destLon,
|
|
String? destName,
|
|
String? profile,
|
|
List<RouteData>? routes,
|
|
int? selectedRouteIndex,
|
|
bool? isLoading,
|
|
String? error,
|
|
bool clearError = false,
|
|
}) {
|
|
return RoutingState(
|
|
originLat: originLat ?? this.originLat,
|
|
originLon: originLon ?? this.originLon,
|
|
originName: originName ?? this.originName,
|
|
destLat: destLat ?? this.destLat,
|
|
destLon: destLon ?? this.destLon,
|
|
destName: destName ?? this.destName,
|
|
profile: profile ?? this.profile,
|
|
routes: routes ?? this.routes,
|
|
selectedRouteIndex: selectedRouteIndex ?? this.selectedRouteIndex,
|
|
isLoading: isLoading ?? this.isLoading,
|
|
error: clearError ? null : (error ?? this.error),
|
|
);
|
|
}
|
|
|
|
RouteData? get selectedRoute =>
|
|
routes.isNotEmpty && selectedRouteIndex < routes.length
|
|
? routes[selectedRouteIndex]
|
|
: null;
|
|
}
|
|
|
|
class RoutingNotifier extends Notifier<RoutingState> {
|
|
late RoutingRepository _repository;
|
|
|
|
@override
|
|
RoutingState build() {
|
|
_repository = ref.watch(routingRepositoryProvider);
|
|
return const RoutingState();
|
|
}
|
|
|
|
void setOrigin(double lat, double lon, String name) {
|
|
state = state.copyWith(
|
|
originLat: lat,
|
|
originLon: lon,
|
|
originName: name,
|
|
routes: [],
|
|
);
|
|
}
|
|
|
|
void setDestination(double lat, double lon, String name) {
|
|
state = state.copyWith(
|
|
destLat: lat,
|
|
destLon: lon,
|
|
destName: name,
|
|
routes: [],
|
|
);
|
|
}
|
|
|
|
void setProfile(String profile) {
|
|
state = state.copyWith(profile: profile, routes: []);
|
|
}
|
|
|
|
void selectRoute(int index) {
|
|
state = state.copyWith(selectedRouteIndex: index);
|
|
}
|
|
|
|
Future<void> calculateRoute() async {
|
|
if (state.originLat == null ||
|
|
state.originLon == null ||
|
|
state.destLat == null ||
|
|
state.destLon == null) {
|
|
state = state.copyWith(error: 'Please set both origin and destination.');
|
|
return;
|
|
}
|
|
|
|
state = state.copyWith(isLoading: true, clearError: true, routes: []);
|
|
|
|
try {
|
|
final routes = await _repository.getRoute(
|
|
profile: state.profile,
|
|
originLat: state.originLat!,
|
|
originLon: state.originLon!,
|
|
destLat: state.destLat!,
|
|
destLon: state.destLon!,
|
|
);
|
|
state = state.copyWith(
|
|
routes: routes,
|
|
selectedRouteIndex: 0,
|
|
isLoading: false,
|
|
);
|
|
} catch (e) {
|
|
state = state.copyWith(
|
|
isLoading: false,
|
|
error: 'Could not calculate route. Please try again.',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
final routingProvider =
|
|
NotifierProvider.autoDispose<RoutingNotifier, RoutingState>(
|
|
RoutingNotifier.new,
|
|
);
|