feat: Update location tracking service to disable automatic broadcasting and add manual control; modify settings screen and related files

This commit is contained in:
Janez T
2025-11-14 10:04:57 +01:00
parent cf780ce636
commit 21daa83c1a
6 changed files with 109 additions and 93 deletions

View File

@@ -47,7 +47,8 @@
"Bash(flutter pub add:*)",
"Bash(flutter run)",
"Bash(echo:*)",
"Bash(pkill:*)"
"Bash(pkill:*)",
"Bash(git restore:*)"
],
"deny": [],
"ask": []

View File

@@ -551,21 +551,17 @@ org.gradle.jvmargs=-Xmx4096m
## Services Reference
### LocationTrackingService (Singleton)
**Purpose**: GPS tracking + intelligent mesh location broadcasting
**Purpose**: GPS tracking for map display and trail recording
**Callbacks**: `onPositionUpdate`, `onError`, `onBroadcastSent`, `onTrackingStateChanged`
**Thresholds**:
- Min distance: 5.0m
- Max distance: 100.0m
- Min time: 30s
**Broadcasting**:
- **Automatic broadcasting DISABLED** - No automatic position adverts to mesh network
- Manual broadcasting available via `broadcastLocationNow()` method
- User must explicitly use the advert button to broadcast location
- GPS tracking continues for map display, currentPosition tracking, and trail recording
**Logic**:
- First update → broadcast immediately
- ≥100m moved → broadcast immediately
- ≥5m + ≥30s → broadcast
**File**: `lib/services/location_tracking_service.dart` (501 lines)
**File**: `lib/services/location_tracking_service.dart`
### MapMarkerService (Singleton)
**Purpose**: Map marker generation + geodesic calculations

View File

@@ -1,4 +1,6 @@
PODS:
- device_info_plus (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.9):
- DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource
@@ -34,55 +36,131 @@ PODS:
- DKImagePickerController/PhotoGallery
- Flutter
- Flutter (1.0.0)
- flutter_background_service_ios (0.0.3):
- Flutter
- flutter_blue_plus_darwin (0.0.2):
- Flutter
- FlutterMacOS
- flutter_compass (0.0.1):
- Flutter
- flutter_local_notifications (0.0.1):
- Flutter
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
- nsd_ios (0.0.1):
- Flutter
- ObjectBox (4.4.1)
- objectbox_flutter_libs (0.0.1):
- Flutter
- ObjectBox (= 4.4.1)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
- SDWebImage (5.21.3):
- SDWebImage/Core (= 5.21.3)
- SDWebImage/Core (5.21.3)
- share_plus (0.0.1):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- SwiftyGif (5.4.5)
- url_launcher_ios (0.0.1):
- Flutter
- vibration (3.0.0):
- Flutter
DEPENDENCIES:
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`)
- flutter_blue_plus_darwin (from `.symlinks/plugins/flutter_blue_plus_darwin/darwin`)
- flutter_compass (from `.symlinks/plugins/flutter_compass/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
- nsd_ios (from `.symlinks/plugins/nsd_ios/ios`)
- objectbox_flutter_libs (from `.symlinks/plugins/objectbox_flutter_libs/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- vibration (from `.symlinks/plugins/vibration/ios`)
SPEC REPOS:
trunk:
- DKImagePickerController
- DKPhotoGallery
- ObjectBox
- SDWebImage
- SwiftyGif
EXTERNAL SOURCES:
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
flutter_background_service_ios:
:path: ".symlinks/plugins/flutter_background_service_ios/ios"
flutter_blue_plus_darwin:
:path: ".symlinks/plugins/flutter_blue_plus_darwin/darwin"
flutter_compass:
:path: ".symlinks/plugins/flutter_compass/ios"
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
geolocator_apple:
:path: ".symlinks/plugins/geolocator_apple/darwin"
nsd_ios:
:path: ".symlinks/plugins/nsd_ios/ios"
objectbox_flutter_libs:
:path: ".symlinks/plugins/objectbox_flutter_libs/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
vibration:
:path: ".symlinks/plugins/vibration/ios"
SPEC CHECKSUMS:
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_background_service_ios: 00d31bdff7b4bfe06d32375df358abe0329cf87e
flutter_blue_plus_darwin: 20a08bfeaa0f7804d524858d3d8744bcc1b6dbc3
flutter_compass: b236ab69b61545cce89fd58527f401a7587d5cc1
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
nsd_ios: 596ad79109ddd3e52d665f650f36428049e3653e
ObjectBox: 7da4aceb5013d041bfafdbc6d744a26918b09757
objectbox_flutter_libs: 09b1dec1b4cd27bf1a5f9bae7ccaa7e43588bf31
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
vibration: 69774ad57825b11c951ee4c46155f455d7a592ce
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e

View File

@@ -198,6 +198,7 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
0F5356670725D838348C6698 /* [CP] Embed Pods Frameworks */,
5C71E5FAEF51EAE4BBF3727A /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -324,6 +325,23 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
5C71E5FAEF51EAE4BBF3727A /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;

View File

@@ -627,42 +627,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
),
const Divider(),
// Location Settings Section
_buildSectionHeader(
AppLocalizations.of(context)!.locationBroadcasting,
),
// Automatic tracking settings
SwitchListTile(
secondary: const Icon(Icons.location_on),
title: Text(AppLocalizations.of(context)!.autoLocationTracking),
subtitle: Text(
AppLocalizations.of(context)!.automaticallyBroadcastPosition,
),
value: _locationService.isTracking,
onChanged: (value) {
if (value) {
_startBackgroundTracking();
} else {
_stopBackgroundTracking();
}
},
),
if (_locationService.isTracking) ...[
ListTile(
leading: const Icon(Icons.tune),
title: Text(AppLocalizations.of(context)!.configureTracking),
subtitle: Text(
AppLocalizations.of(context)!.distanceAndTimeThresholds,
),
trailing: const Icon(Icons.chevron_right),
onTap: () => _showTrackingConfigDialog(),
),
],
const Divider(),
// About Section
_buildSectionHeader(AppLocalizations.of(context)!.about),
ListTile(

View File

@@ -420,52 +420,11 @@ class LocationTrackingService {
}
/// Check if position should be broadcast based on distance and time thresholds
/// DISABLED: Automatic broadcasting removed - use advert button for manual broadcasts
void _checkAndBroadcast(Position position) {
// If never broadcast before, do it now
if (_lastBroadcastPosition == null || _lastBroadcastTime == null) {
_broadcastPosition(position);
return;
}
// Calculate time since last broadcast
final timeSinceLastBroadcast = DateTime.now().difference(
_lastBroadcastTime!,
);
final secondsSinceLastBroadcast = timeSinceLastBroadcast.inSeconds;
// Calculate distance from last broadcast position
final distanceFromLastBroadcast = Geolocator.distanceBetween(
_lastBroadcastPosition!.latitude,
_lastBroadcastPosition!.longitude,
position.latitude,
position.longitude,
);
debugPrint(
' Distance from last broadcast: ${distanceFromLastBroadcast.toStringAsFixed(1)}m',
);
debugPrint(' Time since last broadcast: ${secondsSinceLastBroadcast}s');
// Broadcast if moved beyond max distance threshold
if (distanceFromLastBroadcast >= maxDistanceMeters) {
debugPrint(
' 📤 Triggering broadcast: exceeded max distance (${maxDistanceMeters}m)',
);
_broadcastPosition(position);
return;
}
// Broadcast if minimum time interval passed AND moved beyond min distance
if (secondsSinceLastBroadcast >= minTimeIntervalSeconds &&
distanceFromLastBroadcast >= minDistanceMeters) {
debugPrint(
' 📤 Triggering broadcast: exceeded min time (${minTimeIntervalSeconds}s) and min distance (${minDistanceMeters}m)',
);
_broadcastPosition(position);
return;
}
debugPrint(' ⏸️ Not broadcasting: thresholds not met');
// Automatic broadcasting disabled
// Use the manual advert button instead
debugPrint(' ⏸️ [LocationTracking] Automatic broadcasting disabled (use advert button)');
}
// ============================================================================