Fetching the room display names in background to avoid blocking the main thread.

This commit is contained in:
Stefan Ceriu 2022-02-24 17:45:02 +02:00
parent 97cb8adcee
commit e50f0257d2
6 changed files with 55 additions and 7 deletions

View File

@ -25,7 +25,7 @@ enum HomeScreenViewModelResult {
enum HomeScreenViewAction {
case logout
case loadUserAvatar
case loadRoomAvatar(roomId: String)
case loadRoomData(roomId: String)
}
struct HomeScreenViewState: BindableState {
@ -54,7 +54,8 @@ struct HomeScreenViewState: BindableState {
struct HomeScreenRoom: Identifiable {
let id: String
let displayName: String
var displayName: String?
let topic: String?
let lastMessage: String?

View File

@ -52,8 +52,9 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
switch viewAction {
case .logout:
self.completion?(.logout)
case .loadRoomAvatar(let roomId):
case .loadRoomData(let roomId):
self.loadAvatarForRoomWithIdentifier(roomId)
self.loadRoomDisplayNameForRoomWithIdentifier(roomId)
case .loadUserAvatar:
self.completion?(.loadUserAvatar)
}
@ -63,7 +64,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
self.roomList = roomList
state.rooms = roomList.map { roomModel in
HomeScreenRoom(id: roomModel.identifier,
displayName: roomModel.displayName,
displayName: roomModel.name,
topic: roomModel.topic,
lastMessage: roomModel.lastMessage,
isDirect: roomModel.isDirect,
@ -114,6 +115,31 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
}
}
private func loadRoomDisplayNameForRoomWithIdentifier(_ roomIdentifier: String) {
guard let room = roomList?.filter({ $0.identifier == roomIdentifier }).first else {
return
}
room.loadDisplayName { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let displayName):
self.updateDisplayName(displayName, forRoomWithIdentifier: roomIdentifier)
default:
break
}
}
}
private func updateDisplayName(_ displayName: String, forRoomWithIdentifier roomIdentifier: String) {
guard let index = self.state.rooms.firstIndex(where: { $0.id == roomIdentifier }) else {
return
}
self.state.rooms[index].displayName = displayName
}
private func updateAvatar(_ avatar: UIImage?, forRoomWithIdentifier roomIdentifier: String) {
guard let index = self.state.rooms.firstIndex(where: { $0.id == roomIdentifier }) else {
return

View File

@ -114,7 +114,7 @@ struct RoomCell: View {
.frame(width: 40, height: 40)
.mask(Circle())
} else {
let _ = context.send(viewAction: .loadRoomAvatar(roomId: room.id))
let _ = context.send(viewAction: .loadRoomData(roomId: room.id))
Image(systemName: "person.3")
.frame(width: 40, height: 40)
}
@ -143,7 +143,7 @@ struct RoomCell: View {
}
private func roomName(_ room: HomeScreenRoom) -> String {
room.displayName + (room.isEncrypted ? "🛡": "")
room.displayName ?? room.id + (room.isEncrypted ? "🛡": "")
}
}

View File

@ -23,6 +23,10 @@ struct MockRoomModel: RoomModelProtocol {
let isPublic = Bool.random()
let isEncrypted = Bool.random()
func loadDisplayName(_ completion: @escaping (Result<String, Error>) -> Void) {
completion(.success(displayName))
}
func loadAvatar(_ completion: (Result<UIImage?, Error>) -> Void) {
completion(.success(UIImage(systemName: "wand.and.stars")))
}

View File

@ -10,6 +10,7 @@ import UIKit
import MatrixRustSDK
enum RoomModelError: Error {
case failedRetrievingDisplayName
case failedRetrievingAvatar
}
@ -74,6 +75,22 @@ struct RoomModel: RoomModelProtocol {
return URL(string: urlString)
}
func loadDisplayName(_ completion: @escaping (Result<String, Error>) -> Void) {
DispatchQueue.global(qos: .background).async {
do {
let displayName = try room.displayName()
DispatchQueue.main.async {
completion(.success(displayName))
}
} catch {
DispatchQueue.main.async {
completion(.failure(RoomModelError.failedRetrievingDisplayName))
}
}
}
}
func loadAvatar(_ completion: @escaping (Result<UIImage?, Error>) -> Void) {
DispatchQueue.global(qos: .background).async {
do {

View File

@ -14,7 +14,6 @@ protocol RoomModelProtocol {
var isSpace: Bool { get }
var isEncrypted: Bool { get }
var displayName: String { get }
var name: String? { get }
var topic: String? { get }
@ -22,5 +21,6 @@ protocol RoomModelProtocol {
var avatarURL: URL? { get }
func loadDisplayName(_ completion: @escaping (Result<String, Error>) -> Void)
func loadAvatar(_ completion: @escaping (Result<UIImage?, Error>) -> Void)
}