110 lines
2.9 KiB
Dart
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
|
|
});
|