import 'dart:async'; import 'package:flutter/widgets.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../core/constants/speed_unit.dart'; import '../../../data/models/location_data.dart'; import '../../../data/repositories/location_repository.dart'; /// ViewModel for the speedometer UI. /// /// Thin state manager — subscribes to [LocationRepository] and exposes /// the current display state to the view. No data-layer logic here. class SpeedometerViewModel extends ChangeNotifier { final LocationRepository _repository; final SharedPreferences _prefs; SpeedUnit _displayUnit = SpeedUnit.kmh; LocationData _displayData = LocationData( speed: 0.0, heading: -1.0, displaySpeed: '--', displayHeading: 'N/A', isSpeedValid: false, isHeadingValid: false, timestamp: DateTime.now(), ); LocationData get displayData => _displayData; SpeedUnit get displayUnit => _displayUnit; SpeedometerViewModel({ required LocationRepository repository, required SharedPreferences prefs, }) : _repository = repository, _prefs = prefs; void init() { _repository.locationStream.listen(_onLocationData); _loadSettings(); } void _onLocationData(LocationData data) { _displayData = data; notifyListeners(); } Future _loadSettings() async { _displayUnit = _parseSpeedUnit(_prefs.getString('speed_unit') ?? 'km/h'); notifyListeners(); } static SpeedUnit _parseSpeedUnit(String unit) { switch (unit) { case 'mph': return SpeedUnit.mph; case 'kts': return SpeedUnit.knots; default: return SpeedUnit.kmh; } } double get displaySpeed { return _displayUnit.convert(_displayData.speed); } String get displaySpeedText { return _displayData.displaySpeed; } String get displayHeading { return _displayData.displayHeading; } bool get isSpeedValid { return _displayData.isSpeedValid; } bool get isHeadingValid { return _displayData.isHeadingValid; } }