Caching memberDetailProviders, showing sender display names in home screen last message, cleaner homescreen design.

This commit is contained in:
Stefan Ceriu
2022-04-01 16:05:26 +03:00
parent 86d85f4d2c
commit 711857ac9c
15 changed files with 141 additions and 70 deletions
@@ -0,0 +1,24 @@
//
// MemberDetailProviderManager.swift
// ElementX
//
// Created by Stefan Ceriu on 01/04/2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
class MemberDetailProviderManager {
private var memberDetailProviders: [String: MemberDetailProviderProtocol] = [:]
func memberDetailProviderForRoomProxy(_ roomProxy: RoomProxyProtocol) -> MemberDetailProviderProtocol {
if let memberDetailProvider = memberDetailProviders[roomProxy.id] {
return memberDetailProvider
}
let memberDetailProvider = MemberDetailProvider(roomProxy: roomProxy)
memberDetailProviders[roomProxy.id] = memberDetailProvider
return memberDetailProvider
}
}
@@ -1,5 +1,5 @@
//
// MemberDetailsProvider.swift
// MemberDetailProvider.swift
// ElementX
//
// Created by Stefan Ceriu on 18/03/2022.
@@ -8,7 +8,7 @@
import Foundation
class MemberDetailsProvider: MemberDetailsProviderProtocol {
class MemberDetailProvider: MemberDetailProviderProtocol {
private let roomProxy: RoomProxyProtocol?
private var memberAvatars = [String: String]()
private var memberDisplayNames = [String: String]()
@@ -21,7 +21,7 @@ class MemberDetailsProvider: MemberDetailsProviderProtocol {
self.memberAvatars[userId]
}
func avatarURLForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailsProviderError>) -> Void) {
func avatarURLForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailProviderError>) -> Void) {
guard let roomProxy = roomProxy else {
return
}
@@ -49,7 +49,7 @@ class MemberDetailsProvider: MemberDetailsProviderProtocol {
self.memberDisplayNames[userId]
}
func displayNameForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailsProviderError>) -> Void) {
func displayNameForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailProviderError>) -> Void) {
guard let roomProxy = roomProxy else {
return
}
@@ -1,5 +1,5 @@
//
// MemberDetailsProviderProtocol.swift
// MemberDetailProviderProtocol.swift
// ElementX
//
// Created by Stefan Ceriu on 18/03/2022.
@@ -8,16 +8,16 @@
import Foundation
enum MemberDetailsProviderError: Error {
enum MemberDetailProviderError: Error {
case invalidRoomProxy
case failedRetrievingUserAvatarURL
case failedRetrievingUserDisplayName
}
protocol MemberDetailsProviderProtocol {
protocol MemberDetailProviderProtocol {
func avatarURLForUserId(_ userId: String) -> String?
func avatarURLForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailsProviderError>) -> Void)
func avatarURLForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailProviderError>) -> Void)
func displayNameForUserId(_ userId: String) -> String?
func displayNameForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailsProviderError>) -> Void)
func displayNameForUserId(_ userId: String, completion: @escaping (Result<String?, MemberDetailProviderError>) -> Void)
}
@@ -9,8 +9,9 @@
import Foundation
struct EventBrief {
let id: String
let senderName: String
let eventId: String
let senderId: String
let senderDisplayName: String?
let body: String
let htmlBody: String?
let date: Date
@@ -10,20 +10,27 @@ import Foundation
struct EventBriefFactory: EventBriefFactoryProtocol {
func eventBriefForMessage(_ message: RoomMessageProtocol?) -> EventBrief? {
private let memberDetailProvider: MemberDetailProviderProtocol
init(memberDetailProvider: MemberDetailProviderProtocol) {
self.memberDetailProvider = memberDetailProvider
}
func eventBriefForMessage(_ message: RoomMessageProtocol?, completion: @escaping ((EventBrief?) -> Void)) {
guard let message = message else {
return nil
completion(nil)
return
}
switch message {
case is ImageRoomMessage:
return nil
completion(nil)
case let message as TextRoomMessage:
return buildEventBrief(message: message, htmlBody: message.htmlBody)
buildEventBrief(message: message, htmlBody: message.htmlBody, completion: completion)
case let message as NoticeRoomMessage:
return buildEventBrief(message: message, htmlBody: message.htmlBody)
buildEventBrief(message: message, htmlBody: message.htmlBody, completion: completion)
case let message as EmoteRoomMessage:
return buildEventBrief(message: message, htmlBody: message.htmlBody)
buildEventBrief(message: message, htmlBody: message.htmlBody, completion: completion)
default:
fatalError("Unknown room message.")
}
@@ -31,11 +38,26 @@ struct EventBriefFactory: EventBriefFactoryProtocol {
// MARK: - Private
private func buildEventBrief(message: RoomMessageProtocol, htmlBody: String?) -> EventBrief {
return EventBrief(id: message.id,
senderName: message.sender,
body: message.body,
htmlBody: htmlBody,
date: message.originServerTs)
private func buildEventBrief(message: RoomMessageProtocol, htmlBody: String?, completion: @escaping ((EventBrief?) -> Void)) {
memberDetailProvider.displayNameForUserId(message.sender) { result in
switch result {
case .success(let displayName):
completion(EventBrief(eventId: message.id,
senderId: message.sender,
senderDisplayName: displayName,
body: message.body,
htmlBody: htmlBody,
date: message.originServerTs))
case .failure(let error):
MXLog.error("Failed fetching sender display name with error: \(error)")
completion(EventBrief(eventId: message.id,
senderId: message.sender,
senderDisplayName: nil,
body: message.body,
htmlBody: htmlBody,
date: message.originServerTs))
}
}
}
}
@@ -9,5 +9,5 @@
import Foundation
protocol EventBriefFactoryProtocol {
func eventBriefForMessage(_ message: RoomMessageProtocol?) -> EventBrief?
func eventBriefForMessage(_ message: RoomMessageProtocol?, completion: @escaping ((EventBrief?) -> Void))
}
@@ -71,7 +71,9 @@ class RoomSummary: RoomSummaryProtocol {
self.mediaProvider = mediaProvider
self.eventBriefFactory = eventBriefFactory
lastMessage = eventBriefFactory.eventBriefForMessage(roomProxy.messages.last)
eventBriefFactory.eventBriefForMessage(roomProxy.messages.last) { [weak self] result in
self?.lastMessage = result
}
roomProxy.callbacks.sink { [weak self] callback in
guard let self = self else {
@@ -80,7 +82,9 @@ class RoomSummary: RoomSummaryProtocol {
switch callback {
case .updatedMessages:
self.lastMessage = self.eventBriefFactory.eventBriefForMessage(self.roomProxy.messages.last)
self.eventBriefFactory.eventBriefForMessage(self.roomProxy.messages.last) { [weak self] result in
self?.lastMessage = result
}
}
}
.store(in: &roomUpdateListeners)
@@ -120,7 +124,9 @@ class RoomSummary: RoomSummaryProtocol {
switch result {
case .success:
self.lastMessage = self.eventBriefFactory.eventBriefForMessage(self.roomProxy.messages.last)
self.eventBriefFactory.eventBriefForMessage(self.roomProxy.messages.last) { [weak self] result in
self?.lastMessage = result
}
case .failure(let error):
MXLog.error("Failed back paginating with error: \(error)")
}