Skip to content

Commit

Permalink
Fix attribution dialog presentation (#1982)
Browse files Browse the repository at this point in the history
MAPSIOS-515: Fix attribution dialog presentation
  • Loading branch information
persidskiy authored Jan 16, 2024
1 parent b7a9f9b commit ba7bdc3
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 34 deletions.
56 changes: 32 additions & 24 deletions Apps/Examples/Examples.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions Apps/Examples/Examples/SwiftUI Examples/SwiftUIRoot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ struct SwiftUIRoot: View {
ExampleLink("Puck playground", note: "Display user location using puck.", destination: PuckPlayground())
ExampleLink("Annotation Order", destination: AnnotationsOrderTestExample())
ExampleLink("Simple Map", note: "Camera observing, automatic dark mode support.", destination: SimpleMapExample())
ExampleLink("AttributionURL open (iOS 13+)", note: "Override attribution url opener.", destination: URLOpenIOS13())
ExampleLink("Attribution url via callback", note: "Works on iOS 13+", destination: AttributionManualURLOpen())
if #available(iOS 15.0, *) {
ExampleLink("AttributionURL open (iOS 15+)", note: "Override attribution url opener.", destination: URLOpenIOS15())
ExampleLink("Attribution url open via environment", note: "Works on iOS 15+", destination: AttributionEnvironmentURLOpen())
}
if #available(iOS 16.5, *) {
ExampleLink("Attribution dialog with presented sheet", destination: AttributionDialogueWithSheet())
}

} header: { Text("Testing Examples") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftUI


@available(iOS 15, *)
struct URLOpenIOS15: View {
struct AttributionEnvironmentURLOpen: View {
@State private var alert: String?
var body: some View {
Map()
Expand All @@ -16,8 +16,24 @@ struct URLOpenIOS15: View {
}
}

@available(iOS 16.4, *)
struct AttributionDialogueWithSheet: View {
@State var sheet = true
var body: some View {
Map()
.additionalSafeAreaInsets(.bottom, 70)
.ignoresSafeArea()
.sheet(isPresented: $sheet) {
Text("Tap attribution info button")
.interactiveDismissDisabled()
.presentationBackgroundInteraction(.enabled(upThrough: .large))
.presentationDetents([.height(80), .medium, .large])
}
}
}

@available(iOS 13, *)
struct URLOpenIOS13: View {
struct AttributionManualURLOpen: View {
@State private var alert: String?
var body: some View {
Map(urlOpener: { alert = $0.absoluteString}) {}
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Mapbox welcomes participation and contributions from everyone.
* Fix glitch in chained camera animations.
* Make padding optional in `MapboxMap.camera(for:padding:bearing:pitch:maxZoom:offset:)` and `MapboxMap.camera(for:padding:bearing:pitch:)`.
* Build XCFramework with `SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO` flag to avoid serialized search paths in Swift modules.
* Fixed a bug where the attribution dialog does not appear when there is a presented view controller.

## 11.1.0-rc.1 - 04 January, 2024

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import UIKit

extension UIViewController {
var topmostPresentedViewController: UIViewController {
var result = self
while let presented = result.presentedViewController {
result = presented
}
return result
}
}
4 changes: 2 additions & 2 deletions Sources/MapboxMaps/Foundation/MapView+Attribution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import UIKit

extension MapView: AttributionDialogManagerDelegate {
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController {
return parentViewController!
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController? {
parentViewController?.topmostPresentedViewController
}

func attributionDialogManager(_ attributionDialogManager: AttributionDialogManager, didTriggerActionFor attribution: Attribution) {
Expand Down
5 changes: 3 additions & 2 deletions Sources/MapboxMaps/Style/AttributionDialogManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ internal protocol AttributionDataSource: AnyObject {
}

internal protocol AttributionDialogManagerDelegate: AnyObject {
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController?
func attributionDialogManager(_ attributionDialogManager: AttributionDialogManager, didTriggerActionFor attribution: Attribution)
}

Expand Down Expand Up @@ -121,7 +121,8 @@ extension AttributionDialogManager: InfoButtonOrnamentDelegate {

private func showAttributionDialog(for attributions: [Attribution]) {
guard let viewController = delegate?.viewControllerForPresenting(self) else {
fatalError("No view controller found")
Log.error(forMessage: "Failed to present an attribution dialogue: no presenting view controller found.")
return
}

let title = NSLocalizedString("SDK_NAME",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@testable import MapboxMaps
import XCTest

final class UIViewControllerExtensionsTests: XCTestCase {
func testTopmostPresentedViewController() {
let vc1 = MockViewController()
let vc2 = MockViewController()
let vc3 = MockViewController()

XCTAssertIdentical(vc1.topmostPresentedViewController, vc1)

vc1.simulatePresent(vc2)
XCTAssertIdentical(vc1.topmostPresentedViewController, vc2)

vc2.simulatePresent(vc3)
XCTAssertIdentical(vc1.topmostPresentedViewController, vc3)
}
}

private class MockViewController: UIViewController {
private var _presentedViewControllerOverride: UIViewController?
override var presentedViewController: UIViewController? {
return _presentedViewControllerOverride
}
func simulatePresent(_ vc: UIViewController) {
_presentedViewControllerOverride = vc
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ extension InfoButtonOrnamentTests: AttributionDataSource {
}

extension InfoButtonOrnamentTests: AttributionDialogManagerDelegate {
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController {
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController? {
return parentViewController
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Foundation
final class MockAttributionDialogManagerDelegate: AttributionDialogManagerDelegate {

let viewControllerForPresentingStub = Stub<AttributionDialogManager, UIViewController>(defaultReturnValue: UIViewController())
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController {
func viewControllerForPresenting(_ attributionDialogManager: AttributionDialogManager) -> UIViewController? {
viewControllerForPresentingStub.call(with: attributionDialogManager)
}

Expand Down

0 comments on commit ba7bdc3

Please sign in to comment.