Files
rog_app/lib/features/location/location_provider.dart
2024-04-01 09:26:56 +05:30

110 lines
2.9 KiB
Dart

import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:geolocator/geolocator.dart';
import 'package:rogapp/features/data/user_location.dart';
import 'package:rogapp/features/state/game_view_model.dart';
/// The state for the location feature
class LocationState {
final Position? currentPosition;
final bool isStreamPaused;
LocationState({
this.currentPosition,
this.isStreamPaused = false,
});
LocationState copyWith({
Position? currentPosition,
bool? isStreamPaused,
}) {
return LocationState(
currentPosition: currentPosition ?? this.currentPosition,
isStreamPaused: isStreamPaused ?? this.isStreamPaused,
);
}
}
/// A StateNotifier that manages the location state
class LocationNotifier extends StateNotifier<LocationState> {
final Ref ref;
LocationNotifier(this.ref) : super(LocationState()) {
startListening();
startPeriodicUpdates();
}
StreamSubscription<Position>? _positionSubscription;
Position? _lastPosition;
final double _distanceThreshold = 220.0;
Timer? _periodicUpdateTimer;
void startPeriodicUpdates() {
_periodicUpdateTimer?.cancel();
_periodicUpdateTimer = Timer.periodic(Duration(seconds: 5), (timer) {
if (state.currentPosition != null) {
// Convert Position to UserLocation
UserLocation userLocation =
UserLocation.fromPosition(state.currentPosition!);
ref.read(gameViewModelProvider.notifier).updateLocation(userLocation);
}
});
}
void startListening() {
_positionSubscription =
Geolocator.getPositionStream().listen((Position position) {
if (_shouldUpdatePosition(position)) {
state = state.copyWith(currentPosition: position);
_lastPosition = position;
}
});
}
bool _shouldUpdatePosition(Position newPosition) {
if (_lastPosition == null) return true;
double distance = Geolocator.distanceBetween(
_lastPosition!.latitude,
_lastPosition!.longitude,
newPosition.latitude,
newPosition.longitude,
);
return distance < _distanceThreshold;
}
void stopListening() {
_positionSubscription?.cancel();
_positionSubscription = null;
state = state.copyWith(
currentPosition: null); // Reset the position state or handle as needed
}
void pauseListening() {
_positionSubscription?.pause();
}
void resumeListening() {
_positionSubscription?.resume();
}
void updateCurrentPosition(Position? position) {
state = state.copyWith(currentPosition: position);
}
void updateStreamPaused(bool isPaused) {
state = state.copyWith(isStreamPaused: isPaused);
}
@override
void dispose() {
_positionSubscription?.cancel();
super.dispose();
}
}
final locationNotifierProvider =
StateNotifierProvider<LocationNotifier, LocationState>((ref) {
return LocationNotifier(ref); // Pass ref directly
});