mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:44:05 +00:00
Remove the global UserIndicatorController.alertInfo, replacing it with local alertInfo usage. (#5087)
This commit is contained in:
@@ -226,12 +226,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
|||||||
guard let confirmationParameters = url.confirmationParameters else {
|
guard let confirmationParameters = url.confirmationParameters else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
ServiceLocator.shared.userIndicatorController.alertInfo = .init(id: .init(),
|
navigationRootCoordinator.alertInfo = .init(id: .init(),
|
||||||
title: L10n.dialogConfirmLinkTitle,
|
title: L10n.dialogConfirmLinkTitle,
|
||||||
message: L10n.dialogConfirmLinkMessage(confirmationParameters.displayString,
|
message: L10n.dialogConfirmLinkMessage(confirmationParameters.displayString,
|
||||||
confirmationParameters.internalURL.absoluteString),
|
confirmationParameters.internalURL.absoluteString),
|
||||||
primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil),
|
primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil),
|
||||||
secondaryButton: .init(title: L10n.actionContinue) { openURLAction(confirmationParameters.internalURL) })
|
secondaryButton: .init(title: L10n.actionContinue) { openURLAction(confirmationParameters.internalURL) })
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ import SwiftUI
|
|||||||
overlayModule?.coordinator
|
overlayModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The lowest-level `AlertInfo`, directly available to the root of the app.
|
||||||
|
var alertInfo: AlertInfo<UUID>?
|
||||||
|
|
||||||
/// Sets or replaces the presented coordinator
|
/// Sets or replaces the presented coordinator
|
||||||
/// - Parameter coordinator: the coordinator to display
|
/// - Parameter coordinator: the coordinator to display
|
||||||
func setRootCoordinator(_ coordinator: (any CoordinatorProtocol)?, animated: Bool = true, dismissalCallback: (() -> Void)? = nil) {
|
func setRootCoordinator(_ coordinator: (any CoordinatorProtocol)?, animated: Bool = true, dismissalCallback: (() -> Void)? = nil) {
|
||||||
@@ -159,6 +162,7 @@ private struct NavigationRootCoordinatorView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
rootCoordinator.rootModule?.coordinator?.toPresentable()
|
rootCoordinator.rootModule?.coordinator?.toPresentable()
|
||||||
}
|
}
|
||||||
|
.alert(item: $rootCoordinator.alertInfo)
|
||||||
.animation(.elementDefault, value: rootCoordinator.rootModule)
|
.animation(.elementDefault, value: rootCoordinator.rootModule)
|
||||||
.sheet(item: $rootCoordinator.sheetModule) { module in
|
.sheet(item: $rootCoordinator.sheetModule) { module in
|
||||||
module.coordinator?.toPresentable()
|
module.coordinator?.toPresentable()
|
||||||
|
|||||||
@@ -485,7 +485,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
let secureBackupController = userSession.clientProxy.secureBackupController
|
let secureBackupController = userSession.clientProxy.secureBackupController
|
||||||
|
|
||||||
guard case let .success(isLastDevice) = await userSession.clientProxy.isOnlyDeviceLeft() else {
|
guard case let .success(isLastDevice) = await userSession.clientProxy.isOnlyDeviceLeft() else {
|
||||||
flowParameters.userIndicatorController.alertInfo = .init(id: .init())
|
navigationRootCoordinator.alertInfo = .init(id: .init())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,26 +495,26 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard secureBackupController.recoveryState.value == .enabled else {
|
guard secureBackupController.recoveryState.value == .enabled else {
|
||||||
flowParameters.userIndicatorController.alertInfo = .init(id: .init(),
|
navigationRootCoordinator.alertInfo = .init(id: .init(),
|
||||||
title: L10n.screenSignoutRecoveryDisabledTitle,
|
title: L10n.screenSignoutRecoveryDisabledTitle,
|
||||||
message: L10n.screenSignoutRecoveryDisabledSubtitle,
|
message: L10n.screenSignoutRecoveryDisabledSubtitle,
|
||||||
primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in
|
primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in
|
||||||
self?.actionsSubject.send(.logout)
|
self?.actionsSubject.send(.logout)
|
||||||
}, secondaryButton: .init(title: L10n.commonSettings, role: .cancel) { [weak self] in
|
}, secondaryButton: .init(title: L10n.commonSettings, role: .cancel) { [weak self] in
|
||||||
self?.chatsTabFlowCoordinator.handleAppRoute(.chatBackupSettings, animated: true)
|
self?.chatsTabFlowCoordinator.handleAppRoute(.chatBackupSettings, animated: true)
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard secureBackupController.keyBackupState.value == .enabled else {
|
guard secureBackupController.keyBackupState.value == .enabled else {
|
||||||
flowParameters.userIndicatorController.alertInfo = .init(id: .init(),
|
navigationRootCoordinator.alertInfo = .init(id: .init(),
|
||||||
title: L10n.screenSignoutKeyBackupDisabledTitle,
|
title: L10n.screenSignoutKeyBackupDisabledTitle,
|
||||||
message: L10n.screenSignoutKeyBackupDisabledSubtitle,
|
message: L10n.screenSignoutKeyBackupDisabledSubtitle,
|
||||||
primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in
|
primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in
|
||||||
self?.actionsSubject.send(.logout)
|
self?.actionsSubject.send(.logout)
|
||||||
}, secondaryButton: .init(title: L10n.commonSettings, role: .cancel) { [weak self] in
|
}, secondaryButton: .init(title: L10n.commonSettings, role: .cancel) { [weak self] in
|
||||||
self?.chatsTabFlowCoordinator.handleAppRoute(.chatBackupSettings, animated: true)
|
self?.chatsTabFlowCoordinator.handleAppRoute(.chatBackupSettings, animated: true)
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,12 +522,12 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func logout() {
|
private func logout() {
|
||||||
flowParameters.userIndicatorController.alertInfo = .init(id: .init(),
|
navigationRootCoordinator.alertInfo = .init(id: .init(),
|
||||||
title: L10n.screenSignoutConfirmationDialogTitle,
|
title: L10n.screenSignoutConfirmationDialogTitle,
|
||||||
message: L10n.screenSignoutConfirmationDialogContent,
|
message: L10n.screenSignoutConfirmationDialogContent,
|
||||||
primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in
|
primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in
|
||||||
self?.actionsSubject.send(.logout)
|
self?.actionsSubject.send(.logout)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentSecureBackupLogoutConfirmationScreen() {
|
private func presentSecureBackupLogoutConfirmationScreen() {
|
||||||
|
|||||||
@@ -19524,7 +19524,6 @@ class UserIdentityProxyMock: UserIdentityProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
class UserIndicatorControllerMock: UserIndicatorControllerProtocol, @unchecked Sendable {
|
class UserIndicatorControllerMock: UserIndicatorControllerProtocol, @unchecked Sendable {
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
var alertInfo: AlertInfo<UUID>?
|
|
||||||
|
|
||||||
//MARK: - submitIndicator
|
//MARK: - submitIndicator
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ class UserIndicatorController: ObservableObject, UserIndicatorControllerProtocol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published var alertInfo: AlertInfo<UUID>?
|
|
||||||
|
|
||||||
var window: UIWindow? {
|
var window: UIWindow? {
|
||||||
didSet {
|
didSet {
|
||||||
let hostingController = UIHostingController(rootView: UserIndicatorPresenter(userIndicatorController: self).statusBarHidden(ProcessInfo.isRunningUITests))
|
let hostingController = UIHostingController(rootView: UserIndicatorPresenter(userIndicatorController: self).statusBarHidden(ProcessInfo.isRunningUITests))
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ protocol UserIndicatorControllerProtocol: CoordinatorProtocol {
|
|||||||
func retractAllIndicators()
|
func retractAllIndicators()
|
||||||
|
|
||||||
var window: UIWindow? { get set }
|
var window: UIWindow? { get set }
|
||||||
var alertInfo: AlertInfo<UUID>? { get set }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UserIndicatorControllerProtocol {
|
extension UserIndicatorControllerProtocol {
|
||||||
|
|||||||
@@ -28,6 +28,5 @@ struct UserIndicatorPresenter: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.alert(item: $userIndicatorController.alertInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class OIDCAuthenticationPresenter: NSObject {
|
|||||||
let errorDescription = error.map(String.init(describing:)) ?? "Unknown error"
|
let errorDescription = error.map(String.init(describing:)) ?? "Unknown error"
|
||||||
MXLog.error("Missing callback URL from the web authentication session: \(errorDescription)")
|
MXLog.error("Missing callback URL from the web authentication session: \(errorDescription)")
|
||||||
|
|
||||||
userIndicatorController.alertInfo = AlertInfo(id: UUID())
|
showFailureIndicator()
|
||||||
await authenticationService.abortOIDCLogin(data: oidcData)
|
await authenticationService.abortOIDCLogin(data: oidcData)
|
||||||
return .failure(.oidcError(.unknown))
|
return .failure(.oidcError(.unknown))
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ class OIDCAuthenticationPresenter: NSObject {
|
|||||||
return .failure(.oidcError(.userCancellation))
|
return .failure(.oidcError(.userCancellation))
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
MXLog.error("Error occurred: \(error)")
|
MXLog.error("Error occurred: \(error)")
|
||||||
userIndicatorController.alertInfo = AlertInfo(id: UUID())
|
showFailureIndicator()
|
||||||
return .failure(error)
|
return .failure(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,10 +85,16 @@ class OIDCAuthenticationPresenter: NSObject {
|
|||||||
activeSession?.cancel()
|
activeSession?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private static let loadingIndicatorID = "\(OIDCAuthenticationPresenter.self)-Loading"
|
private var loadingIndicatorID: String {
|
||||||
|
"\(Self.self)-Loading"
|
||||||
|
}
|
||||||
|
|
||||||
|
private var failureIndicatorID: String {
|
||||||
|
"\(Self.self)-Failure"
|
||||||
|
}
|
||||||
|
|
||||||
private func startLoading(delay: Duration? = nil) {
|
private func startLoading(delay: Duration? = nil) {
|
||||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorID,
|
userIndicatorController.submitIndicator(UserIndicator(id: loadingIndicatorID,
|
||||||
type: .modal,
|
type: .modal,
|
||||||
title: L10n.commonLoading,
|
title: L10n.commonLoading,
|
||||||
persistent: true),
|
persistent: true),
|
||||||
@@ -96,7 +102,14 @@ class OIDCAuthenticationPresenter: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func stopLoading() {
|
private func stopLoading() {
|
||||||
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorID)
|
userIndicatorController.retractIndicatorWithId(loadingIndicatorID)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showFailureIndicator() {
|
||||||
|
userIndicatorController.submitIndicator(UserIndicator(id: failureIndicatorID,
|
||||||
|
type: .toast,
|
||||||
|
title: L10n.errorUnknown,
|
||||||
|
iconName: "xmark"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import SwiftUI
|
|||||||
|
|
||||||
enum CreateRoomScreenErrorType: Error {
|
enum CreateRoomScreenErrorType: Error {
|
||||||
case failedCreatingRoom
|
case failedCreatingRoom
|
||||||
|
case failedProcessingMedia
|
||||||
case failedUploadingMedia
|
case failedUploadingMedia
|
||||||
case fileTooLarge
|
case fileTooLarge
|
||||||
case mediaFileError
|
case mediaFileError
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
do {
|
do {
|
||||||
guard case let .success(maxUploadSize) = await userSession.clientProxy.maxMediaUploadSize else {
|
guard case let .success(maxUploadSize) = await userSession.clientProxy.maxMediaUploadSize else {
|
||||||
MXLog.error("Failed to get max upload size")
|
MXLog.error("Failed to get max upload size")
|
||||||
userIndicatorController.alertInfo = AlertInfo(id: .init())
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let mediaInfo = try await mediaUploadingPreprocessor.processMedia(at: fileURL, maxUploadSize: maxUploadSize).get()
|
let mediaInfo = try await mediaUploadingPreprocessor.processMedia(at: fileURL, maxUploadSize: maxUploadSize).get()
|
||||||
@@ -128,7 +128,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
userIndicatorController.alertInfo = AlertInfo(id: .init())
|
state.bindings.alertInfo = .init(id: .failedProcessingMedia)
|
||||||
}
|
}
|
||||||
hideLoadingIndicator()
|
hideLoadingIndicator()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,9 +105,9 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userIndicatorController.alertInfo = .init(id: .init(),
|
state.bindings.alertInfo = .init(id: .unknown,
|
||||||
title: L10n.commonUnableToInviteTitle,
|
title: L10n.commonUnableToInviteTitle,
|
||||||
message: L10n.commonUnableToInviteMessage)
|
message: L10n.commonUnableToInviteMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,10 @@ struct RoomDetailsEditScreenViewStateBindings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum RoomDetailsEditScreenAlertType {
|
enum RoomDetailsEditScreenAlertType {
|
||||||
|
case failedProcessingMedia
|
||||||
case unsavedChanges
|
case unsavedChanges
|
||||||
|
case saveError
|
||||||
|
case unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RoomDetailsEditScreenViewAction {
|
enum RoomDetailsEditScreenViewAction {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
|
|||||||
|
|
||||||
guard case let .success(maxUploadSize) = await clientProxy.maxMediaUploadSize else {
|
guard case let .success(maxUploadSize) = await clientProxy.maxMediaUploadSize else {
|
||||||
MXLog.error("Failed to get max upload size")
|
MXLog.error("Failed to get max upload size")
|
||||||
userIndicatorController.alertInfo = .init(id: .init())
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let mediaResult = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize)
|
let mediaResult = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize)
|
||||||
@@ -95,7 +95,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
|
|||||||
case .success(.image):
|
case .success(.image):
|
||||||
state.localMedia = try? mediaResult.get()
|
state.localMedia = try? mediaResult.get()
|
||||||
case .failure, .success:
|
case .failure, .success:
|
||||||
userIndicatorController.alertInfo = .init(id: .init())
|
state.bindings.alertInfo = .init(id: .failedProcessingMedia)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,9 +161,9 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
|
|||||||
|
|
||||||
actionsSubject.send(.saveFinished)
|
actionsSubject.send(.saveFinished)
|
||||||
} catch {
|
} catch {
|
||||||
userIndicatorController.alertInfo = .init(id: .init(),
|
state.bindings.alertInfo = .init(id: .saveError,
|
||||||
title: L10n.screenRoomDetailsEditionErrorTitle,
|
title: L10n.screenRoomDetailsEditionErrorTitle,
|
||||||
message: L10n.screenRoomDetailsEditionError)
|
message: L10n.screenRoomDetailsEditionError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,11 @@ struct RoomScreenViewState: BindableState {
|
|||||||
struct RoomScreenViewStateBindings {
|
struct RoomScreenViewStateBindings {
|
||||||
/// The view model used to present a QuickLook media preview.
|
/// The view model used to present a QuickLook media preview.
|
||||||
var mediaPreviewViewModel: TimelineMediaPreviewViewModel?
|
var mediaPreviewViewModel: TimelineMediaPreviewViewModel?
|
||||||
|
var alertInfo: AlertInfo<RoomScreenAlertType>?
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RoomScreenAlertType {
|
||||||
|
case unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RoomScreenFooterViewAction {
|
enum RoomScreenFooterViewAction {
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
showLoadingIndicator()
|
showLoadingIndicator()
|
||||||
|
|
||||||
if case .failure = await clientProxy.pinUserIdentity(userID) {
|
if case .failure = await clientProxy.pinUserIdentity(userID) {
|
||||||
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError)
|
state.bindings.alertInfo = .init(id: .unknown, title: L10n.commonError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
showLoadingIndicator()
|
showLoadingIndicator()
|
||||||
|
|
||||||
if case .failure = await clientProxy.withdrawUserIdentityVerification(userID) {
|
if case .failure = await clientProxy.withdrawUserIdentityVerification(userID) {
|
||||||
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError)
|
state.bindings.alertInfo = .init(id: .unknown, title: L10n.commonError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ struct RoomScreen: View {
|
|||||||
.toolbar { toolbar }
|
.toolbar { toolbar }
|
||||||
.toolbarBackground(.visible, for: .navigationBar) // Fix the toolbar's background.
|
.toolbarBackground(.visible, for: .navigationBar) // Fix the toolbar's background.
|
||||||
.overlay { loadingIndicator }
|
.overlay { loadingIndicator }
|
||||||
|
.alert(item: $context.alertInfo)
|
||||||
.timelineMediaPreview(viewModel: $context.mediaPreviewViewModel)
|
.timelineMediaPreview(viewModel: $context.mediaPreviewViewModel)
|
||||||
.track(screen: .Room)
|
.track(screen: .Room)
|
||||||
.sentryTrace("\(Self.self)")
|
.sentryTrace("\(Self.self)")
|
||||||
|
|||||||
+3
@@ -52,7 +52,10 @@ struct UserDetailsEditScreenViewStateBindings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum UserDetailsEditScreenAlertType {
|
enum UserDetailsEditScreenAlertType {
|
||||||
|
case failedProcessingMedia
|
||||||
case unsavedChanges
|
case unsavedChanges
|
||||||
|
case saveError
|
||||||
|
case unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UserDetailsEditScreenViewAction {
|
enum UserDetailsEditScreenViewAction {
|
||||||
|
|||||||
+5
-5
@@ -92,7 +92,7 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
|
|||||||
|
|
||||||
guard case let .success(maxUploadSize) = await clientProxy.maxMediaUploadSize else {
|
guard case let .success(maxUploadSize) = await clientProxy.maxMediaUploadSize else {
|
||||||
MXLog.error("Failed to get max upload size")
|
MXLog.error("Failed to get max upload size")
|
||||||
userIndicatorController.alertInfo = .init(id: .init())
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let mediaResult = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize)
|
let mediaResult = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize)
|
||||||
@@ -101,7 +101,7 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
|
|||||||
case .success(.image):
|
case .success(.image):
|
||||||
state.localMedia = try? mediaResult.get()
|
state.localMedia = try? mediaResult.get()
|
||||||
case .failure, .success:
|
case .failure, .success:
|
||||||
userIndicatorController.alertInfo = .init(id: .init())
|
state.bindings.alertInfo = .init(id: .failedProcessingMedia)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,9 +149,9 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
|
|||||||
|
|
||||||
actionsSubject.send(.dismiss)
|
actionsSubject.send(.dismiss)
|
||||||
} catch {
|
} catch {
|
||||||
userIndicatorController.alertInfo = .init(id: .init(),
|
state.bindings.alertInfo = .init(id: .saveError,
|
||||||
title: L10n.screenEditProfileErrorTitle,
|
title: L10n.screenEditProfileErrorTitle,
|
||||||
message: L10n.screenEditProfileError)
|
message: L10n.screenEditProfileError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,6 +199,9 @@ enum TimelineAlertInfoType: Hashable {
|
|||||||
case sendingFailed
|
case sendingFailed
|
||||||
case encryptionAuthenticity(String)
|
case encryptionAuthenticity(String)
|
||||||
case encryptionForwarder(String)
|
case encryptionForwarder(String)
|
||||||
|
case inviteAgain
|
||||||
|
case unableToInvite
|
||||||
|
case unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RoomMemberState {
|
struct RoomMemberState {
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
|||||||
|
|
||||||
shouldShowInviteAlert
|
shouldShowInviteAlert
|
||||||
.sink { [weak self] _ in
|
.sink { [weak self] _ in
|
||||||
self?.showInviteAlert()
|
self?.displayAlert(.inviteAgain)
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
@@ -865,19 +865,11 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
|||||||
|
|
||||||
// MARK: - Direct chats logics
|
// MARK: - Direct chats logics
|
||||||
|
|
||||||
private func showInviteAlert() {
|
|
||||||
userIndicatorController.alertInfo = .init(id: .init(),
|
|
||||||
title: L10n.screenRoomInviteAgainAlertTitle,
|
|
||||||
message: L10n.screenRoomInviteAgainAlertMessage,
|
|
||||||
primaryButton: .init(title: L10n.actionInvite) { [weak self] in self?.inviteOtherDMUserBack() },
|
|
||||||
secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
private let inviteLoadingIndicatorID = UUID().uuidString
|
private let inviteLoadingIndicatorID = UUID().uuidString
|
||||||
|
|
||||||
private func inviteOtherDMUserBack() {
|
private func inviteOtherDMUserBack() {
|
||||||
guard roomProxy.infoPublisher.value.isUserAloneInDirectRoom else {
|
guard roomProxy.infoPublisher.value.isUserAloneInDirectRoom else {
|
||||||
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError)
|
displayAlert(.unknown)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -892,7 +884,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
|||||||
members.count == 2,
|
members.count == 2,
|
||||||
let otherPerson = members.first(where: { $0.userID != roomProxy.ownUserID && $0.membership == .leave })
|
let otherPerson = members.first(where: { $0.userID != roomProxy.ownUserID && $0.membership == .leave })
|
||||||
else {
|
else {
|
||||||
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError)
|
displayAlert(.unknown)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,9 +892,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
|||||||
case .success:
|
case .success:
|
||||||
break
|
break
|
||||||
case .failure:
|
case .failure:
|
||||||
userIndicatorController.alertInfo = .init(id: .init(),
|
displayAlert(.unableToInvite)
|
||||||
title: L10n.commonUnableToInviteTitle,
|
|
||||||
message: L10n.commonUnableToInviteMessage)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1021,6 +1011,18 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
|||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
appMediator.open(appSettings.historySharingDetailsURL)
|
appMediator.open(appSettings.historySharingDetailsURL)
|
||||||
})
|
})
|
||||||
|
case .inviteAgain:
|
||||||
|
state.bindings.alertInfo = .init(id: .inviteAgain,
|
||||||
|
title: L10n.screenRoomInviteAgainAlertTitle,
|
||||||
|
message: L10n.screenRoomInviteAgainAlertMessage,
|
||||||
|
primaryButton: .init(title: L10n.actionInvite) { [weak self] in self?.inviteOtherDMUserBack() },
|
||||||
|
secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil))
|
||||||
|
case .unableToInvite:
|
||||||
|
state.bindings.alertInfo = .init(id: .unableToInvite,
|
||||||
|
title: L10n.commonUnableToInviteTitle,
|
||||||
|
message: L10n.commonUnableToInviteMessage)
|
||||||
|
case .unknown:
|
||||||
|
state.bindings.alertInfo = .init(id: .unknown, title: L10n.commonError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
|
|||||||
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
viewModel.didSelectMediaUrl(url: .picturesDirectory)
|
viewModel.didSelectMediaUrl(url: .picturesDirectory)
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
try? await Task.sleep(for: .milliseconds(100))
|
||||||
XCTAssertNotNil(userIndicatorController.alertInfo)
|
XCTAssertNotNil(context.alertInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDeleteAvatar() {
|
func testDeleteAvatar() {
|
||||||
|
|||||||
Reference in New Issue
Block a user