Rocket.Chat.ReactNative/ios/RocketChat Watch App/Loaders/MessagesLoader.swift

136 lines
3.1 KiB
Swift

import CoreData
import Combine
import Foundation
protocol MessagesLoading {
func start(on roomID: String)
func loadMore(from date: Date)
func stop()
}
final class MessagesLoader {
private var timer: Timer?
private var cancellable = CancelBag()
private let client: RocketChatClientProtocol
private let database: Database
private let serversDB: ServersDatabase
private var roomID: String?
init(
client: RocketChatClientProtocol,
database: Database,
serversDB: ServersDatabase
) {
self.client = client
self.database = database
self.serversDB = serversDB
}
private func scheduledSyncMessages(in room: Room, from date: Date) {
timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] _ in
self?.syncMessages(in: room, from: date)
}
}
private func syncMessages(in room: Room, from date: Date) {
guard let rid = room.id else { return }
let newUpdatedSince = Date()
client.syncMessages(rid: rid, updatedSince: date)
.receive(on: DispatchQueue.main)
.sink { completion in
if case .failure(let error) = completion {
print(error)
}
} receiveValue: { [weak self] messagesResponse in
let messages = messagesResponse.result.updated
room.updatedSince = newUpdatedSince
for message in messages {
self?.database.process(updatedMessage: message, in: room)
}
self?.scheduledSyncMessages(in: room, from: newUpdatedSince)
self?.markAsRead(in: room)
}
.store(in: &cancellable)
}
private func loadMessages(in room: Room, from date: Date) {
guard let rid = room.id else { return }
client.getHistory(rid: rid, t: room.t ?? "", latest: date)
.receive(on: DispatchQueue.main)
.sink { completion in
if case .failure(let error) = completion {
print(error)
}
} receiveValue: { [weak self] messagesResponse in
let messages = messagesResponse.messages
if messages.count == HISTORY_MESSAGE_COUNT {
room.hasMoreMessages = true
} else {
room.hasMoreMessages = false
}
for message in messages {
self?.database.process(updatedMessage: message, in: room)
}
}
.store(in: &cancellable)
}
private func markAsRead(in room: Room) {
guard (room.unread > 0 || room.alert), let rid = room.id else {
return
}
client.sendRead(rid: rid)
.receive(on: DispatchQueue.main)
.sink { completion in
if case .failure(let error) = completion {
print(error)
}
} receiveValue: { _ in
}
.store(in: &cancellable)
}
}
extension MessagesLoader: MessagesLoading {
func start(on roomID: String) {
stop()
self.roomID = roomID
guard let room = database.room(id: roomID) else { return }
if let updatedSince = room.updatedSince {
loadMessages(in: room, from: updatedSince)
syncMessages(in: room, from: updatedSince)
} else {
loadMessages(in: room, from: .now)
syncMessages(in: room, from: .now)
}
}
func loadMore(from date: Date) {
guard let roomID, let room = database.room(id: roomID) else { return }
loadMessages(in: room, from: date)
}
func stop() {
timer?.invalidate()
cancellable.cancelAll()
}
}