feat: update backend OCR parser, web app, mobile app camera/preview UI, tests, and documentation with sample images
This commit is contained in:
1 parent
aa3233e411
commit
bdb3a49742
71 files changed
+3360
-764
No files matched your search
@@ -3,6 +3,19 @@ import 'package:geolocator/geolocator.dart';
|
||||
|
||||
class LocationService {
|
||||
static Future<Position?> Function()? mockDeterminator;
|
||||
static Stream<Position>? mockStream;
|
||||
|
||||
static Stream<Position> getPositionStream() {
|
||||
if (mockStream != null) {
|
||||
return mockStream!;
|
||||
}
|
||||
return Geolocator.getPositionStream(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 1, // update only when moved 1 meter
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Position?> determinePosition() async {
|
||||
if (mockDeterminator != null) {
|
||||
@@ -29,14 +42,70 @@ class LocationService {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Strategy 1: Try balanced/network-based location (fast, works indoors)
|
||||
try {
|
||||
return await Geolocator.getCurrentPosition(
|
||||
final position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.medium,
|
||||
timeLimit: const Duration(seconds: 7),
|
||||
);
|
||||
debugPrint(
|
||||
'GPS balanced/indoor fix: ${position.latitude}, ${position.longitude} '
|
||||
'(accuracy: ${position.accuracy.toStringAsFixed(1)}m)',
|
||||
);
|
||||
return position;
|
||||
} catch (e) {
|
||||
debugPrint('getCurrentPosition balanced failed: $e. Trying high accuracy...');
|
||||
}
|
||||
|
||||
// Strategy 2: Try high accuracy (GPS satellites) with forceAndroidLocationManager to bypass cache
|
||||
try {
|
||||
final position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
forceAndroidLocationManager: true,
|
||||
timeLimit: const Duration(seconds: 10),
|
||||
);
|
||||
debugPrint(
|
||||
'GPS high fix: ${position.latitude}, ${position.longitude} '
|
||||
'(accuracy: ${position.accuracy.toStringAsFixed(1)}m)',
|
||||
);
|
||||
return position;
|
||||
} catch (e) {
|
||||
debugPrint('getCurrentPosition high failed: $e. Checking last known position...');
|
||||
}
|
||||
|
||||
// Strategy 3: Use last known position ONLY if it is super recent (within 2 minutes)
|
||||
final lastKnown = await Geolocator.getLastKnownPosition();
|
||||
if (lastKnown != null) {
|
||||
final age = DateTime.now().difference(lastKnown.timestamp);
|
||||
if (age.inMinutes <= 2) {
|
||||
debugPrint(
|
||||
'Using recent last-known position (${age.inSeconds}s old): '
|
||||
'${lastKnown.latitude}, ${lastKnown.longitude}',
|
||||
);
|
||||
return lastKnown;
|
||||
}
|
||||
debugPrint(
|
||||
'Last-known position is too stale (${age.inMinutes}m old) — '
|
||||
'retrying low accuracy GPS fix...',
|
||||
);
|
||||
}
|
||||
|
||||
// Strategy 4: Last resort — bypass Google Fused Location and try low accuracy
|
||||
// forceAndroidLocationManager forces a real hardware GPS read if enabled
|
||||
try {
|
||||
final position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.low,
|
||||
forceAndroidLocationManager: true,
|
||||
timeLimit: const Duration(seconds: 5),
|
||||
);
|
||||
debugPrint(
|
||||
'GPS low fix via LocationManager: ${position.latitude}, ${position.longitude} '
|
||||
'(accuracy: ${position.accuracy.toStringAsFixed(1)}m)',
|
||||
);
|
||||
return position;
|
||||
} catch (e) {
|
||||
debugPrint('getCurrentPosition failed: $e. Attempting getLastKnownPosition...');
|
||||
return await Geolocator.getLastKnownPosition();
|
||||
debugPrint('All GPS strategies failed: $e');
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Error in LocationService: $e');
|
||||
@@ -44,3 +113,4 @@ class LocationService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user