mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-05-18 14:45:07 +02:00
Merge pull request #41 from dougborg/fix/map-jitter-on-touch
Fix map jitter/wiggle when touching at low zoom
This commit is contained in:
@@ -32,6 +32,7 @@ class GpsController {
|
||||
List<OsmNode> Function()? _getNearbyNodes;
|
||||
List<NodeProfile> Function()? _getEnabledProfiles;
|
||||
VoidCallback? _onMapMovedProgrammatically;
|
||||
bool Function()? _isUserInteracting;
|
||||
|
||||
/// Get the current GPS location (if available)
|
||||
LatLng? get currentLocation => _currentLocation;
|
||||
@@ -49,6 +50,7 @@ class GpsController {
|
||||
required List<OsmNode> Function() getNearbyNodes,
|
||||
required List<NodeProfile> Function() getEnabledProfiles,
|
||||
VoidCallback? onMapMovedProgrammatically,
|
||||
bool Function()? isUserInteracting,
|
||||
}) async {
|
||||
debugPrint('[GpsController] Initializing GPS controller');
|
||||
|
||||
@@ -61,7 +63,8 @@ class GpsController {
|
||||
_getNearbyNodes = getNearbyNodes;
|
||||
_getEnabledProfiles = getEnabledProfiles;
|
||||
_onMapMovedProgrammatically = onMapMovedProgrammatically;
|
||||
|
||||
_isUserInteracting = isUserInteracting;
|
||||
|
||||
// Start location tracking
|
||||
await _startLocationTracking();
|
||||
}
|
||||
@@ -235,9 +238,10 @@ class GpsController {
|
||||
if (followMeMode == FollowMeMode.off || _mapController == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
try {
|
||||
if (_isUserInteracting?.call() == true) return;
|
||||
|
||||
if (followMeMode == FollowMeMode.follow) {
|
||||
// Follow position, preserve rotation
|
||||
_mapController!.animateTo(
|
||||
@@ -352,5 +356,6 @@ class GpsController {
|
||||
_getNearbyNodes = null;
|
||||
_getEnabledProfiles = null;
|
||||
_onMapMovedProgrammatically = null;
|
||||
_isUserInteracting = null;
|
||||
}
|
||||
}
|
||||
+43
-27
@@ -80,6 +80,9 @@ class MapViewState extends State<MapView> {
|
||||
|
||||
// State for proximity alert banner
|
||||
bool _showProximityBanner = false;
|
||||
|
||||
// Track active pointers to suppress follow-me animations during touch
|
||||
int _activePointers = 0;
|
||||
|
||||
|
||||
|
||||
@@ -189,6 +192,7 @@ class MapViewState extends State<MapView> {
|
||||
// Refresh nodes when GPS controller moves the map
|
||||
_refreshNodesFromProvider();
|
||||
},
|
||||
isUserInteracting: () => _activePointers > 0,
|
||||
);
|
||||
|
||||
// Fetch initial cameras
|
||||
@@ -380,10 +384,21 @@ class MapViewState extends State<MapView> {
|
||||
children: [
|
||||
SheetAwareMap(
|
||||
sheetHeight: widget.sheetHeight,
|
||||
child: FlutterMap(
|
||||
key: ValueKey('map_${appState.offlineMode}_${appState.selectedTileType?.id ?? 'none'}_${_tileManager.mapRebuildKey}'),
|
||||
mapController: _controller.mapController,
|
||||
options: MapOptions(
|
||||
child: Listener(
|
||||
onPointerDown: (_) {
|
||||
_activePointers++;
|
||||
_controller.stopAnimations();
|
||||
},
|
||||
onPointerUp: (_) {
|
||||
if (_activePointers > 0) _activePointers--;
|
||||
},
|
||||
onPointerCancel: (_) {
|
||||
if (_activePointers > 0) _activePointers--;
|
||||
},
|
||||
child: FlutterMap(
|
||||
key: ValueKey('map_${appState.offlineMode}_${appState.selectedTileType?.id ?? 'none'}_${_tileManager.mapRebuildKey}'),
|
||||
mapController: _controller.mapController,
|
||||
options: MapOptions(
|
||||
initialCenter: _gpsController.currentLocation ?? _positionManager.initialLocation ?? LatLng(37.7749, -122.4194),
|
||||
initialZoom: _positionManager.initialZoom ?? 15,
|
||||
minZoom: 1.0,
|
||||
@@ -486,30 +501,31 @@ class MapViewState extends State<MapView> {
|
||||
_dataManager.showZoomWarningIfNeeded(context, pos.zoom, appState.uploadMode);
|
||||
}
|
||||
},
|
||||
),
|
||||
children: [
|
||||
_tileManager.buildTileLayer(
|
||||
selectedProvider: appState.selectedTileProvider,
|
||||
selectedTileType: appState.selectedTileType,
|
||||
),
|
||||
cameraLayers,
|
||||
// Custom scale bar that respects user's distance unit preference
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final safeArea = MediaQuery.of(context).padding;
|
||||
return CustomScaleBar(
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: EdgeInsets.only(
|
||||
left: leftPositionWithSafeArea(8, safeArea),
|
||||
bottom: bottomPositionFromButtonBar(kScaleBarSpacingAboveButtonBar, safeArea.bottom),
|
||||
),
|
||||
maxWidthPx: 120,
|
||||
barHeight: 8,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
children: [
|
||||
_tileManager.buildTileLayer(
|
||||
selectedProvider: appState.selectedTileProvider,
|
||||
selectedTileType: appState.selectedTileType,
|
||||
),
|
||||
cameraLayers,
|
||||
// Custom scale bar that respects user's distance unit preference
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final safeArea = MediaQuery.of(context).padding;
|
||||
return CustomScaleBar(
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: EdgeInsets.only(
|
||||
left: leftPositionWithSafeArea(8, safeArea),
|
||||
bottom: bottomPositionFromButtonBar(kScaleBarSpacingAboveButtonBar, safeArea.bottom)
|
||||
),
|
||||
maxWidthPx: 120,
|
||||
barHeight: 8,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// All map overlays (mode indicator, zoom, attribution, add pin)
|
||||
|
||||
Reference in New Issue
Block a user