Compare commits

..

No commits in common. "8b53075a922055438d7d63c9c109ca5b423ed816" and "4c8815f7cfdb40307d81e61645db75d7b9c3a1cb" have entirely different histories.

View file

@ -41,14 +41,20 @@ class _MapScreenState extends ConsumerState<MapScreen> {
final apiClient = ref.watch(apiClientProvider); final apiClient = ref.watch(apiClientProvider);
final styleAsync = ref.watch(mapStyleProvider(apiClient.baseUrl)); final styleAsync = ref.watch(mapStyleProvider(apiClient.baseUrl));
// Move the map only for programmatic state changes (locateUser, // Listen for zoom/center changes from the provider and move the map.
// zoomIn/zoomOut). Gesture-driven pans no longer call updateCamera(), // Skip the move if the map controller is already at the target position
// so this listener only fires for intentional moves and won't interfere // (meaning the state change came from a user gesture via onPositionChanged).
// with the TileLayer's in-flight tile loads. // Without this guard, every gesture-driven pan calls _mapController.move()
// with the position the map is already at, which triggers a tile
// recalculation that cancels in-flight tile loads and produces a
// partially-rendered (diagonal) map.
ref.listen<MapState>(mapProvider, (previous, next) { ref.listen<MapState>(mapProvider, (previous, next) {
if (previous?.center != next.center || previous?.zoom != next.zoom) { if (previous?.center != next.center || previous?.zoom != next.zoom) {
final camera = _mapController.camera;
if (camera.center != next.center || camera.zoom != next.zoom) {
_mapController.move(next.center, next.zoom); _mapController.move(next.center, next.zoom);
} }
}
}); });
return Scaffold( return Scaffold(
@ -63,12 +69,12 @@ class _MapScreenState extends ConsumerState<MapScreen> {
minZoom: 0, minZoom: 0,
maxZoom: 18, maxZoom: 18,
onPositionChanged: (position, hasGesture) { onPositionChanged: (position, hasGesture) {
// Intentionally not syncing gesture-driven position changes if (hasGesture) {
// back to the provider. Doing so caused ref.listen to call ref.read(mapProvider.notifier).updateCamera(
// _mapController.move() on every pan/zoom frame, which made position.center,
// flutter_map's TileLayer cancel in-flight tile loads — position.zoom,
// producing a partially-rendered (diagonal) map and crashes );
// when zooming out during tile loading. }
}, },
onTap: (tapPosition, point) { onTap: (tapPosition, point) {
ref.read(mapProvider.notifier).clearSelectedPlace(); ref.read(mapProvider.notifier).clearSelectedPlace();