Files
gps-speedo/lib/gps_service.dart
T
Mikkeli Matlock 6d1cf5fac3 feat: implement GpsDataManager architecture with modular design
- Add GpsDataManager singleton service for centralized GPS data processing
- Refactor main app to use processed GPS data streams instead of raw position data
- Add haptic feedback to all main UI tap interactions (theme, unit, navigation)
- Implement faster GPS update frequency (500ms timeLimit in LocationSettings)
- Clean up verbose debug logging while preserving essential error logs
- Remove unused debug variables and imports
- Preserve existing background survival mechanisms and overlay lifecycle
- Add temporary GPS simulation while resolving geolocator engine conflicts

Architecture improvements:
- Clean data flow: GPS Hardware → GpsDataManager → Main App → Overlay
- Single source of truth for processed GPS data in manager
- Separation of concerns: GPS logic isolated from UI components
- Foundation ready for intelligent caching logic implementation

Technical notes:
- GPS engine conflict detected, temporarily using simulation data
- All functionality tested and working with test data
- Real GPS integration pending engine conflict resolution

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-31 01:15:00 +09:00

47 lines
1.5 KiB
Dart

import 'dart:async';
import 'package:geolocator/geolocator.dart';
import 'package:permission_handler/permission_handler.dart';
class GpsService {
static double? _lastValidHeading;
static Stream<Position> get positionStream {
return Geolocator.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: 0,
timeLimit: Duration(milliseconds: 500), // Force updates every 500ms for faster GPS refresh
),
);
}
static Future<bool> requestPermissions() async {
final permission = await Permission.locationWhenInUse.request();
return permission.isGranted;
}
static Future<bool> isLocationServiceEnabled() async {
return await Geolocator.isLocationServiceEnabled();
}
static double getCachedHeading(double heading) {
if (heading >= 0 && heading <= 360) {
_lastValidHeading = heading;
return heading;
}
return _lastValidHeading ?? 0.0;
}
static String getCompassDirection(double heading) {
final cachedHeading = getCachedHeading(heading);
const directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
final index = ((cachedHeading + 22.5) / 45).floor() % 8;
return directions[index];
}
static String formatHeading(double heading) {
final cachedHeading = getCachedHeading(heading);
return '${cachedHeading.round()} ${getCompassDirection(heading)}'; // don't add that degree symbol, this is cooler
}
}