diff --git a/README.md b/README.md index b9349a9..e07874c 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ cp lib/keys.dart.example lib/keys.dart - Add ability to downvote suspected locations which are old enough - Turn by turn navigation or at least swipe nav sheet up to see a list - Import/Export map providers +- Import default profiles from the website to capture changes without pushing an update? ### Future Features & Wishlist - Tap pending queue item to edit again before submitting diff --git a/assets/changelog.json b/assets/changelog.json index 39b5265..13ec504 100644 --- a/assets/changelog.json +++ b/assets/changelog.json @@ -1,7 +1,8 @@ { "2.6.3": { "content": [ - "• Prevent edit submissions where nothing (location, tags, direction) has been changed" + "• Prevent edit submissions where nothing (location, tags, direction) has been changed", + "• FIXED: Node data not loading in sandbox mode - improved cache integration and status reporting for development testing" ] }, "2.6.2": { diff --git a/lib/services/node_data_manager.dart b/lib/services/node_data_manager.dart index f0ced29..94da51a 100644 --- a/lib/services/node_data_manager.dart +++ b/lib/services/node_data_manager.dart @@ -78,15 +78,79 @@ class NodeDataManager extends ChangeNotifier { } } - // Handle sandbox mode (always fetch from OSM API, no caching) + // Handle sandbox mode (always fetch from OSM API, but integrate with cache system for UI) if (uploadMode == UploadMode.sandbox) { debugPrint('[NodeDataManager] Sandbox mode: fetching from OSM API'); - return fetchOsmApiNodes( - bounds: bounds, - profiles: profiles, - uploadMode: uploadMode, - maxResults: 0, - ); + + // Track user-initiated requests for status reporting + final requestKey = '${bounds.hashCode}_${profiles.map((p) => p.id).join('_')}_$uploadMode'; + + if (isUserInitiated && _userInitiatedRequests.contains(requestKey)) { + debugPrint('[NodeDataManager] Sandbox request already in progress for this area'); + return _cache.getNodesFor(bounds); + } + + // Start status tracking for user-initiated requests + if (isUserInitiated) { + _userInitiatedRequests.add(requestKey); + NetworkStatus.instance.setLoading(); + debugPrint('[NodeDataManager] Starting user-initiated sandbox request'); + } else { + debugPrint('[NodeDataManager] Starting background sandbox request (no status reporting)'); + } + + try { + final nodes = await fetchOsmApiNodes( + bounds: bounds, + profiles: profiles, + uploadMode: uploadMode, + maxResults: 0, + ); + + // Add nodes to cache for UI integration (even though we don't rely on cache for subsequent fetches) + if (nodes.isNotEmpty) { + _cache.addOrUpdateNodes(nodes); + _cache.markAreaAsFetched(bounds, nodes); + } else { + // Mark area as fetched even with no nodes so UI knows we've checked this area + _cache.markAreaAsFetched(bounds, []); + } + + // Update UI + notifyListeners(); + + // Set success after the next frame renders, but only for user-initiated requests + if (isUserInitiated) { + WidgetsBinding.instance.addPostFrameCallback((_) { + NetworkStatus.instance.setSuccess(); + }); + debugPrint('[NodeDataManager] User-initiated sandbox request completed successfully: ${nodes.length} nodes'); + } + + return nodes; + + } catch (e) { + debugPrint('[NodeDataManager] Sandbox fetch failed: $e'); + + // Only report errors for user-initiated requests + if (isUserInitiated) { + if (e is RateLimitError) { + NetworkStatus.instance.setRateLimited(); + } else if (e.toString().contains('timeout')) { + NetworkStatus.instance.setTimeout(); + } else { + NetworkStatus.instance.setError(); + } + debugPrint('[NodeDataManager] User-initiated sandbox request failed: $e'); + } + + // Return whatever we have in cache for this area (likely empty for sandbox) + return _cache.getNodesFor(bounds); + } finally { + if (isUserInitiated) { + _userInitiatedRequests.remove(requestKey); + } + } } // Production mode: check cache first diff --git a/lib/widgets/map/node_refresh_controller.dart b/lib/widgets/map/node_refresh_controller.dart index dedb4d7..0105d72 100644 --- a/lib/widgets/map/node_refresh_controller.dart +++ b/lib/widgets/map/node_refresh_controller.dart @@ -70,12 +70,18 @@ class NodeRefreshController { } final zoom = controller.mapController.camera.zoom; - if (zoom < kNodeMinZoomLevel) { - // Show a snackbar-style bubble warning + // Use the correct minimum zoom level based on upload mode + final minZoom = uploadMode == UploadMode.sandbox ? kOsmApiMinZoomLevel : kNodeMinZoomLevel; + + if (zoom < minZoom) { + // Show a snackbar-style bubble warning with mode-specific message if (context.mounted) { + final message = uploadMode == UploadMode.sandbox + ? 'Nodes not drawn below zoom level $minZoom in sandbox mode (OSM API limits)' + : 'Nodes not drawn below zoom level $minZoom'; ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('Nodes not drawn below zoom level $kNodeMinZoomLevel'), + content: Text(message), duration: const Duration(seconds: 2), ), );