From dc5333e8612d65226da50f34b2996029195cf59f Mon Sep 17 00:00:00 2001 From: Charles Plante Date: Wed, 27 May 2026 16:39:57 -0400 Subject: [PATCH] fix(ios): apply fadeWhenFacingNorth independently of enabled On iOS, CompassSettings.fadeWhenFacingNorth was ignored unless enabled was also set. CompassController.updateSettings only assigned compass.visibility inside `if let visible = settings.enabled { ... }`, so a call that set only fadeWhenFacingNorth never reached the native API and the compass stayed .adaptive, fading out at north. Android applies each field independently, so the platforms behaved differently. Apply enabled and fadeWhenFacingNorth independently, reading the current visibility for whichever field the caller didn't provide, mirroring the Android CompassMappings implementation. Related to #602. --- CHANGELOG.md | 1 + example/integration_test/compass_test.dart | 31 +++++++++++++++++++ .../Classes/CompassController.swift | 22 +++++++------ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38231296b..310a1f574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### main +* Fix iOS compass ignoring `CompassSettings.fadeWhenFacingNorth` (and visibility in general) unless `enabled` was also set. `enabled` and `fadeWhenFacingNorth` are now applied independently, matching the Android behaviour ([#602](https://github.com/mapbox/mapbox-maps-flutter/issues/602)). * Deprecate `MapboxMap.onTapListener` and `MapboxMap.onLongTapListener` in favor of the `MapboxMap.addInterfaction` API. * Add `MapboxMap.httpService.setMaxRequestsPerHost` to cap the number of concurrent HTTP requests per host issued by the underlying HTTP service. Useful for reducing the chance of hitting per-token rate limits during offline tile region downloads. diff --git a/example/integration_test/compass_test.dart b/example/integration_test/compass_test.dart index 642fd31d2..95e6faf26 100644 --- a/example/integration_test/compass_test.dart +++ b/example/integration_test/compass_test.dart @@ -53,4 +53,35 @@ void main() { // expect(updatedSettings.image, iconData); } }); + + // Regression test for https://github.com/mapbox/mapbox-maps-flutter/issues/602 + // On iOS `fadeWhenFacingNorth` was ignored unless `enabled` was also passed, + // so it must be applicable on its own and stay consistent with Android. + testWidgets('fadeWhenFacingNorth applies without enabled', + (WidgetTester tester) async { + final mapFuture = app.main(); + await tester.pumpAndSettle(); + final mapboxMap = await mapFuture; + final compass = mapboxMap.compass; + + // Start from a known visible + fading state. + await compass.updateSettings( + CompassSettings(enabled: true, fadeWhenFacingNorth: true)); + expect((await compass.getSettings()).fadeWhenFacingNorth, true); + expect((await compass.getSettings()).visibility, true); + + // Passing only `fadeWhenFacingNorth: false` must stop the fade (iOS: + // .visible) while keeping the compass visible. + await compass.updateSettings(CompassSettings(fadeWhenFacingNorth: false)); + var updatedSettings = await compass.getSettings(); + expect(updatedSettings.fadeWhenFacingNorth, false); + expect(updatedSettings.visibility, true); + + // Passing only `fadeWhenFacingNorth: true` must re-enable the fade (iOS: + // .adaptive) without hiding the compass. + await compass.updateSettings(CompassSettings(fadeWhenFacingNorth: true)); + updatedSettings = await compass.getSettings(); + expect(updatedSettings.fadeWhenFacingNorth, true); + expect(updatedSettings.visibility, true); + }); } diff --git a/ios/mapbox_maps_flutter/Sources/mapbox_maps_flutter/Classes/CompassController.swift b/ios/mapbox_maps_flutter/Sources/mapbox_maps_flutter/Classes/CompassController.swift index 26a7aba75..423ca1540 100644 --- a/ios/mapbox_maps_flutter/Sources/mapbox_maps_flutter/Classes/CompassController.swift +++ b/ios/mapbox_maps_flutter/Sources/mapbox_maps_flutter/Classes/CompassController.swift @@ -25,17 +25,21 @@ final class CompassController: CompassSettingsInterface { compass.image = UIImage(data: data, scale: UIScreen.main.scale) } - if let visible = settings.enabled { - let fadeWhenFacingNorth = settings.fadeWhenFacingNorth ?? true + // Apply `enabled` and `fadeWhenFacingNorth` independently so either can be + // changed on its own — matching the Android implementation (CompassMappings.kt). + // Previously visibility was only updated when `enabled` was non-nil, so + // `fadeWhenFacingNorth: false` was silently ignored on iOS and the compass + // kept fading at north. + if settings.enabled != nil || settings.fadeWhenFacingNorth != nil { + let current = compass.visibility + let enabled = settings.enabled ?? (current != .hidden) + let fadeWhenFacingNorth = settings.fadeWhenFacingNorth ?? (current == .adaptive) - let visibility: OrnamentVisibility - switch (visible, fadeWhenFacingNorth) { - case (true, true): visibility = .adaptive - case (true, false): visibility = .visible - case (false, _): visibility = .hidden + switch (enabled, fadeWhenFacingNorth) { + case (true, true): compass.visibility = .adaptive + case (true, false): compass.visibility = .visible + case (false, _): compass.visibility = .hidden } - - compass.visibility = visibility } ornaments.options.compass = compass