mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-08-14 23:20:46 +02:00
Fix node edge blinking, prevent nav+edit conflicts, smarter follow-me w/rt nav
This commit is contained in:
@@ -24,6 +24,21 @@ class MapDataManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand bounds by the given multiplier, maintaining center point.
|
||||
/// Used to expand rendering bounds to prevent nodes blinking at screen edges.
|
||||
LatLngBounds _expandBounds(LatLngBounds bounds, double multiplier) {
|
||||
final centerLat = (bounds.north + bounds.south) / 2;
|
||||
final centerLng = (bounds.east + bounds.west) / 2;
|
||||
|
||||
final latSpan = (bounds.north - bounds.south) * multiplier / 2;
|
||||
final lngSpan = (bounds.east - bounds.west) * multiplier / 2;
|
||||
|
||||
return LatLngBounds(
|
||||
LatLng(centerLat - latSpan, centerLng - lngSpan),
|
||||
LatLng(centerLat + latSpan, centerLng + lngSpan),
|
||||
);
|
||||
}
|
||||
|
||||
/// Get nodes to render based on current map state
|
||||
/// Returns a MapDataResult containing all relevant node data and limit state
|
||||
MapDataResult getNodesForRendering({
|
||||
@@ -39,10 +54,13 @@ class MapDataManager {
|
||||
bool isLimitActive = false;
|
||||
|
||||
if (currentZoom >= minZoom) {
|
||||
// Above minimum zoom - get cached nodes directly (no Provider needed)
|
||||
allNodes = (mapBounds != null)
|
||||
? NodeProviderWithCache.instance.getCachedNodesForBounds(mapBounds)
|
||||
: <OsmNode>[];
|
||||
// Above minimum zoom - get cached nodes with expanded bounds to prevent edge blinking
|
||||
if (mapBounds != null) {
|
||||
final expandedBounds = _expandBounds(mapBounds, kNodeRenderingBoundsExpansion);
|
||||
allNodes = NodeProviderWithCache.instance.getCachedNodesForBounds(expandedBounds);
|
||||
} else {
|
||||
allNodes = <OsmNode>[];
|
||||
}
|
||||
|
||||
// Filter out invalid coordinates before applying limit
|
||||
final validNodes = allNodes.where((node) {
|
||||
|
||||
@@ -62,16 +62,22 @@ class MarkerLayerBuilder {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
|
||||
// Determine if we should dim node markers (when suspected location is selected)
|
||||
final shouldDimNodes = appState.selectedSuspectedLocation != null;
|
||||
// Determine if nodes should be dimmed and/or disabled
|
||||
final shouldDimNodes = appState.selectedSuspectedLocation != null ||
|
||||
appState.isInSearchMode ||
|
||||
appState.showingOverview;
|
||||
|
||||
// Disable node interactions when navigation is in conflicting state
|
||||
final shouldDisableNodeTaps = appState.isInSearchMode || appState.showingOverview;
|
||||
|
||||
final markers = NodeMarkersBuilder.buildNodeMarkers(
|
||||
nodes: nodesToRender,
|
||||
mapController: mapController.mapController,
|
||||
userLocation: userLocation,
|
||||
selectedNodeId: selectedNodeId,
|
||||
onNodeTap: onNodeTap,
|
||||
onNodeTap: onNodeTap, // Keep the original callback
|
||||
shouldDim: shouldDimNodes,
|
||||
enabled: !shouldDisableNodeTaps, // Use enabled parameter instead
|
||||
);
|
||||
|
||||
// Build suspected location markers (respect same zoom and count limits as nodes)
|
||||
@@ -101,7 +107,9 @@ class MarkerLayerBuilder {
|
||||
locations: filteredSuspectedLocations,
|
||||
mapController: mapController.mapController,
|
||||
selectedLocationId: appState.selectedSuspectedLocation?.ticketNo,
|
||||
onLocationTap: onSuspectedLocationTap,
|
||||
onLocationTap: onSuspectedLocationTap, // Keep the original callback
|
||||
shouldDimAll: shouldDisableNodeTaps,
|
||||
enabled: !shouldDisableNodeTaps, // Use enabled parameter instead
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ class NodeMapMarker extends StatefulWidget {
|
||||
final OsmNode node;
|
||||
final MapController mapController;
|
||||
final void Function(OsmNode)? onNodeTap;
|
||||
final bool enabled;
|
||||
|
||||
const NodeMapMarker({
|
||||
required this.node,
|
||||
required this.mapController,
|
||||
this.onNodeTap,
|
||||
this.enabled = true,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@@ -31,6 +33,8 @@ class _NodeMapMarkerState extends State<NodeMapMarker> {
|
||||
static const Duration tapTimeout = kMarkerTapTimeout;
|
||||
|
||||
void _onTap() {
|
||||
if (!widget.enabled) return; // Don't respond to taps when disabled
|
||||
|
||||
_tapTimer = Timer(tapTimeout, () {
|
||||
// Don't center immediately - let the sheet opening handle the coordinated animation
|
||||
|
||||
@@ -48,6 +52,8 @@ class _NodeMapMarkerState extends State<NodeMapMarker> {
|
||||
}
|
||||
|
||||
void _onDoubleTap() {
|
||||
if (!widget.enabled) return; // Don't respond to double taps when disabled
|
||||
|
||||
_tapTimer?.cancel();
|
||||
widget.mapController.move(widget.node.coord, widget.mapController.camera.zoom + kNodeDoubleTapZoomDelta);
|
||||
}
|
||||
@@ -96,6 +102,7 @@ class NodeMarkersBuilder {
|
||||
int? selectedNodeId,
|
||||
void Function(OsmNode)? onNodeTap,
|
||||
bool shouldDim = false,
|
||||
bool enabled = true,
|
||||
}) {
|
||||
final markers = <Marker>[
|
||||
// Node markers
|
||||
@@ -116,6 +123,7 @@ class NodeMarkersBuilder {
|
||||
node: n,
|
||||
mapController: mapController,
|
||||
onNodeTap: onNodeTap,
|
||||
enabled: enabled,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -13,11 +13,13 @@ class SuspectedLocationMapMarker extends StatefulWidget {
|
||||
final SuspectedLocation location;
|
||||
final MapController mapController;
|
||||
final void Function(SuspectedLocation)? onLocationTap;
|
||||
final bool enabled;
|
||||
|
||||
const SuspectedLocationMapMarker({
|
||||
required this.location,
|
||||
required this.mapController,
|
||||
this.onLocationTap,
|
||||
this.enabled = true,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@@ -31,6 +33,8 @@ class _SuspectedLocationMapMarkerState extends State<SuspectedLocationMapMarker>
|
||||
static const Duration tapTimeout = kMarkerTapTimeout;
|
||||
|
||||
void _onTap() {
|
||||
if (!widget.enabled) return; // Don't respond to taps when disabled
|
||||
|
||||
_tapTimer = Timer(tapTimeout, () {
|
||||
// Use callback if provided, otherwise fallback to direct modal
|
||||
if (widget.onLocationTap != null) {
|
||||
@@ -46,6 +50,8 @@ class _SuspectedLocationMapMarkerState extends State<SuspectedLocationMapMarker>
|
||||
}
|
||||
|
||||
void _onDoubleTap() {
|
||||
if (!widget.enabled) return; // Don't respond to double taps when disabled
|
||||
|
||||
_tapTimer?.cancel();
|
||||
widget.mapController.move(widget.location.centroid, widget.mapController.camera.zoom + kNodeDoubleTapZoomDelta);
|
||||
}
|
||||
@@ -73,6 +79,8 @@ class SuspectedLocationMarkersBuilder {
|
||||
required MapController mapController,
|
||||
String? selectedLocationId,
|
||||
void Function(SuspectedLocation)? onLocationTap,
|
||||
bool shouldDimAll = false,
|
||||
bool enabled = true,
|
||||
}) {
|
||||
final markers = <Marker>[];
|
||||
|
||||
@@ -81,7 +89,7 @@ class SuspectedLocationMarkersBuilder {
|
||||
|
||||
// Check if this location should be highlighted (selected) or dimmed
|
||||
final isSelected = selectedLocationId == location.ticketNo;
|
||||
final shouldDim = selectedLocationId != null && !isSelected;
|
||||
final shouldDim = shouldDimAll || (selectedLocationId != null && !isSelected);
|
||||
|
||||
markers.add(
|
||||
Marker(
|
||||
@@ -94,6 +102,7 @@ class SuspectedLocationMarkersBuilder {
|
||||
location: location,
|
||||
mapController: mapController,
|
||||
onLocationTap: onLocationTap,
|
||||
enabled: enabled,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user