| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import 'dart:async';
- import 'package:flutter/foundation.dart';
- import '../../data/models/gps_speed.dart';
- import '../../data/services/telemetry_bridge.dart';
- /// Polls the native GPS speed snapshot. Starting never asks for permission; it
- /// simply returns false when precise location is not already allowed or GPS is
- /// disabled.
- class GpsSpeedController extends ChangeNotifier {
- GpsSpeedController(this._platform, {DateTime Function()? clock})
- : _clock = clock ?? DateTime.now;
- final TelemetryPlatform _platform;
- final DateTime Function() _clock;
- GpsSpeed _state = const GpsSpeed();
- Timer? _timer;
- bool _active = false;
- bool _polling = false;
- bool _disposed = false;
- bool get hasPermission => _state.hasPermission;
- bool get hasSpeed => _state.isFresh(_clock());
- double? get speedKmh => hasSpeed ? _state.speedKmh : null;
- Future<void> start() async {
- if (_active) return;
- _active = true;
- final started = await _platform.startGpsSpeed();
- if (!started) {
- _active = false;
- _notify();
- return;
- }
- _timer = Timer.periodic(const Duration(seconds: 1), (_) => _poll());
- await _poll();
- }
- /// Asks for precise location access and starts the fallback when granted.
- ///
- /// Used only by the Settings switches that explicitly choose GPS speed; the
- /// normal resume path still never prompts.
- Future<bool> requestPermission() async {
- final granted = await _platform.ensureLocationPermission();
- if (!granted) {
- _notify();
- return false;
- }
- _timer?.cancel();
- _timer = null;
- _active = false;
- await start();
- return true;
- }
- void stop() {
- _active = false;
- _timer?.cancel();
- _timer = null;
- _state = const GpsSpeed();
- unawaited(_platform.stopGpsSpeed());
- _notify();
- }
- Future<void> _poll() async {
- if (!_active || _polling) return;
- _polling = true;
- try {
- final next = await _platform.getGpsSpeed();
- if (next != _state) {
- _state = next;
- _notify();
- }
- } finally {
- _polling = false;
- }
- }
- void _notify() {
- if (!_disposed) notifyListeners();
- }
- @override
- void dispose() {
- _disposed = true;
- _timer?.cancel();
- unawaited(_platform.stopGpsSpeed());
- super.dispose();
- }
- }
|