From 748ec818ac51183098867790fc5761ab5400e978 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Tue, 4 Aug 2026 13:42:51 +0200 Subject: [PATCH] remove map tiler url from matrix wellknown --- ElementX.xcodeproj/project.pbxproj | 36 ++++---- .../Sources/Application/AppCoordinator.swift | 1 - .../Application/Settings/AppSettings.swift | 19 ++-- .../Settings/MapTilerConfiguration.swift | 38 ++++++++ .../Settings/MapTilerSettings.swift | 40 --------- .../PinnedEventsTimelineFlowCoordinator.swift | 2 +- .../RoomFlowCoordinator.swift | 2 +- .../Sources/Mocks/SDK/ClientSDKMock.swift | 2 - ElementX/Sources/Other/MapLibre/MapURLs.swift | 58 ++++--------- .../LocationSharingScreenViewModel.swift | 2 +- .../ComposerToolbarViewModel.swift | 2 +- .../Screens/Timeline/TimelineModels.swift | 2 +- .../Screens/Timeline/TimelineViewModel.swift | 2 +- .../LiveLocationRoomTimelineView.swift | 4 +- .../LocationRoomTimelineView.swift | 4 +- .../AuthenticationService.swift | 1 - ElementX/Sources/Services/Client/Client.swift | 14 --- .../UserSession/UserSessionStore.swift | 1 - Enterprise | 2 +- .../LocationSharingScreenViewModelTests.swift | 6 +- .../Sources/MapTilerURLBuilderTests.swift | 87 ++++++------------- .../Sources/MatrixClientWellKnownTests.swift | 75 ---------------- 22 files changed, 120 insertions(+), 280 deletions(-) create mode 100644 ElementX/Sources/Application/Settings/MapTilerConfiguration.swift delete mode 100644 ElementX/Sources/Application/Settings/MapTilerSettings.swift delete mode 100644 UnitTests/Sources/MatrixClientWellKnownTests.swift diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index ec9d20dc1..423769083 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -65,6 +65,7 @@ 0728314DD51AC3819F818EA8 /* LogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2711E5996016ABD6EAAEB58A /* LogLevel.swift */; }; 07376A5274822EB45CC320C7 /* InvitedRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A21027F05874B1BCC3E452B /* InvitedRoomProxyMock.swift */; }; 0743CF689EBDAAF1CC0B4283 /* DeclineAndBlockScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011AFA4990C585D157829679 /* DeclineAndBlockScreenViewModel.swift */; }; + 074F741578307EF0179EE47C /* MapTilerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */; }; 07756D532EFE33DD1FA258E5 /* GeoURITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */; }; 07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */; }; 0847D85F823B55A3E95D16CC /* RoomPreviewProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D94852AD5BB376CBCC3544 /* RoomPreviewProxy.swift */; }; @@ -331,7 +332,6 @@ 34C752A73717C691582DC6C7 /* UnsupportedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */; }; 34F1261CEF6D6A00D559B520 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CFD5EB0B0EEA4549FB49784 /* SettingsScreen.swift */; }; 352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */; }; - 354AFFDB2C05EC300E61D402 /* MapTilerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C3A7F76FE12E274D2ED8DF4 /* MapTilerSettings.swift */; }; 355B11D08CE0CEF97A813236 /* AppRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A9E3FBE8A66B5A17AD7F74 /* AppRoutes.swift */; }; 3582056513A384F110EC8274 /* MediaPlayerProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */; }; 358290C2E4574456FE0C2DF6 /* LocationSharingScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B73675A21580971E9ADF66A /* LocationSharingScreenViewModelProtocol.swift */; }; @@ -521,7 +521,6 @@ 5415236FA271AF7885D4995E /* NotificationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3AB32690C6CE5C62A86D6FA /* NotificationItemProxy.swift */; }; 5470E62F65AE1803BBF3D528 /* CXProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86E1BAA7232081635662A83F /* CXProviderMock.swift */; }; 54804A7D8298F7E8ACAFDD76 /* SearchScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44C70BD39FC34A9FD2467540 /* SearchScreenViewModelProtocol.swift */; }; - 54A9F957307CC55242564CE5 /* MapTilerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C3A7F76FE12E274D2ED8DF4 /* MapTilerSettings.swift */; }; 54AE8860D668AFD96E7E177B /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; }; 54FDA3625AACBD9E438D084D /* BlurEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07934EF08BB39353E4A94272 /* BlurEffectView.swift */; }; 5500904C40D67D131E7E9A26 /* NotificationContentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BB243B26D54EF1A0C422C0 /* NotificationContentBuilder.swift */; }; @@ -586,7 +585,6 @@ 5FA1DCE55973862632961D7C /* PhotoLibraryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7495E1119753B06FF2C2279 /* PhotoLibraryManager.swift */; }; 5FCD8AFA364206EE32B909A3 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B050A6B233D95807A09289E7 /* Settings.bundle */; }; 601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */; }; - 60A02A6FCE475B7F0A070836 /* MatrixClientWellKnownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2216751513D9DC0A855D657C /* MatrixClientWellKnownTests.swift */; }; 60ED66E63A169E47489348A8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; }; 611BEE29B8B622204E1E6B04 /* SecurityAndPrivacyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97F2F6B6E56055EF173A2DD3 /* SecurityAndPrivacyScreenCoordinator.swift */; }; 612196AF7826846A50C07FA6 /* SpaceServiceRoom.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAA1B97A17A750AC706B112 /* SpaceServiceRoom.swift */; }; @@ -971,6 +969,7 @@ 9A0326D2375075871D2AB537 /* ResolveVerifiedUserSendFailureScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574CB70E82D7EAEA538E4135 /* ResolveVerifiedUserSendFailureScreenViewModel.swift */; }; 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; 9A8E6FCD86B89970EC72EFD8 /* BugReportServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F7FC9580CABF797A2E6213A /* BugReportServiceMock.swift */; }; + 9AC47275B8E1EB0976BA7A80 /* MapTilerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */; }; 9AC5F8142413862A9E3A2D98 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 9C73F37731C9FDED1BB24C1C /* Collections */; }; 9B03943616A1147539DF7F08 /* RoomChangePermissionsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D041A857614A9AE13C7795 /* RoomChangePermissionsScreenViewModelTests.swift */; }; 9B356742E035D90A8BB5CABE /* ProposedViewSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFE0E493FB55E5A62E7852A /* ProposedViewSize.swift */; }; @@ -1130,7 +1129,6 @@ B5E455C9689EA600EDB3E9E0 /* NavigationRootCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA28F29C9F93E93CC3C2C715 /* NavigationRootCoordinator.swift */; }; B6048166B4AA4CEFEA9B77A6 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; B6064D82FCDCB829601C1F59 /* SecureBackupLogoutConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEE10AB666891E6A675E5E /* SecureBackupLogoutConfirmationScreen.swift */; }; - B66FBE9B08C202B955B7F6AC /* MapTilerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C3A7F76FE12E274D2ED8DF4 /* MapTilerSettings.swift */; }; B6B62437B92B6CA4083AA899 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; B6DA66EFC13A90846B625836 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91DE43B8815918E590912DDA /* InfoPlist.strings */; }; B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */; }; @@ -1200,6 +1198,7 @@ C1A5C386319835FB0C77736B /* ReportContentScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */; }; C1D0AB8222D7BAFC9AF9C8C0 /* MapLibreMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 622D09D4ECE759189009AEAF /* MapLibreMapView.swift */; }; C26DB49C06C00B5DF1A991A5 /* InviteUsersScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1454CF3AABD242F55C8A2615 /* InviteUsersScreenModels.swift */; }; + C280BD841DA2EB6B5BC84F84 /* MapTilerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */; }; C2879369106A419A5071F1F8 /* VoiceMessageRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */; }; C292A8DA07E6DBD66E946383 /* RageshakeConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC598338E7CF41107293AB5 /* RageshakeConfiguration.swift */; }; C3317EF833AB4060988DF098 /* SAS.strings in Resources */ = {isa = PBXBuildFile; fileRef = 135FC689EA39AE1D34153B58 /* SAS.strings */; }; @@ -1839,7 +1838,6 @@ 1BEE119165C106FA83F253EF /* AnalyticsServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsServiceMock.swift; sourceTree = ""; }; 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupControllerProtocol.swift; sourceTree = ""; }; 1C25B6EBEB414431187D73B7 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = ""; }; - 1C3A7F76FE12E274D2ED8DF4 /* MapTilerSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerSettings.swift; sourceTree = ""; }; 1C4724D5CB16CFA5853EF8F9 /* SearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchScreenViewModel.swift; sourceTree = ""; }; 1C78111573987B1D79ED0868 /* LinkMetadataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkMetadataProvider.swift; sourceTree = ""; }; 1C782FCBBCC9A0CD30453C50 /* ChatsTabFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsTabFlowCoordinator.swift; sourceTree = ""; }; @@ -1879,7 +1877,6 @@ 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineItemProtocol.swift; sourceTree = ""; }; 21BA866267F84BF4350B0CB7 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-BR"; path = "pt-BR.lproj/Localizable.stringsdict"; sourceTree = ""; }; 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserFlowTests.swift; sourceTree = ""; }; - 2216751513D9DC0A855D657C /* MatrixClientWellKnownTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixClientWellKnownTests.swift; sourceTree = ""; }; 226A56746AD99ABDA97189E1 /* SpaceServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceServiceProxy.swift; sourceTree = ""; }; 22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModelProtocol.swift; sourceTree = ""; }; 227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = ""; }; @@ -2474,6 +2471,7 @@ 89BB11A792EF6F70B95B467E /* EncryptionResetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetTests.swift; sourceTree = ""; }; 89D7846847BA9D2C5346ED9C /* EditAvatarButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAvatarButtonStyle.swift; sourceTree = ""; }; 89FBFC09F9DAFF1E4BA97849 /* FormButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormButtonStyles.swift; sourceTree = ""; }; + 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerConfiguration.swift; sourceTree = ""; }; 8A8DCBD0ABAADFDE5AF17E1F /* LiveLocationRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveLocationRoomTimelineItem.swift; sourceTree = ""; }; 8A9AE4967817E9608E22EB44 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; 8AE0C9653870803E4F91F474 /* RoomListFiltersStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersStateTests.swift; sourceTree = ""; }; @@ -5089,7 +5087,6 @@ 5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */, D80807B554CF9C524F98674F /* ManageRoomMemberSheetViewModelTests.swift */, 1D262A26713C18BB70C82CA5 /* MapTilerURLBuilderTests.swift */, - 2216751513D9DC0A855D657C /* MatrixClientWellKnownTests.swift */, F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */, F505E3D79018B6EFF953F647 /* MediaEventsTimelineScreenViewModelTests.swift */, 2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */, @@ -6704,7 +6701,7 @@ F78B4E56DBFFD4A7A39D10F5 /* AudioPlaybackSpeed.swift */, 0A2074C0449B83D5858BD2D7 /* FrequentlyUsedEmoji.swift */, DA2FEFA393FC7D2870263012 /* LiveLocationSession.swift */, - 1C3A7F76FE12E274D2ED8DF4 /* MapTilerSettings.swift */, + 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */, 002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */, 8FC598338E7CF41107293AB5 /* RageshakeConfiguration.swift */, 69A05E85E4872C3221C5C287 /* RemotePreference.swift */, @@ -7663,16 +7660,16 @@ projectDirPath = ""; projectRoot = ""; targets = ( - C0FAEB81CFD9776CD78CE489 /* ElementX */, - FEB53A5BC378C913769656D8 /* NSE */, - 19F0C845D67E9BEA4BE7133E /* ShareExtension */, - 676A87694F0F247B2AF1A142 /* MatrixRustSDKMocks */, - 32C23C8D224D46EFE62AFAD0 /* UnitTests */, - 7A17BE29BAC81ADBAC6349D9 /* PreviewTests */, - 0E28CD62691FDBC63147D5E3 /* UITests */, - D3DB351B7FBE0F49649171FC /* IntegrationTests */, C0C687DE1D270F9895FEE186 /* AccessibilityTests */, + C0FAEB81CFD9776CD78CE489 /* ElementX */, + D3DB351B7FBE0F49649171FC /* IntegrationTests */, + 676A87694F0F247B2AF1A142 /* MatrixRustSDKMocks */, + FEB53A5BC378C913769656D8 /* NSE */, F8E276FD6DC43EADB85241BC /* Periphery */, + 7A17BE29BAC81ADBAC6349D9 /* PreviewTests */, + 19F0C845D67E9BEA4BE7133E /* ShareExtension */, + 0E28CD62691FDBC63147D5E3 /* UITests */, + 32C23C8D224D46EFE62AFAD0 /* UnitTests */, ); }; /* End PBXProject section */ @@ -7980,7 +7977,7 @@ D3ED5692672892F9F1E7375A /* LiveLocationSession.swift in Sources */, 0728314DD51AC3819F818EA8 /* LogLevel.swift in Sources */, AD2A81B65A9F6163012086F1 /* MXLog.swift in Sources */, - 54A9F957307CC55242564CE5 /* MapTilerSettings.swift in Sources */, + 9AC47275B8E1EB0976BA7A80 /* MapTilerConfiguration.swift in Sources */, 52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */, 8B76191B9DDD1AC90A6E3A35 /* MediaFileHandleProxy.swift in Sources */, 68184EF36396424FE19A727D /* MediaLoader.swift in Sources */, @@ -8096,7 +8093,6 @@ 7434A7F02D587A920B376A9A /* LoginScreenViewModelTests.swift in Sources */, 1C1750C009F7214B967928BC /* ManageRoomMemberSheetViewModelTests.swift in Sources */, 3BEBDCB42BABFA3B456FECA7 /* MapTilerURLBuilderTests.swift in Sources */, - 60A02A6FCE475B7F0A070836 /* MatrixClientWellKnownTests.swift in Sources */, 2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */, 7070E5CA0095CBEFAA7DE466 /* MediaEventsTimelineScreenViewModelTests.swift in Sources */, 4B978C09567387EF4366BD7A /* MediaLoaderTests.swift in Sources */, @@ -8224,7 +8220,7 @@ A0646F23876D6326AD27FF52 /* LiveLocationSession.swift in Sources */, DA10C99BA43A0F1E732F6274 /* LogLevel.swift in Sources */, 0638CBDE3098B1C3F23AFCFA /* MXLog.swift in Sources */, - B66FBE9B08C202B955B7F6AC /* MapTilerSettings.swift in Sources */, + 074F741578307EF0179EE47C /* MapTilerConfiguration.swift in Sources */, 1A3783005E6945F8583AF997 /* NSItemProvider.swift in Sources */, E7416C2EFDC2D475F69127FE /* NotificationTone.swift in Sources */, F43564003B017DB148DB1503 /* OAuthConfiguration.swift in Sources */, @@ -8737,7 +8733,7 @@ C1D0AB8222D7BAFC9AF9C8C0 /* MapLibreMapView.swift in Sources */, C9BE065FA7D4E77E4C61CB69 /* MapLibreModels.swift in Sources */, E2DDA49BD62F03F180A42E30 /* MapLibreStaticMapView.swift in Sources */, - 354AFFDB2C05EC300E61D402 /* MapTilerSettings.swift in Sources */, + C280BD841DA2EB6B5BC84F84 /* MapTilerConfiguration.swift in Sources */, 63DCEBC1DD555E0D645B9E98 /* MapTilerURLBuilderProtocol.swift in Sources */, F382E2FE3AC3719BC1F22D9C /* MapURLs.swift in Sources */, 67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */, diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 1fd958aed..f6f4a2917 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -849,7 +849,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg tearDownUserSession() appSettings.resetSessionSpecificSettings() - appSettings.mapTilerSettings.reset() appHooks.remoteSettingsHook.reset(appSettings) // Reset analytics diff --git a/ElementX/Sources/Application/Settings/AppSettings.swift b/ElementX/Sources/Application/Settings/AppSettings.swift index 8fcc5b0b8..463dbd8f2 100644 --- a/ElementX/Sources/Application/Settings/AppSettings.swift +++ b/ElementX/Sources/Application/Settings/AppSettings.swift @@ -25,6 +25,7 @@ nonisolated protocol CommonSettingsProtocol: AnyObject, Sendable { var bugReportRageshakeURL: RemotePreference { get } var contentScannerURL: RemotePreference { get } var forceDisableE2EE: RemotePreference { get } + var mapTilerConfiguration: RemotePreference { get } var enableOnlySignedDeviceIsolationMode: Bool { get } var threadsEnabled: Bool { get } @@ -95,7 +96,7 @@ final nonisolated class AppSettings: @unchecked Sendable { accountProvisioningHost: String, bugReportApplicationID: String, analyticsTermsURL: URL?, - mapTilerConfiguration: MapTilerSettings.Configuration) { + mapTilerConfiguration: MapTilerConfiguration) { self.accountProviders = accountProviders self.allowOtherAccountProviders = allowOtherAccountProviders self.hideBrandChrome = hideBrandChrome @@ -116,7 +117,7 @@ final nonisolated class AppSettings: @unchecked Sendable { self.accountProvisioningHost = accountProvisioningHost self.bugReportApplicationID = bugReportApplicationID self.analyticsTermsURL = analyticsTermsURL - mapTilerSettings = RemotePreference(.configuration(mapTilerConfiguration)) + self.mapTilerConfiguration = RemotePreference(mapTilerConfiguration) } // MARK: - Application @@ -376,15 +377,13 @@ final nonisolated class AppSettings: @unchecked Sendable { // MARK: - Maps /// The locally-bundled MapTiler configuration. - static let bundledMapTilerConfiguration = MapTilerSettings.Configuration(baseURL: "https://api.maptiler.com/maps", - apiKey: Secrets.mapLibreAPIKey, - lightStyleID: "9bc819c8-e627-474a-a348-ec144fe3d810", - darkStyleID: "dea61faf-292b-4774-9660-58fcef89a7f3") + static let bundledMapTilerConfiguration = MapTilerConfiguration(baseURL: "https://api.maptiler.com/maps", + apiKey: Secrets.mapLibreAPIKey, + lightStyleID: "9bc819c8-e627-474a-a348-ec144fe3d810", + darkStyleID: "dea61faf-292b-4774-9660-58fcef89a7f3") - /// The resolved map tile settings. Defaults to ``MapTilerSettings.configuration(_:)`` with the - /// bundled configuration and is remotely overridden with ``MapTilerSettings.url(_:)`` when - /// the homeserver advertises a `style.json` URL via the matrix client well-known. - private(set) var mapTilerSettings = RemotePreference(.configuration(AppSettings.bundledMapTilerConfiguration)) + /// The MapTiler configuration used to build map URLs, which defaults to the bundled one. + private(set) var mapTilerConfiguration = RemotePreference(AppSettings.bundledMapTilerConfiguration) // MARK: - Presence diff --git a/ElementX/Sources/Application/Settings/MapTilerConfiguration.swift b/ElementX/Sources/Application/Settings/MapTilerConfiguration.swift new file mode 100644 index 000000000..5b4b6a8fd --- /dev/null +++ b/ElementX/Sources/Application/Settings/MapTilerConfiguration.swift @@ -0,0 +1,38 @@ +// +// Copyright 2025 Element Creations Ltd. +// Copyright 2025 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. +// Please see LICENSE files in the repository root for full details. +// + +import Foundation + +/// All of the configuration necessary to use MapTiler maps. +/// +/// The style IDs need to be generated with the account that the API key belongs to. For more information read +/// [FORKING.md](https://github.com/element-hq/element-x-ios/blob/develop/docs/FORKING.md#setup-the-location-sharing) +nonisolated struct MapTilerConfiguration: Equatable, Codable { + let baseURL: URL + /// The API key for fetching map tiles. When empty, the server at ``baseURL`` is expected to + /// provide the key itself, so none is sent with the requests. + /// + /// When not set, location sharing will be disabled and any received locations will be shown + /// in the timeline with a generic blurred map image. + let apiKey: String? + /// A MapLibre style ID for a light-mode map. + let lightStyleID: String + /// A MapLibre style ID for a dark-mode map. + let darkStyleID: String + + enum CodingKeys: String, CodingKey { + case baseURL = "base_url" + case apiKey = "api_key" + case lightStyleID = "light_style_id" + case darkStyleID = "dark_style_id" + } + + var isEnabled: Bool { + apiKey != nil + } +} diff --git a/ElementX/Sources/Application/Settings/MapTilerSettings.swift b/ElementX/Sources/Application/Settings/MapTilerSettings.swift deleted file mode 100644 index 8de9052da..000000000 --- a/ElementX/Sources/Application/Settings/MapTilerSettings.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2025 Element Creations Ltd. -// Copyright 2025 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. -// Please see LICENSE files in the repository root for full details. -// - -import Foundation - -/// The map tile settings used to build interactive and static map URLs. -/// -/// Either resolves to a locally-bundled MapTiler configuration, or to a remote -/// `style.json` URL -nonisolated enum MapTilerSettings: Equatable { - /// All of the configuration necessary to use MapTiler maps. - /// - /// The style IDs need to be generated with the account that the API key belongs to. For more information read - /// [FORKING.md](https://github.com/element-hq/element-x-ios/blob/develop/docs/FORKING.md#setup-the-location-sharing) - struct Configuration: Equatable { - let baseURL: URL - /// The API key for fetching map tiles. When not set, location sharing will be disabled and - /// any received locations will be shown in the timeline with a generic blurred map image. - let apiKey: String? - /// A MapLibre style ID for a light-mode map. - let lightStyleID: String - /// A MapLibre style ID for a dark-mode map. - let darkStyleID: String - } - - case configuration(Configuration) - case url(URL) - - var isEnabled: Bool { - switch self { - case .configuration(let configuration): configuration.apiKey != nil - case .url: true - } - } -} diff --git a/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift index d3d3ae3d8..0fdd7388e 100644 --- a/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift @@ -107,7 +107,7 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { let stackCoordinator = NavigationStackCoordinator() let params = LocationSharingScreenCoordinatorParameters(interactionMode: interactionMode, - mapURLBuilder: flowParameters.appSettings.mapTilerSettings.publisher.value, + mapURLBuilder: flowParameters.appSettings.mapTilerConfiguration.publisher.value, roomProxy: roomProxy, timelineController: timelineController, liveLocationManager: flowParameters.userSession.liveLocationManager, diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index f16dadad6..9fb2f49dc 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -1175,7 +1175,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let stackCoordinator = NavigationStackCoordinator() let params = LocationSharingScreenCoordinatorParameters(interactionMode: interactionMode, - mapURLBuilder: flowParameters.appSettings.mapTilerSettings.publisher.value, + mapURLBuilder: flowParameters.appSettings.mapTilerConfiguration.publisher.value, roomProxy: roomProxy, timelineController: timelineController, liveLocationManager: flowParameters.userSession.liveLocationManager, diff --git a/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift b/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift index 30a5318e4..29177c9df 100644 --- a/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift +++ b/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift @@ -21,7 +21,6 @@ nonisolated extension ClientSDKMock { var supportsOAuthCreatePrompt = true var supportsPasswordLogin = true var elementWellKnown: String? - var tileServerMapStyleURL: String? var validCredentials = (username: "alice", password: "12345678") // MARK: Session @@ -69,7 +68,6 @@ nonisolated extension ClientSDKMock { throw MockError.generic } } - tileServerReturnValue = configuration.tileServerMapStyleURL.map { TileServerInfo(mapStyleUrl: $0) } } } diff --git a/ElementX/Sources/Other/MapLibre/MapURLs.swift b/ElementX/Sources/Other/MapLibre/MapURLs.swift index 78ab86066..8da4f9e22 100644 --- a/ElementX/Sources/Other/MapLibre/MapURLs.swift +++ b/ElementX/Sources/Other/MapLibre/MapURLs.swift @@ -8,17 +8,12 @@ import CoreLocation -extension MapTilerSettings: MapTilerURLBuilderProtocol { +extension MapTilerConfiguration: MapTilerURLBuilderProtocol { /// For interactive MGLMap components func interactiveMapURL(for style: MapTilerStyle) -> URL? { - switch self { - case .configuration(let configuration): - var url = configuration.styleURL(for: style) - url?.appendPathComponent("style.json", conformingTo: .json) - return url - case .url(let url): - return url - } + var url = styleURL(for: style) + url?.appendPathComponent("style.json", conformingTo: .json) + return url } /// Used in the timeline where a full MGLMapView loading is unwanted @@ -27,47 +22,30 @@ extension MapTilerSettings: MapTilerURLBuilderProtocol { zoomLevel: Double, size: CGSize, attribution: MapTilerAttributionPlacement) -> URL? { - let staticComponent = String(format: "static/%f,%f,%f/%dx%d@2x.png", - coordinates.longitude, - coordinates.latitude, - zoomLevel, - Int(size.width), - Int(size.height)) - switch self { - case .configuration(let configuration): - var url = configuration.styleURL(for: style) - url?.appendPathComponent(staticComponent, conformingTo: .png) - url?.append(queryItems: [.init(name: "attribution", value: attribution.rawValue)]) - return url - case .url(let url): - // The override is a full URL to a `style.json` (with any necessary query items, - // such as an embedded API key). Derive the static URL by replacing the trailing - // `style.json` component while preserving existing query items. - guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return nil } - var pathComponents = components.path.split(separator: "/", omittingEmptySubsequences: false).map(String.init) - guard pathComponents.last == "style.json" else { return nil } - pathComponents.removeLast() - pathComponents.append(staticComponent) - components.path = pathComponents.joined(separator: "/") - - var queryItems = components.queryItems ?? [] - queryItems.append(.init(name: "attribution", value: attribution.rawValue)) - components.queryItems = queryItems - - return components.url - } + var url = styleURL(for: style) + url?.appendPathComponent(String(format: "static/%f,%f,%f/%dx%d@2x.png", + coordinates.longitude, + coordinates.latitude, + zoomLevel, + Int(size.width), + Int(size.height)), + conformingTo: .png) + url?.append(queryItems: [.init(name: "attribution", value: attribution.rawValue)]) + return url } } // MARK: - Private -private extension MapTilerSettings.Configuration { +private extension MapTilerConfiguration { func styleURL(for style: MapTilerStyle) -> URL? { guard let apiKey else { return nil } var url: URL = baseURL url.appendPathComponent(styleID(for: style), conformingTo: .item) - url.append(queryItems: [URLQueryItem(name: "key", value: apiKey)]) + if !apiKey.isEmpty { + url.append(queryItems: [URLQueryItem(name: "key", value: apiKey)]) + } return url } diff --git a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift index 282564e35..c2b56dedd 100644 --- a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift +++ b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift @@ -435,7 +435,7 @@ extension LocationSharingScreenViewModel { let appSettings = AppSettings.volatile() return LocationSharingScreenViewModel(interactionMode: interactionMode, - mapURLBuilder: appSettings.mapTilerSettings.publisher.value, + mapURLBuilder: appSettings.mapTilerConfiguration.publisher.value, roomProxy: roomProxy, timelineController: TimelineControllerMock(.init()), liveLocationManager: LiveLocationManagerMock(), diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift index 3674ca1e2..75d21dd94 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift @@ -65,7 +65,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool super.init(initialViewState: ComposerToolbarViewState(wysiwygViewModel: wysiwygViewModel, isRoomEncrypted: roomProxy.infoPublisher.value.isEncrypted, - isLocationSharingEnabled: appSettings.mapTilerSettings.publisher.value.isEnabled, + isLocationSharingEnabled: appSettings.mapTilerConfiguration.publisher.value.isEnabled, bindings: .init()), mediaProvider: mediaProvider) diff --git a/ElementX/Sources/Screens/Timeline/TimelineModels.swift b/ElementX/Sources/Screens/Timeline/TimelineModels.swift index 3e923d339..ca85a6cbb 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineModels.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineModels.swift @@ -151,7 +151,7 @@ struct TimelineViewState: BindableState { var linkMetadataProvider: LinkMetadataProviderProtocol? - var mapTilerSettings: MapTilerSettings + var mapTilerConfiguration: MapTilerConfiguration var stoppedLiveLocationIDs: Set = [] diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift index 2c4b0ce77..aebaaf594 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -106,7 +106,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { pinnedEventIDs: roomProxy.infoPublisher.value.pinnedEventIDs, emojiProvider: emojiProvider, linkMetadataProvider: hideTimelineMedia ? nil : linkMetadataProvider, - mapTilerSettings: appSettings.mapTilerSettings.publisher.value, + mapTilerConfiguration: appSettings.mapTilerConfiguration.publisher.value, bindings: .init(reactionsCollapsed: [:])), mediaProvider: userSession.mediaProvider, contentScannerService: userSession.contentScannerService) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LiveLocationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LiveLocationRoomTimelineView.swift index a9e3a416e..17cb60a64 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LiveLocationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LiveLocationRoomTimelineView.swift @@ -64,7 +64,7 @@ struct LiveLocationRoomTimelineView: View { } } .onTapGesture { - guard context.viewState.mapTilerSettings.isEnabled, + guard context.viewState.mapTilerConfiguration.isEnabled, timelineItem.content.lastGeoURI != nil, isLive else { return @@ -93,7 +93,7 @@ struct LiveLocationRoomTimelineView: View { private var liveContent: some View { if let geoURI = timelineItem.content.lastGeoURI { MapLibreStaticMapView(geoURI: geoURI, - mapURLBuilder: context.viewState.mapTilerSettings, + mapURLBuilder: context.viewState.mapTilerConfiguration, attributionPlacement: .topLeft, mapSize: .init(width: mapAspectRatio * mapMaxHeight, height: mapMaxHeight)) { LocationMarkerView(kind: .liveUser(.init(sender: timelineItem.sender)), diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift index e0701e528..34af44082 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift @@ -18,7 +18,7 @@ struct LocationRoomTimelineView: View { .accessibilityElement(children: .ignore) .accessibilityLabel(L10n.commonSharedLocation) .onTapGesture { - guard context.viewState.mapTilerSettings.isEnabled else { return } + guard context.viewState.mapTilerConfiguration.isEnabled else { return } context.send(viewAction: .mediaTapped(itemID: timelineItem.id)) } } @@ -28,7 +28,7 @@ struct LocationRoomTimelineView: View { private var mainContent: some View { if let geoURI = timelineItem.content.geoURI { MapLibreStaticMapView(geoURI: geoURI, - mapURLBuilder: context.viewState.mapTilerSettings, + mapURLBuilder: context.viewState.mapTilerConfiguration, mapSize: .init(width: mapAspectRatio * mapMaxHeight, height: mapMaxHeight)) { LocationMarkerView(kind: timelineItem.content.kind == .sender ? .staticUser(.init(sender: timelineItem.sender)) : .pin, mediaProvider: context.mediaProvider) diff --git a/ElementX/Sources/Services/Authentication/AuthenticationService.swift b/ElementX/Sources/Services/Authentication/AuthenticationService.swift index 19c7a6fd1..3d48d4c50 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationService.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationService.swift @@ -259,7 +259,6 @@ class AuthenticationService: AuthenticationServiceProtocol { appSettings: appSettings, appHooks: appHooks) try await appHooks.remoteSettingsHook.initializeCache(using: client, applyingTo: appSettings).get() - await client.updateMapTilerSettings(in: appSettings) return client } diff --git a/ElementX/Sources/Services/Client/Client.swift b/ElementX/Sources/Services/Client/Client.swift index c1b922e1d..c20a870de 100644 --- a/ElementX/Sources/Services/Client/Client.swift +++ b/ElementX/Sources/Services/Client/Client.swift @@ -29,18 +29,4 @@ nonisolated extension ClientProtocol { return .failure(.sdkError(error)) } } - - /// Reads the homeserver-advertised map tile server (`tile_server.map_style_url` - /// from the matrix client well-known) and applies it to ``AppSettings``. - /// - /// Clears any previously applied URL when none is advertised (or the well-known - /// is unavailable), so each session start reflects the latest server-side - /// configuration. - func updateMapTilerSettings(in appSettings: AppSettings) async { - if let url = await tileServer().flatMap({ URL(string: $0.mapStyleUrl) }) { - appSettings.mapTilerSettings.applyRemoteValue(.url(url)) - } else { - appSettings.mapTilerSettings.reset() - } - } } diff --git a/ElementX/Sources/Services/UserSession/UserSessionStore.swift b/ElementX/Sources/Services/UserSession/UserSessionStore.swift index 33ba9cea8..c6f36745e 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionStore.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionStore.swift @@ -152,7 +152,6 @@ class UserSessionStore: UserSessionStoreProtocol { MXLog.info("Set up session for user \(credentials.userID) at: \(credentials.restorationToken.sessionDirectories)") Task(priority: .low) { await appHooks.remoteSettingsHook.updateCache(using: client) } - Task(priority: .low) { await client.updateMapTilerSettings(in: appSettings) } return try await .success(setupProxyForClient(client)) } catch UserSessionStoreError.failedSettingUpClientProxy(let error) { diff --git a/Enterprise b/Enterprise index 72cded434..a429f633a 160000 --- a/Enterprise +++ b/Enterprise @@ -1 +1 @@ -Subproject commit 72cded434ac6b56cdd3446682be555a686b22021 +Subproject commit a429f633a9c3ff1306127ba380b1bc6360d1ffcb diff --git a/UnitTests/Sources/LocationSharingScreenViewModelTests.swift b/UnitTests/Sources/LocationSharingScreenViewModelTests.swift index 4a14377ad..b565e9fcf 100644 --- a/UnitTests/Sources/LocationSharingScreenViewModelTests.swift +++ b/UnitTests/Sources/LocationSharingScreenViewModelTests.swift @@ -420,7 +420,7 @@ struct LocationSharingScreenViewModelTests { let appSettings = AppSettings.volatile() viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil), - mapURLBuilder: appSettings.mapTilerSettings.publisher.value, + mapURLBuilder: appSettings.mapTilerConfiguration.publisher.value, roomProxy: roomProxyMock, timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))), liveLocationManager: LiveLocationManagerMock(.init()), @@ -633,7 +633,7 @@ struct LocationSharingScreenViewModelTests { appSettings = AppSettings.volatile() timelineProxy = TimelineProxyMock(.init()) viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true), - mapURLBuilder: appSettings.mapTilerSettings.publisher.value, + mapURLBuilder: appSettings.mapTilerConfiguration.publisher.value, roomProxy: JoinedRoomProxyMock(.init(members: members)), timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)), liveLocationManager: liveLocationManagerMock, @@ -661,7 +661,7 @@ struct LocationSharingScreenViewModelTests { roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: sender, initialLiveLocationShare: initialShare), - mapURLBuilder: appSettings.mapTilerSettings.publisher.value, + mapURLBuilder: appSettings.mapTilerConfiguration.publisher.value, roomProxy: roomProxyMock, timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))), liveLocationManager: LiveLocationManagerMock(.init()), diff --git a/UnitTests/Sources/MapTilerURLBuilderTests.swift b/UnitTests/Sources/MapTilerURLBuilderTests.swift index 9a8f08dc7..07e1970c4 100644 --- a/UnitTests/Sources/MapTilerURLBuilderTests.swift +++ b/UnitTests/Sources/MapTilerURLBuilderTests.swift @@ -20,10 +20,10 @@ struct MapTilerURLBuilderTests { var builder: MapTilerURLBuilderProtocol init() { - builder = MapTilerSettings.configuration(.init(baseURL: Self.baseURL, - apiKey: Self.apiKey, - lightStyleID: Self.lightStyleID, - darkStyleID: Self.darkStyleID)) + builder = MapTilerConfiguration(baseURL: Self.baseURL, + apiKey: Self.apiKey, + lightStyleID: Self.lightStyleID, + darkStyleID: Self.darkStyleID) } @Test @@ -59,10 +59,10 @@ struct MapTilerURLBuilderTests { @Test mutating func nilAPIKey() { - let configuration = MapTilerSettings.configuration(.init(baseURL: Self.baseURL, - apiKey: nil, - lightStyleID: Self.lightStyleID, - darkStyleID: Self.darkStyleID)) + let configuration = MapTilerConfiguration(baseURL: Self.baseURL, + apiKey: nil, + lightStyleID: Self.lightStyleID, + darkStyleID: Self.darkStyleID) #expect(!configuration.isEnabled) builder = configuration @@ -78,65 +78,28 @@ struct MapTilerURLBuilderTests { #expect(dynamicMapURL == nil) } - // MARK: - Override URL - @Test - mutating func overrideInteractiveMap() { - let overrideURL: URL = "https://maps.example.com/maps/streets-v2/style.json?key=server_key" - let configuration = MapTilerSettings.url(overrideURL) + mutating func emptyAPIKey() { + // An empty key means the server proxies it for us, so location sharing remains enabled + // but the URLs mustn't contain a key. + let configuration = MapTilerConfiguration(baseURL: Self.baseURL, + apiKey: "", + lightStyleID: Self.lightStyleID, + darkStyleID: Self.darkStyleID) #expect(configuration.isEnabled) builder = configuration - // The override is returned as-is for the interactive map, ignoring light/dark. - #expect(builder.interactiveMapURL(for: .light) == overrideURL) - #expect(builder.interactiveMapURL(for: .dark) == overrideURL) - } - - @Test - mutating func overrideStaticMapPreservesQueryItems() { - // The override includes an embedded API key as a query item — it must be preserved - // when deriving the static map URL. - let overrideURL: URL = "https://maps.example.com/maps/streets-v2/style.json?key=server_key" - builder = MapTilerSettings.url(overrideURL) + let staticMapURL = builder.staticMapTileImageURL(for: .dark, + coordinates: .init(latitude: 1, longitude: 2), + zoomLevel: 5, + size: .init(width: 300, height: 200), + attribution: .topLeft) + let expectedStaticMapURL: URL = "http://www.foo.com/dea61faf-292b-4774-9660-58fcef89a7f3/static/2.000000,1.000000,5.000000/300x200@2x.png?attribution=topleft" + #expect(staticMapURL == expectedStaticMapURL) - let url = builder.staticMapTileImageURL(for: .light, - coordinates: .init(latitude: 1, longitude: 2), - zoomLevel: 5, - size: .init(width: 300, height: 200), - attribution: .topLeft) - - let expectedURL: URL = "https://maps.example.com/maps/streets-v2/static/2.000000,1.000000,5.000000/300x200@2x.png?key=server_key&attribution=topleft" - #expect(url == expectedURL) - } - - @Test - mutating func overrideStaticMapWithoutQueryItems() { - // An override without a key (e.g. self-hosted server proxying the key) still works. - let overrideURL: URL = "https://maps.example.com/maps/streets-v2/style.json" - builder = MapTilerSettings.url(overrideURL) - - let url = builder.staticMapTileImageURL(for: .dark, - coordinates: .init(latitude: 1, longitude: 2), - zoomLevel: 5, - size: .init(width: 300, height: 200), - attribution: .hidden) - - let expectedURL: URL = "https://maps.example.com/maps/streets-v2/static/2.000000,1.000000,5.000000/300x200@2x.png?attribution=false" - #expect(url == expectedURL) - } - - @Test - mutating func overrideMissingStyleJSONFails() { - // If the override URL doesn't end in /style.json we can't derive a static URL. - let overrideURL: URL = "https://maps.example.com/maps/streets-v2/" - builder = MapTilerSettings.url(overrideURL) - - let url = builder.staticMapTileImageURL(for: .light, - coordinates: .init(latitude: 1, longitude: 2), - zoomLevel: 5, - size: .init(width: 300, height: 200), - attribution: .topLeft) - #expect(url == nil) + let dynamicMapURL = builder.interactiveMapURL(for: .light) + let expectedDynamicMapURL: URL = "http://www.foo.com/9bc819c8-e627-474a-a348-ec144fe3d810/style.json" + #expect(dynamicMapURL == expectedDynamicMapURL) } } diff --git a/UnitTests/Sources/MatrixClientWellKnownTests.swift b/UnitTests/Sources/MatrixClientWellKnownTests.swift deleted file mode 100644 index 7fc9eeb01..000000000 --- a/UnitTests/Sources/MatrixClientWellKnownTests.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright 2025 Element Creations Ltd. -// Copyright 2025 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. -// Please see LICENSE files in the repository root for full details. -// - -@testable import ElementX -import Foundation -import MatrixRustSDKMocks -import Testing - -/// Exercises ``ClientProtocol.updateMapTilerSettings(in:)``. The SDK is now the -/// source of truth for parsing the matrix client well-known and exposing the -/// `tile_server` field as a typed ``TileServerInfo``; these tests just check -/// that we forward it into ``AppSettings`` correctly. -struct MatrixClientWellKnownTests { - private static let mapStyleURLString = "https://maps.example.com/maps/streets-v2/style.json?key=server" - - @Test - func mapStyleURLIsApplied() async throws { - let appSettings = AppSettings.volatile() - let client = ClientSDKMock(.init(tileServerMapStyleURL: Self.mapStyleURLString)) - - await client.updateMapTilerSettings(in: appSettings) - - #expect(appSettings.mapTilerSettings.isRemotelyConfigured) - let expectedURL = try #require(URL(string: Self.mapStyleURLString)) - #expect(appSettings.mapTilerSettings.publisher.value == .url(expectedURL)) - } - - @Test - func missingTileServerClearsExistingOverride() async throws { - let appSettings = AppSettings.volatile() - let expectedURL = try #require(URL(string: Self.mapStyleURLString)) - appSettings.mapTilerSettings.applyRemoteValue(.url(expectedURL)) - #expect(appSettings.mapTilerSettings.isRemotelyConfigured) - - // The SDK returns nil when the homeserver hasn't advertised a tile server. - let client = ClientSDKMock(.init()) - await client.updateMapTilerSettings(in: appSettings) - - #expect(!appSettings.mapTilerSettings.isRemotelyConfigured) - } - - @Test - func invalidMapStyleURLClearsOverride() async throws { - let appSettings = AppSettings.volatile() - let expectedURL = try #require(URL(string: Self.mapStyleURLString)) - appSettings.mapTilerSettings.applyRemoteValue(.url(expectedURL)) - - // The SDK returns the string verbatim — if it isn't a valid URL we just - // drop any previous override rather than crash. - let client = ClientSDKMock(.init(tileServerMapStyleURL: "")) - await client.updateMapTilerSettings(in: appSettings) - - #expect(!appSettings.mapTilerSettings.isRemotelyConfigured) - } - - @Test - func mapTilerSettingsResolveToOverride() async { - let appSettings = AppSettings.volatile() - let client = ClientSDKMock(.init(tileServerMapStyleURL: Self.mapStyleURLString)) - - await client.updateMapTilerSettings(in: appSettings) - - switch appSettings.mapTilerSettings.publisher.value { - case .url(let url): - #expect(url.absoluteString == Self.mapStyleURLString) - case .configuration: - Issue.record("Expected the resolved settings to be .url") - } - } -}