mv-experiment #1

Merged
fmodf merged 88 commits from mv-experiment into develop 2024-09-03 15:13:59 +00:00
2 changed files with 141 additions and 74 deletions
Showing only changes of commit 29349296b0 - Show all commits

View file

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