This commit is contained in:
fmodf 2024-08-19 07:22:54 +02:00
parent 087aeba94a
commit 29349296b0
2 changed files with 141 additions and 74 deletions

View file

@ -12,7 +12,7 @@ final class MessagesStore: ObservableObject {
private let client: Client private let client: Client
private var messagesCancellable: AnyCancellable? private var messagesCancellable: AnyCancellable?
private let archiveMessageFetcher = ArchiveMessageFetcher() private let archiver = ArchiveMessageFetcher()
init(roster: Roster, client: Client) { init(roster: Roster, client: Client) {
self.client = client self.client = client
@ -65,103 +65,170 @@ private extension MessagesStore {
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { _ in .sink { _ in
} receiveValue: { [weak self] messages in } receiveValue: { [weak self] messages in
self?.messages = messages guard let self else { return }
if messages.isEmpty { self.messages = messages
self?.requestLastArchivedMessages() Task {
await self.archiver.initialFetch(messages, self.roster, self.client)
} }
} }
} }
} }
// MARK: - Archived messages // MARK: - Fetch archived messages
extension MessagesStore { extension MessagesStore {
func requestEarliestArchivedMessages() { func fetchForward() {
guard let beforeId = messages.last?.id else { return }
Task { Task {
await archiveMessageFetcher.fetchBeforeMessages(roster, client, beforeId: beforeId) await archiver.fetchForward(roster, client)
} }
} }
func requestLatestArchivedMessages() { func fetchBackward() {
guard let afterId = messages.first?.id else { return }
Task { Task {
await archiveMessageFetcher.fetchAfterMessages(roster, client, afterId: afterId) await archiver.fetchBackward(roster, client)
}
}
private func requestLastArchivedMessages() {
Task {
await archiveMessageFetcher.fetchLastMessages(roster, client)
} }
} }
} }
private actor ArchiveMessageFetcher { private actor ArchiveMessageFetcher {
private var afterAvailable = true private var initFetchStarted = false
private var beforeAvailable = true private var forwardRsm: RSM.Query?
private var isFetching = false private var backwardRsm: RSM.Query?
private var fetchingIsPossinle = true
func fetchLastMessages(_ roster: Roster, _ client: Client) async { func initialFetch(_ messages: [Message], _ roster: Roster, _ client: Client) async {
if !fetchingIsPossinle { return } if initFetchStarted { return }
while isFetching { initFetchStarted = true
await Task.yield()
}
isFetching = true
let query: RSM.Query = .init(lastItems: Const.mamRequestLimit)
do { do {
_ = try await client.fetchArchiveMessages(for: roster, query: query) if let firstExistId = messages.first?.id {
} catch AppError.featureNotSupported { let result = try await client.fetchArchiveMessages(for: roster, query: .init(before: firstExistId, max: Const.mamRequestLimit))
fetchingIsPossinle = false result.complete ? forwardRsm = nil : (forwardRsm = .init(after: result.rsm?.last, max: Const.mamRequestLimit))
result.complete ? backwardRsm = nil : (backwardRsm = .init(before: result.rsm?.first, max: Const.mamRequestLimit))
} else {
let result = try await client.fetchArchiveMessages(for: roster, query: .init(lastItems: Const.mamRequestLimit))
result.complete ? backwardRsm = nil : (backwardRsm = .init(before: result.rsm?.first, max: Const.mamRequestLimit))
}
} catch { } catch {
logIt(.error, "Error requesting archived messages: \(error)") logIt(.error, "Error requesting archived messages: \(error)")
initFetchStarted = false
}
} }
isFetching = false func fetchForward(_ roster: Roster, _ client: Client) {
guard let rsm = forwardRsm else { return }
Task {
let result = try await client.fetchArchiveMessages(for: roster, query: rsm)
result.complete ? (forwardRsm = nil) : (forwardRsm = .init(after: result.rsm?.last, max: Const.mamRequestLimit))
}
} }
func fetchBeforeMessages(_ roster: Roster, _ client: Client, beforeId: String) async { func fetchBackward(_ roster: Roster, _ client: Client) {
if !fetchingIsPossinle || !beforeAvailable { return } guard let rsm = backwardRsm else { return }
while isFetching { Task {
await Task.yield() let result = try await client.fetchArchiveMessages(for: roster, query: rsm)
result.complete ? (backwardRsm = nil) : (backwardRsm = .init(before: result.rsm?.first, max: Const.mamRequestLimit))
} }
isFetching = true
let query: RSM.Query = .init(before: beforeId, max: Const.mamRequestLimit)
do {
let result = try await client.fetchArchiveMessages(for: roster, query: query)
if result.complete {
beforeAvailable = false
}
} catch AppError.featureNotSupported {
fetchingIsPossinle = false
} catch {
logIt(.error, "Error requesting archived messages: \(error)")
} }
isFetching = false // func fetchBackward(_ roster: Roster, _ client: Client) {
// guard let rsm = backwardRsm else { return }
// Task {
// let result = try await client.fetchArchiveMessages(for: roster, query: rsm)
// result.complete ? (backwardRsm = nil) : (backwardRsm = .init(before: result.rsm?.first, max: Const.mamRequestLimit))
// }
// }
} }
func fetchAfterMessages(_ roster: Roster, _ client: Client, afterId: String) async { // MARK: - Archived messages
if !fetchingIsPossinle || !afterAvailable { return } // extension MessagesStore {
while isFetching { // func requestEarliestArchivedMessages() {
await Task.yield() // guard let beforeId = messages.first?.id else { return }
} // Task {
isFetching = true // await archiveMessageFetcher.fetchAfterMessages(roster, client, afterId: beforeId)
// // await archiveMessageFetcher.fetchBeforeMessages(roster, client, beforeId: beforeId)
// }
// }
//
// func requestLatestArchivedMessages() {
// guard let afterId = messages.last?.id else { return }
// Task {
// await archiveMessageFetcher.fetchBeforeMessages(roster, client, beforeId: afterId)
// // await archiveMessageFetcher.fetchAfterMessages(roster, client, afterId: afterId)
// }
// }
//
// private func requestLastArchivedMessages() {
// Task {
// await archiveMessageFetcher.fetchLastMessages(roster, client)
// }
// }
// }
let query: RSM.Query = .init(after: afterId, max: Const.mamRequestLimit) // private actor ArchiveMessageFetcher {
do { // private var afterAvailable = true
let result = try await client.fetchArchiveMessages(for: roster, query: query) // private var beforeAvailable = true
if result.complete { // private var isFetching = false
afterAvailable = false // private var fetchingIsPossinle = true
} //
} catch AppError.featureNotSupported { // func fetchLastMessages(_ roster: Roster, _ client: Client) async {
fetchingIsPossinle = false // if !fetchingIsPossinle { return }
} catch { // while isFetching {
logIt(.error, "Error requesting archived messages: \(error)") // await Task.yield()
} // }
// isFetching = true
isFetching = false //
} // let query: RSM.Query = .init(lastItems: Const.mamRequestLimit)
} // do {
// _ = try await client.fetchArchiveMessages(for: roster, query: query)
// } catch AppError.featureNotSupported {
// fetchingIsPossinle = false
// } catch {
// logIt(.error, "Error requesting archived messages: \(error)")
// }
//
// isFetching = false
// }
//
// func fetchBeforeMessages(_ roster: Roster, _ client: Client, beforeId: String) async {
// if !fetchingIsPossinle || !beforeAvailable { return }
// while isFetching {
// await Task.yield()
// }
// isFetching = true
//
// let query: RSM.Query = .init(before: beforeId, max: Const.mamRequestLimit)
// do {
// let result = try await client.fetchArchiveMessages(for: roster, query: query)
// if result.complete {
// beforeAvailable = false
// }
// } catch AppError.featureNotSupported {
// fetchingIsPossinle = false
// } catch {
// logIt(.error, "Error requesting archived messages: \(error)")
// }
//
// isFetching = false
// }
//
// func fetchAfterMessages(_ roster: Roster, _ client: Client, afterId: String) async {
// if !fetchingIsPossinle || !afterAvailable { return }
// while isFetching {
// await Task.yield()
// }
// isFetching = true
//
// let query: RSM.Query = .init(after: afterId, max: Const.mamRequestLimit)
// do {
// let result = try await client.fetchArchiveMessages(for: roster, query: query)
// if result.complete {
// afterAvailable = false
// }
// } catch AppError.featureNotSupported {
// fetchingIsPossinle = false
// } catch {
// logIt(.error, "Error requesting archived messages: \(error)")
// }
//
// isFetching = false
// }
// }

View file

@ -46,7 +46,7 @@ struct ConversationScreen: View {
autoScroll = true autoScroll = true
} }
if message.id == messages.last?.id { if message.id == messages.last?.id {
messagesStore.requestEarliestArchivedMessages() messagesStore.fetchBackward()
} }
} }
.onDisappear { .onDisappear {