auto-open tags sheet for submissions (pending testing/feedback)

This commit is contained in:
stopflock
2026-07-26 03:46:00 -05:00
parent 8148ad55c2
commit 837f59bfde
5 changed files with 57 additions and 7 deletions
+2 -2
View File
@@ -3,10 +3,10 @@
"content": [ "content": [
"• Make node tags selectable / copyable", "• Make node tags selectable / copyable",
"• Add status indicator to details sheet for pending nodes", "• 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": { "2.10.4": {
"content": [ "content": [
"• Catch and correct a couple rare map bounds issues", "• Catch and correct a couple rare map bounds issues",
+28 -2
View File
@@ -64,6 +64,12 @@ class AppState extends ChangeNotifier {
VoidCallback? _tutorialCompletionCallback; // Callback when tutorial is completed VoidCallback? _tutorialCompletionCallback; // Callback when tutorial is completed
Timer? _messageCheckTimer; 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() { AppState() {
instance = this; instance = this;
_authState = AuthState(); _authState = AuthState();
@@ -584,24 +590,44 @@ class AppState extends ChangeNotifier {
void commitSession() { void commitSession() {
final session = _sessionState.commitSession(); final session = _sessionState.commitSession();
if (session != null) { if (session != null) {
_uploadQueueState.addFromSession(session, uploadMode: uploadMode); final upload = _uploadQueueState.addFromSession(session, uploadMode: uploadMode);
_startUploader(); _startUploader();
if (kAutoOpenNodeSheetAfterSubmit && upload.tempNodeId != null) {
_pendingFocusNodeId = upload.tempNodeId;
}
} }
} }
void commitEditSession() { void commitEditSession() {
final session = _sessionState.commitEditSession(); final session = _sessionState.commitEditSession();
if (session != null) { if (session != null) {
_uploadQueueState.addFromEditSession(session, uploadMode: uploadMode); final upload = _uploadQueueState.addFromEditSession(session, uploadMode: uploadMode);
_startUploader(); _startUploader();
if (kAutoOpenNodeSheetAfterSubmit && upload.tempNodeId != null) {
_pendingFocusNodeId = upload.tempNodeId;
}
} }
} }
void deleteNode(OsmNode node, {String? changesetComment}) { void deleteNode(OsmNode node, {String? changesetComment}) {
_uploadQueueState.addFromNodeDeletion(node, uploadMode: uploadMode, changesetComment: changesetComment); _uploadQueueState.addFromNodeDeletion(node, uploadMode: uploadMode, changesetComment: changesetComment);
_startUploader(); _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 ---------- // ---------- Search Methods ----------
Future<void> search(String query) async { Future<void> search(String query) async {
await _searchState.search(query); await _searchState.search(query);
+3
View File
@@ -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 // 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) 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 // 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 const bool kEnableNon360FOVs = false; // Set to true to allow custom FOV values in profiles
+18
View File
@@ -8,6 +8,8 @@ import '../app_state.dart';
import '../dev_config.dart'; import '../dev_config.dart';
import '../widgets/map_view.dart'; import '../widgets/map_view.dart';
import '../services/localization_service.dart'; import '../services/localization_service.dart';
import '../services/map_data_provider.dart';
import '../widgets/node_tag_sheet.dart'; import '../widgets/node_tag_sheet.dart';
import '../widgets/download_area_dialog.dart'; import '../widgets/download_area_dialog.dart';
@@ -455,6 +457,22 @@ class _HomeScreenState extends State<HomeScreen> 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 // Pass the active sheet height directly to the map
final activeSheetHeight = _sheetCoordinator.activeSheetHeight; final activeSheetHeight = _sheetCoordinator.activeSheetHeight;
+6 -3
View File
@@ -121,7 +121,7 @@ class UploadQueueState extends ChangeNotifier {
} }
// Add a completed session to the upload queue // 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( final upload = PendingUpload(
coord: session.target!, coord: session.target!,
direction: _formatDirectionsForSubmission(session.directions, session.profile), direction: _formatDirectionsForSubmission(session.directions, session.profile),
@@ -159,10 +159,11 @@ class UploadQueueState extends ChangeNotifier {
NodeProviderWithCache.instance.notifyListeners(); NodeProviderWithCache.instance.notifyListeners();
notifyListeners(); notifyListeners();
return upload;
} }
// Add a completed edit session to the upload queue // 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 // Determine operation type and coordinates
final UploadOperation operation; final UploadOperation operation;
final LatLng coordToUse; final LatLng coordToUse;
@@ -250,10 +251,11 @@ class UploadQueueState extends ChangeNotifier {
NodeProviderWithCache.instance.notifyListeners(); NodeProviderWithCache.instance.notifyListeners();
notifyListeners(); notifyListeners();
return upload;
} }
// Add a node deletion to the upload queue // 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( final upload = PendingUpload(
coord: node.coord, coord: node.coord,
direction: node.directionDeg.isNotEmpty ? node.directionDeg.first : 0, // Direction not used for deletions but required for API 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(); NodeProviderWithCache.instance.notifyListeners();
notifyListeners(); notifyListeners();
return upload;
} }
void clearQueue() { void clearQueue() {