Complete v2.0 ultra-lightweight rebuild with premium color themes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Mikkeli Matlock
2025-08-24 22:35:20 +09:00
parent 23b232f8f0
commit bab90a9830
37 changed files with 550 additions and 315 deletions
-136
View File
@@ -1,136 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:permission_handler/permission_handler.dart';
class LocationProvider extends ChangeNotifier {
Position? _currentPosition;
double _currentSpeed = 0.0;
double _totalDistance = 0.0;
DateTime? _tripStartTime;
bool _isTracking = false;
bool _hasLocationPermission = false;
String _errorMessage = '';
StreamSubscription<Position>? _positionStreamSubscription;
Position? _previousPosition;
Position? get currentPosition => _currentPosition;
double get currentSpeed => _currentSpeed;
double get totalDistance => _totalDistance;
DateTime? get tripStartTime => _tripStartTime;
bool get isTracking => _isTracking;
bool get hasLocationPermission => _hasLocationPermission;
String get errorMessage => _errorMessage;
double? get latitude => _currentPosition?.latitude;
double? get longitude => _currentPosition?.longitude;
double? get accuracy => _currentPosition?.accuracy;
Duration get tripDuration {
if (_tripStartTime == null) return Duration.zero;
return DateTime.now().difference(_tripStartTime!);
}
Future<void> initializeLocation() async {
await _checkLocationPermission();
if (_hasLocationPermission) {
await _startLocationTracking();
}
}
Future<void> _checkLocationPermission() async {
final permission = await Permission.locationWhenInUse.status;
if (permission.isDenied) {
final result = await Permission.locationWhenInUse.request();
_hasLocationPermission = result.isGranted;
} else if (permission.isPermanentlyDenied) {
_hasLocationPermission = false;
_errorMessage = 'Location permission is permanently denied. Please enable it in settings.';
} else {
_hasLocationPermission = permission.isGranted;
}
if (!_hasLocationPermission) {
_errorMessage = 'Location permission is required for the speedometer to work.';
} else {
_errorMessage = '';
}
notifyListeners();
}
Future<void> _startLocationTracking() async {
if (!_hasLocationPermission) return;
try {
final isLocationServiceEnabled = await Geolocator.isLocationServiceEnabled();
if (!isLocationServiceEnabled) {
_errorMessage = 'Location services are disabled. Please enable them.';
notifyListeners();
return;
}
const locationSettings = LocationSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: 0,
);
_positionStreamSubscription = Geolocator.getPositionStream(
locationSettings: locationSettings,
).listen(
_onLocationUpdate,
onError: (error) {
_errorMessage = 'Location error: $error';
notifyListeners();
},
);
_isTracking = true;
_tripStartTime = DateTime.now();
notifyListeners();
} catch (e) {
_errorMessage = 'Failed to start location tracking: $e';
notifyListeners();
}
}
void _onLocationUpdate(Position position) {
_currentPosition = position;
_currentSpeed = position.speed;
if (_previousPosition != null) {
final distance = Geolocator.distanceBetween(
_previousPosition!.latitude,
_previousPosition!.longitude,
position.latitude,
position.longitude,
);
_totalDistance += distance;
}
_previousPosition = position;
_errorMessage = '';
notifyListeners();
}
void resetTrip() {
_totalDistance = 0.0;
_tripStartTime = DateTime.now();
_previousPosition = _currentPosition;
notifyListeners();
}
Future<void> stopTracking() async {
await _positionStreamSubscription?.cancel();
_positionStreamSubscription = null;
_isTracking = false;
notifyListeners();
}
@override
void dispose() {
stopTracking();
super.dispose();
}
}
-110
View File
@@ -1,110 +0,0 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
enum SpeedUnit { kmh, mph, knots }
enum SpeedometerStyle { digital, analog }
class SettingsProvider extends ChangeNotifier {
bool _isDarkMode = false;
SpeedUnit _speedUnit = SpeedUnit.kmh;
SpeedometerStyle _speedometerStyle = SpeedometerStyle.digital;
bool _showCoordinates = false;
bool _showDistance = false;
bool _showTripTime = false;
bool _showAccuracy = false;
bool get isDarkMode => _isDarkMode;
SpeedUnit get speedUnit => _speedUnit;
SpeedometerStyle get speedometerStyle => _speedometerStyle;
bool get showCoordinates => _showCoordinates;
bool get showDistance => _showDistance;
bool get showTripTime => _showTripTime;
bool get showAccuracy => _showAccuracy;
String get speedUnitString {
switch (_speedUnit) {
case SpeedUnit.kmh:
return 'km/h';
case SpeedUnit.mph:
return 'mph';
case SpeedUnit.knots:
return 'knots';
}
}
SettingsProvider() {
_loadSettings();
}
Future<void> _loadSettings() async {
final prefs = await SharedPreferences.getInstance();
_isDarkMode = prefs.getBool('isDarkMode') ?? false;
_speedUnit = SpeedUnit.values[prefs.getInt('speedUnit') ?? 0];
_speedometerStyle = SpeedometerStyle.values[prefs.getInt('speedometerStyle') ?? 0];
_showCoordinates = prefs.getBool('showCoordinates') ?? false;
_showDistance = prefs.getBool('showDistance') ?? false;
_showTripTime = prefs.getBool('showTripTime') ?? false;
_showAccuracy = prefs.getBool('showAccuracy') ?? false;
notifyListeners();
}
Future<void> setDarkMode(bool value) async {
_isDarkMode = value;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isDarkMode', value);
notifyListeners();
}
Future<void> setSpeedUnit(SpeedUnit unit) async {
_speedUnit = unit;
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('speedUnit', unit.index);
notifyListeners();
}
Future<void> setSpeedometerStyle(SpeedometerStyle style) async {
_speedometerStyle = style;
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('speedometerStyle', style.index);
notifyListeners();
}
Future<void> setShowCoordinates(bool value) async {
_showCoordinates = value;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('showCoordinates', value);
notifyListeners();
}
Future<void> setShowDistance(bool value) async {
_showDistance = value;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('showDistance', value);
notifyListeners();
}
Future<void> setShowTripTime(bool value) async {
_showTripTime = value;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('showTripTime', value);
notifyListeners();
}
Future<void> setShowAccuracy(bool value) async {
_showAccuracy = value;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('showAccuracy', value);
notifyListeners();
}
double convertSpeed(double speedMps) {
switch (_speedUnit) {
case SpeedUnit.kmh:
return speedMps * 3.6;
case SpeedUnit.mph:
return speedMps * 2.237;
case SpeedUnit.knots:
return speedMps * 1.944;
}
}
}