From ca895f7d44f9a263c405eec9c52086884cbeabae Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 27 Jun 2024 11:05:34 +0300 Subject: [PATCH 1/2] Fixes #2911 - Make Element Call widget URL configurable --- .../Sources/Application/AppSettings.swift | 8 +- .../UserSessionFlowCoordinator.swift | 6 +- .../Mocks/Generated/GeneratedMocks.swift | 65 ++++++ .../Mocks/Generated/SDKGeneratedMocks.swift | 220 ++++++++++++------ .../CallScreen/CallScreenCoordinator.swift | 10 +- .../CallScreen/CallScreenViewModel.swift | 16 +- .../Screens/CallScreen/View/CallScreen.swift | 10 +- .../DeveloperOptionsScreenModels.swift | 1 + .../View/DeveloperOptionsScreen.swift | 5 +- .../Sources/Services/Client/ClientProxy.swift | 55 +++-- .../Services/Client/ClientProxyProtocol.swift | 5 + .../Services/Client/ElementWellKnown.swift | 42 ++++ 12 files changed, 338 insertions(+), 105 deletions(-) create mode 100644 ElementX/Sources/Services/Client/ElementWellKnown.swift diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index d97bbfdba1..725bb3effd 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -39,7 +39,7 @@ final class AppSettings { case sharePresence case hideUnreadMessagesBadge - case elementCallBaseURL + case elementCallBaseURLOverride case elementCallEncryptionEnabled // Feature flags @@ -249,8 +249,10 @@ final class AppSettings { // MARK: - Element Call - @UserPreference(key: UserDefaultsKeys.elementCallBaseURL, defaultValue: "https://call.element.io", storageType: .userDefaults(store)) - var elementCallBaseURL: URL + let elementCallBaseURL: URL = "https://call.element.io" + + @UserPreference(key: UserDefaultsKeys.elementCallBaseURLOverride, defaultValue: nil, storageType: .userDefaults(store)) + var elementCallBaseURLOverride: URL? // MARK: - Users diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 04bbceb546..a5568372f8 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -555,9 +555,11 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { private func presentCallScreen(roomProxy: RoomProxyProtocol) { let callScreenCoordinator = CallScreenCoordinator(parameters: .init(elementCallService: elementCallService, + clientProxy: userSession.clientProxy, roomProxy: roomProxy, - callBaseURL: appSettings.elementCallBaseURL, - clientID: InfoPlistReader.main.bundleIdentifier)) + clientID: InfoPlistReader.main.bundleIdentifier, + elementCallBaseURL: appSettings.elementCallBaseURL, + elementCallBaseURLOverride: appSettings.elementCallBaseURLOverride)) callScreenCoordinator.actions .sink { [weak self] action in diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 8484ca2461..5a7414b47b 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -1920,6 +1920,7 @@ class ClientProxyMock: ClientProxyProtocol { set(value) { underlyingHomeserver = value } } var underlyingHomeserver: String! + var userIDServerName: String? var userDisplayNamePublisher: CurrentValuePublisher { get { return underlyingUserDisplayNamePublisher } set(value) { underlyingUserDisplayNamePublisher = value } @@ -3564,6 +3565,70 @@ class ClientProxyMock: ClientProxyProtocol { return resolveRoomAliasReturnValue } } + //MARK: - getElementWellKnown + + var getElementWellKnownUnderlyingCallsCount = 0 + var getElementWellKnownCallsCount: Int { + get { + if Thread.isMainThread { + return getElementWellKnownUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = getElementWellKnownUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + getElementWellKnownUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + getElementWellKnownUnderlyingCallsCount = newValue + } + } + } + } + var getElementWellKnownCalled: Bool { + return getElementWellKnownCallsCount > 0 + } + + var getElementWellKnownUnderlyingReturnValue: Result! + var getElementWellKnownReturnValue: Result! { + get { + if Thread.isMainThread { + return getElementWellKnownUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = getElementWellKnownUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + getElementWellKnownUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + getElementWellKnownUnderlyingReturnValue = newValue + } + } + } + } + var getElementWellKnownClosure: (() async -> Result)? + + func getElementWellKnown() async -> Result { + getElementWellKnownCallsCount += 1 + if let getElementWellKnownClosure = getElementWellKnownClosure { + return await getElementWellKnownClosure() + } else { + return getElementWellKnownReturnValue + } + } //MARK: - ignoreUser var ignoreUserUnderlyingCallsCount = 0 diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index 3c59bdd6e8..c21a8d6e1f 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -1439,6 +1439,81 @@ open class ClientSDKMock: MatrixRustSDK.Client { } } + //MARK: - getUrl + + open var getUrlUrlThrowableError: Error? + var getUrlUrlUnderlyingCallsCount = 0 + open var getUrlUrlCallsCount: Int { + get { + if Thread.isMainThread { + return getUrlUrlUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = getUrlUrlUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + getUrlUrlUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + getUrlUrlUnderlyingCallsCount = newValue + } + } + } + } + open var getUrlUrlCalled: Bool { + return getUrlUrlCallsCount > 0 + } + open var getUrlUrlReceivedUrl: String? + open var getUrlUrlReceivedInvocations: [String] = [] + + var getUrlUrlUnderlyingReturnValue: String! + open var getUrlUrlReturnValue: String! { + get { + if Thread.isMainThread { + return getUrlUrlUnderlyingReturnValue + } else { + var returnValue: String? = nil + DispatchQueue.main.sync { + returnValue = getUrlUrlUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + getUrlUrlUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + getUrlUrlUnderlyingReturnValue = newValue + } + } + } + } + open var getUrlUrlClosure: ((String) async throws -> String)? + + open override func getUrl(url: String) async throws -> String { + if let error = getUrlUrlThrowableError { + throw error + } + getUrlUrlCallsCount += 1 + getUrlUrlReceivedUrl = url + DispatchQueue.main.async { + self.getUrlUrlReceivedInvocations.append(url) + } + if let getUrlUrlClosure = getUrlUrlClosure { + return try await getUrlUrlClosure(url) + } else { + return getUrlUrlReturnValue + } + } + //MARK: - homeserver var homeserverUnderlyingCallsCount = 0 @@ -3277,6 +3352,75 @@ open class ClientSDKMock: MatrixRustSDK.Client { return userIdReturnValue } } + + //MARK: - userIdServerName + + open var userIdServerNameThrowableError: Error? + var userIdServerNameUnderlyingCallsCount = 0 + open var userIdServerNameCallsCount: Int { + get { + if Thread.isMainThread { + return userIdServerNameUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = userIdServerNameUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + userIdServerNameUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + userIdServerNameUnderlyingCallsCount = newValue + } + } + } + } + open var userIdServerNameCalled: Bool { + return userIdServerNameCallsCount > 0 + } + + var userIdServerNameUnderlyingReturnValue: String! + open var userIdServerNameReturnValue: String! { + get { + if Thread.isMainThread { + return userIdServerNameUnderlyingReturnValue + } else { + var returnValue: String? = nil + DispatchQueue.main.sync { + returnValue = userIdServerNameUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + userIdServerNameUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + userIdServerNameUnderlyingReturnValue = newValue + } + } + } + } + open var userIdServerNameClosure: (() throws -> String)? + + open override func userIdServerName() throws -> String { + if let error = userIdServerNameThrowableError { + throw error + } + userIdServerNameCallsCount += 1 + if let userIdServerNameClosure = userIdServerNameClosure { + return try userIdServerNameClosure() + } else { + return userIdServerNameReturnValue + } + } } open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { init() { @@ -9170,82 +9314,6 @@ open class NotificationSettingsSDKMock: MatrixRustSDK.NotificationSettings { try await unmuteRoomRoomIdIsEncryptedIsOneToOneClosure?(roomId, isEncrypted, isOneToOne) } } -open class OidcAuthorizationDataSDKMock: MatrixRustSDK.OidcAuthorizationData { - init() { - super.init(noPointer: .init()) - } - - public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { - fatalError("init(unsafeFromRawPointer:) has not been implemented") - } - - fileprivate var pointer: UnsafeMutableRawPointer! - - //MARK: - loginUrl - - var loginUrlUnderlyingCallsCount = 0 - open var loginUrlCallsCount: Int { - get { - if Thread.isMainThread { - return loginUrlUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = loginUrlUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - loginUrlUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - loginUrlUnderlyingCallsCount = newValue - } - } - } - } - open var loginUrlCalled: Bool { - return loginUrlCallsCount > 0 - } - - var loginUrlUnderlyingReturnValue: String! - open var loginUrlReturnValue: String! { - get { - if Thread.isMainThread { - return loginUrlUnderlyingReturnValue - } else { - var returnValue: String? = nil - DispatchQueue.main.sync { - returnValue = loginUrlUnderlyingReturnValue - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - loginUrlUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - loginUrlUnderlyingReturnValue = newValue - } - } - } - } - open var loginUrlClosure: (() -> String)? - - open override func loginUrl() -> String { - loginUrlCallsCount += 1 - if let loginUrlClosure = loginUrlClosure { - return loginUrlClosure() - } else { - return loginUrlReturnValue - } - } -} open class QrCodeDataSDKMock: MatrixRustSDK.QrCodeData { init() { super.init(noPointer: .init()) diff --git a/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift b/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift index 80d3aebb11..2ddbe5ff70 100644 --- a/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift +++ b/ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift @@ -19,9 +19,11 @@ import SwiftUI struct CallScreenCoordinatorParameters { let elementCallService: ElementCallServiceProtocol + let clientProxy: ClientProxyProtocol let roomProxy: RoomProxyProtocol - let callBaseURL: URL let clientID: String + let elementCallBaseURL: URL + let elementCallBaseURLOverride: URL? } enum CallScreenCoordinatorAction { @@ -39,9 +41,11 @@ final class CallScreenCoordinator: CoordinatorProtocol { init(parameters: CallScreenCoordinatorParameters) { viewModel = CallScreenViewModel(elementCallService: parameters.elementCallService, + clientProxy: parameters.clientProxy, roomProxy: parameters.roomProxy, - callBaseURL: parameters.callBaseURL, - clientID: parameters.clientID) + clientID: parameters.clientID, + elementCallBaseURL: parameters.elementCallBaseURL, + elementCallBaseURLOverride: parameters.elementCallBaseURLOverride) } func start() { diff --git a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift index a49f1f9e09..2bc91fa676 100644 --- a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift +++ b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift @@ -38,9 +38,11 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol /// - callBaseURL: Which Element Call instance should be used /// - clientID: Something to identify the current client on the Element Call side init(elementCallService: ElementCallServiceProtocol, + clientProxy: ClientProxyProtocol, roomProxy: RoomProxyProtocol, - callBaseURL: URL, - clientID: String) { + clientID: String, + elementCallBaseURL: URL, + elementCallBaseURLOverride: URL?) { self.elementCallService = elementCallService self.roomProxy = roomProxy @@ -90,7 +92,15 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol .store(in: &cancellables) Task { - switch await widgetDriver.start(baseURL: callBaseURL, clientID: clientID) { + let baseURL = if let elementCallBaseURLOverride { + elementCallBaseURLOverride + } else if case .success(let wellKnown) = await clientProxy.getElementWellKnown(), let wellKnownCallWidgetURL = wellKnown?.call?.widgetURL { + wellKnownCallWidgetURL + } else { + elementCallBaseURL + } + + switch await widgetDriver.start(baseURL: baseURL, clientID: clientID) { case .success(let url): state.url = url case .failure(let error): diff --git a/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift b/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift index 8b20c41138..4a876ee5c5 100644 --- a/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift +++ b/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift @@ -172,7 +172,11 @@ private struct WebView: UIViewRepresentable { struct CallScreen_Previews: PreviewProvider { static let viewModel = { + let clientProxy = ClientProxyMock() + clientProxy.getElementWellKnownReturnValue = .success(nil) + let roomProxy = RoomProxyMock() + roomProxy.sendCallNotificationIfNeeededReturnValue = .success(()) let widgetDriver = ElementCallWidgetDriverMock() widgetDriver.underlyingMessagePublisher = .init() @@ -182,9 +186,11 @@ struct CallScreen_Previews: PreviewProvider { roomProxy.elementCallWidgetDriverReturnValue = widgetDriver return CallScreenViewModel(elementCallService: ElementCallServiceMock(.init()), + clientProxy: clientProxy, roomProxy: roomProxy, - callBaseURL: "https://call.element.io", - clientID: "io.element.elementx") + clientID: "io.element.elementx", + elementCallBaseURL: "https://call.element.io", + elementCallBaseURLOverride: nil) }() static var previews: some View { diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index 249f3053e9..f0f1204a0e 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -47,6 +47,7 @@ protocol DeveloperOptionsProtocol: AnyObject { var logLevel: TracingConfiguration.LogLevel { get set } var hideUnreadMessagesBadge: Bool { get set } var elementCallBaseURL: URL { get set } + var elementCallBaseURLOverride: URL? { get set } var fuzzyRoomListSearchEnabled: Bool { get set } } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index 444fba9521..a27ae31121 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -38,14 +38,15 @@ struct DeveloperOptionsScreen: View { } Section("Element Call") { - TextField(context.elementCallBaseURL.absoluteString, text: $elementCallBaseURLString) + TextField(context.elementCallBaseURL?.absoluteString ?? elementCallBaseURLOverride?.absoluteString, + text: $elementCallBaseURLString) .submitLabel(.done) .onSubmit { guard let url = URL(string: elementCallBaseURLString) else { return } - context.elementCallBaseURL = url + context.elementCallBaseURLOverride = url } .autocorrectionDisabled(true) .autocapitalization(.none) diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 593a0b52b2..8ae882bdeb 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -21,6 +21,7 @@ import OrderedCollections import MatrixRustSDK +// swiftlint:disable file_length class ClientProxy: ClientProxyProtocol { private let client: ClientProtocol private let networkMonitor: NetworkMonitorProtocol @@ -188,19 +189,6 @@ class ClientProxy: ClientProxyProtocol { .store(in: &cancellables) } - private func updateVerificationState(_ verificationState: VerificationState) { - let verificationState: SessionVerificationState = switch verificationState { - case .unknown: - .unknown - case .unverified: - .unverified - case .verified: - .verified - } - - verificationStateSubject.send(verificationState) - } - var userID: String { do { return try client.userId() @@ -214,7 +202,7 @@ class ClientProxy: ClientProxyProtocol { do { return try client.deviceId() } catch { - MXLog.error("Failed retrieving device id with error: \(error)") + MXLog.error("Failed retrieving deviceID with error: \(error)") return nil } } @@ -222,6 +210,15 @@ class ClientProxy: ClientProxyProtocol { var homeserver: String { client.homeserver() } + + var userIDServerName: String? { + do { + return try client.userIdServerName() + } catch { + MXLog.error("Failed retrieving userID server name with error: \(error)") + return nil + } + } private(set) lazy var pusherNotificationClientIdentifier: String? = { // NOTE: The result is stored as part of the restoration token. Any changes @@ -616,6 +613,23 @@ class ClientProxy: ClientProxyProtocol { return .failure(.sdkError(error)) } } + + func getElementWellKnown() async -> Result { + guard let userIDServerName, + var url = URL(string: userIDServerName) else { + return .failure(.invalidUserIDServerName) + } + + url.append(path: "/.well-known/element/element.json") + + do { + let response = try await client.getUrl(url: url.absoluteString) + let sdkWellKnown = try makeElementWellKnown(string: response) + return .success(ElementWellKnown(sdkWellKnown)) + } catch { + return .failure(.sdkError(error)) + } + } // MARK: Ignored users @@ -691,6 +705,19 @@ class ClientProxy: ClientProxyProtocol { } // MARK: - Private + + private func updateVerificationState(_ verificationState: VerificationState) { + let verificationState: SessionVerificationState = switch verificationState { + case .unknown: + .unknown + case .unverified: + .unverified + case .verified: + .verified + } + + verificationStateSubject.send(verificationState) + } private func loadUserAvatarURLFromCache() { loadCachedAvatarURLTask = Task { diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 6562b1f46e..3d9ec1b19e 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -41,6 +41,7 @@ enum ClientProxyError: Error { case sdkError(Error) case invalidMedia + case invalidUserIDServerName case failedUploadingMedia(Error, MatrixErrorCode) } @@ -94,6 +95,8 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { var deviceID: String? { get } var homeserver: String { get } + + var userIDServerName: String? { get } var userDisplayNamePublisher: CurrentValuePublisher { get } @@ -162,6 +165,8 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func roomDirectorySearchProxy() -> RoomDirectorySearchProxyProtocol func resolveRoomAlias(_ alias: String) async -> Result + + func getElementWellKnown() async -> Result // MARK: - Ignored users diff --git a/ElementX/Sources/Services/Client/ElementWellKnown.swift b/ElementX/Sources/Services/Client/ElementWellKnown.swift new file mode 100644 index 0000000000..044fe6ee2e --- /dev/null +++ b/ElementX/Sources/Services/Client/ElementWellKnown.swift @@ -0,0 +1,42 @@ +// +// Copyright 2024 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import MatrixRustSDK + +struct ElementWellKnown { + struct Call { + let widgetURL: URL? + + init?(_ wellKnown: MatrixRustSDK.ElementCallWellKnown?) { + guard let wellKnown else { + return nil + } + + widgetURL = URL(string: wellKnown.widgetUrl) + } + } + + let call: Call? + + init?(_ wellKnown: MatrixRustSDK.ElementWellKnown?) { + guard let wellKnown else { + return nil + } + + call = Call(wellKnown.call) + } +} From c96102e69cdfe3bc93cc0038128b79e1be751038 Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 2 Jul 2024 08:58:28 +0100 Subject: [PATCH 2/2] Rebase on SDK update. --- ElementX.xcodeproj/project.pbxproj | 4 ++++ .../CallScreen/CallScreenViewModel.swift | 4 ++-- .../DeveloperOptionsScreenCoordinator.swift | 3 ++- .../DeveloperOptionsScreenModels.swift | 2 +- .../DeveloperOptionsScreenViewModel.swift | 4 ++-- .../View/DeveloperOptionsScreen.swift | 11 ++++------- .../Services/Client/ElementWellKnown.swift | 17 +++++------------ 7 files changed, 20 insertions(+), 25 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index d2bdf853f7..05945acfc3 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -264,6 +264,7 @@ 3F2148F11164C7C5609984EB /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 2B788C81F6369D164ADEB917 /* GZIP */; }; 3F327A62D233933F54F0F33A /* SwiftOGG in Frameworks */ = {isa = PBXBuildFile; productRef = 3FE40E79C36E7903121E6E3B /* SwiftOGG */; }; 3F70E237CE4C3FAB02FC227F /* NotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C830A64609CBD152F06E0457 /* NotificationConstants.swift */; }; + 3F997171C3C79A45E92BF9EF /* ElementWellKnown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FAC366FF299BCC555D756E /* ElementWellKnown.swift */; }; 401BB28CD6B7DD6B4E7863E7 /* ServerConfirmationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */; }; 407DCE030E0F9B7C9861D38A /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 1081D3630AAD3ACEDDEC3A98 /* LRUCache */; }; 40B79D20A873620F7F128A2C /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; }; @@ -1621,6 +1622,7 @@ 78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitCoordinatorTests.swift; sourceTree = ""; }; 7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerMock.swift; sourceTree = ""; }; 796CBD0C56FA0D3AEDAB255B /* SessionVerificationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenCoordinator.swift; sourceTree = ""; }; + 79FAC366FF299BCC555D756E /* ElementWellKnown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementWellKnown.swift; sourceTree = ""; }; 7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenCoordinator.swift; sourceTree = ""; }; 7A5D2323D7B6BF4913EB7EED /* landscape_test_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = landscape_test_image.jpg; sourceTree = ""; }; 7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -3862,6 +3864,7 @@ D09A267106B9585D3D0CFC0D /* ClientError.swift */, 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */, 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */, + 79FAC366FF299BCC555D756E /* ElementWellKnown.swift */, ); path = Client; sourceTree = ""; @@ -6060,6 +6063,7 @@ 48416BBEB8DDF3E4DED0EDB6 /* ElementCallServiceProtocol.swift in Sources */, 07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */, 370AF5BFCD4384DD455479B6 /* ElementCallWidgetDriverProtocol.swift in Sources */, + 3F997171C3C79A45E92BF9EF /* ElementWellKnown.swift in Sources */, 7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */, 7361B011A79BF723D8C9782B /* EmojiCategory.swift in Sources */, E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */, diff --git a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift index 2bc91fa676..6086449eb9 100644 --- a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift +++ b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift @@ -94,8 +94,8 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol Task { let baseURL = if let elementCallBaseURLOverride { elementCallBaseURLOverride - } else if case .success(let wellKnown) = await clientProxy.getElementWellKnown(), let wellKnownCallWidgetURL = wellKnown?.call?.widgetURL { - wellKnownCallWidgetURL + } else if case .success(let wellKnown) = await clientProxy.getElementWellKnown(), let wellKnownCall = wellKnown?.call { + wellKnownCall.widgetURL } else { elementCallBaseURL } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift index 28d11c608c..1b4d9061c8 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenCoordinator.swift @@ -32,7 +32,8 @@ final class DeveloperOptionsScreenCoordinator: CoordinatorProtocol { } init() { - viewModel = DeveloperOptionsScreenViewModel(developerOptions: ServiceLocator.shared.settings) + viewModel = DeveloperOptionsScreenViewModel(developerOptions: ServiceLocator.shared.settings, + elementCallBaseURL: ServiceLocator.shared.settings.elementCallBaseURL) viewModel.actions .sink { [weak self] action in diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index f0f1204a0e..ff80493fa4 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -21,6 +21,7 @@ enum DeveloperOptionsScreenViewModelAction { } struct DeveloperOptionsScreenViewState: BindableState { + let elementCallBaseURL: URL var bindings: DeveloperOptionsScreenViewStateBindings } @@ -46,7 +47,6 @@ enum DeveloperOptionsScreenViewAction { protocol DeveloperOptionsProtocol: AnyObject { var logLevel: TracingConfiguration.LogLevel { get set } var hideUnreadMessagesBadge: Bool { get set } - var elementCallBaseURL: URL { get set } var elementCallBaseURLOverride: URL? { get set } var fuzzyRoomListSearchEnabled: Bool { get set } } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift index 57292aee40..7d218a5308 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenViewModel.swift @@ -26,9 +26,9 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve actionsSubject.eraseToAnyPublisher() } - init(developerOptions: DeveloperOptionsProtocol) { + init(developerOptions: DeveloperOptionsProtocol, elementCallBaseURL: URL) { let bindings = DeveloperOptionsScreenViewStateBindings(developerOptions: developerOptions) - let state = DeveloperOptionsScreenViewState(bindings: bindings) + let state = DeveloperOptionsScreenViewState(elementCallBaseURL: elementCallBaseURL, bindings: bindings) super.init(initialViewState: state) } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index a27ae31121..e79e114b5f 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -38,14 +38,10 @@ struct DeveloperOptionsScreen: View { } Section("Element Call") { - TextField(context.elementCallBaseURL?.absoluteString ?? elementCallBaseURLOverride?.absoluteString, - text: $elementCallBaseURLString) + TextField(context.viewState.elementCallBaseURL.absoluteString, text: $elementCallBaseURLString) .submitLabel(.done) .onSubmit { - guard let url = URL(string: elementCallBaseURLString) else { - return - } - + guard let url = URL(string: elementCallBaseURLString) else { return } context.elementCallBaseURLOverride = url } .autocorrectionDisabled(true) @@ -149,7 +145,8 @@ private struct LogLevelConfigurationView: View { // MARK: - Previews struct DeveloperOptionsScreen_Previews: PreviewProvider { - static let viewModel = DeveloperOptionsScreenViewModel(developerOptions: ServiceLocator.shared.settings) + static let viewModel = DeveloperOptionsScreenViewModel(developerOptions: ServiceLocator.shared.settings, + elementCallBaseURL: ServiceLocator.shared.settings.elementCallBaseURL) static var previews: some View { NavigationStack { DeveloperOptionsScreen(context: viewModel.context) diff --git a/ElementX/Sources/Services/Client/ElementWellKnown.swift b/ElementX/Sources/Services/Client/ElementWellKnown.swift index 044fe6ee2e..c65e0090b2 100644 --- a/ElementX/Sources/Services/Client/ElementWellKnown.swift +++ b/ElementX/Sources/Services/Client/ElementWellKnown.swift @@ -19,24 +19,17 @@ import MatrixRustSDK struct ElementWellKnown { struct Call { - let widgetURL: URL? + let widgetURL: URL - init?(_ wellKnown: MatrixRustSDK.ElementCallWellKnown?) { - guard let wellKnown else { - return nil - } - - widgetURL = URL(string: wellKnown.widgetUrl) + init?(_ wellKnown: MatrixRustSDK.ElementCallWellKnown) { + guard let widgetURL = URL(string: wellKnown.widgetUrl) else { return nil } + self.widgetURL = widgetURL } } let call: Call? - init?(_ wellKnown: MatrixRustSDK.ElementWellKnown?) { - guard let wellKnown else { - return nil - } - + init?(_ wellKnown: MatrixRustSDK.ElementWellKnown) { call = Call(wellKnown.call) } }