diff --git a/ConversationsClassic/AppData/Client/Client+MartinMessages.swift b/ConversationsClassic/AppData/Client/Client+MartinMessages.swift index 9a3359f..a5b44c0 100644 --- a/ConversationsClassic/AppData/Client/Client+MartinMessages.swift +++ b/ConversationsClassic/AppData/Client/Client+MartinMessages.swift @@ -39,6 +39,8 @@ final class ClientMartinMessagesManager { var contentType: MessageContentType = .text if message.hints.contains(.noStore) { contentType = .typing + // for now just skip it + return } // From/To diff --git a/ConversationsClassic/AppData/Store/ConversationStore.swift b/ConversationsClassic/AppData/Store/ConversationStore.swift index fac55ad..dac3f9c 100644 --- a/ConversationsClassic/AppData/Store/ConversationStore.swift +++ b/ConversationsClassic/AppData/Store/ConversationStore.swift @@ -12,23 +12,24 @@ final class ConversationStore: ObservableObject { private let blockSize = Const.messagesPageSize private let messagesMax = Const.messagesMaxSize - private var messagesObservation: AnyDatabaseCancellable + private var messagesCancellable: AnyCancellable? init(roster: Roster, client: Client) { self.client = client self.roster = roster - - // observe change messages in database - messagesObservation = DatabaseRegionObservation(tracking: Message.all()).start(in: Database.shared.dbQueue) { _ in - // Handle error - } onChange: { _ in - print("Messages were changed") - } } } extension ConversationStore { func loadMoreBackward() async { + let earliestDate = messages.last?.date ?? Date() + resubscribe(.before(earliestDate)) + // let fetchedMessages = await fetchBlock(earliestDate, nil) + // messages.append(contentsOf: fetchedMessages) + // if messages.count > messagesMax { + // messages.removeFirst(messages.count - messagesMax) + // } + // guard let lastMessage = messages.last else { return } // let messages = await fetchBlock(lastMessage.date, nil) // self.messages.append(contentsOf: messages) @@ -41,17 +42,66 @@ extension ConversationStore { } } -extension ConversationStore { - private func fetchBlock(_ beforeDate: Date?, _ afterDate: Date?) async -> [Message] { - print(beforeDate, afterDate) - return [] - // let messages = await client.fetchMessages() - // self.messages.append(contentsOf: messages) +private extension ConversationStore { + enum FetchDirection { + case before(Date) + case after(Date) } - private func cutMessages() { - // if messages.count > messagesMax { - // messages.removeFirst(messages.count - messagesMax) - // } + func resubscribe(_ side: FetchDirection) { + switch side { + case .before(let date): + messagesCancellable = ValueObservation.tracking(Message + .filter( + (Column("to") == roster.bareJid && Column("from") == roster.contactBareJid) || + (Column("from") == roster.bareJid && Column("to") == roster.contactBareJid) + ) + .filter(Column("date") < date) + .limit(blockSize) + .order(Column("date").desc) + .fetchAll + ) + .publisher(in: Database.shared.dbQueue, scheduling: .immediate) + .sink { _ in + } receiveValue: { [weak self] messages in + self?.processFetched(messages, side) + } + + case .after(let date): + messagesCancellable = ValueObservation.tracking(Message + .filter( + (Column("to") == roster.bareJid && Column("from") == roster.contactBareJid) || + (Column("from") == roster.bareJid && Column("to") == roster.contactBareJid) + ) + .filter(Column("date") > date) + .limit(blockSize) + .order(Column("date").desc) + .fetchAll + ) + .publisher(in: Database.shared.dbQueue, scheduling: .immediate) + .sink { _ in + } receiveValue: { [weak self] messages in + self?.processFetched(messages, side) + } + } + } + + func processFetched(_ messages: [Message], _ side: FetchDirection) { + switch side { + case .before: + self.messages.append(contentsOf: messages) + + case .after: + self.messages.insert(contentsOf: messages, at: 0) + } + + Task { + await processAttachments(messages) + } + } + + func processAttachments(_ messages: [Message]) async { + // load attachment here + print(messages.count) } } diff --git a/ConversationsClassic/View/Main/Conversation/ConversationScreen.swift b/ConversationsClassic/View/Main/Conversation/ConversationScreen.swift index c9f4ff2..12e71ec 100644 --- a/ConversationsClassic/View/Main/Conversation/ConversationScreen.swift +++ b/ConversationsClassic/View/Main/Conversation/ConversationScreen.swift @@ -101,6 +101,9 @@ struct ConversationScreen: View { .safeAreaInset(edge: .bottom, spacing: 0) { ConversationTextInput(autoScroll: $autoScroll) } + .task { + await conversation.loadMoreBackward() + } } }