diff --git a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart index 993000b6..9fe34469 100644 --- a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart +++ b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/location_map.dart @@ -117,8 +117,9 @@ class _LocationMapState extends ConsumerState } } else if (widget.selectedPosition != null && widget.selectedPosition != oldWidget.selectedPosition) { - final mapState = ref.read(locationMapViewModelProvider); - if (mapState.isFollowing) _centerOnDevice(); + final firstFix = oldWidget.selectedPosition == null; + final isFollowing = ref.read(locationMapViewModelProvider).isFollowing; + if (firstFix || isFollowing) _centerOnDevice(); } if (widget.positionHistory.length > 1 && @@ -661,6 +662,7 @@ class _LocationMapState extends ConsumerState child: MapActionsPanel( actionsExpanded: mapState.actionsExpanded, hasPosition: widget.selectedPosition != null, + isFollowing: mapState.isFollowing, onToggleExpanded: _vm.toggleActionsExpanded, onListTap: _showListSheet, onAddGeofence: () => _vm.startPlacing(PlacingMode.geofence), @@ -671,8 +673,34 @@ class _LocationMapState extends ConsumerState ref.read(sfTrackingProvider).legacyLocationMapRefreshTapped(), ); widget.onRefreshPosition(); + showTopSnackbar( + context, + message: context.translate(I18n.locationMapRefreshRequested), + type: MessageType.info, + ); }, onCenterTap: _centerOnDevice, + onToggleFollow: () { + final willActivate = !mapState.isFollowing; + _vm.toggleFollowing(); + unawaited( + ref + .read(sfTrackingProvider) + .legacyLocationMapFollowToggled(willActivate), + ); + if (willActivate && widget.selectedPosition != null) { + _centerOnDevice(); + } + showTopSnackbar( + context, + message: context.translate( + willActivate + ? I18n.locationMapFollowEnabled + : I18n.locationMapFollowDisabled, + ), + type: MessageType.success, + ); + }, ), ), ]; diff --git a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/map_controls/map_actions_panel.dart b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/map_controls/map_actions_panel.dart index a75c8abd..083702de 100644 --- a/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/map_controls/map_actions_panel.dart +++ b/modules/legacy/modules/location/lib/src/features/location/presentation/widgets/map_controls/map_actions_panel.dart @@ -6,6 +6,7 @@ import 'map_action_button.dart'; class MapActionsPanel extends StatelessWidget { final bool actionsExpanded; final bool hasPosition; + final bool isFollowing; final VoidCallback onToggleExpanded; final VoidCallback onListTap; final VoidCallback onAddGeofence; @@ -13,11 +14,13 @@ class MapActionsPanel extends StatelessWidget { final VoidCallback onShareTap; final VoidCallback onRefreshTap; final VoidCallback onCenterTap; + final VoidCallback onToggleFollow; const MapActionsPanel({ super.key, required this.actionsExpanded, required this.hasPosition, + required this.isFollowing, required this.onToggleExpanded, required this.onListTap, required this.onAddGeofence, @@ -25,6 +28,7 @@ class MapActionsPanel extends StatelessWidget { required this.onShareTap, required this.onRefreshTap, required this.onCenterTap, + required this.onToggleFollow, }); @override @@ -67,6 +71,12 @@ class MapActionsPanel extends StatelessWidget { if (hasPosition) ...[ const SizedBox(height: 8), MapActionButton(icon: Icons.my_location, onTap: onCenterTap), + const SizedBox(height: 8), + MapActionButton( + icon: isFollowing ? Icons.gps_fixed : Icons.gps_not_fixed, + isActive: isFollowing, + onTap: onToggleFollow, + ), ], ], ); diff --git a/packages/sf_localizations/assets/l10n/de.json b/packages/sf_localizations/assets/l10n/de.json index 05f51c81..a3627351 100644 --- a/packages/sf_localizations/assets/l10n/de.json +++ b/packages/sf_localizations/assets/l10n/de.json @@ -580,6 +580,9 @@ "locationMapStyleLight": "Hell", "locationMapStyleDark": "Dunkel", "locationMapStyleSatellite": "Satellit", + "locationMapRefreshRequested": "Standort wird von der Uhr angefordert…", + "locationMapFollowEnabled": "Automatische Verfolgung aktiviert", + "locationMapFollowDisabled": "Automatische Verfolgung deaktiviert", "locationLayerGeofences": "Sicherheitszonen", "locationLayerFrequentPlaces": "Häufige Orte", "locationLayerHistory": "Verlauf", diff --git a/packages/sf_localizations/assets/l10n/en.json b/packages/sf_localizations/assets/l10n/en.json index 5ec5f6de..6ecbf23b 100755 --- a/packages/sf_localizations/assets/l10n/en.json +++ b/packages/sf_localizations/assets/l10n/en.json @@ -715,6 +715,9 @@ "locationMapStyleLight": "Light", "locationMapStyleDark": "Dark", "locationMapStyleSatellite": "Satellite", + "locationMapRefreshRequested": "Requesting location from the watch…", + "locationMapFollowEnabled": "Auto-follow enabled", + "locationMapFollowDisabled": "Auto-follow disabled", "locationLayerGeofences": "Safety zones", "locationLayerFrequentPlaces": "Frequent Places", "locationLayerHistory": "History", diff --git a/packages/sf_localizations/assets/l10n/es.json b/packages/sf_localizations/assets/l10n/es.json index ef1758d2..71ba56d5 100644 --- a/packages/sf_localizations/assets/l10n/es.json +++ b/packages/sf_localizations/assets/l10n/es.json @@ -716,6 +716,9 @@ "locationMapStyleLight": "Claro", "locationMapStyleDark": "Oscuro", "locationMapStyleSatellite": "Satélite", + "locationMapRefreshRequested": "Solicitando ubicación al reloj…", + "locationMapFollowEnabled": "Seguimiento automático activado", + "locationMapFollowDisabled": "Seguimiento automático desactivado", "locationLayerGeofences": "Zonas de seguridad", "locationLayerFrequentPlaces": "Lugares Frecuentes", "locationLayerHistory": "Historial", diff --git a/packages/sf_localizations/assets/l10n/fr.json b/packages/sf_localizations/assets/l10n/fr.json index ee740af2..94c6db6b 100644 --- a/packages/sf_localizations/assets/l10n/fr.json +++ b/packages/sf_localizations/assets/l10n/fr.json @@ -580,6 +580,9 @@ "locationMapStyleLight": "Clair", "locationMapStyleDark": "Sombre", "locationMapStyleSatellite": "Satellite", + "locationMapRefreshRequested": "Demande de localisation à la montre…", + "locationMapFollowEnabled": "Suivi automatique activé", + "locationMapFollowDisabled": "Suivi automatique désactivé", "locationLayerGeofences": "Zones de sécurité", "locationLayerFrequentPlaces": "Lieux fréquents", "locationLayerHistory": "Historique", diff --git a/packages/sf_localizations/assets/l10n/it.json b/packages/sf_localizations/assets/l10n/it.json index aa62404d..6fa7b975 100644 --- a/packages/sf_localizations/assets/l10n/it.json +++ b/packages/sf_localizations/assets/l10n/it.json @@ -580,6 +580,9 @@ "locationMapStyleLight": "Chiaro", "locationMapStyleDark": "Scuro", "locationMapStyleSatellite": "Satellite", + "locationMapRefreshRequested": "Richiesta posizione all'orologio…", + "locationMapFollowEnabled": "Tracciamento automatico attivato", + "locationMapFollowDisabled": "Tracciamento automatico disattivato", "locationLayerGeofences": "Zone di sicurezza", "locationLayerFrequentPlaces": "Luoghi frequenti", "locationLayerHistory": "Cronologia", diff --git a/packages/sf_localizations/assets/l10n/pt.json b/packages/sf_localizations/assets/l10n/pt.json index 1df78003..305f8f63 100644 --- a/packages/sf_localizations/assets/l10n/pt.json +++ b/packages/sf_localizations/assets/l10n/pt.json @@ -580,6 +580,9 @@ "locationMapStyleLight": "Claro", "locationMapStyleDark": "Escuro", "locationMapStyleSatellite": "Satélite", + "locationMapRefreshRequested": "Solicitando localização ao relógio…", + "locationMapFollowEnabled": "Seguimento automático ativado", + "locationMapFollowDisabled": "Seguimento automático desativado", "locationLayerGeofences": "Zonas de segurança", "locationLayerFrequentPlaces": "Lugares frequentes", "locationLayerHistory": "Histórico", diff --git a/packages/sf_localizations/lib/src/generated/i18n.dart b/packages/sf_localizations/lib/src/generated/i18n.dart index 1d776115..1639ca22 100755 --- a/packages/sf_localizations/lib/src/generated/i18n.dart +++ b/packages/sf_localizations/lib/src/generated/i18n.dart @@ -567,6 +567,9 @@ class I18n { static const String locationMapStyleSatellite = 'locationMapStyleSatellite'; static const String locationMapStyleStandard = 'locationMapStyleStandard'; static const String locationMapStyleVoyager = 'locationMapStyleVoyager'; + static const String locationMapRefreshRequested = 'locationMapRefreshRequested'; + static const String locationMapFollowEnabled = 'locationMapFollowEnabled'; + static const String locationMapFollowDisabled = 'locationMapFollowDisabled'; static const String locationNewFrequentPlace = 'locationNewFrequentPlace'; static const String locationNewGeofence = 'locationNewGeofence'; static const String locationPlace = 'locationPlace'; diff --git a/packages/sf_tracking/lib/src/mixins/location_tracking.dart b/packages/sf_tracking/lib/src/mixins/location_tracking.dart index 86fec660..40c1d8cc 100644 --- a/packages/sf_tracking/lib/src/mixins/location_tracking.dart +++ b/packages/sf_tracking/lib/src/mixins/location_tracking.dart @@ -114,6 +114,11 @@ mixin LocationTracking on Tracking { Future legacyLocationMapRefreshTapped() => trackEvent('${_prefix}_map_refresh_tapped'); + Future legacyLocationMapFollowToggled(bool active) => trackEvent( + '${_prefix}_map_follow_toggled', + {'active': active.toString()}, + ); + Future legacyLocationListSheetOpened() => trackEvent('${_prefix}_list_sheet_opened');