110 lines
2.9 KiB
Swift
110 lines
2.9 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()
|
|
|
|
@Dependency private var client: RocketChatClientProtocol
|
|
@Dependency private var database: Database
|
|
@Dependency private var serversDB: ServersDatabase
|
|
|
|
private var roomID: String?
|
|
|
|
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.rid, let roomID = room.id else { return }
|
|
|
|
let newUpdatedSince = Date()
|
|
|
|
client.syncMessages(rid: rid, updatedSince: date)
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] completion in
|
|
if case .failure = completion {
|
|
self?.scheduledSyncMessages(in: room, from: newUpdatedSince)
|
|
}
|
|
} receiveValue: { [weak self] messagesResponse in
|
|
self?.database.handleMessagesResponse(messagesResponse, in: roomID, newUpdatedSince: newUpdatedSince)
|
|
|
|
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.rid, let roomID = 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
|
|
self?.database.handleHistoryResponse(messagesResponse, in: roomID)
|
|
}
|
|
.store(in: &cancellable)
|
|
}
|
|
|
|
private func markAsRead(in room: Room) {
|
|
guard (room.unread > 0 || room.alert), let rid = room.rid, let roomID = room.id else {
|
|
return
|
|
}
|
|
|
|
client.sendRead(rid: rid)
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { completion in
|
|
if case .failure(let error) = completion {
|
|
print(error)
|
|
}
|
|
} receiveValue: { [weak self] readResponse in
|
|
self?.database.handleReadResponse(readResponse, in: roomID)
|
|
}
|
|
.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()
|
|
}
|
|
}
|