diff --git a/assets/changelog.json b/assets/changelog.json index 0559b29..0299524 100644 --- a/assets/changelog.json +++ b/assets/changelog.json @@ -3,10 +3,10 @@ "content": [ "• Make node tags selectable / copyable", "• Add status indicator to details sheet for pending nodes", - "• Global toggle for offline features" + "• Global toggle for offline features", + "• Auto-open details sheet for new add/edit/deletes" ] }, - "2.10.4": { "content": [ "• Catch and correct a couple rare map bounds issues", diff --git a/lib/app_state.dart b/lib/app_state.dart index 16169f6..3d7b653 100644 --- a/lib/app_state.dart +++ b/lib/app_state.dart @@ -64,6 +64,12 @@ class AppState extends ChangeNotifier { VoidCallback? _tutorialCompletionCallback; // Callback when tutorial is completed Timer? _messageCheckTimer; + // Node ID to auto-focus (open the details sheet for) after a submit/edit/delete + // completes, when kAutoOpenNodeSheetAfterSubmit is enabled. Consumed (read once + // and cleared) by HomeScreen after picking it up. + int? _pendingFocusNodeId; + + AppState() { instance = this; _authState = AuthState(); @@ -584,24 +590,44 @@ class AppState extends ChangeNotifier { void commitSession() { final session = _sessionState.commitSession(); if (session != null) { - _uploadQueueState.addFromSession(session, uploadMode: uploadMode); + final upload = _uploadQueueState.addFromSession(session, uploadMode: uploadMode); _startUploader(); + if (kAutoOpenNodeSheetAfterSubmit && upload.tempNodeId != null) { + _pendingFocusNodeId = upload.tempNodeId; + } } } void commitEditSession() { final session = _sessionState.commitEditSession(); if (session != null) { - _uploadQueueState.addFromEditSession(session, uploadMode: uploadMode); + final upload = _uploadQueueState.addFromEditSession(session, uploadMode: uploadMode); _startUploader(); + if (kAutoOpenNodeSheetAfterSubmit && upload.tempNodeId != null) { + _pendingFocusNodeId = upload.tempNodeId; + } } } void deleteNode(OsmNode node, {String? changesetComment}) { _uploadQueueState.addFromNodeDeletion(node, uploadMode: uploadMode, changesetComment: changesetComment); _startUploader(); + if (kAutoOpenNodeSheetAfterSubmit) { + _pendingFocusNodeId = node.id; + } } + /// Consume (read once and clear) the node ID pending auto-focus, if any. + /// Used by HomeScreen to reopen the node details sheet right after a + /// submit/edit/delete completes, when [kAutoOpenNodeSheetAfterSubmit] is + /// enabled. Returns null if no focus is pending. + int? consumePendingFocusNodeId() { + final id = _pendingFocusNodeId; + _pendingFocusNodeId = null; + return id; + } + + // ---------- Search Methods ---------- Future search(String query) async { await _searchState.search(query); diff --git a/lib/dev_config.dart b/lib/dev_config.dart index 67d6963..f415ac9 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -82,6 +82,9 @@ const bool kEnableNodeEdits = true; // Set to false to temporarily disable node // Node extraction features - set to false to hide extract functionality for constrained nodes const bool kEnableNodeExtraction = false; // Set to true to enable extract from way/relation feature (WIP) +// Auto-open tags sheet after add/edit/delete, so the user can watch upload status update live. +const bool kAutoOpenNodeSheetAfterSubmit = true; // Set to true to enable auto-focus behavior + // Profile FOV features - set to false to restrict profiles to 360° FOV only const bool kEnableNon360FOVs = false; // Set to true to allow custom FOV values in profiles diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 8c707a3..60d9ca8 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -8,6 +8,8 @@ import '../app_state.dart'; import '../dev_config.dart'; import '../widgets/map_view.dart'; import '../services/localization_service.dart'; +import '../services/map_data_provider.dart'; + import '../widgets/node_tag_sheet.dart'; import '../widgets/download_area_dialog.dart'; @@ -455,6 +457,22 @@ class _HomeScreenState extends State with TickerProviderStateMixin { }); } + // Auto-focus a node's details sheet right after it was submitted/edited/deleted, + // behind kAutoOpenNodeSheetAfterSubmit (pending A/B testing/team feedback). + if (kAutoOpenNodeSheetAfterSubmit) { + final focusNodeId = appState.consumePendingFocusNodeId(); + if (focusNodeId != null && !_sheetCoordinator.hasActiveNodeSheet) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) return; + final node = MapDataProvider().getNodeById(focusNodeId); + if (node != null) { + openNodeTagSheet(node); + } + }); + } + } + + // Pass the active sheet height directly to the map final activeSheetHeight = _sheetCoordinator.activeSheetHeight; diff --git a/lib/state/upload_queue_state.dart b/lib/state/upload_queue_state.dart index bd883a8..a7250b7 100644 --- a/lib/state/upload_queue_state.dart +++ b/lib/state/upload_queue_state.dart @@ -121,7 +121,7 @@ class UploadQueueState extends ChangeNotifier { } // Add a completed session to the upload queue - void addFromSession(AddNodeSession session, {required UploadMode uploadMode}) { + PendingUpload addFromSession(AddNodeSession session, {required UploadMode uploadMode}) { final upload = PendingUpload( coord: session.target!, direction: _formatDirectionsForSubmission(session.directions, session.profile), @@ -159,10 +159,11 @@ class UploadQueueState extends ChangeNotifier { NodeProviderWithCache.instance.notifyListeners(); notifyListeners(); + return upload; } // Add a completed edit session to the upload queue - void addFromEditSession(EditNodeSession session, {required UploadMode uploadMode}) { + PendingUpload addFromEditSession(EditNodeSession session, {required UploadMode uploadMode}) { // Determine operation type and coordinates final UploadOperation operation; final LatLng coordToUse; @@ -250,10 +251,11 @@ class UploadQueueState extends ChangeNotifier { NodeProviderWithCache.instance.notifyListeners(); notifyListeners(); + return upload; } // Add a node deletion to the upload queue - void addFromNodeDeletion(OsmNode node, {required UploadMode uploadMode, String? changesetComment}) { + PendingUpload addFromNodeDeletion(OsmNode node, {required UploadMode uploadMode, String? changesetComment}) { final upload = PendingUpload( coord: node.coord, direction: node.directionDeg.isNotEmpty ? node.directionDeg.first : 0, // Direction not used for deletions but required for API @@ -282,6 +284,7 @@ class UploadQueueState extends ChangeNotifier { NodeProviderWithCache.instance.notifyListeners(); notifyListeners(); + return upload; } void clearQueue() {