mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Introduced the concepts of room summary and event brief.
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// EventBrief.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 01/04/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct EventBrief {
|
||||
let id: String
|
||||
let senderName: String
|
||||
let body: String
|
||||
let htmlBody: String?
|
||||
let date: Date
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// EventBriefFactory.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 01/04/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct EventBriefFactory: EventBriefFactoryProtocol {
|
||||
|
||||
func eventBriefForMessage(_ message: RoomMessageProtocol?) -> EventBrief? {
|
||||
guard let message = message else {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch message {
|
||||
case is ImageRoomMessage:
|
||||
return nil
|
||||
case let message as TextRoomMessage:
|
||||
return buildEventBrief(message: message, htmlBody: message.htmlBody)
|
||||
case let message as NoticeRoomMessage:
|
||||
return buildEventBrief(message: message, htmlBody: message.htmlBody)
|
||||
case let message as EmoteRoomMessage:
|
||||
return buildEventBrief(message: message, htmlBody: message.htmlBody)
|
||||
default:
|
||||
fatalError("Unknown room message.")
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// EventBriefFactoryProtocol.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 01/04/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol EventBriefFactoryProtocol {
|
||||
func eventBriefForMessage(_ message: RoomMessageProtocol?) -> EventBrief?
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// MockRoomSummary.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 01/04/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
struct MockRoomSummary: RoomSummaryProtocol {
|
||||
var id: String = UUID().uuidString
|
||||
|
||||
var name: String?
|
||||
|
||||
var topic: String?
|
||||
|
||||
var isDirect: Bool = false
|
||||
|
||||
var isEncrypted: Bool = false
|
||||
|
||||
var isSpace: Bool = false
|
||||
|
||||
var isTombstoned: Bool = false
|
||||
|
||||
var displayName: String?
|
||||
|
||||
var lastMessage: EventBrief?
|
||||
|
||||
var avatar: UIImage?
|
||||
|
||||
func loadData() {
|
||||
|
||||
}
|
||||
|
||||
var callbacks = PassthroughSubject<RoomSummaryCallback, Never>()
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
//
|
||||
// RoomSummary.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 01/04/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
class RoomSummary: RoomSummaryProtocol {
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let mediaProvider: MediaProviderProtocol
|
||||
private let eventBriefFactory: EventBriefFactoryProtocol
|
||||
|
||||
private var hasLoadedData = false
|
||||
private var roomUpdateListeners = Set<AnyCancellable>()
|
||||
|
||||
var id: String {
|
||||
roomProxy.id
|
||||
}
|
||||
|
||||
var name: String? {
|
||||
roomProxy.name
|
||||
}
|
||||
|
||||
var topic: String? {
|
||||
roomProxy.topic
|
||||
}
|
||||
|
||||
var isDirect: Bool {
|
||||
roomProxy.isDirect
|
||||
}
|
||||
|
||||
var isEncrypted: Bool {
|
||||
roomProxy.isEncrypted
|
||||
}
|
||||
|
||||
var isSpace: Bool {
|
||||
roomProxy.isSpace
|
||||
}
|
||||
|
||||
var isTombstoned: Bool {
|
||||
roomProxy.isTombstoned
|
||||
}
|
||||
|
||||
private(set) var displayName: String? {
|
||||
didSet {
|
||||
self.callbacks.send(.updatedData)
|
||||
}
|
||||
}
|
||||
|
||||
private(set) var lastMessage: EventBrief? {
|
||||
didSet {
|
||||
self.callbacks.send(.updatedData)
|
||||
}
|
||||
}
|
||||
|
||||
private(set) var avatar: UIImage? {
|
||||
didSet {
|
||||
self.callbacks.send(.updatedData)
|
||||
}
|
||||
}
|
||||
|
||||
let callbacks = PassthroughSubject<RoomSummaryCallback, Never>()
|
||||
|
||||
init(roomProxy: RoomProxyProtocol, mediaProvider: MediaProviderProtocol, eventBriefFactory: EventBriefFactoryProtocol) {
|
||||
self.roomProxy = roomProxy
|
||||
self.mediaProvider = mediaProvider
|
||||
self.eventBriefFactory = eventBriefFactory
|
||||
|
||||
lastMessage = eventBriefFactory.eventBriefForMessage(roomProxy.messages.last)
|
||||
|
||||
roomProxy.callbacks.sink { [weak self] callback in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
|
||||
switch callback {
|
||||
case .updatedMessages:
|
||||
self.lastMessage = self.eventBriefFactory.eventBriefForMessage(self.roomProxy.messages.last)
|
||||
}
|
||||
}
|
||||
.store(in: &roomUpdateListeners)
|
||||
}
|
||||
|
||||
func loadData() {
|
||||
if hasLoadedData {
|
||||
return
|
||||
}
|
||||
|
||||
loadDisplayName()
|
||||
loadLastMessage()
|
||||
loadAvatar()
|
||||
|
||||
hasLoadedData = true
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func loadDisplayName() {
|
||||
roomProxy.displayName { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch result {
|
||||
case .success(let displayName):
|
||||
self.displayName = displayName
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed fetching room display name with error: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func loadLastMessage() {
|
||||
if roomProxy.messages.last == nil {
|
||||
roomProxy.paginateBackwards(count: 1) { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch result {
|
||||
case .success:
|
||||
self.lastMessage = self.eventBriefFactory.eventBriefForMessage(self.roomProxy.messages.last)
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed back paginating with error: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func loadAvatar() {
|
||||
if let avatarURL = roomProxy.avatarURL {
|
||||
mediaProvider.loadImageFromURL(avatarURL) { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch result {
|
||||
case .success(let image):
|
||||
self.avatar = image
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed fetching room avatar with error: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// RoomSummaryProtocol.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 01/04/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
enum RoomSummaryCallback {
|
||||
case updatedData
|
||||
}
|
||||
|
||||
protocol RoomSummaryProtocol {
|
||||
var id: String { get }
|
||||
var name: String? { get }
|
||||
var topic: String? { get }
|
||||
var isDirect: Bool { get }
|
||||
var isEncrypted: Bool { get }
|
||||
var isSpace: Bool { get }
|
||||
var isTombstoned: Bool { get }
|
||||
|
||||
var displayName: String? { get }
|
||||
var lastMessage: EventBrief? { get }
|
||||
var avatar: UIImage? { get }
|
||||
|
||||
var callbacks: PassthroughSubject<RoomSummaryCallback, Never> { get }
|
||||
|
||||
func loadData()
|
||||
}
|
||||
Reference in New Issue
Block a user