Pin max nodes indicator to screen, not map. Clean up cruft.

This commit is contained in:
stopflock
2025-12-07 17:51:23 -06:00
parent 7fb467872a
commit 98e7e499d4
4 changed files with 100 additions and 22 deletions

View File

@@ -0,0 +1,69 @@
# V1.8.3 Node Limit Indicator Fix
## Problem
The node limit indicator would disappear when the navigation sheet opened during search/routing, particularly noticeable on Android. The indicator would appear correctly when just the search bar showed, but disappear when the navigation sheet auto-opened.
## Root Cause
The issue was in the **map positioning architecture**, specifically with `SheetAwareMap`. Here's what happens:
1. **Search activated**: Search bar appears → node limit indicator shifts down 60px (works correctly)
2. **Navigation sheet opens**: Navigation sheet auto-opens → `sheetHeight` changes from 0 to ~300px
3. **Map repositioning**: `SheetAwareMap` uses `AnimatedPositioned` with `top: -sheetHeight` to move the entire map up
4. **Indicator disappears**: The node limit indicator, positioned at `top: 8.0 + searchBarOffset`, gets moved up by 300px along with the map, placing it off-screen
The indicators were positioned relative to the map's coordinate system, but when the sheet opened, the entire map (including indicators) was moved up by the sheet height to keep the center visible above the sheet.
## Solution
**Brutalist fix**: Move the node limit indicator out of the map coordinate system and into screen coordinates alongside other UI overlays.
### Files Changed
- **map_view.dart**: Moved node limit indicator from inside SheetAwareMap to main Stack
- **pubspec.yaml**: Version bump to 1.8.3+33
- **changelog.json**: Added release notes
### Architecture Changes
```dart
// BEFORE - mixed coordinate systems (confusing!)
return Stack([
SheetAwareMap( // Map coordinates
child: FlutterMap([
cameraLayers: Stack([
NodeLimitIndicator(...) // ❌ Map coordinates (moves with map)
])
])
),
NetworkStatusIndicator(...), // ✅ Screen coordinates (fixed to screen)
]);
// AFTER - consistent coordinate system (clean!)
return Stack([
SheetAwareMap( // Map coordinates
child: FlutterMap([
cameraLayers: Stack([
// Only map data (nodes, overlays) - no UI indicators
])
])
),
NodeLimitIndicator(...), // ✅ Screen coordinates (fixed to screen)
NetworkStatusIndicator(...), // ✅ Screen coordinates (fixed to screen)
]);
```
## Architecture Insight
The fix revealed a **mixed coordinate system anti-pattern**. All UI overlays (compass, search box, zoom buttons, indicators) should use screen coordinates for consistency. Only map data (nodes, overlays, FOV cones) should be in map coordinates.
## Result
- Node limit indicator stays visible when navigation sheets open
- Network status indicator also fixed for consistency
- Indicators maintain correct screen position during all sheet transitions
- Consistent behavior across iOS and Android
## Testing Notes
To test this fix:
1. Start app and wait for nodes to load (node limit indicator should appear if >max nodes)
2. Tap search button → search bar appears, indicator shifts down 60px
3. Navigation sheet auto-opens → indicator stays visible in screen position (no longer affected by map movement)
4. Cancel search → indicator returns to original position
5. Repeat workflow → should work reliably every time
The fix ensures indicators stay in their intended screen positions using consistent coordinate system architecture.

View File

@@ -1,4 +1,10 @@
{
"1.8.3": {
"content": [
"• Fixed node limit indicator disappearing when navigation sheet opens during search/routing",
"• Improved indicator architecture - moved node limit indicator to screen coordinates for consistency with other UI overlays"
]
},
"1.8.2": {
"content": [
"• Fixed map positioning for node tags and suspected location sheets - map now correctly centers above sheet when opened",

View File

@@ -4,7 +4,7 @@ import 'package:flutter_map_animations/flutter_map_animations.dart';
import 'package:latlong2/latlong.dart';
import 'package:provider/provider.dart';
import '../app_state.dart';
import '../app_state.dart' show AppState, FollowMeMode, UploadMode;
import '../services/offline_area_service.dart';
import '../services/network_status.dart';
import '../services/prefetch_area_service.dart';
@@ -28,7 +28,6 @@ import 'network_status_indicator.dart';
import 'node_limit_indicator.dart';
import 'proximity_alert_banner.dart';
import '../dev_config.dart';
import '../app_state.dart' show FollowMeMode;
import '../services/proximity_alert_service.dart';
import 'sheet_aware_map.dart';
@@ -249,6 +248,11 @@ class MapViewState extends State<MapView> {
);
}
/// Calculate search bar offset for screen-positioned indicators
double _calculateScreenIndicatorSearchOffset(AppState appState) {
return (!appState.offlineMode && appState.isInSearchMode) ? 60.0 : 0.0;
}
@override
void didUpdateWidget(covariant MapView oldWidget) {
@@ -370,23 +374,6 @@ class MapViewState extends State<MapView> {
children: [
...overlayLayers,
markerLayer,
// Node limit indicator (top-left) - shown when limit is active
Builder(
builder: (context) {
final appState = context.read<AppState>();
// Add search bar offset when search bar is visible
final searchBarOffset = (!appState.offlineMode && appState.isInSearchMode) ? 60.0 : 0.0;
return NodeLimitIndicator(
isActive: nodeData.isLimitActive,
renderedCount: nodeData.nodesToRender.length,
totalCount: nodeData.validNodesCount,
top: 8.0 + searchBarOffset,
left: 8.0,
);
},
),
],
);
},
@@ -540,12 +527,28 @@ class MapViewState extends State<MapView> {
onSearchPressed: widget.onSearchPressed,
),
// Node limit indicator (top-left) - shown when limit is active
Builder(
builder: (context) {
final appState = context.watch<AppState>();
final searchBarOffset = _calculateScreenIndicatorSearchOffset(appState);
return NodeLimitIndicator(
isActive: nodeData.isLimitActive,
renderedCount: nodeData.nodesToRender.length,
totalCount: nodeData.validNodesCount,
top: 8.0 + searchBarOffset,
left: 8.0,
);
},
),
// Network status indicator (top-left) - conditionally shown
if (appState.networkStatusIndicatorEnabled)
Builder(
builder: (context) {
// Calculate position based on node limit indicator presence and search bar
final searchBarOffset = (!appState.offlineMode && appState.isInSearchMode) ? 60.0 : 0.0;
final appState = context.watch<AppState>();
final searchBarOffset = _calculateScreenIndicatorSearchOffset(appState);
final nodeLimitOffset = nodeData.isLimitActive ? 48.0 : 0.0; // Height of node limit indicator + spacing
return NetworkStatusIndicator(

View File

@@ -1,7 +1,7 @@
name: deflockapp
description: Map public surveillance infrastructure with OpenStreetMap
publish_to: "none"
version: 1.8.2+32 # The thing after the + is the version code, incremented with each release
version: 1.8.3+33 # 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+