diff --git a/ElementX/Sources/Application/BuildSettings.swift b/ElementX/Sources/Application/BuildSettings.swift index 19736e7771..aff8550b44 100644 --- a/ElementX/Sources/Application/BuildSettings.swift +++ b/ElementX/Sources/Application/BuildSettings.swift @@ -17,11 +17,19 @@ import Foundation final class BuildSettings { + static var defaults: UserDefaults = { + guard let userDefaults = UserDefaults(suiteName: ElementInfoPlist.appGroupIdentifier) else { + fatalError("[RiotSettings] Fail to load shared UserDefaults") + } + return userDefaults + }() + // MARK: - Servers static let defaultHomeserverAddress = "matrix.org" - static let slidingSyncProxyBaseURL = URL(staticString: "https://slidingsync.lab.element.dev") - + + static let defaultSlidingSyncProxyBaseURLString = "https://slidingsync.lab.element.dev" + // MARK: - Bug report static let bugReportServiceBaseURL = URL(staticString: "https://riot.im/bugreports") diff --git a/ElementX/Sources/Other/ElementSettings.swift b/ElementX/Sources/Other/ElementSettings.swift index 745214c1cd..e83f12e939 100644 --- a/ElementX/Sources/Other/ElementSettings.swift +++ b/ElementX/Sources/Other/ElementSettings.swift @@ -25,6 +25,7 @@ final class ElementSettings: ObservableObject { case timelineStyle case enableAnalytics case isIdentifiedForAnalytics + case slidingSyncProxyBaseURLString } static let shared = ElementSettings() @@ -59,4 +60,9 @@ final class ElementSettings: ObservableObject { @AppStorage(UserDefaultsKeys.timelineStyle.rawValue, store: store) var timelineStyle = BuildSettings.defaultRoomTimelineStyle + + // MARK: - Client + + @AppStorage(UserDefaultsKeys.slidingSyncProxyBaseURLString.rawValue, store: store) + var slidingSyncProxyBaseURLString = BuildSettings.defaultSlidingSyncProxyBaseURLString } diff --git a/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionModels.swift b/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionModels.swift index 1c3c9f8e42..7ccdab1e4e 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionModels.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionModels.swift @@ -59,6 +59,8 @@ struct ServerSelectionViewState: BindableState { struct ServerSelectionBindings { /// The homeserver address input by the user. var homeserverAddress: String + /// The sliding sync proxy address input by the user. + var slidingSyncProxyAddress: String /// Information describing the currently displayed alert. var alertInfo: AlertInfo? } diff --git a/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionViewModel.swift b/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionViewModel.swift index 2c9cc7d6a3..d5aa5e65bf 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelection/ServerSelectionViewModel.swift @@ -30,7 +30,9 @@ class ServerSelectionViewModel: ServerSelectionViewModelType, ServerSelectionVie // MARK: - Setup init(homeserverAddress: String, isModallyPresented: Bool) { - let bindings = ServerSelectionBindings(homeserverAddress: homeserverAddress) + let bindings = ServerSelectionBindings(homeserverAddress: homeserverAddress, + slidingSyncProxyAddress: ElementSettings.shared.slidingSyncProxyBaseURLString) + super.init(initialViewState: ServerSelectionViewState(bindings: bindings, isModallyPresented: isModallyPresented)) } @@ -40,6 +42,10 @@ class ServerSelectionViewModel: ServerSelectionViewModelType, ServerSelectionVie override func process(viewAction: ServerSelectionViewAction) async { switch viewAction { case .confirm: + if !state.bindings.slidingSyncProxyAddress.isEmpty { + ElementSettings.shared.slidingSyncProxyBaseURLString = state.bindings.slidingSyncProxyAddress + } + callback?(.confirm(homeserverAddress: state.bindings.homeserverAddress)) case .dismiss: callback?(.dismiss) diff --git a/ElementX/Sources/Screens/Authentication/ServerSelection/View/ServerSelectionScreen.swift b/ElementX/Sources/Screens/Authentication/ServerSelection/View/ServerSelectionScreen.swift index d3e2e8feca..9ab8c448dd 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelection/View/ServerSelectionScreen.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelection/View/ServerSelectionScreen.swift @@ -17,18 +17,8 @@ import SwiftUI struct ServerSelectionScreen: View { - // MARK: - Properties - - // MARK: Private - - @FocusState var isTextFieldFocused: Bool - - // MARK: Public - @ObservedObject var context: ServerSelectionViewModel.Context - // MARK: Views - var body: some View { ScrollView { VStack(spacing: 0) { @@ -69,8 +59,8 @@ struct ServerSelectionScreen: View { var serverForm: some View { VStack(alignment: .leading, spacing: 12) { TextField(ElementL10n.ftueAuthChooseServerEntryHint, text: $context.homeserverAddress) - .focused($isTextFieldFocused) - .textFieldStyle(.elementInput(footerText: context.viewState.footerMessage, + .textFieldStyle(.elementInput(labelText: ElementL10n.hsUrl, + footerText: context.viewState.footerMessage, isError: context.viewState.isShowingFooterError)) .keyboardType(.URL) .autocapitalization(.none) @@ -80,6 +70,17 @@ struct ServerSelectionScreen: View { .onSubmit(submit) .accessibilityIdentifier("addressTextField") + Divider() + + TextField(ElementL10n.ftueAuthChooseServerEntryHint, text: $context.slidingSyncProxyAddress) + .textFieldStyle(.elementInput(labelText: "Sliding sync proxy URL")) + .keyboardType(.URL) + .autocapitalization(.none) + .disableAutocorrection(true) + .submitLabel(.done) + .onSubmit(submit) + .accessibilityIdentifier("slidingSyncProxyAddressTextField") + Button(action: submit) { Text(context.viewState.buttonTitle) } diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 2de3baeb7d..220ebbdcdc 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -21,7 +21,7 @@ typealias HomeScreenViewModelType = StateStoreViewModel() @@ -84,7 +78,7 @@ class ClientProxy: ClientProxyProtocol { await Task.dispatch(on: clientQueue) { do { - let slidingSyncBuilder = try client.slidingSync().homeserver(url: BuildSettings.slidingSyncProxyBaseURL.absoluteString) + let slidingSyncBuilder = try client.slidingSync().homeserver(url: ElementSettings.shared.slidingSyncProxyBaseURLString) let slidingSyncView = try SlidingSyncViewBuilder() .timelineLimit(limit: 10) @@ -94,16 +88,18 @@ class ClientProxy: ClientProxyProtocol { .syncMode(mode: .fullSync) .build() - self.slidingSync = try slidingSyncBuilder + let slidingSync = try slidingSyncBuilder .addView(v: slidingSyncView) .withCommonExtensions() .build() - - self.roomSummaryProviderInternal = RoomSummaryProvider(slidingSyncController: self.slidingSync, - slidingSyncView: slidingSyncView, - roomMessageFactory: RoomMessageFactory()) + + self.roomSummaryProvider = RoomSummaryProvider(slidingSyncController: slidingSync, + slidingSyncView: slidingSyncView, + roomMessageFactory: RoomMessageFactory()) + + self.slidingSync = slidingSync } catch { - fatalError("Failed configuring sliding sync") + MXLog.error("Failed configuring sliding sync with error: \(error)") } } @@ -150,15 +146,15 @@ class ClientProxy: ClientProxyProtocol { return } - slidingSync.setObserver(observer: WeakClientProxyWrapper(clientProxy: self)) - slidingSyncObserverToken = slidingSync.sync() + slidingSync?.setObserver(observer: WeakClientProxyWrapper(clientProxy: self)) + slidingSyncObserverToken = slidingSync?.sync() } func stopSync() { client.setDelegate(delegate: nil) slidingSyncObserverToken?.cancel() - slidingSync.setObserver(observer: nil) + slidingSync?.setObserver(observer: nil) } func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? { @@ -252,7 +248,7 @@ class ClientProxy: ClientProxyProtocol { private func roomTupleForIdentifier(_ identifier: String) -> (SlidingSyncRoom?, Room?) { do { - let slidingSyncRoom = try slidingSync.getRoom(roomId: identifier) + let slidingSyncRoom = try slidingSync?.getRoom(roomId: identifier) let fullRoom = slidingSyncRoom?.fullRoom() return (slidingSyncRoom, fullRoom) @@ -271,7 +267,7 @@ class ClientProxy: ClientProxyProtocol { } fileprivate func didReceiveSlidingSyncUpdate(summary: UpdateSummary) { - roomSummaryProvider.updateRoomsWithIdentifiers(summary.rooms) + roomSummaryProvider?.updateRoomsWithIdentifiers(summary.rooms) callbacks.send(.receivedSyncUpdate) } diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 7f94303045..9ddbc83363 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -46,7 +46,7 @@ protocol ClientProxyProtocol { var restorationToken: RestorationToken? { get } - var roomSummaryProvider: RoomSummaryProviderProtocol { get } + var roomSummaryProvider: RoomSummaryProviderProtocol? { get } func startSync() diff --git a/ElementX/Sources/Services/Client/MockClientProxy.swift b/ElementX/Sources/Services/Client/MockClientProxy.swift index 3adab27b62..b6b9e8ba22 100644 --- a/ElementX/Sources/Services/Client/MockClientProxy.swift +++ b/ElementX/Sources/Services/Client/MockClientProxy.swift @@ -26,7 +26,7 @@ struct MockClientProxy: ClientProxyProtocol { let homeserver = "" let restorationToken: RestorationToken? = nil - var roomSummaryProvider: RoomSummaryProviderProtocol = MockRoomSummaryProvider() + var roomSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider() func startSync() { } diff --git a/changelog.d/320.feature b/changelog.d/320.feature new file mode 100644 index 0000000000..d3579343c7 --- /dev/null +++ b/changelog.d/320.feature @@ -0,0 +1 @@ +Expose sliding sync proxy configuration URL on the server selection screen \ No newline at end of file