diff --git a/assets/changelog.json b/assets/changelog.json index 603aa4f..fc156ff 100644 --- a/assets/changelog.json +++ b/assets/changelog.json @@ -1,4 +1,11 @@ { + "2.3.1": { + "content": [ + "• Follow-me mode now automatically restores when add/edit/tag sheets are closed", + "• Follow-me button is greyed out while node sheets are open (add/edit/tag) since following doesn't make sense during node operations" + "• Drop support for approximate location since I can't get it to work reliably; apologies" + ] + }, "2.3.0": { "content": [ "• Concurrent upload queue processing", @@ -8,6 +15,7 @@ "2.2.1": { "content": [ "• Fixed network status indicator timing out prematurely", + "• Improved GPS follow-me reliability - fixed sync issues that could cause tracking to stop working", "• Network status now accurately shows 'taking a while' when requests split or backoff, and only shows 'timed out' for actual network failures" ] }, @@ -271,4 +279,4 @@ "• New suspected locations feature" ] } -} \ No newline at end of file +} diff --git a/lib/screens/coordinators/sheet_coordinator.dart b/lib/screens/coordinators/sheet_coordinator.dart index 73b3f86..14f15f4 100644 --- a/lib/screens/coordinators/sheet_coordinator.dart +++ b/lib/screens/coordinators/sheet_coordinator.dart @@ -9,6 +9,7 @@ import '../../widgets/add_node_sheet.dart'; import '../../widgets/edit_node_sheet.dart'; import '../../widgets/navigation_sheet.dart'; import '../../widgets/measured_sheet.dart'; +import '../../state/settings_state.dart' show FollowMeMode; /// Coordinates all bottom sheet operations including opening, closing, height tracking, /// and sheet-related validation logic. @@ -25,6 +26,9 @@ class SheetCoordinator { // Flag to prevent map bounce when transitioning from tag sheet to edit sheet bool _transitioningToEdit = false; + + // Follow-me state restoration + FollowMeMode? _followMeModeBeforeSheet; // Getters for accessing heights double get addSheetHeight => _addSheetHeight; @@ -88,7 +92,8 @@ class SheetCoordinator { return; } - // Disable follow-me when adding a node so the map doesn't jump around + // Save current follow-me mode and disable it while sheet is open + _followMeModeBeforeSheet = appState.followMeMode; appState.setFollowMeMode(FollowMeMode.off); appState.startAddSession(); @@ -120,6 +125,9 @@ class SheetCoordinator { debugPrint('[SheetCoordinator] AddNodeSheet dismissed - canceling session'); appState.cancelSession(); } + + // Restore follow-me mode that was active before sheet opened + _restoreFollowMeMode(appState); }); } @@ -132,7 +140,8 @@ class SheetCoordinator { }) { final appState = context.read(); - // Disable follow-me when editing a node so the map doesn't jump around + // Save current follow-me mode and disable it while sheet is open + _followMeModeBeforeSheet = appState.followMeMode; appState.setFollowMeMode(FollowMeMode.off); final session = appState.editSession!; // should be non-null when this is called @@ -185,6 +194,9 @@ class SheetCoordinator { debugPrint('[SheetCoordinator] EditNodeSheet dismissed - canceling edit session'); appState.cancelEditSession(); } + + // Restore follow-me mode that was active before sheet opened + _restoreFollowMeMode(appState); }); } @@ -250,4 +262,16 @@ class SheetCoordinator { _tagSheetHeight = 0.0; onStateChanged(); } + + /// Restore the follow-me mode that was active before opening a node sheet + void _restoreFollowMeMode(AppState appState) { + if (_followMeModeBeforeSheet != null) { + debugPrint('[SheetCoordinator] Restoring follow-me mode: ${_followMeModeBeforeSheet}'); + appState.setFollowMeMode(_followMeModeBeforeSheet!); + _followMeModeBeforeSheet = null; // Clear stored state + } + } + + /// Check if any node editing/viewing sheet is currently open + bool get hasActiveNodeSheet => _addSheetHeight > 0 || _editSheetHeight > 0 || _tagSheetHeight > 0; } \ No newline at end of file diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 49305c3..44f7f1c 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -433,7 +433,7 @@ class _HomeScreenState extends State with TickerProviderStateMixin { IconButton( tooltip: _getFollowMeTooltip(appState.followMeMode), icon: Icon(_getFollowMeIcon(appState.followMeMode)), - onPressed: _mapViewKey.currentState?.hasLocation == true + onPressed: (_mapViewKey.currentState?.hasLocation == true && !_sheetCoordinator.hasActiveNodeSheet) ? () { final oldMode = appState.followMeMode; final newMode = _getNextFollowMeMode(oldMode); @@ -444,7 +444,7 @@ class _HomeScreenState extends State with TickerProviderStateMixin { _mapViewKey.currentState?.retryLocationInit(); } } - : null, // Grey out when no location + : null, // Grey out when no location or when node sheet is open ), AnimatedBuilder( animation: LocalizationService.instance, diff --git a/lib/widgets/map/gps_controller.dart b/lib/widgets/map/gps_controller.dart index 5046d36..33e7c04 100644 --- a/lib/widgets/map/gps_controller.dart +++ b/lib/widgets/map/gps_controller.dart @@ -10,11 +10,11 @@ import '../../services/proximity_alert_service.dart'; import '../../models/osm_node.dart'; import '../../models/node_profile.dart'; -/// Simple GPS controller that respects permissions and provides location updates. +/// Simple GPS controller that handles precise location permissions only. /// Key principles: /// - Respect "denied forever" - stop trying -/// - Retry "denied" - user might enable later -/// - Accept whatever accuracy is available once granted +/// - Retry "denied" - user might enable later +/// - Only works with precise location permissions class GpsController { StreamSubscription? _positionSub; Timer? _retryTimer; diff --git a/pubspec.yaml b/pubspec.yaml index 2b79857..8c4b28d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: deflockapp description: Map public surveillance infrastructure with OpenStreetMap publish_to: "none" -version: 2.3.0+38 # The thing after the + is the version code, incremented with each release +version: 2.3.1+38 # The thing after the + is the version code, incremented with each release environment: sdk: ">=3.5.0 <4.0.0" # oauth2_client 4.x needs Dart 3.5+