diff --git a/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift b/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift index 3e03164dd..510b55499 100644 --- a/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift +++ b/ElementX/Sources/Other/MapLibre/MapLibreMapView.swift @@ -65,7 +65,7 @@ struct MapLibreMapView: UIViewRepresentable { // Don't set the same value twice. Otherwise, if there is an error loading the map, a loop // is caused as the `error` binding being set, which triggers this update, which sets a // new URL, which causes another error, and so it goes on round and round in a circle. - let dynamicMapURL = mapURLBuilder.dynamicMapURL(for: .init(colorScheme)) + let dynamicMapURL = mapURLBuilder.interactiveMapURL(for: .init(colorScheme)) if mapView.styleURL != dynamicMapURL { mapView.styleURL = dynamicMapURL } @@ -86,7 +86,7 @@ struct MapLibreMapView: UIViewRepresentable { } private func makeMapView() -> MGLMapView { - let mapView = MGLMapView(frame: .zero, styleURL: mapURLBuilder.dynamicMapURL(for: colorScheme == .dark ? .dark : .light)) + let mapView = MGLMapView(frame: .zero, styleURL: mapURLBuilder.interactiveMapURL(for: colorScheme == .dark ? .dark : .light)) mapView.logoViewPosition = .topLeft mapView.attributionButtonPosition = .topLeft mapView.attributionButtonMargins = .init(x: mapView.logoView.frame.maxX + 8, y: mapView.logoView.center.y / 2) diff --git a/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift b/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift index 3572f9735..e30aa479e 100644 --- a/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift +++ b/ElementX/Sources/Other/MapLibre/MapLibreStaticMapView.swift @@ -36,11 +36,11 @@ struct MapLibreStaticMapView: View { var body: some View { GeometryReader { geometry in - if let url = mapURLBuilder.staticMapURL(for: colorScheme.mapStyle, - coordinates: coordinates, - zoomLevel: zoomLevel, - size: mapSize, // temporary using a fixed size since the refresh doesn't work properly on the UITableView based timeline - attribution: mapTilerAttributionPlacement) { + if let url = mapURLBuilder.staticMapTileImageURL(for: colorScheme.mapStyle, + coordinates: coordinates, + zoomLevel: zoomLevel, + size: mapSize, // temporary using a fixed size since the refresh doesn't work properly on the UITableView based timeline + attribution: mapTilerAttributionPlacement) { AsyncImage(url: url) { phase in switch phase { case .empty: @@ -114,13 +114,13 @@ struct MapLibreStaticMapView_Previews: PreviewProvider, TestablePreview { } private struct MapTilerURLBuilderMock: MapTilerURLBuilderProtocol { - func dynamicMapURL(for style: MapTilerStyle) -> URL? { nil } + func interactiveMapURL(for style: MapTilerStyle) -> URL? { nil } - func staticMapURL(for style: MapTilerStyle, - coordinates: CLLocationCoordinate2D, - zoomLevel: Double, - size: CGSize, - attribution: MapTilerAttributionPlacement) -> URL? { + func staticMapTileImageURL(for style: MapTilerStyle, + coordinates: CLLocationCoordinate2D, + zoomLevel: Double, + size: CGSize, + attribution: MapTilerAttributionPlacement) -> URL? { switch style { case .light: return URL(string: "https://www.maptiler.com/img/cloud/home/map5.webp") diff --git a/ElementX/Sources/Other/MapLibre/MapTilerURLBuilderProtocol.swift b/ElementX/Sources/Other/MapLibre/MapTilerURLBuilderProtocol.swift index 3b7f1f19b..6031a11c7 100644 --- a/ElementX/Sources/Other/MapLibre/MapTilerURLBuilderProtocol.swift +++ b/ElementX/Sources/Other/MapLibre/MapTilerURLBuilderProtocol.swift @@ -9,11 +9,11 @@ import CoreLocation protocol MapTilerURLBuilderProtocol { - func dynamicMapURL(for style: MapTilerStyle) -> URL? + func interactiveMapURL(for style: MapTilerStyle) -> URL? - func staticMapURL(for style: MapTilerStyle, - coordinates: CLLocationCoordinate2D, - zoomLevel: Double, - size: CGSize, - attribution: MapTilerAttributionPlacement) -> URL? + func staticMapTileImageURL(for style: MapTilerStyle, + coordinates: CLLocationCoordinate2D, + zoomLevel: Double, + size: CGSize, + attribution: MapTilerAttributionPlacement) -> URL? } diff --git a/ElementX/Sources/Other/MapLibre/MapURLs.swift b/ElementX/Sources/Other/MapLibre/MapURLs.swift index d3df0091e..9e5effe98 100644 --- a/ElementX/Sources/Other/MapLibre/MapURLs.swift +++ b/ElementX/Sources/Other/MapLibre/MapURLs.swift @@ -9,18 +9,20 @@ import CoreLocation extension MapTilerConfiguration: MapTilerURLBuilderProtocol { - func dynamicMapURL(for style: MapTilerStyle) -> URL? { - var url = makeNewURL(for: style) + /// For interactive MGLMap components + func interactiveMapURL(for style: MapTilerStyle) -> URL? { + var url = styleURL(for: style) url?.appendPathComponent("style.json", conformingTo: .json) return url } - func staticMapURL(for style: MapTilerStyle, - coordinates: CLLocationCoordinate2D, - zoomLevel: Double, - size: CGSize, - attribution: MapTilerAttributionPlacement) -> URL? { - var url = makeNewURL(for: style) + /// Used in the timeline where a full MGLMapView loading is unwanted + func staticMapTileImageURL(for style: MapTilerStyle, + coordinates: CLLocationCoordinate2D, + zoomLevel: Double, + size: CGSize, + attribution: MapTilerAttributionPlacement) -> URL? { + var url = styleURL(for: style) url?.appendPathComponent(String(format: "static/%f,%f,%f/%dx%d@2x.png", coordinates.longitude, coordinates.latitude, @@ -34,7 +36,7 @@ extension MapTilerConfiguration: MapTilerURLBuilderProtocol { // MARK: Private - private func makeNewURL(for style: MapTilerStyle) -> URL? { + private func styleURL(for style: MapTilerStyle) -> URL? { guard let apiKey else { return nil } var url: URL = baseURL diff --git a/UnitTests/Sources/MapTilerURLBuilderTests.swift b/UnitTests/Sources/MapTilerURLBuilderTests.swift index deb9a05b1..44664e6d2 100644 --- a/UnitTests/Sources/MapTilerURLBuilderTests.swift +++ b/UnitTests/Sources/MapTilerURLBuilderTests.swift @@ -26,29 +26,29 @@ final class MapTilerURLBuilderTests: XCTestCase { } func testStaticMapBuilder() { - let url = builder.staticMapURL(for: .light, - coordinates: .init(latitude: 1, longitude: 2), - zoomLevel: 5, - size: .init(width: 300, height: 200), - attribution: .hidden) + let url = builder.staticMapTileImageURL(for: .light, + coordinates: .init(latitude: 1, longitude: 2), + zoomLevel: 5, + size: .init(width: 300, height: 200), + attribution: .hidden) let expectedURL: URL = "http://www.foo.com/9bc819c8-e627-474a-a348-ec144fe3d810/static/2.000000,1.000000,5.000000/300x200@2x.png?key=some_key&attribution=false" XCTAssertEqual(url, expectedURL) } func testStaticMapBuilderWithAttribution() { - let url = builder.staticMapURL(for: .dark, - coordinates: .init(latitude: 1, longitude: 2), - zoomLevel: 5, - size: .init(width: 300, height: 200), - attribution: .topLeft) + let url = builder.staticMapTileImageURL(for: .dark, + coordinates: .init(latitude: 1, longitude: 2), + zoomLevel: 5, + size: .init(width: 300, height: 200), + attribution: .topLeft) let expectedURL: URL = "http://www.foo.com/dea61faf-292b-4774-9660-58fcef89a7f3/static/2.000000,1.000000,5.000000/300x200@2x.png?key=some_key&attribution=topleft" XCTAssertEqual(url, expectedURL) } func testDynamicMapBuilder() { - let url = builder.dynamicMapURL(for: .dark) + let url = builder.interactiveMapURL(for: .dark) let expectedURL: URL = "http://www.foo.com/dea61faf-292b-4774-9660-58fcef89a7f3/style.json?key=some_key" XCTAssertEqual(url, expectedURL) } @@ -62,14 +62,14 @@ final class MapTilerURLBuilderTests: XCTestCase { builder = configuration - let staticMapURL = builder.staticMapURL(for: .dark, - coordinates: .init(latitude: 1, longitude: 2), - zoomLevel: 5, - size: .init(width: 300, height: 200), - attribution: .topLeft) + let staticMapURL = builder.staticMapTileImageURL(for: .dark, + coordinates: .init(latitude: 1, longitude: 2), + zoomLevel: 5, + size: .init(width: 300, height: 200), + attribution: .topLeft) XCTAssertNil(staticMapURL) - let dynamicMapURL = builder.dynamicMapURL(for: .light) + let dynamicMapURL = builder.interactiveMapURL(for: .light) XCTAssertNil(dynamicMapURL) } }