feat(location-map): auto-center on first fix, follow toggle, refresh feedback
This commit is contained in:
@@ -117,8 +117,9 @@ class _LocationMapState extends ConsumerState<LocationMap>
|
||||
}
|
||||
} 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<LocationMap>
|
||||
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<LocationMap>
|
||||
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,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -114,6 +114,11 @@ mixin LocationTracking on Tracking {
|
||||
Future<void> legacyLocationMapRefreshTapped() =>
|
||||
trackEvent('${_prefix}_map_refresh_tapped');
|
||||
|
||||
Future<void> legacyLocationMapFollowToggled(bool active) => trackEvent(
|
||||
'${_prefix}_map_follow_toggled',
|
||||
{'active': active.toString()},
|
||||
);
|
||||
|
||||
Future<void> legacyLocationListSheetOpened() =>
|
||||
trackEvent('${_prefix}_list_sheet_opened');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user