Room list service (#1138)

* Adopt the new RoomListService

* Use client.roomListWithEncryption

* Store the roomList so that it doesn't get dropped and create problems on the rust side

* Use roomListService instead of old roomList client method

* Added back documentation removed by mistake

* Tweaks following code review, SDK bump
This commit is contained in:
Stefan Ceriu
2023-06-22 19:59:32 +03:00
committed by GitHub
parent 6018221e1e
commit 652fd3cf76
12 changed files with 109 additions and 96 deletions
@@ -38,12 +38,11 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol {
statePublisher = .init(.notLoaded)
case .loaded(let rooms):
roomListPublisher = .init(rooms)
statePublisher = .init(.fullyLoaded)
statePublisher = .init(.loaded(totalNumberOfRooms: UInt(rooms.count)))
}
}
func subscribeIfNecessary(entriesFunction: EntriesFunction,
entriesLoadingStateFunction: LoadingStateFunction?) async { }
func setRoomList(_ roomList: RoomList) { }
func updateVisibleRange(_ range: Range<Int>) { }
}
@@ -19,12 +19,14 @@ import Foundation
import MatrixRustSDK
class RoomSummaryProvider: RoomSummaryProviderProtocol {
private let roomListService: RoomListProtocol
private let roomListService: RoomListServiceProtocol
private let eventStringBuilder: RoomEventStringBuilder
private let name: String
private let serialDispatchQueue: DispatchQueue
private var roomList: RoomListProtocol?
private var cancellables = Set<AnyCancellable>()
private var listUpdatesTaskHandle: TaskHandle?
private var stateUpdatesTaskHandle: TaskHandle?
@@ -49,7 +51,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
}
}
init(roomListService: RoomListProtocol,
init(roomListService: RoomListServiceProtocol,
eventStringBuilder: RoomEventStringBuilder,
name: String) {
self.roomListService = roomListService
@@ -63,37 +65,35 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
.store(in: &cancellables)
}
func subscribeIfNecessary(entriesFunction: EntriesFunction,
entriesLoadingStateFunction: LoadingStateFunction?) async {
func setRoomList(_ roomList: RoomList) {
guard listUpdatesTaskHandle == nil, stateUpdatesTaskHandle == nil else {
return
}
self.roomList = roomList
do {
let listUpdatesSubscriptionResult = try await entriesFunction(RoomListEntriesListenerProxy { [weak self] update in
let listUpdatesSubscriptionResult = try roomList.entries(listener: RoomListEntriesListenerProxy { [weak self] update in
guard let self else { return }
MXLog.verbose("\(name): Received list update")
diffPublisher.send(update)
})
listUpdatesTaskHandle = listUpdatesSubscriptionResult.entriesStream
rooms = listUpdatesSubscriptionResult.entries.map { roomListEntry in
buildSummaryForRoomListEntry(roomListEntry)
}
if let entriesLoadingStateFunction {
let stateUpdatesSubscriptionResult = try await entriesLoadingStateFunction(RoomListStateObserver { [weak self] state in
guard let self else { return }
MXLog.info("\(name): Received state update: \(state)")
stateSubject.send(RoomSummaryProviderState(slidingSyncState: state))
})
stateSubject.send(RoomSummaryProviderState(slidingSyncState: stateUpdatesSubscriptionResult.entriesLoadingState))
stateUpdatesTaskHandle = stateUpdatesSubscriptionResult.entriesLoadingStateStream
}
let stateUpdatesSubscriptionResult = try roomList.loadingState(listener: RoomListStateObserver { [weak self] state in
guard let self else { return }
MXLog.info("\(name): Received state update: \(state)")
stateSubject.send(RoomSummaryProviderState(roomListState: state))
})
stateUpdatesTaskHandle = stateUpdatesSubscriptionResult.stateStream
stateSubject.send(RoomSummaryProviderState(roomListState: stateUpdatesSubscriptionResult.state))
} catch {
MXLog.error("Failed setting up room list entry listener with error: \(error)")
}
@@ -266,16 +266,12 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
}
extension RoomSummaryProviderState {
init(slidingSyncState: SlidingSyncListLoadingState) {
switch slidingSyncState {
init(roomListState: RoomListLoadingState) {
switch roomListState {
case .notLoaded:
self = .notLoaded
case .preloaded:
self = .preloaded
case .partiallyLoaded:
self = .partiallyLoaded
case .fullyLoaded:
self = .fullyLoaded
case .loaded(let maximumNumberOfRooms):
self = .loaded(totalNumberOfRooms: UInt(maximumNumberOfRooms ?? 0))
}
}
}
@@ -314,14 +310,14 @@ private class RoomListEntriesListenerProxy: RoomListEntriesListener {
}
}
private class RoomListStateObserver: SlidingSyncListStateObserver {
private let onUpdateClosure: (SlidingSyncListLoadingState) -> Void
private class RoomListStateObserver: RoomListLoadingStateListener {
private let onUpdateClosure: (RoomListLoadingState) -> Void
init(_ onUpdateClosure: @escaping (SlidingSyncListLoadingState) -> Void) {
init(_ onUpdateClosure: @escaping (RoomListLoadingState) -> Void) {
self.onUpdateClosure = onUpdateClosure
}
func didReceiveUpdate(newState: SlidingSyncListLoadingState) {
onUpdateClosure(newState)
func onUpdate(state: RoomListLoadingState) {
onUpdateClosure(state)
}
}
@@ -20,9 +20,25 @@ import MatrixRustSDK
enum RoomSummaryProviderState {
case notLoaded
case preloaded
case partiallyLoaded
case fullyLoaded
case loaded(totalNumberOfRooms: UInt)
var isLoaded: Bool {
switch self {
case .loaded:
return true
default:
return false
}
}
var totalNumberOfRooms: UInt? {
switch self {
case .loaded(let totalNumberOfRooms):
return totalNumberOfRooms
default:
return nil
}
}
}
enum RoomSummary: CustomStringConvertible {
@@ -61,19 +77,15 @@ enum RoomSummary: CustomStringConvertible {
}
protocol RoomSummaryProviderProtocol {
typealias EntriesFunction = (RoomListEntriesListener) async throws -> RoomListEntriesResult
typealias LoadingStateFunction = (SlidingSyncListStateObserver) async throws -> RoomListEntriesLoadingStateResult
/// Publishes the currently available room summaries
var roomListPublisher: CurrentValuePublisher<[RoomSummary], Never> { get }
/// Publishes the current state the summary provider is finding itself in
var statePublisher: CurrentValuePublisher<RoomSummaryProviderState, Never> { get }
/// A separate subscription method is needed instead of running this in the constructor because the invites list is added later on the Rust side.
/// This is outside of the constructor because the invites list is added later on the Rust side.
/// Wanted to be able to build the InvitesSummaryProvider directly instead of having to inform the HomeScreenViewModel about it later
func subscribeIfNecessary(entriesFunction: EntriesFunction,
entriesLoadingStateFunction: LoadingStateFunction?) async
func setRoomList(_ roomList: RoomList)
func updateVisibleRange(_ range: Range<Int>)
}