Files
element-x-ios/ElementX/Sources/Services/Room/RoomProxy.swift
T
Doug 02eb4b35e2 Add SwiftFormat to the project. (#129)
* Run swiftformat for whitespace.
* Run swiftformat with some rules.
2022-07-06 14:49:05 +01:00

195 lines
5.6 KiB
Swift

//
// RoomProxy.swift
// ElementX
//
// Created by Stefan Ceriu on 14.02.2022.
// Copyright © 2022 Element. All rights reserved.
//
import Combine
import Foundation
import UIKit
import MatrixRustSDK
private class WeakRoomProxyWrapper: RoomDelegate {
private weak var roomProxy: RoomProxy?
init(roomProxy: RoomProxy) {
self.roomProxy = roomProxy
}
// MARK: - RoomDelegate
func didReceiveMessage(message: AnyMessage) {
roomProxy?.appendMessage(message)
}
}
class RoomProxy: RoomProxyProtocol {
private let room: Room
private let roomMessageFactory: RoomMessageFactoryProtocol
private let backgroundTaskService: BackgroundTaskServiceProtocol
private var backwardStream: BackwardsStreamProtocol?
private var sendMessageBgTask: BackgroundTaskProtocol?
private(set) var displayName: String?
let callbacks = PassthroughSubject<RoomProxyCallback, Never>()
private(set) var messages: [RoomMessageProtocol]
init(room: Room,
roomMessageFactory: RoomMessageFactoryProtocol,
backgroundTaskService: BackgroundTaskServiceProtocol) {
self.room = room
self.roomMessageFactory = roomMessageFactory
self.backgroundTaskService = backgroundTaskService
messages = []
room.setDelegate(delegate: WeakRoomProxyWrapper(roomProxy: self))
backwardStream = room.startLiveEventListener()
}
deinit {
room.setDelegate(delegate: nil)
}
var id: String {
room.id()
}
var name: String? {
room.name()
}
var topic: String? {
room.topic()
}
var isDirect: Bool {
room.isDirect()
}
var isPublic: Bool {
room.isPublic()
}
var isSpace: Bool {
room.isSpace()
}
var isEncrypted: Bool {
room.isEncrypted()
}
var isTombstoned: Bool {
room.isTombstoned()
}
var avatarURL: String? {
room.avatarUrl()
}
var encryptionBadgeImage: UIImage? {
guard isEncrypted else {
return nil
}
// return trusted image for now, should be updated after verification status known
return Asset.Images.encryptionTrusted.image
}
func loadAvatarURLForUserId(_ userId: String) async -> Result<String?, RoomProxyError> {
await Task.detached { () -> Result<String?, RoomProxyError> in
do {
let avatarURL = try self.room.memberAvatarUrl(userId: userId)
return .success(avatarURL)
} catch {
return .failure(.failedRetrievingMemberAvatarURL)
}
}
.value
}
func loadDisplayNameForUserId(_ userId: String) async -> Result<String?, RoomProxyError> {
await Task.detached { () -> Result<String?, RoomProxyError> in
do {
let displayName = try self.room.memberDisplayName(userId: userId)
return .success(displayName)
} catch {
return .failure(.failedRetrievingMemberDisplayName)
}
}
.value
}
func loadDisplayName() async -> Result<String, RoomProxyError> {
await Task.detached { () -> Result<String, RoomProxyError> in
if let displayName = self.displayName {
return .success(displayName)
}
do {
let displayName = try self.room.displayName()
self.displayName = displayName
return .success(displayName)
} catch {
return .failure(.failedRetrievingDisplayName)
}
}
.value
}
func paginateBackwards(count: UInt) async -> Result<Void, RoomProxyError> {
await Task.detached { () -> Result<Void, RoomProxyError> in
guard let backwardStream = self.backwardStream else {
return .failure(RoomProxyError.backwardStreamNotAvailable)
}
Benchmark.startTrackingForIdentifier("BackPagination \(self.id)", message: "Backpaginating \(count) message(s) in room \(self.id)")
let sdkMessages = backwardStream.paginateBackwards(count: UInt64(count))
Benchmark.endTrackingForIdentifier("BackPagination \(self.id)", message: "Finished backpaginating \(count) message(s) in room \(self.id)")
let messages = sdkMessages.map { message in
self.roomMessageFactory.buildRoomMessageFrom(message)
}.reversed()
self.messages.insert(contentsOf: messages, at: 0)
return .success(())
}
.value
}
func sendMessage(_ message: String) async -> Result<Void, RoomProxyError> {
sendMessageBgTask = backgroundTaskService.startBackgroundTask(withName: "SendMessage", isReusable: true)
defer {
sendMessageBgTask?.stop()
}
let messageContent = messageEventContentFromMarkdown(md: message)
let transactionId = genTransactionId()
return await Task(priority: .high) { () -> Result<Void, RoomProxyError> in
do {
try self.room.send(msg: messageContent, txnId: transactionId)
return .success(())
} catch {
return .failure(.failedSendingMessage)
}
}
.value
}
// MARK: - Private
fileprivate func appendMessage(_ message: AnyMessage) {
let message = roomMessageFactory.buildRoomMessageFrom(message)
messages.append(message)
callbacks.send(.updatedMessages)
}
}