198 lines
5.8 KiB
Dart
198 lines
5.8 KiB
Dart
import 'package:equatable/equatable.dart';
|
|
import 'package:intaleq_maps/intaleq_maps.dart';
|
|
import '../../../data/models/route_model.dart';
|
|
import '../../../data/models/place_model.dart';
|
|
|
|
enum NavigationStatus {
|
|
initial,
|
|
loading,
|
|
mapReady,
|
|
routePreview,
|
|
navigating,
|
|
arrived,
|
|
error,
|
|
}
|
|
|
|
enum MapThemeType {
|
|
vectorLight,
|
|
vectorDark,
|
|
satellite,
|
|
}
|
|
|
|
class NavigationState extends Equatable {
|
|
final NavigationStatus status;
|
|
final LatLng? myLocation;
|
|
final double altitude; // Altitude AMSL in meters (defaults to 0.0)
|
|
final double heading;
|
|
final double speed;
|
|
final List<RouteData> routes;
|
|
final int selectedRouteIndex;
|
|
final LatLng? destination;
|
|
final String destinationTitle;
|
|
final List<Map<String, dynamic>> routeSteps;
|
|
final int currentStepIndex;
|
|
final String currentInstruction;
|
|
final String nextInstruction;
|
|
final double distanceToNextStep;
|
|
final double remainingDistance;
|
|
final double remainingDuration;
|
|
final int currentManeuverModifier;
|
|
final String arrivalTime;
|
|
final bool isMuted;
|
|
final bool isCameraLocked;
|
|
final MapThemeType mapTheme;
|
|
final Set<Marker> markers;
|
|
final Set<Polyline> polylines;
|
|
final List<PlaceModel> searchResults;
|
|
final bool isSelectingLocationOnMap;
|
|
final bool isOnline;
|
|
final String? errorMessage;
|
|
|
|
const NavigationState({
|
|
this.status = NavigationStatus.initial,
|
|
this.myLocation,
|
|
this.altitude = 0.0,
|
|
this.heading = 0.0,
|
|
this.speed = 0.0,
|
|
this.routes = const [],
|
|
this.selectedRouteIndex = 0,
|
|
this.destination,
|
|
this.destinationTitle = '',
|
|
this.routeSteps = const [],
|
|
this.currentStepIndex = 0,
|
|
this.currentInstruction = '',
|
|
this.nextInstruction = '',
|
|
this.distanceToNextStep = 0.0,
|
|
this.remainingDistance = 0.0,
|
|
this.remainingDuration = 0.0,
|
|
this.currentManeuverModifier = 0,
|
|
this.arrivalTime = '--:--',
|
|
this.isMuted = false,
|
|
this.isCameraLocked = true,
|
|
this.mapTheme = MapThemeType.vectorLight,
|
|
this.markers = const {},
|
|
this.polylines = const {},
|
|
this.searchResults = const [],
|
|
this.isSelectingLocationOnMap = false,
|
|
this.isOnline = true,
|
|
this.errorMessage,
|
|
});
|
|
|
|
RouteData? get currentRoute =>
|
|
routes.isNotEmpty && selectedRouteIndex < routes.length
|
|
? routes[selectedRouteIndex]
|
|
: null;
|
|
|
|
bool get isNavigating => status == NavigationStatus.navigating;
|
|
|
|
String get formattedRemainingDistance {
|
|
if (remainingDistance >= 1000) {
|
|
return '${(remainingDistance / 1000).toStringAsFixed(1)} كم';
|
|
}
|
|
return '${remainingDistance.round()} م';
|
|
}
|
|
|
|
String get formattedRemainingDuration {
|
|
final int minutes = (remainingDuration / 60).round();
|
|
if (minutes >= 60) {
|
|
final int hours = minutes ~/ 60;
|
|
final int remMin = minutes % 60;
|
|
return '$hours س $remMin د';
|
|
}
|
|
return '$minutes دقيقة';
|
|
}
|
|
|
|
NavigationState copyWith({
|
|
NavigationStatus? status,
|
|
LatLng? myLocation,
|
|
double? altitude,
|
|
double? heading,
|
|
double? speed,
|
|
List<RouteData>? routes,
|
|
int? selectedRouteIndex,
|
|
LatLng? destination,
|
|
String? destinationTitle,
|
|
List<Map<String, dynamic>>? routeSteps,
|
|
int? currentStepIndex,
|
|
String? currentInstruction,
|
|
String? nextInstruction,
|
|
double? distanceToNextStep,
|
|
double? remainingDistance,
|
|
double? remainingDuration,
|
|
int? currentManeuverModifier,
|
|
String? arrivalTime,
|
|
bool? isMuted,
|
|
bool? isCameraLocked,
|
|
MapThemeType? mapTheme,
|
|
Set<Marker>? markers,
|
|
Set<Polyline>? polylines,
|
|
List<PlaceModel>? searchResults,
|
|
bool? isSelectingLocationOnMap,
|
|
bool? isOnline,
|
|
String? errorMessage,
|
|
}) {
|
|
return NavigationState(
|
|
status: status ?? this.status,
|
|
myLocation: myLocation ?? this.myLocation,
|
|
altitude: altitude ?? this.altitude,
|
|
heading: heading ?? this.heading,
|
|
speed: speed ?? this.speed,
|
|
routes: routes ?? this.routes,
|
|
selectedRouteIndex: selectedRouteIndex ?? this.selectedRouteIndex,
|
|
destination: destination ?? this.destination,
|
|
destinationTitle: destinationTitle ?? this.destinationTitle,
|
|
routeSteps: routeSteps ?? this.routeSteps,
|
|
currentStepIndex: currentStepIndex ?? this.currentStepIndex,
|
|
currentInstruction: currentInstruction ?? this.currentInstruction,
|
|
nextInstruction: nextInstruction ?? this.nextInstruction,
|
|
distanceToNextStep: distanceToNextStep ?? this.distanceToNextStep,
|
|
remainingDistance: remainingDistance ?? this.remainingDistance,
|
|
remainingDuration: remainingDuration ?? this.remainingDuration,
|
|
currentManeuverModifier:
|
|
currentManeuverModifier ?? this.currentManeuverModifier,
|
|
arrivalTime: arrivalTime ?? this.arrivalTime,
|
|
isMuted: isMuted ?? this.isMuted,
|
|
isCameraLocked: isCameraLocked ?? this.isCameraLocked,
|
|
mapTheme: mapTheme ?? this.mapTheme,
|
|
markers: markers ?? this.markers,
|
|
polylines: polylines ?? this.polylines,
|
|
searchResults: searchResults ?? this.searchResults,
|
|
isSelectingLocationOnMap:
|
|
isSelectingLocationOnMap ?? this.isSelectingLocationOnMap,
|
|
isOnline: isOnline ?? this.isOnline,
|
|
errorMessage: errorMessage ?? this.errorMessage,
|
|
);
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
status,
|
|
myLocation,
|
|
altitude,
|
|
heading,
|
|
speed,
|
|
routes,
|
|
selectedRouteIndex,
|
|
destination,
|
|
destinationTitle,
|
|
routeSteps,
|
|
currentStepIndex,
|
|
currentInstruction,
|
|
nextInstruction,
|
|
distanceToNextStep,
|
|
remainingDistance,
|
|
remainingDuration,
|
|
currentManeuverModifier,
|
|
arrivalTime,
|
|
isMuted,
|
|
isCameraLocked,
|
|
mapTheme,
|
|
markers,
|
|
polylines,
|
|
searchResults,
|
|
isSelectingLocationOnMap,
|
|
isOnline,
|
|
errorMessage,
|
|
];
|
|
}
|