diff --git a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift index dfe588d33..d4a8fd1f0 100644 --- a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift +++ b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift @@ -188,8 +188,8 @@ class SpaceDetailViewController: UIViewController { switch viewState { case .loading: self.renderLoading() - case .loaded(let space, let joinRule, let inviterId, let inviter, let membersCount): - self.renderLoaded(space: space, joinRule: joinRule, inviterId: inviterId, inviter: inviter, membersCount: membersCount) + case .loaded(let parameters): + self.renderLoaded(parameters: parameters) case .error(let error): self.render(error: error) } @@ -199,10 +199,10 @@ class SpaceDetailViewController: UIViewController { self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) } - private func renderLoaded(space: MXSpace, joinRule: MXRoomJoinRule?, inviterId: String?, inviter: MXUser?, membersCount: UInt) { + private func renderLoaded(parameters: SpaceDetailLoadedParameters) { self.activityPresenter.removeCurrentActivityIndicator(animated: true) - guard let summary = space.summary else { + guard let summary = parameters.space.summary else { MXLog.error("[SpaceDetailViewController] setupViews: no summary found") return } @@ -220,17 +220,17 @@ class SpaceDetailViewController: UIViewController { self.avatarView.fill(with: avatarViewData) self.topicLabel.text = summary.topic - let joinRuleString = joinRule == .public ? VectorL10n.spacePublicJoinRule : VectorL10n.spacePrivateJoinRule + let joinRuleString = parameters.joinRule == .public ? VectorL10n.spacePublicJoinRule : VectorL10n.spacePrivateJoinRule let membersCount = summary.membersCount.members let membersString = membersCount == 1 ? VectorL10n.roomTitleOneMember : VectorL10n.roomTitleMembers("\(membersCount)") self.spaceTypeLabel.text = "\(joinRuleString) ยท \(membersString)" - self.inviterIdLabel.text = inviterId - if let inviterId = inviterId { - self.inviterTitleLabel.text = "\(inviter?.displayname ?? inviterId) invited you" + self.inviterIdLabel.text = parameters.inviterId + if let inviterId = parameters.inviterId { + self.inviterTitleLabel.text = "\(parameters.inviter?.displayname ?? inviterId) invited you" - if let inviter = inviter { + if let inviter = parameters.inviter { let avatarViewData = AvatarViewData(avatarUrl: inviter.avatarUrl, mediaManager: self.mediaManager, fallbackImage: .matrixItem(inviter.userId, inviter.displayname)) self.inviterAvatarView.fill(with: avatarViewData) } diff --git a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift index 488921e48..193e59952 100644 --- a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift +++ b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift @@ -63,7 +63,7 @@ class SpaceDetailViewModel: SpaceDetailViewModelType { return } - self.update(viewState: .loaded(space, nil, nil, nil, 0)) + self.update(viewState: .loaded(SpaceDetailLoadedParameters(space: space, joinRule: nil, inviterId: nil, inviter: nil, membersCount: 0))) self.update(viewState: .loading) space.room.state { state in @@ -82,7 +82,7 @@ class SpaceDetailViewModel: SpaceDetailViewModelType { } }) - self.update(viewState: .loaded(space, joinRule, inviterId, inviter, membersCount)) + self.update(viewState: .loaded(SpaceDetailLoadedParameters(space: space, joinRule: joinRule, inviterId: inviterId, inviter: inviter, membersCount: membersCount))) } } diff --git a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewState.swift b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewState.swift index c448b4c9d..0bdcd3c9a 100644 --- a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewState.swift +++ b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewState.swift @@ -16,9 +16,17 @@ import Foundation +struct SpaceDetailLoadedParameters { + let space: MXSpace + let joinRule: MXRoomJoinRule? + let inviterId: String? + let inviter: MXUser? + let membersCount: UInt +} + /// SpaceDetailViewController view state enum SpaceDetailViewState { case loading - case loaded(_ space: MXSpace, _ joinRule: MXRoomJoinRule?, _ inviterId: String?, _ inviter: MXUser?, _ membersCount: UInt) + case loaded(_ paremeters: SpaceDetailLoadedParameters) case error(Error) } diff --git a/Riot/Modules/Spaces/SpaceList/SpaceListViewController.swift b/Riot/Modules/Spaces/SpaceList/SpaceListViewController.swift index 5d7701057..79f5f2dba 100644 --- a/Riot/Modules/Spaces/SpaceList/SpaceListViewController.swift +++ b/Riot/Modules/Spaces/SpaceList/SpaceListViewController.swift @@ -41,8 +41,6 @@ final class SpaceListViewController: UIViewController { private var activityPresenter: ActivityIndicatorPresenter! private var sections: [SpaceListSection] = [] - private var homeIndexPath: IndexPath = IndexPath(row: 0, section: 0) - private var selectedIndexPath: IndexPath = IndexPath(row: 0, section: 0) // MARK: - Setup @@ -104,7 +102,6 @@ final class SpaceListViewController: UIViewController { } private func setupTableView() { - self.selectedIndexPath = self.homeIndexPath self.tableView.separatorStyle = .none self.tableView.rowHeight = UITableView.automaticDimension self.tableView.estimatedRowHeight = Constants.estimatedRowHeight @@ -117,8 +114,10 @@ final class SpaceListViewController: UIViewController { switch viewState { case .loading: self.renderLoading() - case .loaded(let sections, let homeIndexPath): - self.renderLoaded(sections: sections, homeIndexPath: homeIndexPath) + case .loaded(let sections): + self.renderLoaded(sections: sections) + case .selectionChanged(let indexPath): + self.renderSelectionChanged(at: indexPath) case .error(let error): self.render(error: error) } @@ -131,16 +130,14 @@ final class SpaceListViewController: UIViewController { } } - private func renderLoaded(sections: [SpaceListSection], homeIndexPath: IndexPath) { - let isHomeSelected = self.selectedIndexPath.section == self.homeIndexPath.section + private func renderLoaded(sections: [SpaceListSection]) { self.activityPresenter.removeCurrentActivityIndicator(animated: true) self.sections = sections self.tableView.reloadData() - self.homeIndexPath = homeIndexPath - if isHomeSelected { - self.selectedIndexPath = self.homeIndexPath - } - self.tableView.selectRow(at: selectedIndexPath, animated: true, scrollPosition: .none) + } + + private func renderSelectionChanged(at indexPath: IndexPath) { + self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none) } private func render(error: Error) { @@ -155,15 +152,6 @@ extension SpaceListViewController: SpaceListViewModelViewDelegate { func spaceListViewModel(_ viewModel: SpaceListViewModelType, didUpdateViewState viewSate: SpaceListViewState) { self.render(viewState: viewSate) } - - func spaceListViewModel(_ viewModel: SpaceListViewModelType, didSelectSpaceAt indexPath: IndexPath) { - self.selectedIndexPath = IndexPath(row: indexPath.row, section: indexPath.section) - self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none) - } - - func spaceListViewModelRevertSelection(_ viewModel: SpaceListViewModelType) { - self.tableView.selectRow(at: self.selectedIndexPath, animated: true, scrollPosition: .none) - } } // MARK: - UITableViewDataSource @@ -216,9 +204,7 @@ extension SpaceListViewController: UITableViewDataSource { extension SpaceListViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if selectedIndexPath != indexPath { - self.viewModel.process(viewAction: .selectRow(at: indexPath, from: tableView.cellForRow(at: indexPath))) - } + self.viewModel.process(viewAction: .selectRow(at: indexPath, from: tableView.cellForRow(at: indexPath))) } } diff --git a/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift b/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift index 596bed395..6302be959 100644 --- a/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift +++ b/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift @@ -34,7 +34,9 @@ final class SpaceListViewModel: SpaceListViewModelType { private var currentOperation: MXHTTPOperation? private var sections: [SpaceListSection] = [] - + private var selectedIndexPath: IndexPath = IndexPath(row: 0, section: 0) + private var homeIndexPath: IndexPath = IndexPath(row: 0, section: 0) + // MARK: Public weak var viewDelegate: SpaceListViewModelViewDelegate? @@ -60,18 +62,23 @@ final class SpaceListViewModel: SpaceListViewModelType { case .loadData: self.loadData() case .selectRow(at: let indexPath, from: let sourceView): + guard self.selectedIndexPath != indexPath else { + return + } let section = self.sections[indexPath.section] switch section { case .home: self.selectHome() - self.viewDelegate?.spaceListViewModel(self, didSelectSpaceAt: indexPath) + self.selectedIndexPath = indexPath + self.update(viewState: .selectionChanged(indexPath)) case .spaces(let viewDataList): let spaceViewData = viewDataList[indexPath.row] if spaceViewData.isInvite { self.selectInvite(with: spaceViewData.spaceId, from: sourceView) } else { self.selectSpace(with: spaceViewData.spaceId) - self.viewDelegate?.spaceListViewModel(self, didSelectSpaceAt: indexPath) + self.selectedIndexPath = indexPath + self.update(viewState: .selectionChanged(indexPath)) } } case .moreAction(at: let indexPath, from: let sourceView): @@ -86,7 +93,7 @@ final class SpaceListViewModel: SpaceListViewModelType { } func revertItemSelection() { - self.viewDelegate?.spaceListViewModelRevertSelection(self) + self.update(viewState: .selectionChanged(self.selectedIndexPath)) } // MARK: - Private @@ -118,7 +125,12 @@ final class SpaceListViewModel: SpaceListViewModelType { self.sections = sections let homeIndexPath = viewDataList.invites.isEmpty ? IndexPath(row: 0, section: 0) : IndexPath(row: 0, section: 1) - self.update(viewState: .loaded(sections, homeIndexPath)) + if self.selectedIndexPath.section == self.homeIndexPath.section { + self.selectedIndexPath = homeIndexPath + } + self.homeIndexPath = homeIndexPath + self.update(viewState: .loaded(sections)) + self.update(viewState: .selectionChanged(self.selectedIndexPath)) } private func selectHome() { diff --git a/Riot/Modules/Spaces/SpaceList/SpaceListViewModelType.swift b/Riot/Modules/Spaces/SpaceList/SpaceListViewModelType.swift index 99ed95595..77916dec1 100644 --- a/Riot/Modules/Spaces/SpaceList/SpaceListViewModelType.swift +++ b/Riot/Modules/Spaces/SpaceList/SpaceListViewModelType.swift @@ -20,8 +20,6 @@ import Foundation protocol SpaceListViewModelViewDelegate: AnyObject { func spaceListViewModel(_ viewModel: SpaceListViewModelType, didUpdateViewState viewSate: SpaceListViewState) - func spaceListViewModel(_ viewModel: SpaceListViewModelType, didSelectSpaceAt indexPath: IndexPath) - func spaceListViewModelRevertSelection(_ viewModel: SpaceListViewModelType) } protocol SpaceListViewModelCoordinatorDelegate: AnyObject { diff --git a/Riot/Modules/Spaces/SpaceList/SpaceListViewState.swift b/Riot/Modules/Spaces/SpaceList/SpaceListViewState.swift index a9f69265f..451dff10f 100644 --- a/Riot/Modules/Spaces/SpaceList/SpaceListViewState.swift +++ b/Riot/Modules/Spaces/SpaceList/SpaceListViewState.swift @@ -21,6 +21,7 @@ import Foundation /// SpaceListViewController view state enum SpaceListViewState { case loading - case loaded(_ sections: [SpaceListSection], _ homeIndexPath: IndexPath) + case loaded(_ sections: [SpaceListSection]) + case selectionChanged(_ indexPath: IndexPath) case error(Error) }