Have the UserIndicatorController use a separate window, switch to using one single instance throughout the application

This commit is contained in:
Stefan Ceriu
2023-11-09 15:10:50 +02:00
committed by Stefan Ceriu
parent 1102beb3dd
commit 4b26a798dc
44 changed files with 210 additions and 221 deletions
@@ -103,7 +103,6 @@ class AuthenticationCoordinator: CoordinatorProtocol {
private func showServerSelectionScreen(isModallyPresented: Bool) {
let navigationCoordinator = NavigationStackCoordinator()
let userIndicatorController: UserIndicatorControllerProtocol! = isModallyPresented ? UserIndicatorController(rootCoordinator: navigationCoordinator) : userIndicatorController
let parameters = ServerSelectionScreenCoordinatorParameters(authenticationService: authenticationService,
userIndicatorController: userIndicatorController,
@@ -138,7 +137,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
if isModallyPresented {
navigationCoordinator.setRootCoordinator(coordinator)
navigationStackCoordinator.setSheetCoordinator(userIndicatorController)
navigationStackCoordinator.setSheetCoordinator(navigationCoordinator)
} else {
navigationStackCoordinator.push(coordinator)
}
@@ -27,7 +27,7 @@ struct BugReportScreenCoordinatorParameters {
let userID: String
let deviceID: String?
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol?
let screenshot: UIImage?
let isModallyPresented: Bool
}
@@ -19,7 +19,7 @@ import SwiftUI
struct CreateRoomCoordinatorParameters {
let userSession: UserSessionProtocol
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
let createRoomParameters: CurrentValuePublisher<CreateRoomFlowParameters, Never>
let selectedUsers: CurrentValuePublisher<[UserProfileProxy], Never>
}
@@ -23,7 +23,7 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol
private let userSession: UserSessionProtocol
private var createRoomParameters: CreateRoomFlowParameters
private let analytics: AnalyticsService
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private var actionsSubject: PassthroughSubject<CreateRoomViewModelAction, Never> = .init()
@@ -35,7 +35,7 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol
createRoomParameters: CurrentValuePublisher<CreateRoomFlowParameters, Never>,
selectedUsers: CurrentValuePublisher<[UserProfileProxy], Never>,
analytics: AnalyticsService,
userIndicatorController: UserIndicatorControllerProtocol?) {
userIndicatorController: UserIndicatorControllerProtocol) {
let parameters = createRoomParameters.value
self.userSession = userSession
@@ -174,13 +174,13 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol
private static let loadingIndicatorIdentifier = "CreateRoomLoading"
private func showLoadingIndicator() {
userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
}
private func hideLoadingIndicator() {
userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
}
@@ -216,7 +216,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
createRoomParameters: .init(parameters),
selectedUsers: .init(selectedUsers),
analytics: ServiceLocator.shared.analytics,
userIndicatorController: nil)
userIndicatorController: UserIndicatorControllerMock())
}()
static let emtpyViewModel = {
@@ -228,7 +228,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
createRoomParameters: .init(parameters),
selectedUsers: .init([]),
analytics: ServiceLocator.shared.analytics,
userIndicatorController: nil)
userIndicatorController: UserIndicatorControllerMock())
}()
static var previews: some View {
@@ -22,7 +22,7 @@ struct InviteUsersScreenCoordinatorParameters {
let roomType: InviteUsersScreenRoomType
let mediaProvider: MediaProviderProtocol
let userDiscoveryService: UserDiscoveryServiceProtocol
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
}
enum InviteUsersScreenCoordinatorAction {
@@ -25,7 +25,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
private let mediaProvider: MediaProviderProtocol
private let userDiscoveryService: UserDiscoveryServiceProtocol
private let appSettings: AppSettings
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let actionsSubject: PassthroughSubject<InviteUsersScreenViewModelAction, Never> = .init()
@@ -38,7 +38,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
mediaProvider: MediaProviderProtocol,
userDiscoveryService: UserDiscoveryServiceProtocol,
appSettings: AppSettings,
userIndicatorController: UserIndicatorControllerProtocol?) {
userIndicatorController: UserIndicatorControllerProtocol) {
self.roomType = roomType
self.mediaProvider = mediaProvider
self.userDiscoveryService = userDiscoveryService
@@ -169,11 +169,11 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
private let userIndicatorID = UUID().uuidString
private func showLoader() {
userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID, type: .modal, title: L10n.commonLoading, persistent: true), delay: .milliseconds(200))
userIndicatorController.submitIndicator(UserIndicator(id: userIndicatorID, type: .modal, title: L10n.commonLoading, persistent: true), delay: .milliseconds(200))
}
private func hideLoader() {
userIndicatorController?.retractIndicatorWithId(userIndicatorID)
userIndicatorController.retractIndicatorWithId(userIndicatorID)
}
}
@@ -29,10 +29,10 @@ enum CameraPickerError: Error {
}
struct CameraPicker: UIViewControllerRepresentable {
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let callback: (CameraPickerAction) -> Void
init(userIndicatorController: UserIndicatorControllerProtocol?, callback: @escaping (CameraPickerAction) -> Void) {
init(userIndicatorController: UserIndicatorControllerProtocol, callback: @escaping (CameraPickerAction) -> Void) {
self.userIndicatorController = userIndicatorController
self.callback = callback
}
@@ -68,9 +68,9 @@ struct CameraPicker: UIViewControllerRepresentable {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
picker.delegate = nil
cameraPicker.userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading))
cameraPicker.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading))
defer {
cameraPicker.userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
cameraPicker.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
if let videoURL = info[.mediaURL] as? URL {
@@ -27,10 +27,10 @@ enum DocumentPickerError: Error {
}
struct DocumentPicker: UIViewControllerRepresentable {
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let callback: (DocumentPickerAction) -> Void
init(userIndicatorController: UserIndicatorControllerProtocol?, callback: @escaping (DocumentPickerAction) -> Void) {
init(userIndicatorController: UserIndicatorControllerProtocol, callback: @escaping (DocumentPickerAction) -> Void) {
self.userIndicatorController = userIndicatorController
self.callback = callback
}
@@ -72,9 +72,9 @@ struct DocumentPicker: UIViewControllerRepresentable {
picker.delegate = nil
documentPicker.userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading))
documentPicker.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading))
defer {
documentPicker.userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
documentPicker.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
do {
@@ -28,7 +28,7 @@ enum MediaPickerScreenCoordinatorAction {
}
class MediaPickerScreenCoordinator: CoordinatorProtocol {
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let source: MediaPickerScreenSource
private let callback: ((MediaPickerScreenCoordinatorAction) -> Void)?
@@ -92,6 +92,6 @@ class MediaPickerScreenCoordinator: CoordinatorProtocol {
}
private func showError() {
userIndicatorController?.submitIndicator(UserIndicator(title: L10n.screenMediaPickerErrorFailedSelection))
userIndicatorController.submitIndicator(UserIndicator(title: L10n.screenMediaPickerErrorFailedSelection))
}
}
@@ -29,10 +29,10 @@ enum PhotoLibraryPickerError: Error {
}
struct PhotoLibraryPicker: UIViewControllerRepresentable {
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let callback: (PhotoLibraryPickerAction) -> Void
init(userIndicatorController: UserIndicatorControllerProtocol?, callback: @escaping (PhotoLibraryPickerAction) -> Void) {
init(userIndicatorController: UserIndicatorControllerProtocol, callback: @escaping (PhotoLibraryPickerAction) -> Void) {
self.userIndicatorController = userIndicatorController
self.callback = callback
}
@@ -73,9 +73,9 @@ struct PhotoLibraryPicker: UIViewControllerRepresentable {
picker.delegate = nil
photoLibraryPicker.userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading))
photoLibraryPicker.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading))
defer {
photoLibraryPicker.userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
photoLibraryPicker.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
provider.loadFileRepresentation(forTypeIdentifier: contentType.identifier) { [weak self] url, error in
@@ -18,7 +18,7 @@ import Combine
import SwiftUI
struct MediaUploadPreviewScreenCoordinatorParameters {
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
let roomProxy: RoomProxyProtocol
let mediaUploadingPreprocessor: MediaUploadingPreprocessor
let title: String?
@@ -21,7 +21,7 @@ import SwiftUI
typealias MediaUploadPreviewScreenViewModelType = StateStoreViewModel<MediaUploadPreviewScreenViewState, MediaUploadPreviewScreenViewAction>
class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, MediaUploadPreviewScreenViewModelProtocol {
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let roomProxy: RoomProxyProtocol
private let mediaUploadingPreprocessor: MediaUploadingPreprocessor
private let url: URL
@@ -37,7 +37,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
actionsSubject.eraseToAnyPublisher()
}
init(userIndicatorController: UserIndicatorControllerProtocol?,
init(userIndicatorController: UserIndicatorControllerProtocol,
roomProxy: RoomProxyProtocol,
mediaUploadingPreprocessor: MediaUploadingPreprocessor,
title: String?,
@@ -105,7 +105,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
private static let loadingIndicatorIdentifier = "MediaUploadPreviewLoading"
private func startLoading(progressPublisher: CurrentValuePublisher<Double, Never>) {
userIndicatorController?.submitIndicator(
userIndicatorController.submitIndicator(
UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal(progress: .published(progressPublisher), interactiveDismissDisabled: false, allowsInteraction: true),
title: L10n.commonSending,
@@ -114,11 +114,11 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
}
private func stopLoading() {
userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
requestHandle = nil
}
private func showError(label: String) {
userIndicatorController?.submitIndicator(UserIndicator(title: label))
userIndicatorController.submitIndicator(UserIndicator(title: label))
}
}
@@ -21,7 +21,7 @@ struct ReportContentScreenCoordinatorParameters {
let eventID: String
let senderID: String
let roomProxy: RoomProxyProtocol
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
}
enum ReportContentScreenCoordinatorAction {
@@ -81,7 +81,7 @@ final class ReportContentScreenCoordinator: CoordinatorProtocol {
private static let loadingIndicatorIdentifier = "ReportContentLoading"
private func startLoading() {
parameters.userIndicatorController?.submitIndicator(
parameters.userIndicatorController.submitIndicator(
UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: L10n.commonSending,
@@ -90,10 +90,10 @@ final class ReportContentScreenCoordinator: CoordinatorProtocol {
}
private func stopLoading() {
parameters.userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
parameters.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
private func showError(description: String) {
parameters.userIndicatorController?.submitIndicator(UserIndicator(title: description))
parameters.userIndicatorController.submitIndicator(UserIndicator(title: description))
}
}
@@ -22,7 +22,7 @@ struct RoomDetailsEditScreenCoordinatorParameters {
let mediaProvider: MediaProviderProtocol
weak var navigationStackCoordinator: NavigationStackCoordinator?
let roomProxy: RoomProxyProtocol
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
}
enum RoomDetailsEditScreenCoordinatorAction {
@@ -71,9 +71,8 @@ final class RoomDetailsEditScreenCoordinator: CoordinatorProtocol {
private func displayMediaPickerWithSource(_ source: MediaPickerScreenSource) {
let stackCoordinator = NavigationStackCoordinator()
let userIndicatorController = UserIndicatorController(rootCoordinator: stackCoordinator)
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: userIndicatorController, source: source) { [weak self] action in
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: parameters.userIndicatorController, source: source) { [weak self] action in
guard let self else { return }
switch action {
case .cancel:
@@ -85,6 +84,6 @@ final class RoomDetailsEditScreenCoordinator: CoordinatorProtocol {
}
stackCoordinator.setRootCoordinator(mediaPickerCoordinator)
parameters.navigationStackCoordinator?.setSheetCoordinator(userIndicatorController)
parameters.navigationStackCoordinator?.setSheetCoordinator(stackCoordinator)
}
}
@@ -22,7 +22,7 @@ typealias RoomDetailsEditScreenViewModelType = StateStoreViewModel<RoomDetailsEd
class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDetailsEditScreenViewModelProtocol {
private let actionsSubject: PassthroughSubject<RoomDetailsEditScreenViewModelAction, Never> = .init()
private let roomProxy: RoomProxyProtocol
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let mediaPreprocessor: MediaUploadingPreprocessor = .init()
var actions: AnyPublisher<RoomDetailsEditScreenViewModelAction, Never> {
@@ -32,7 +32,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
init(accountOwner: RoomMemberProxyProtocol,
mediaProvider: MediaProviderProtocol,
roomProxy: RoomProxyProtocol,
userIndicatorController: UserIndicatorControllerProtocol?) {
userIndicatorController: UserIndicatorControllerProtocol) {
self.roomProxy = roomProxy
self.userIndicatorController = userIndicatorController
@@ -75,12 +75,12 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
Task {
let userIndicatorID = UUID().uuidString
defer {
userIndicatorController?.retractIndicatorWithId(userIndicatorID)
userIndicatorController.retractIndicatorWithId(userIndicatorID)
}
userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
userIndicatorController.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
let mediaResult = await mediaPreprocessor.processMedia(at: url)
@@ -88,7 +88,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
case .success(.image):
state.localMedia = try? mediaResult.get()
case .failure, .success:
userIndicatorController?.alertInfo = .init(id: .init())
userIndicatorController.alertInfo = .init(id: .init())
}
}
}
@@ -99,12 +99,12 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
Task {
let userIndicatorID = UUID().uuidString
defer {
userIndicatorController?.retractIndicatorWithId(userIndicatorID)
userIndicatorController.retractIndicatorWithId(userIndicatorID)
}
userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.screenRoomDetailsUpdatingRoom,
persistent: true))
userIndicatorController.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.screenRoomDetailsUpdatingRoom,
persistent: true))
do {
try await withThrowingTaskGroup(of: Void.self) { group in
@@ -135,9 +135,9 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
actionsSubject.send(.saveFinished)
} catch {
userIndicatorController?.alertInfo = .init(id: .init(),
title: L10n.screenRoomDetailsEditionErrorTitle,
message: L10n.screenRoomDetailsEditionError)
userIndicatorController.alertInfo = .init(id: .init(),
title: L10n.screenRoomDetailsEditionErrorTitle,
message: L10n.screenRoomDetailsEditionError)
}
}
}
@@ -112,11 +112,11 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
private func presentInviteUsersScreen() {
let inviteUsersStackCoordinator = NavigationStackCoordinator()
let userIndicatorController = UserIndicatorController(rootCoordinator: inviteUsersStackCoordinator)
let inviteParameters = InviteUsersScreenCoordinatorParameters(selectedUsers: .init(selectedUsers),
roomType: .room(roomProxy: parameters.roomProxy),
mediaProvider: parameters.mediaProvider,
userDiscoveryService: parameters.userDiscoveryService, userIndicatorController: userIndicatorController)
userDiscoveryService: parameters.userDiscoveryService,
userIndicatorController: parameters.userIndicatorController)
let coordinator = InviteUsersScreenCoordinator(parameters: inviteParameters)
inviteUsersStackCoordinator.setRootCoordinator(coordinator)
@@ -137,20 +137,19 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
navigationStackCoordinator?.setSheetCoordinator(userIndicatorController) { [weak self] in
navigationStackCoordinator?.setSheetCoordinator(inviteUsersStackCoordinator) { [weak self] in
self?.selectedUsers.value = []
}
}
private func presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol) {
let navigationStackCoordinator = NavigationStackCoordinator()
let userIndicatorController = UserIndicatorController(rootCoordinator: navigationStackCoordinator)
let roomDetailsEditParameters = RoomDetailsEditScreenCoordinatorParameters(accountOwner: accountOwner,
mediaProvider: parameters.mediaProvider,
navigationStackCoordinator: navigationStackCoordinator,
roomProxy: parameters.roomProxy,
userIndicatorController: userIndicatorController)
userIndicatorController: parameters.userIndicatorController)
let roomDetailsEditCoordinator = RoomDetailsEditScreenCoordinator(parameters: roomDetailsEditParameters)
roomDetailsEditCoordinator.actions.sink { [weak self] action in
@@ -163,7 +162,7 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
navigationStackCoordinator.setRootCoordinator(roomDetailsEditCoordinator)
self.navigationStackCoordinator?.setSheetCoordinator(userIndicatorController)
self.navigationStackCoordinator?.setSheetCoordinator(navigationStackCoordinator)
}
private func toggleUser(_ user: UserProfileProxy) {
@@ -19,7 +19,7 @@ import SwiftUI
struct SecureBackupKeyBackupScreenCoordinatorParameters {
let secureBackupController: SecureBackupControllerProtocol
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
}
enum SecureBackupKeyBackupScreenCoordinatorAction {
@@ -19,7 +19,7 @@ import SwiftUI
struct SecureBackupRecoveryKeyScreenCoordinatorParameters {
let secureBackupController: SecureBackupControllerProtocol
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
}
enum SecureBackupRecoveryKeyScreenCoordinatorAction {
@@ -21,14 +21,14 @@ typealias SecureBackupRecoveryKeyScreenViewModelType = StateStoreViewModel<Secur
class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewModelType, SecureBackupRecoveryKeyScreenViewModelProtocol {
private let secureBackupController: SecureBackupControllerProtocol
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private var actionsSubject: PassthroughSubject<SecureBackupRecoveryKeyScreenViewModelAction, Never> = .init()
var actions: AnyPublisher<SecureBackupRecoveryKeyScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(secureBackupController: SecureBackupControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol?) {
init(secureBackupController: SecureBackupControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol) {
self.secureBackupController = secureBackupController
self.userIndicatorController = userIndicatorController
@@ -66,7 +66,7 @@ class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewM
}
case .copyKey:
UIPasteboard.general.string = state.recoveryKey
userIndicatorController?.submitIndicator(.init(title: "Copied recovery key"))
userIndicatorController.submitIndicator(.init(title: "Copied recovery key"))
state.doneButtonEnabled = true
case .keySaved:
state.doneButtonEnabled = true
@@ -228,6 +228,6 @@ struct SecureBackupRecoveryKeyScreen_Previews: PreviewProvider, TestablePreview
let backupController = SecureBackupControllerMock()
backupController.underlyingRecoveryKeyState = CurrentValueSubject<SecureBackupRecoveryKeyState, Never>(recoveryKeyState).asCurrentValuePublisher()
return SecureBackupRecoveryKeyScreenViewModel(secureBackupController: backupController, userIndicatorController: nil)
return SecureBackupRecoveryKeyScreenViewModel(secureBackupController: backupController, userIndicatorController: UserIndicatorControllerMock())
}
}
@@ -21,7 +21,7 @@ struct SecureBackupScreenCoordinatorParameters {
let appSettings: AppSettings
let secureBackupController: SecureBackupControllerProtocol
weak var navigationStackCoordinator: NavigationStackCoordinator?
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
}
enum SecureBackupScreenCoordinatorAction { }
@@ -51,10 +51,9 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
switch action {
case .recoveryKey:
let navigationStackCoordinator = NavigationStackCoordinator()
let userIndicatorController = UserIndicatorController(rootCoordinator: navigationStackCoordinator)
let recoveryKeyCoordinator = SecureBackupRecoveryKeyScreenCoordinator(parameters: .init(secureBackupController: parameters.secureBackupController,
userIndicatorController: userIndicatorController))
userIndicatorController: parameters.userIndicatorController))
recoveryKeyCoordinator.actions.sink { [weak self] action in
guard let self else { return }
@@ -76,13 +75,12 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
navigationStackCoordinator.setRootCoordinator(recoveryKeyCoordinator, animated: true)
parameters.navigationStackCoordinator?.setSheetCoordinator(userIndicatorController)
parameters.navigationStackCoordinator?.setSheetCoordinator(navigationStackCoordinator)
case .keyBackup:
let navigationStackCoordinator = NavigationStackCoordinator()
let userIndicatorController = UserIndicatorController(rootCoordinator: navigationStackCoordinator)
let keyBackupCoordinator = SecureBackupKeyBackupScreenCoordinator(parameters: .init(secureBackupController: parameters.secureBackupController,
userIndicatorController: userIndicatorController))
userIndicatorController: parameters.userIndicatorController))
keyBackupCoordinator.actions.sink { [weak self] action in
switch action {
@@ -94,7 +92,7 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
navigationStackCoordinator.setRootCoordinator(keyBackupCoordinator, animated: true)
parameters.navigationStackCoordinator?.setSheetCoordinator(userIndicatorController)
parameters.navigationStackCoordinator?.setSheetCoordinator(navigationStackCoordinator)
}
}
.store(in: &cancellables)
@@ -107,10 +105,10 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
// MARK: - Private
private func showSuccessIndicator(title: String) {
parameters.userIndicatorController?.submitIndicator(.init(id: .init(),
type: .modal(progress: .none, interactiveDismissDisabled: false, allowsInteraction: false),
title: title,
iconName: "checkmark",
persistent: false))
parameters.userIndicatorController.submitIndicator(.init(id: .init(),
type: .modal(progress: .none, interactiveDismissDisabled: false, allowsInteraction: false),
title: title,
iconName: "checkmark",
persistent: false))
}
}
@@ -21,7 +21,7 @@ typealias SecureBackupScreenViewModelType = StateStoreViewModel<SecureBackupScre
class SecureBackupScreenViewModel: SecureBackupScreenViewModelType, SecureBackupScreenViewModelProtocol {
private let secureBackupController: SecureBackupControllerProtocol
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private var actionsSubject: PassthroughSubject<SecureBackupScreenViewModelAction, Never> = .init()
var actions: AnyPublisher<SecureBackupScreenViewModelAction, Never> {
@@ -29,7 +29,7 @@ class SecureBackupScreenViewModel: SecureBackupScreenViewModelType, SecureBackup
}
init(secureBackupController: SecureBackupControllerProtocol,
userIndicatorController: UserIndicatorControllerProtocol?,
userIndicatorController: UserIndicatorControllerProtocol,
chatBackupDetailsURL: URL) {
self.secureBackupController = secureBackupController
self.userIndicatorController = userIndicatorController
@@ -70,7 +70,7 @@ class SecureBackupScreenViewModel: SecureBackupScreenViewModelType, SecureBackup
private func enableBackup() {
Task {
let loadingIndicatorIdentifier = "SecureBackupScreenLoading"
userIndicatorController?.submitIndicator(.init(id: loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading, persistent: true))
userIndicatorController.submitIndicator(.init(id: loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading, persistent: true))
switch await secureBackupController.enable() {
case .success:
break
@@ -79,7 +79,7 @@ class SecureBackupScreenViewModel: SecureBackupScreenViewModelType, SecureBackup
state.bindings.alertInfo = .init(id: .init())
}
userIndicatorController?.retractIndicatorWithId(loadingIndicatorIdentifier)
userIndicatorController.retractIndicatorWithId(loadingIndicatorIdentifier)
}
}
}
@@ -160,7 +160,7 @@ struct SecureBackupScreen_Previews: PreviewProvider, TestablePreview {
backupController.underlyingRecoveryKeyState = CurrentValueSubject<SecureBackupRecoveryKeyState, Never>(recoveryKeyState).asCurrentValuePublisher()
return SecureBackupScreenViewModel(secureBackupController: backupController,
userIndicatorController: nil,
userIndicatorController: UserIndicatorControllerMock(),
chatBackupDetailsURL: .sharedPublicDirectory)
}
}
@@ -19,7 +19,7 @@ import SwiftUI
struct SettingsScreenCoordinatorParameters {
weak var navigationStackCoordinator: NavigationStackCoordinator?
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
let userSession: UserSessionProtocol
let appLockService: AppLockServiceProtocol
let bugReportService: BugReportServiceProtocol
@@ -258,6 +258,6 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
}
private func showSuccess(label: String) {
parameters.userIndicatorController?.submitIndicator(UserIndicator(title: label))
parameters.userIndicatorController.submitIndicator(UserIndicator(title: label))
}
}
@@ -21,7 +21,7 @@ struct UserDetailsEditScreenCoordinatorParameters {
let clientProxy: ClientProxyProtocol
let mediaProvider: MediaProviderProtocol
weak var navigationStackCoordinator: NavigationStackCoordinator?
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
}
enum UserDetailsEditScreenCoordinatorAction { }
@@ -67,9 +67,8 @@ final class UserDetailsEditScreenCoordinator: CoordinatorProtocol {
private func displayMediaPickerWithSource(_ source: MediaPickerScreenSource) {
let stackCoordinator = NavigationStackCoordinator()
let userIndicatorController = UserIndicatorController(rootCoordinator: stackCoordinator)
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: userIndicatorController, source: source) { [weak self] action in
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: parameters.userIndicatorController, source: source) { [weak self] action in
guard let self else { return }
switch action {
case .cancel:
@@ -81,6 +80,6 @@ final class UserDetailsEditScreenCoordinator: CoordinatorProtocol {
}
stackCoordinator.setRootCoordinator(mediaPickerCoordinator)
parameters.navigationStackCoordinator?.setSheetCoordinator(userIndicatorController)
parameters.navigationStackCoordinator?.setSheetCoordinator(stackCoordinator)
}
}
@@ -22,7 +22,7 @@ typealias UserDetailsEditScreenViewModelType = StateStoreViewModel<UserDetailsEd
class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDetailsEditScreenViewModelProtocol {
private let actionsSubject: PassthroughSubject<UserDetailsEditScreenViewModelAction, Never> = .init()
private let clientProxy: ClientProxyProtocol
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let mediaPreprocessor: MediaUploadingPreprocessor = .init()
var actions: AnyPublisher<UserDetailsEditScreenViewModelAction, Never> {
@@ -31,7 +31,7 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
init(clientProxy: ClientProxyProtocol,
mediaProvider: MediaProviderProtocol,
userIndicatorController: UserIndicatorControllerProtocol?) {
userIndicatorController: UserIndicatorControllerProtocol) {
self.clientProxy = clientProxy
self.userIndicatorController = userIndicatorController
@@ -90,12 +90,12 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
Task {
let userIndicatorID = UUID().uuidString
defer {
userIndicatorController?.retractIndicatorWithId(userIndicatorID)
userIndicatorController.retractIndicatorWithId(userIndicatorID)
}
userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
userIndicatorController.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
let mediaResult = await mediaPreprocessor.processMedia(at: url)
@@ -103,7 +103,7 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
case .success(.image):
state.localMedia = try? mediaResult.get()
case .failure, .success:
userIndicatorController?.alertInfo = .init(id: .init(), title: L10n.commonError, message: L10n.errorUnknown)
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError, message: L10n.errorUnknown)
}
}
}
@@ -114,12 +114,12 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
Task {
let userIndicatorID = UUID().uuidString
defer {
userIndicatorController?.retractIndicatorWithId(userIndicatorID)
userIndicatorController.retractIndicatorWithId(userIndicatorID)
}
userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.screenEditProfileUpdatingDetails,
persistent: true))
userIndicatorController.submitIndicator(UserIndicator(id: userIndicatorID,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.screenEditProfileUpdatingDetails,
persistent: true))
do {
try await withThrowingTaskGroup(of: Void.self) { group in
@@ -142,9 +142,9 @@ class UserDetailsEditScreenViewModel: UserDetailsEditScreenViewModelType, UserDe
try await group.waitForAll()
}
} catch {
userIndicatorController?.alertInfo = .init(id: .init(),
title: L10n.screenEditProfileErrorTitle,
message: L10n.screenEditProfileError)
userIndicatorController.alertInfo = .init(id: .init(),
title: L10n.screenEditProfileErrorTitle,
message: L10n.screenEditProfileError)
}
}
}
@@ -19,7 +19,7 @@ import SwiftUI
struct StartChatScreenCoordinatorParameters {
let userSession: UserSessionProtocol
weak var userIndicatorController: UserIndicatorControllerProtocol?
let userIndicatorController: UserIndicatorControllerProtocol
weak var navigationStackCoordinator: NavigationStackCoordinator?
let userDiscoveryService: UserDiscoveryServiceProtocol
}
@@ -44,15 +44,7 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
private var selectedUsersPublisher: CurrentValuePublisher<[UserProfileProxy], Never> {
selectedUsers.asCurrentValuePublisher()
}
private var navigationStackCoordinator: NavigationStackCoordinator? {
parameters.navigationStackCoordinator
}
private var userIndicatorController: UserIndicatorControllerProtocol? {
parameters.userIndicatorController
}
var actions: AnyPublisher<StartChatScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
@@ -95,7 +87,8 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
let inviteParameters = InviteUsersScreenCoordinatorParameters(selectedUsers: selectedUsersPublisher,
roomType: .draft,
mediaProvider: parameters.userSession.mediaProvider,
userDiscoveryService: parameters.userDiscoveryService)
userDiscoveryService: parameters.userDiscoveryService,
userIndicatorController: parameters.userIndicatorController)
let coordinator = InviteUsersScreenCoordinator(parameters: inviteParameters)
coordinator.actions.sink { [weak self] action in
guard let self else { return }
@@ -113,7 +106,7 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
navigationStackCoordinator?.push(coordinator) { [weak self] in
parameters.navigationStackCoordinator?.push(coordinator) { [weak self] in
self?.createRoomParameters.send(.init())
self?.selectedUsers.send([])
}
@@ -121,7 +114,7 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
private func openCreateRoomScreen() {
let createParameters = CreateRoomCoordinatorParameters(userSession: parameters.userSession,
userIndicatorController: userIndicatorController,
userIndicatorController: parameters.userIndicatorController,
createRoomParameters: createRoomParametersPublisher,
selectedUsers: selectedUsersPublisher)
let coordinator = CreateRoomCoordinator(parameters: createParameters)
@@ -144,7 +137,7 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
}
.store(in: &cancellables)
navigationStackCoordinator?.push(coordinator)
parameters.navigationStackCoordinator?.push(coordinator)
}
// MARK: - Private
@@ -152,13 +145,12 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
let mediaUploadingPreprocessor = MediaUploadingPreprocessor()
private func displayMediaPickerWithSource(_ source: MediaPickerScreenSource) {
let stackCoordinator = NavigationStackCoordinator()
let userIndicatorController = UserIndicatorController(rootCoordinator: stackCoordinator)
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: userIndicatorController, source: source) { [weak self] action in
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: parameters.userIndicatorController, source: source) { [weak self] action in
guard let self else { return }
switch action {
case .cancel:
navigationStackCoordinator?.setSheetCoordinator(nil)
parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
case .selectMediaAtURL(let url):
processAvatar(from: url)
}
@@ -166,11 +158,11 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
stackCoordinator.setRootCoordinator(mediaPickerCoordinator)
navigationStackCoordinator?.setSheetCoordinator(userIndicatorController)
parameters.navigationStackCoordinator?.setSheetCoordinator(stackCoordinator)
}
private func processAvatar(from url: URL) {
navigationStackCoordinator?.setSheetCoordinator(nil)
parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
showLoadingIndicator()
Task { [weak self] in
guard let self else { return }
@@ -180,7 +172,7 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
parameters.avatarImageMedia = media
createRoomParameters.send(parameters)
} catch {
userIndicatorController?.alertInfo = AlertInfo(id: .init(), title: L10n.commonError, message: L10n.errorUnknown)
parameters.userIndicatorController.alertInfo = AlertInfo(id: .init(), title: L10n.commonError, message: L10n.errorUnknown)
}
hideLoadingIndicator()
}
@@ -201,13 +193,13 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
private static let loadingIndicatorIdentifier = "StartChatCoordinatorLoading"
private func showLoadingIndicator() {
userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: L10n.commonLoading,
persistent: true))
parameters.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: L10n.commonLoading,
persistent: true))
}
private func hideLoadingIndicator() {
userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
parameters.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
}
@@ -23,7 +23,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
private let userSession: UserSessionProtocol
private let appSettings: AppSettings
private let analytics: AnalyticsService
private weak var userIndicatorController: UserIndicatorControllerProtocol?
private let userIndicatorController: UserIndicatorControllerProtocol
private let userDiscoveryService: UserDiscoveryServiceProtocol
private let actionsSubject: PassthroughSubject<StartChatScreenViewModelAction, Never> = .init()
@@ -35,7 +35,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
init(userSession: UserSessionProtocol,
appSettings: AppSettings,
analytics: AnalyticsService,
userIndicatorController: UserIndicatorControllerProtocol?,
userIndicatorController: UserIndicatorControllerProtocol,
userDiscoveryService: UserDiscoveryServiceProtocol) {
self.userSession = userSession
self.appSettings = appSettings
@@ -162,13 +162,13 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
private static let loadingIndicatorIdentifier = "StartChatLoading"
private func showLoadingIndicator() {
userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false),
title: L10n.commonLoading,
persistent: true))
}
private func hideLoadingIndicator() {
userIndicatorController?.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
}
@@ -145,7 +145,7 @@ struct StartChatScreen_Previews: PreviewProvider, TestablePreview {
let viewModel = StartChatScreenViewModel(userSession: userSession,
appSettings: ServiceLocator.shared.settings,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: nil,
userIndicatorController: UserIndicatorControllerMock(),
userDiscoveryService: userDiscoveryService)
return viewModel
}()