Add room's update publisher (#952)

* Add room update publisher

* Cleanup

* Update room’s title

* Add refresh logic in RoomDetailsScreenViewModel

* Fix UTs

* Add UT

* Update timeline listener in RoomProxy

* Fix caching in LoadableAvatarImage

* Cleanup

* Update RoomProxy api

* Inject room proxy in RoomScreenViewModel

* Cleanup

* Fix UTs
This commit is contained in:
Alfonso Grillo
2023-05-25 12:42:58 +02:00
committed by GitHub
parent c59921103d
commit bf2102e5d1
15 changed files with 169 additions and 105 deletions
@@ -36,7 +36,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
canonicalAlias: roomProxy.canonicalAlias,
isEncrypted: roomProxy.isEncrypted,
isDirect: roomProxy.isDirect,
title: roomProxy.displayName ?? roomProxy.name ?? "Unknown Room",
title: roomProxy.roomTitle,
topic: roomProxy.topic,
avatarURL: roomProxy.avatarURL,
permalink: roomProxy.permalink,
@@ -81,6 +81,13 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
// MARK: - Private
private func setupSubscriptions() {
switch roomProxy.registerTimelineListenerIfNeeded() {
case .success, .failure(.roomListenerAlreadyRegistered):
break
case .failure:
MXLog.error("Failed to register a room listener in room's details for the room \(roomProxy.id)")
}
roomProxy.membersPublisher
.sink { [weak self] members in
guard let self else { return }
@@ -102,6 +109,16 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
}
}
.store(in: &cancellables)
roomProxy.updatesPublisher
.throttle(for: .seconds(1), scheduler: DispatchQueue.main, latest: true)
.sink { [weak self] _ in
guard let self else { return }
self.state.title = self.roomProxy.roomTitle
self.state.topic = self.roomProxy.topic
self.state.avatarURL = self.roomProxy.avatarURL
}
.store(in: &cancellables)
}
private func buildMembersDetails(members: [RoomMemberProxyProtocol]) async -> RoomMembersDetails {
@@ -44,8 +44,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
viewModel = RoomScreenViewModel(timelineController: parameters.timelineController,
mediaProvider: parameters.mediaProvider,
roomName: parameters.roomProxy.displayName ?? parameters.roomProxy.name,
roomAvatarUrl: parameters.roomProxy.avatarURL)
roomProxy: parameters.roomProxy)
}
// MARK: - Public
@@ -76,7 +75,6 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
}
func stop() {
parameters.roomProxy.removeTimelineListener()
viewModel.context.send(viewAction: .markRoomAsRead)
}
@@ -27,17 +27,18 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
static let toastErrorID = "RoomScreenToastError"
}
private let roomProxy: RoomProxyProtocol
private let timelineController: RoomTimelineControllerProtocol
init(timelineController: RoomTimelineControllerProtocol,
mediaProvider: MediaProviderProtocol,
roomName: String?,
roomAvatarUrl: URL? = nil) {
roomProxy: RoomProxyProtocol) {
self.roomProxy = roomProxy
self.timelineController = timelineController
super.init(initialViewState: RoomScreenViewState(roomId: timelineController.roomID,
roomTitle: roomName ?? "Unknown room 💥",
roomAvatarURL: roomAvatarUrl,
roomTitle: roomProxy.roomTitle,
roomAvatarURL: roomProxy.avatarURL,
timelineStyle: ServiceLocator.shared.settings.timelineStyle,
bindings: .init(composerText: "", composerFocused: false)),
imageProvider: mediaProvider)
@@ -70,6 +71,16 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
return self.contextMenuActionsForItemId(itemId)
}
roomProxy
.updatesPublisher
.throttle(for: .seconds(1), scheduler: DispatchQueue.main, latest: true)
.sink { [weak self] _ in
guard let self else { return }
self.state.roomTitle = roomProxy.roomTitle
self.state.roomAvatarURL = roomProxy.avatarURL
}
.store(in: &cancellables)
ServiceLocator.shared.settings.$timelineStyle
.weakAssign(to: \.state.timelineStyle, on: self)
.store(in: &cancellables)
@@ -406,5 +417,5 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
extension RoomScreenViewModel {
static let mock = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
mediaProvider: MockMediaProvider(),
roomName: "Preview room")
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")))
}
@@ -59,8 +59,7 @@ struct RoomHeaderView_Previews: PreviewProvider {
static var bodyPlain: some View {
let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
mediaProvider: MockMediaProvider(),
roomName: "Some Room name",
roomAvatarUrl: URL.picturesDirectory)
roomProxy: RoomProxyMock(with: .init(displayName: "Some Room name", avatarURL: URL.picturesDirectory)))
RoomHeaderView(context: viewModel.context)
.previewLayout(.sizeThatFits)
@@ -71,8 +70,7 @@ struct RoomHeaderView_Previews: PreviewProvider {
static var bodyEncrypted: some View {
let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
mediaProvider: MockMediaProvider(),
roomName: "Some Room name",
roomAvatarUrl: nil)
roomProxy: RoomProxyMock(with: .init(displayName: "Some Room name")))
RoomHeaderView(context: viewModel.context)
.previewLayout(.sizeThatFits)
@@ -133,7 +133,7 @@ struct RoomScreen: View {
struct RoomScreen_Previews: PreviewProvider {
static let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
mediaProvider: MockMediaProvider(),
roomName: "Preview room")
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")))
static var previews: some View {
NavigationStack {
@@ -84,7 +84,7 @@ struct TimelineView: UIViewControllerRepresentable {
struct TimelineTableView_Previews: PreviewProvider {
static let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
mediaProvider: MockMediaProvider(),
roomName: "Preview room")
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")))
static var previews: some View {
NavigationStack {