mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Adopting different timeline item types exposed from rust.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// ImageRoomMessage.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 16/03/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
struct ImageRoomMessage: RoomMessageProtocol {
|
||||
private let message: MatrixRustSDK.ImageMessage
|
||||
|
||||
init(message: MatrixRustSDK.ImageMessage) {
|
||||
self.message = message
|
||||
}
|
||||
|
||||
var id: String {
|
||||
message.baseMessage().id()
|
||||
}
|
||||
|
||||
var content: String {
|
||||
message.baseMessage().content()
|
||||
}
|
||||
|
||||
var sender: String {
|
||||
message.baseMessage().sender()
|
||||
}
|
||||
|
||||
var originServerTs: Date {
|
||||
Date(timeIntervalSince1970: TimeInterval(message.baseMessage().originServerTs()))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// RoomMessageFactory.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 16/03/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
struct RoomMessageFactory {
|
||||
func buildRoomMessageFrom(_ message: AnyMessage) -> RoomMessageProtocol {
|
||||
if let textMessage = message.text() {
|
||||
return TextRoomMessage(message: textMessage)
|
||||
} else if let imageMessage = message.image() {
|
||||
return ImageRoomMessage(message: imageMessage)
|
||||
} else {
|
||||
fatalError("One of these must exist")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// RoomMessageProtocol.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 16/03/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol RoomMessageProtocol {
|
||||
var id: String { get }
|
||||
var content: String { get }
|
||||
var sender: String { get }
|
||||
var originServerTs: Date { get }
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// TextRoomMessage.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 16/03/2022.
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import MatrixRustSDK
|
||||
|
||||
struct TextRoomMessage: RoomMessageProtocol {
|
||||
private let message: MatrixRustSDK.TextMessage
|
||||
|
||||
init(message: MatrixRustSDK.TextMessage) {
|
||||
self.message = message
|
||||
}
|
||||
|
||||
var id: String {
|
||||
message.baseMessage().id()
|
||||
}
|
||||
|
||||
var content: String {
|
||||
message.baseMessage().content()
|
||||
}
|
||||
|
||||
var sender: String {
|
||||
message.baseMessage().sender()
|
||||
}
|
||||
|
||||
var originServerTs: Date {
|
||||
Date(timeIntervalSince1970: TimeInterval(message.baseMessage().originServerTs()))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// MockRoomProxy.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 17.02.2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Combine
|
||||
import MatrixRustSDK
|
||||
|
||||
struct MockRoomProxy: RoomProxyProtocol {
|
||||
let id = UUID().uuidString
|
||||
let name: String? = nil
|
||||
let displayName: String
|
||||
|
||||
let topic: String? = nil
|
||||
let lastMessage: String? = "Last message"
|
||||
|
||||
let avatarURL: URL? = nil
|
||||
|
||||
let isDirect = Bool.random()
|
||||
let isSpace = Bool.random()
|
||||
let isPublic = Bool.random()
|
||||
let isEncrypted = Bool.random()
|
||||
|
||||
var callbacks = PassthroughSubject<RoomProxyCallback, Never>()
|
||||
|
||||
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")))
|
||||
}
|
||||
|
||||
func startLiveEventListener() {
|
||||
|
||||
}
|
||||
|
||||
func paginateBackwards(count: UInt, callback: ((Result<[RoomMessageProtocol], Error>) -> Void)?) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
//
|
||||
// RoomProxy.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 14.02.2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
import MatrixRustSDK
|
||||
|
||||
enum RoomProxyError: Error {
|
||||
case failedRetrievingDisplayName
|
||||
case failedRetrievingAvatar
|
||||
case backwardStreamNotAvailable
|
||||
}
|
||||
|
||||
private class WeakRoomProxyWrapper: RoomDelegate {
|
||||
private weak var roomProxy: RoomProxy?
|
||||
|
||||
init(roomProxy: RoomProxy) {
|
||||
self.roomProxy = roomProxy
|
||||
}
|
||||
|
||||
// MARK: - RoomDelegate
|
||||
|
||||
func didReceiveMessage(message: AnyMessage) {
|
||||
DispatchQueue.main.async {
|
||||
self.roomProxy?.appendMessage(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RoomProxy: RoomProxyProtocol, Equatable {
|
||||
private let room: Room
|
||||
private let messageFactory: RoomMessageFactory
|
||||
private let processingQueue: DispatchQueue
|
||||
|
||||
private var backwardStream: BackwardsStreamProtocol?
|
||||
|
||||
let callbacks = PassthroughSubject<RoomProxyCallback, Never>()
|
||||
|
||||
init(room: Room, messageFactory: RoomMessageFactory) {
|
||||
self.room = room
|
||||
self.messageFactory = messageFactory
|
||||
processingQueue = DispatchQueue(label: "RoomProxyProcessingQueue")
|
||||
|
||||
processingQueue.async {
|
||||
self.backwardStream = room.startLiveEventListener()
|
||||
}
|
||||
|
||||
room.setDelegate(delegate: WeakRoomProxyWrapper(roomProxy: self))
|
||||
}
|
||||
|
||||
var id: String {
|
||||
return room.id()
|
||||
}
|
||||
|
||||
var isDirect: Bool {
|
||||
return room.isDirect()
|
||||
}
|
||||
|
||||
var isPublic: Bool {
|
||||
return room.isPublic()
|
||||
}
|
||||
|
||||
var isSpace: Bool {
|
||||
return room.isSpace()
|
||||
}
|
||||
|
||||
var isEncrypted: Bool {
|
||||
return room.isEncrypted()
|
||||
}
|
||||
|
||||
var name: String? {
|
||||
return room.name()
|
||||
}
|
||||
|
||||
var topic: String? {
|
||||
return room.topic()
|
||||
}
|
||||
|
||||
var lastMessage: String? {
|
||||
didSet {
|
||||
if lastMessage == oldValue {
|
||||
return
|
||||
}
|
||||
|
||||
callbacks.send(.updatedLastMessage)
|
||||
}
|
||||
}
|
||||
|
||||
var avatarURL: URL? {
|
||||
guard let urlString = room.avatarUrl() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return URL(string: urlString)
|
||||
}
|
||||
|
||||
func loadDisplayName(_ completion: @escaping (Result<String, Error>) -> Void) {
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
do {
|
||||
let displayName = try self.room.displayName()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(displayName))
|
||||
}
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(RoomProxyError.failedRetrievingDisplayName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadAvatar(_ completion: @escaping (Result<UIImage?, Error>) -> Void) {
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
do {
|
||||
let avatarData = try self.room.avatar()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(UIImage(data: Data(bytes: avatarData, count: avatarData.count))))
|
||||
}
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(RoomProxyError.failedRetrievingAvatar))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func paginateBackwards(count: UInt, callback: ((Result<[RoomMessageProtocol], Error>) -> Void)?) {
|
||||
MXLog.debug("Started backpaginating")
|
||||
processingQueue.async {
|
||||
guard let backwardStream = self.backwardStream else {
|
||||
DispatchQueue.main.async {
|
||||
callback?(.failure(RoomProxyError.backwardStreamNotAvailable))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let messages = backwardStream.paginateBackwards(count: UInt64(count)).map { message in
|
||||
self.messageFactory.buildRoomMessageFrom(message)
|
||||
}
|
||||
|
||||
MXLog.debug("Finished backpaginating")
|
||||
|
||||
DispatchQueue.main.async {
|
||||
callback?(.success(messages))
|
||||
if self.lastMessage == nil {
|
||||
self.lastMessage = messages.last?.content ?? ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Equatable
|
||||
|
||||
static func == (lhs: RoomProxy, rhs: RoomProxy) -> Bool {
|
||||
lhs.id == rhs.id
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
fileprivate func appendMessage(_ message: AnyMessage) {
|
||||
let message = self.messageFactory.buildRoomMessageFrom(message)
|
||||
lastMessage = message.content
|
||||
|
||||
callbacks.send(.addedMessage(message))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// RoomProxyProtocol.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 17.02.2022.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
import MatrixRustSDK
|
||||
|
||||
enum RoomProxyCallback {
|
||||
case addedMessage(RoomMessageProtocol)
|
||||
case updatedLastMessage
|
||||
}
|
||||
|
||||
protocol RoomProxyProtocol {
|
||||
var id: String { get }
|
||||
var isDirect: Bool { get }
|
||||
var isPublic: Bool { get }
|
||||
var isSpace: Bool { get }
|
||||
var isEncrypted: Bool { 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)
|
||||
|
||||
func paginateBackwards(count: UInt, callback: ((Result<[RoomMessageProtocol], Error>) -> Void)?)
|
||||
|
||||
var callbacks: PassthroughSubject<RoomProxyCallback, Never> { get }
|
||||
}
|
||||
Reference in New Issue
Block a user