From 7ad302e5e7e6958e7e4417f4d1a84e5165e0a8c0 Mon Sep 17 00:00:00 2001 From: Flavio Alescio Date: Wed, 3 May 2023 16:26:35 +0200 Subject: [PATCH] persisting create room parameter in volatile memory --- .../CreateRoom/CreateRoomCoordinator.swift | 9 +++---- .../Screens/CreateRoom/CreateRoomModels.swift | 9 +++---- .../CreateRoom/CreateRoomViewModel.swift | 24 ++++++++++++++++--- .../InviteUsersScreenCoordinator.swift | 18 +++++++++++--- .../StartChatScreenCoordinator.swift | 16 ++++++++++++- .../UITests/UITestsAppCoordinator.swift | 6 +++-- 6 files changed, 65 insertions(+), 17 deletions(-) diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift index bddbea6ca..409161973 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomCoordinator.swift @@ -19,11 +19,12 @@ import SwiftUI struct CreateRoomCoordinatorParameters { let userSession: UserSessionProtocol - let selectedUsers: [UserProfile] + let createRoomParameters: CreateRoomVolatileParameters } enum CreateRoomCoordinatorAction { case createRoom + case deselectUser(UserProfile) } final class CreateRoomCoordinator: CoordinatorProtocol { @@ -38,15 +39,15 @@ final class CreateRoomCoordinator: CoordinatorProtocol { init(parameters: CreateRoomCoordinatorParameters) { self.parameters = parameters - // TODO: Check if any stored data are present and restore them - viewModel = CreateRoomViewModel(userSession: parameters.userSession, selectedUsers: parameters.selectedUsers) + viewModel = CreateRoomViewModel(userSession: parameters.userSession, createRoomParameters: parameters.createRoomParameters) } func start() { viewModel.actions.sink { [weak self] action in guard let self else { return } switch action { - // TODO: Store data for previous screen + case .deselectUser(let user): + self.actionsSubject.send(.deselectUser(user)) case .createRoom: self.actionsSubject.send(.createRoom) } diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift index f3ad3d826..563dcc665 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift @@ -18,11 +18,12 @@ import Foundation enum CreateRoomViewModelAction { case createRoom + case deselectUser(UserProfile) } struct CreateRoomViewState: BindableState { var selectedUsers: [UserProfile] - var bindings = CreateRoomViewStateBindings() + var bindings: CreateRoomViewStateBindings var canCreateRoom: Bool { !bindings.roomName.isEmpty @@ -30,9 +31,9 @@ struct CreateRoomViewState: BindableState { } struct CreateRoomViewStateBindings { - var roomName = "" - var roomTopic = "" - var isRoomPrivate = true + var roomName: String + var roomTopic: String + var isRoomPrivate: Bool } enum CreateRoomViewAction { diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift index 4ef43ed1b..7e462e760 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift @@ -21,13 +21,17 @@ typealias CreateRoomViewModelType = StateStoreViewModel = .init() - + private let createRoomParameters: CreateRoomVolatileParameters var actions: AnyPublisher { actionsSubject.eraseToAnyPublisher() } - init(userSession: UserSessionProtocol, selectedUsers: [UserProfile]) { - super.init(initialViewState: CreateRoomViewState(selectedUsers: selectedUsers), imageProvider: userSession.mediaProvider) + init(userSession: UserSessionProtocol, createRoomParameters: CreateRoomVolatileParameters) { + let bindings = CreateRoomViewStateBindings(roomName: createRoomParameters.name, roomTopic: createRoomParameters.topic, isRoomPrivate: createRoomParameters.isRoomPrivate) + self.createRoomParameters = createRoomParameters + super.init(initialViewState: CreateRoomViewState(selectedUsers: createRoomParameters.selectedUsers, bindings: bindings), imageProvider: userSession.mediaProvider) + + setupBindings() } // MARK: - Public @@ -38,10 +42,24 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol actionsSubject.send(.createRoom) case .deselectUser(let user): state.selectedUsers.removeAll(where: { $0.userID == user.userID }) + actionsSubject.send(.deselectUser(user)) case .selectPrivateRoom: state.bindings.isRoomPrivate = true case .selectPublicRoom: state.bindings.isRoomPrivate = false } } + + // MARK: - Private + + private func setupBindings() { + context.$viewState + .map(\.bindings) + .sink { [weak self] bindings in + self?.createRoomParameters.name = bindings.roomName + self?.createRoomParameters.topic = bindings.roomTopic + self?.createRoomParameters.isRoomPrivate = bindings.isRoomPrivate + } + .store(in: &cancellables) + } } diff --git a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift index 6a8bc8fe1..fd42481e7 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenCoordinator.swift @@ -21,6 +21,7 @@ struct InviteUsersScreenCoordinatorParameters { let navigationStackCoordinator: NavigationStackCoordinator? let userSession: UserSessionProtocol let userDiscoveryService: UserDiscoveryServiceProtocol + let createRoomParameters: CreateRoomVolatileParameters? } enum InviteUsersScreenCoordinatorAction { @@ -62,8 +63,19 @@ final class InviteUsersScreenCoordinator: CoordinatorProtocol { } private func openCreateRoomScreenWith(_ users: [UserProfile]) { - let paramenters = CreateRoomCoordinatorParameters(userSession: parameters.userSession, selectedUsers: users) - let createRoomCoordinator = CreateRoomCoordinator(parameters: paramenters) - parameters.navigationStackCoordinator?.push(createRoomCoordinator) + guard let createRoomParameters = parameters.createRoomParameters else { return } + createRoomParameters.selectedUsers = users + let paramenters = CreateRoomCoordinatorParameters(userSession: parameters.userSession, createRoomParameters: createRoomParameters) + let coordinator = CreateRoomCoordinator(parameters: paramenters) + coordinator.actions.sink { [weak self] result in + switch result { + case .deselectUser(let user): + self?.viewModel.context.send(viewAction: .deselectUser(user)) + default: + break + } + } + .store(in: &cancellables) + parameters.navigationStackCoordinator?.push(coordinator) } } diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift index daedda732..870a5416a 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenCoordinator.swift @@ -35,6 +35,9 @@ final class StartChatScreenCoordinator: CoordinatorProtocol { private let actionsSubject: PassthroughSubject = .init() private var cancellables: Set = .init() + // this is needed to persist some data in this flow and then destroy them when the flow is eneded + private var createRoomParameters = CreateRoomVolatileParameters() + var actions: AnyPublisher { actionsSubject.eraseToAnyPublisher() } @@ -70,7 +73,11 @@ final class StartChatScreenCoordinator: CoordinatorProtocol { // MARK: - Private private func presentInviteUsersScreen() { - let inviteParameters = InviteUsersScreenCoordinatorParameters(navigationStackCoordinator: parameters.navigationStackCoordinator, userSession: parameters.userSession, userDiscoveryService: parameters.userDiscoveryService) + createRoomParameters = .init() + let inviteParameters = InviteUsersScreenCoordinatorParameters(navigationStackCoordinator: parameters.navigationStackCoordinator, + userSession: parameters.userSession, + userDiscoveryService: parameters.userDiscoveryService, + createRoomParameters: createRoomParameters) let coordinator = InviteUsersScreenCoordinator(parameters: inviteParameters) coordinator.actions.sink { [weak self] result in switch result { @@ -82,3 +89,10 @@ final class StartChatScreenCoordinator: CoordinatorProtocol { parameters.navigationStackCoordinator?.push(coordinator) } } + +class CreateRoomVolatileParameters { + var name = "" + var topic = "" + var selectedUsers: [UserProfile] = [] + var isRoomPrivate = true +} diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index fb2e02110..bea394e90 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -409,14 +409,16 @@ class MockScreen: Identifiable { userDiscoveryMock.fetchSuggestionsReturnValue = .success([.mockAlice, .mockBob, .mockCharlie]) userDiscoveryMock.searchProfilesWithReturnValue = .success([]) let userSession = MockUserSession(clientProxy: MockClientProxy(userID: "@mock:client.com"), mediaProvider: MockMediaProvider()) - let coordinator = InviteUsersScreenCoordinator(parameters: .init(navigationStackCoordinator: navigationStackCoordinator, userSession: userSession, userDiscoveryService: userDiscoveryMock)) + let coordinator = InviteUsersScreenCoordinator(parameters: .init(navigationStackCoordinator: navigationStackCoordinator, userSession: userSession, userDiscoveryService: userDiscoveryMock, createRoomParameters: nil)) navigationStackCoordinator.setRootCoordinator(coordinator) return navigationStackCoordinator case .createRoom: let navigationStackCoordinator = NavigationStackCoordinator() let clientProxy = MockClientProxy(userID: "@mock:client.com") let mockUserSession = MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider()) - let parameters = CreateRoomCoordinatorParameters(userSession: mockUserSession, selectedUsers: [.mockAlice, .mockBob, .mockCharlie]) + let createRoomParameters = CreateRoomVolatileParameters() + createRoomParameters.selectedUsers = [.mockAlice, .mockBob, .mockCharlie] + let parameters = CreateRoomCoordinatorParameters(userSession: mockUserSession, createRoomParameters: createRoomParameters) let coordinator = CreateRoomCoordinator(parameters: parameters) navigationStackCoordinator.setRootCoordinator(coordinator) return navigationStackCoordinator