diff --git a/ElementX/Sources/Modules/HomeScreen/HomeScreenModels.swift b/ElementX/Sources/Modules/HomeScreen/HomeScreenModels.swift index 9e58cc143..82ed9f716 100644 --- a/ElementX/Sources/Modules/HomeScreen/HomeScreenModels.swift +++ b/ElementX/Sources/Modules/HomeScreen/HomeScreenModels.swift @@ -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? diff --git a/ElementX/Sources/Modules/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Modules/HomeScreen/HomeScreenViewModel.swift index 78c2a518b..ab1a99ca4 100644 --- a/ElementX/Sources/Modules/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Modules/HomeScreen/HomeScreenViewModel.swift @@ -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 diff --git a/ElementX/Sources/Modules/HomeScreen/View/HomeScreen.swift b/ElementX/Sources/Modules/HomeScreen/View/HomeScreen.swift index 1b5df61a8..1967646b7 100644 --- a/ElementX/Sources/Modules/HomeScreen/View/HomeScreen.swift +++ b/ElementX/Sources/Modules/HomeScreen/View/HomeScreen.swift @@ -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 ? "🛡": "") } } diff --git a/ElementX/Sources/Modules/Models/MockRoomModel.swift b/ElementX/Sources/Modules/Models/MockRoomModel.swift index 906b0bca8..e1e7adcc8 100644 --- a/ElementX/Sources/Modules/Models/MockRoomModel.swift +++ b/ElementX/Sources/Modules/Models/MockRoomModel.swift @@ -23,6 +23,10 @@ struct MockRoomModel: RoomModelProtocol { let isPublic = Bool.random() let isEncrypted = Bool.random() + func loadDisplayName(_ completion: @escaping (Result) -> Void) { + completion(.success(displayName)) + } + func loadAvatar(_ completion: (Result) -> Void) { completion(.success(UIImage(systemName: "wand.and.stars"))) } diff --git a/ElementX/Sources/Modules/Models/RoomModel.swift b/ElementX/Sources/Modules/Models/RoomModel.swift index 74eb96714..8aff42f23 100644 --- a/ElementX/Sources/Modules/Models/RoomModel.swift +++ b/ElementX/Sources/Modules/Models/RoomModel.swift @@ -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) -> 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) -> Void) { DispatchQueue.global(qos: .background).async { do { diff --git a/ElementX/Sources/Modules/Models/RoomModelProtocol.swift b/ElementX/Sources/Modules/Models/RoomModelProtocol.swift index 35466b8d7..e4bc8036c 100644 --- a/ElementX/Sources/Modules/Models/RoomModelProtocol.swift +++ b/ElementX/Sources/Modules/Models/RoomModelProtocol.swift @@ -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) -> Void) func loadAvatar(_ completion: @escaping (Result) -> Void) }