Skip to content

Commit

Permalink
Fetching the room display names in background to avoid blocking the m…
Browse files Browse the repository at this point in the history
…ain thread.
  • Loading branch information
stefanceriu committed Feb 24, 2022
1 parent 97cb8ad commit e50f025
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 7 deletions.
5 changes: 3 additions & 2 deletions ElementX/Sources/Modules/HomeScreen/HomeScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ enum HomeScreenViewModelResult {
enum HomeScreenViewAction {
case logout
case loadUserAvatar
case loadRoomAvatar(roomId: String)
case loadRoomData(roomId: String)
}

struct HomeScreenViewState: BindableState {
Expand Down Expand Up @@ -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?
Expand Down
30 changes: 28 additions & 2 deletions ElementX/Sources/Modules/HomeScreen/HomeScreenViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions ElementX/Sources/Modules/HomeScreen/View/HomeScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -143,7 +143,7 @@ struct RoomCell: View {
}

private func roomName(_ room: HomeScreenRoom) -> String {
room.displayName + (room.isEncrypted ? "🛡": "")
room.displayName ?? room.id + (room.isEncrypted ? "🛡": "")
}
}

Expand Down
4 changes: 4 additions & 0 deletions ElementX/Sources/Modules/Models/MockRoomModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")))
}
Expand Down
17 changes: 17 additions & 0 deletions ElementX/Sources/Modules/Models/RoomModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import UIKit
import MatrixRustSDK

enum RoomModelError: Error {
case failedRetrievingDisplayName
case failedRetrievingAvatar
}

Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion ElementX/Sources/Modules/Models/RoomModelProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ protocol RoomModelProtocol {
var isSpace: Bool { get }
var isEncrypted: Bool { get }

var displayName: String { get }
var name: String? { get }

var topic: String? { get }
var lastMessage: String? { get }

var avatarURL: URL? { get }

func loadDisplayName(_ completion: @escaping (Result<String, Error>) -> Void)
func loadAvatar(_ completion: @escaping (Result<UIImage?, Error>) -> Void)
}

0 comments on commit e50f025

Please sign in to comment.