mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:06:00 +00:00
Move navigation coordination away from the SettingsScreenCoordinator and into the SettingsFlowCoordinator
This commit is contained in:
@@ -18,32 +18,31 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsScreenCoordinatorParameters {
|
||||
weak var navigationStackCoordinator: NavigationStackCoordinator?
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
let userSession: UserSessionProtocol
|
||||
let appLockService: AppLockServiceProtocol
|
||||
let bugReportService: BugReportServiceProtocol
|
||||
let notificationSettings: NotificationSettingsProxyProtocol
|
||||
let secureBackupController: SecureBackupControllerProtocol
|
||||
let appSettings: AppSettings
|
||||
}
|
||||
|
||||
enum SettingsScreenCoordinatorAction {
|
||||
case dismiss
|
||||
case logout
|
||||
case clearCache
|
||||
case secureBackup
|
||||
/// Logout without a confirmation. The user forgot their PIN.
|
||||
case forceLogout
|
||||
case userDetails
|
||||
case accountProfile
|
||||
case analytics
|
||||
case appLock
|
||||
case bugReport
|
||||
case about
|
||||
case sessionVerification
|
||||
case accountSessions
|
||||
case notifications
|
||||
case advancedSettings
|
||||
case developerOptions
|
||||
}
|
||||
|
||||
final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: SettingsScreenCoordinatorParameters
|
||||
private var viewModel: SettingsScreenViewModelProtocol
|
||||
|
||||
// periphery:ignore - retaining purpose
|
||||
private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator?
|
||||
|
||||
private let actionsSubject: PassthroughSubject<SettingsScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
@@ -67,29 +66,29 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
case .close:
|
||||
actionsSubject.send(.dismiss)
|
||||
case .userDetails:
|
||||
presentUserDetailsEditScreen()
|
||||
actionsSubject.send(.userDetails)
|
||||
case .accountProfile:
|
||||
presentAccountProfileURL()
|
||||
actionsSubject.send(.accountProfile)
|
||||
case .analytics:
|
||||
presentAnalyticsScreen()
|
||||
actionsSubject.send(.analytics)
|
||||
case .appLock:
|
||||
presentAppLockSetupFlow()
|
||||
actionsSubject.send(.appLock)
|
||||
case .reportBug:
|
||||
presentBugReportScreen()
|
||||
actionsSubject.send(.bugReport)
|
||||
case .about:
|
||||
presentLegalInformationScreen()
|
||||
actionsSubject.send(.about)
|
||||
case .sessionVerification:
|
||||
presentSessionVerificationScreen()
|
||||
actionsSubject.send(.sessionVerification)
|
||||
case .secureBackup:
|
||||
actionsSubject.send(.secureBackup)
|
||||
case .accountSessionsList:
|
||||
presentAccountSessionsListURL()
|
||||
actionsSubject.send(.accountSessions)
|
||||
case .notifications:
|
||||
presentNotificationSettings()
|
||||
actionsSubject.send(.notifications)
|
||||
case .advancedSettings:
|
||||
self.presentAdvancedSettings()
|
||||
actionsSubject.send(.advancedSettings)
|
||||
case .developerOptions:
|
||||
presentDeveloperOptions()
|
||||
actionsSubject.send(.developerOptions)
|
||||
case .logout:
|
||||
actionsSubject.send(.logout)
|
||||
}
|
||||
@@ -102,163 +101,4 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(SettingsScreen(context: viewModel.context))
|
||||
}
|
||||
|
||||
// MARK: - OIDC Account Management
|
||||
|
||||
private func presentAccountProfileURL() {
|
||||
guard let url = viewModel.context.viewState.accountProfileURL else {
|
||||
MXLog.error("Account URL is missing.")
|
||||
return
|
||||
}
|
||||
presentAccountManagementURL(url)
|
||||
}
|
||||
|
||||
private func presentAccountSessionsListURL() {
|
||||
guard let url = viewModel.context.viewState.accountSessionsListURL else {
|
||||
MXLog.error("Account URL is missing.")
|
||||
return
|
||||
}
|
||||
presentAccountManagementURL(url)
|
||||
}
|
||||
|
||||
private var accountSettingsPresenter: OIDCAccountSettingsPresenter?
|
||||
private func presentAccountManagementURL(_ url: URL) {
|
||||
guard let window = viewModel.context.viewState.window else {
|
||||
MXLog.error("The window is missing.")
|
||||
return
|
||||
}
|
||||
|
||||
// Note to anyone in the future if you come back here to make this open in Safari instead of a WAS.
|
||||
// As of iOS 16, there is an issue on the simulator with accessing the cookie but it works on a device. 🤷♂️
|
||||
accountSettingsPresenter = OIDCAccountSettingsPresenter(accountURL: url, presentationAnchor: window)
|
||||
accountSettingsPresenter?.start()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func presentUserDetailsEditScreen() {
|
||||
let coordinator = UserDetailsEditScreenCoordinator(parameters: .init(clientProxy: parameters.userSession.clientProxy,
|
||||
mediaProvider: parameters.userSession.mediaProvider,
|
||||
navigationStackCoordinator: parameters.navigationStackCoordinator,
|
||||
userIndicatorController: parameters.userIndicatorController))
|
||||
|
||||
parameters.navigationStackCoordinator?.push(coordinator)
|
||||
}
|
||||
|
||||
private func presentAnalyticsScreen() {
|
||||
let coordinator = AnalyticsSettingsScreenCoordinator(parameters: .init(appSettings: parameters.appSettings,
|
||||
analytics: ServiceLocator.shared.analytics))
|
||||
parameters.navigationStackCoordinator?.push(coordinator)
|
||||
}
|
||||
|
||||
private func presentAppLockSetupFlow() {
|
||||
guard let navigationStackCoordinator = parameters.navigationStackCoordinator else {
|
||||
MXLog.error("The navigation stack has gone! 🌫️")
|
||||
return
|
||||
}
|
||||
|
||||
let coordinator = AppLockSetupFlowCoordinator(presentingFlow: .settings,
|
||||
appLockService: parameters.appLockService,
|
||||
navigationStackCoordinator: navigationStackCoordinator)
|
||||
coordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .complete:
|
||||
// The flow coordinator tidies up the stack, no need to do anything.
|
||||
appLockSetupFlowCoordinator = nil
|
||||
case .forceLogout:
|
||||
actionsSubject.send(.forceLogout)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
appLockSetupFlowCoordinator = coordinator
|
||||
coordinator.start()
|
||||
}
|
||||
|
||||
private func presentBugReportScreen() {
|
||||
let params = BugReportScreenCoordinatorParameters(bugReportService: parameters.bugReportService,
|
||||
userID: parameters.userSession.userID,
|
||||
deviceID: parameters.userSession.deviceID,
|
||||
userIndicatorController: parameters.userIndicatorController,
|
||||
screenshot: nil,
|
||||
isModallyPresented: false)
|
||||
let coordinator = BugReportScreenCoordinator(parameters: params)
|
||||
coordinator.completion = { [weak self] result in
|
||||
switch result {
|
||||
case .finish:
|
||||
self?.showSuccess(label: L10n.actionDone)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
self?.parameters.navigationStackCoordinator?.pop()
|
||||
}
|
||||
|
||||
parameters.navigationStackCoordinator?.push(coordinator)
|
||||
}
|
||||
|
||||
private func presentLegalInformationScreen() {
|
||||
parameters.navigationStackCoordinator?.push(LegalInformationScreenCoordinator(appSettings: parameters.appSettings))
|
||||
}
|
||||
|
||||
private func presentSessionVerificationScreen() {
|
||||
guard let sessionVerificationController = parameters.userSession.sessionVerificationController else {
|
||||
fatalError("The sessionVerificationController should aways be valid at this point")
|
||||
}
|
||||
|
||||
let verificationParameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController)
|
||||
let coordinator = SessionVerificationScreenCoordinator(parameters: verificationParameters)
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .done:
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(coordinator) { [weak self] in
|
||||
self?.parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func presentNotificationSettings() {
|
||||
let notificationParameters = NotificationSettingsScreenCoordinatorParameters(navigationStackCoordinator: parameters.navigationStackCoordinator,
|
||||
userSession: parameters.userSession,
|
||||
userNotificationCenter: UNUserNotificationCenter.current(),
|
||||
notificationSettings: parameters.notificationSettings,
|
||||
isModallyPresented: false)
|
||||
let coordinator = NotificationSettingsScreenCoordinator(parameters: notificationParameters)
|
||||
parameters.navigationStackCoordinator?.push(coordinator)
|
||||
}
|
||||
|
||||
private func presentAdvancedSettings() {
|
||||
let coordinator = AdvancedSettingsScreenCoordinator()
|
||||
parameters.navigationStackCoordinator?.push(coordinator)
|
||||
}
|
||||
|
||||
private func presentDeveloperOptions() {
|
||||
let coordinator = DeveloperOptionsScreenCoordinator()
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .clearCache:
|
||||
actionsSubject.send(.clearCache)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
parameters.navigationStackCoordinator?.push(coordinator)
|
||||
}
|
||||
|
||||
private func showSuccess(label: String) {
|
||||
parameters.userIndicatorController.submitIndicator(UserIndicator(title: label))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,6 @@ struct SettingsScreenViewState: BindableState {
|
||||
var isSessionVerified: Bool?
|
||||
var showSecureBackupBadge = false
|
||||
var showDeveloperOptions: Bool
|
||||
|
||||
/// The presentation anchor used to display the OIDC account URL.
|
||||
var window: UIWindow?
|
||||
}
|
||||
|
||||
enum SettingsScreenViewAction {
|
||||
@@ -64,7 +61,4 @@ enum SettingsScreenViewAction {
|
||||
case developerOptions
|
||||
case advancedSettings
|
||||
case logout
|
||||
|
||||
/// Updates the window used for the OIDC account URL anchor.
|
||||
case updateWindow(UIWindow)
|
||||
}
|
||||
|
||||
@@ -94,12 +94,6 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
actionsSubject.send(.advancedSettings)
|
||||
case .developerOptions:
|
||||
actionsSubject.send(.developerOptions)
|
||||
|
||||
case .updateWindow(let window):
|
||||
Task {
|
||||
guard state.window != window else { return }
|
||||
state.window = window
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,6 @@ struct SettingsScreen: View {
|
||||
.navigationTitle(L10n.commonSettings)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbar }
|
||||
.introspect(.window, on: .supportedVersions) { window in
|
||||
context.send(viewAction: .updateWindow(window))
|
||||
}
|
||||
}
|
||||
|
||||
private var userSection: some View {
|
||||
|
||||
Reference in New Issue
Block a user