Load room details on appearance. Avoid overwhelming the rust runtime and slow down the room timeline loading.

This commit is contained in:
Stefan Ceriu
2022-03-16 14:52:25 +02:00
parent 0611076b3c
commit 7491b2cd60
7 changed files with 65 additions and 29 deletions

View File

@@ -64,7 +64,7 @@ struct HomeScreenRoom: Identifiable {
var displayName: String?
let topic: String?
let lastMessage: String?
var lastMessage: String?
var avatar: UIImage?

View File

@@ -28,7 +28,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
private var roomUpdateListeners = Set<AnyCancellable>()
private var roomList: [RoomProxyProtocol]? {
didSet {
self.state.isLoadingRooms = (roomList == nil)
self.state.isLoadingRooms = (roomList?.count ?? 0 == 0)
}
}
@@ -50,8 +50,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
case .logout:
self.completion?(.logout)
case .loadRoomData(let roomIdentifier):
self.loadAvatarForRoomWithIdentifier(roomIdentifier)
self.loadRoomDisplayNameForRoomWithIdentifier(roomIdentifier)
self.loadRoomDataForIdentifier(roomIdentifier)
case .loadUserAvatar:
self.completion?(.loadUserAvatar)
case .selectRoom(let roomIdentifier):
@@ -60,27 +59,25 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
}
func updateWithRoomList(_ roomList: [RoomProxyProtocol]) {
self.roomList = roomList
state.rooms = roomList.map { roomProxy in
roomFromProxy(roomProxy)
}
roomUpdateListeners.removeAll()
self.roomList = roomList
roomList.forEach({ roomProxy in
roomProxy.paginateBackwards(count: 1, callback: nil)
roomProxy.callbacks.sink { [weak self] callback in
switch callback {
case .updatedLastMessage:
self?.updateRoomForProxy(roomProxy)
self?.loadLastMessageForRoomWithIdentifier(roomProxy.id)
default:
break
}
}
.store(in: &roomUpdateListeners)
})
state.rooms = roomList.map { roomProxy in
roomFromProxy(roomProxy)
}
}
func updateWithUserAvatar(_ avatar: UIImage?) {
@@ -89,6 +86,12 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
// MARK: - Private
private func loadRoomDataForIdentifier(_ roomIdentifier: String) {
loadAvatarForRoomWithIdentifier(roomIdentifier)
loadRoomDisplayNameForRoomWithIdentifier(roomIdentifier)
loadLastMessageForRoomWithIdentifier(roomIdentifier)
}
private func loadAvatarForRoomWithIdentifier(_ roomIdentifier: String) {
guard let room = roomList?.filter({ $0.id == roomIdentifier }).first,
let cacheKey = room.avatarURL?.path else {
@@ -126,6 +129,14 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
}
}
private func updateAvatar(_ avatar: UIImage?, forRoomWithIdentifier roomIdentifier: String) {
guard let index = self.state.rooms.firstIndex(where: { $0.id == roomIdentifier }) else {
return
}
self.state.rooms[index].avatar = avatar
}
private func loadRoomDisplayNameForRoomWithIdentifier(_ roomIdentifier: String) {
guard let room = roomList?.filter({ $0.id == roomIdentifier }).first else {
return
@@ -151,24 +162,37 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
self.state.rooms[index].displayName = displayName
}
private func updateAvatar(_ avatar: UIImage?, forRoomWithIdentifier roomIdentifier: String) {
private func loadLastMessageForRoomWithIdentifier(_ roomIdentifier: String) {
guard let room = roomList?.filter({ $0.id == roomIdentifier }).first else {
return
}
if let lastMessage = room.lastMessage {
self.updateLastMessage(lastMessage, forRoomWithIdentifier: roomIdentifier)
} else {
room.paginateBackwards(count: 1) { result in
switch result {
case .success(let messages):
guard let lastMessage = messages.last else {
return
}
self.updateLastMessage(lastMessage.content(), forRoomWithIdentifier: roomIdentifier)
default:
break
}
}
}
}
private func updateLastMessage(_ lastMessage: String, forRoomWithIdentifier roomIdentifier: String) {
guard let index = self.state.rooms.firstIndex(where: { $0.id == roomIdentifier }) else {
return
}
self.state.rooms[index].avatar = avatar
self.state.rooms[index].lastMessage = lastMessage
}
private func updateRoomForProxy(_ roomProxy: RoomProxyProtocol) {
state.rooms.updateEach { room in
if room.id != roomProxy.id {
return
}
room = roomFromProxy(roomProxy)
}
}
private func roomFromProxy(_ roomProxy: RoomProxyProtocol) -> HomeScreenRoom {
HomeScreenRoom(id: roomProxy.id,
displayName: roomProxy.name,

View File

@@ -114,7 +114,6 @@ struct RoomCell: View {
.frame(width: 40, height: 40)
.mask(Circle())
} else {
let _ = context.send(viewAction: .loadRoomData(roomIdentifier: room.id))
Image(systemName: "person.3")
.frame(width: 40, height: 40)
}
@@ -140,6 +139,9 @@ struct RoomCell: View {
}
}
.frame(minHeight: 60.0)
.onAppear {
context.send(viewAction: .loadRoomData(roomIdentifier: room.id))
}
}
}

View File

@@ -34,8 +34,8 @@ class LoginScreenViewModel: LoginScreenViewModelType, LoginScreenViewModelProtoc
// MARK: - Setup
init() {
super.init(initialViewState: LoginScreenViewState(bindings: LoginScreenViewStateBindings(username: "",
password: "")))
super.init(initialViewState: LoginScreenViewState(bindings: LoginScreenViewStateBindings(username: "@stefan.ceriu-element01:matrix.org",
password: "radeon")))
}
// MARK: - Public

View File

@@ -134,6 +134,8 @@ class AuthenticationCoordinator: Coordinator {
completion(.success(()))
}
} catch {
MXLog.error("Failed logging in with error: \(error)")
DispatchQueue.main.async {
completion(.failure(.failedLoggingIn))
}
@@ -156,6 +158,8 @@ class AuthenticationCoordinator: Coordinator {
completion(.success(()))
}
} catch {
MXLog.error("Failed restoring login with error: \(error)")
DispatchQueue.main.async {
completion(.failure(.failedRestoringLogin))
}

View File

@@ -101,6 +101,8 @@ class UserSession: ClientDelegate {
self.rooms = rooms
}
}
client.setDelegate(delegate: nil)
}
// MARK: Private

View File

@@ -82,6 +82,10 @@ class RoomProxy: RoomProxyProtocol, Equatable {
var lastMessage: String? {
didSet {
if lastMessage == oldValue {
return
}
callbacks.send(.updatedLastMessage)
}
}
@@ -141,7 +145,7 @@ class RoomProxy: RoomProxyProtocol, Equatable {
callback?(.success(messages))
if self.lastMessage == nil {
self.lastMessage = messages.last?.content()
self.lastMessage = messages.last?.content() ?? ""
}
}
}