This commit is contained in:
fmodf 2024-06-26 11:29:30 +02:00
parent 20c89c65e9
commit 995d627fde
5 changed files with 45 additions and 56 deletions

View file

@ -5,4 +5,6 @@ enum DatabaseAction: Codable {
case storedRostersLoaded(rosters: [Roster]) case storedRostersLoaded(rosters: [Roster])
case storedChatsLoaded(chats: [Chat]) case storedChatsLoaded(chats: [Chat])
case storeMessageFailed(reason: String)
} }

View file

@ -16,25 +16,6 @@ final class ConversationMiddleware {
case .conversationAction(.makeConversationActive): case .conversationAction(.makeConversationActive):
return Just(AppAction.changeFlow(.conversation)).eraseToAnyPublisher() return Just(AppAction.changeFlow(.conversation)).eraseToAnyPublisher()
// case .xmppAction(.xmppMessageReceived(let message)):
// return Future<AppAction, Never> { promise in
// let currentChat = state.conversationsState.currentChat
// if message.from == currentChat?.participant, message.to == currentChat?.account, message.contentType != .typing {
// promise(.success(.conversationAction(.messageForCurrentConversationReceived(message))))
// } else {
// promise(.success(.empty))
// }
// }
// .eraseToAnyPublisher()
//
// case .conversationAction(.messageForCurrentConversationReceived(let message)):
// return Future<AppAction, Never> { promise in
// var currentMessages = state.conversationsState.currentMessages
// currentMessages.append(message)
// promise(.success(.conversationAction(.messagesUpdated(messages: currentMessages))))
// }
// .eraseToAnyPublisher()
default: default:
return Empty().eraseToAnyPublisher() return Empty().eraseToAnyPublisher()
} }

View file

@ -34,6 +34,7 @@ final class DatabaseMiddleware {
.store(in: &cancellables) .store(in: &cancellables)
} }
// swiftlint:disable:next function_body_length
func middleware(state _: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> { func middleware(state _: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {
switch action { switch action {
// MARK: Accounts // MARK: Accounts
@ -156,52 +157,27 @@ final class DatabaseMiddleware {
// MARK: Conversation and messages // MARK: Conversation and messages
case .conversationAction(.makeConversationActive(let chat, _)): case .conversationAction(.makeConversationActive(let chat, _)):
return Future<AppAction, Never> { [weak self] promise in subscribeToMessages(chat: chat)
guard let wSelf = self else { return Empty().eraseToAnyPublisher()
promise(.success(.empty))
return
}
// Observe changes for current conversation
wSelf.conversationCancellables = []
ValueObservation
.tracking(
Message
.filter(
Column("from") == chat.account ||
Column("from") == chat.participant ||
Column("to") == chat.participant ||
Column("to") == chat.participant
)
.order(Column("timestamp").asc)
.fetchAll
)
.publisher(in: wSelf.database._db, scheduling: .immediate)
.sink { _ in
// Handle completion
} receiveValue: { messages in
DispatchQueue.main.async {
store.dispatch(.conversationAction(.messagesUpdated(messages: messages)))
}
}
.store(in: &wSelf.conversationCancellables)
promise(.success(.empty))
}
.eraseToAnyPublisher()
case .xmppAction(.xmppMessageReceived(let message)): case .xmppAction(.xmppMessageReceived(let message)):
return Future<AppAction, Never> { promise in return Future<AppAction, Never> { promise in
Task(priority: .background) { [weak self] in Task(priority: .background) { [weak self] in
guard let database = self?.database else { guard let database = self?.database else {
promise(.success(.databaseAction(.storeMessageFailed(reason: L10n.Global.Error.genericDbError))))
return
}
guard message.contentType != .typing else {
promise(.success(.empty)) promise(.success(.empty))
return return
} }
do { do {
try database._db.write { db in try database._db.write { db in
try message.insert(db) try message.insert(db)
promise(.success(.empty))
} }
promise(.success(.empty))
} catch { } catch {
promise(.success(.databaseAction(.updateAccountFailed))) promise(.success(.databaseAction(.storeMessageFailed(reason: error.localizedDescription))))
} }
} }
} }
@ -215,3 +191,29 @@ final class DatabaseMiddleware {
} }
} }
} }
private extension DatabaseMiddleware {
func subscribeToMessages(chat: Chat) {
conversationCancellables = []
ValueObservation
.tracking(
Message
.filter(
Column("to") == chat.account ||
(Column("from") == chat.account && Column("to") == chat.participant)
)
.order(Column("date").asc)
.fetchAll
)
.publisher(in: database._db, scheduling: .immediate)
.sink { res in
print("!!!---Messages received: \(res)")
// Handle completion
} receiveValue: { messages in
DispatchQueue.main.async {
store.dispatch(.conversationAction(.messagesUpdated(messages: messages)))
}
}
.store(in: &conversationCancellables)
}
}

View file

@ -1,5 +1,6 @@
import Combine import Combine
import Foundation import Foundation
import SwiftUI
let isConsoleLoggingEnabled = false let isConsoleLoggingEnabled = false
@ -13,7 +14,8 @@ let isConsoleLoggingEnabled = false
var stateStr = "\(state)" var stateStr = "\(state)"
stateStr = String(stateStr.prefix(prefixLength)) + " ..." stateStr = String(stateStr.prefix(prefixLength)) + " ..."
let str = "\(timeStr) ➡️ \(actionStr)\n\(timeStr)\(stateStr)\n" let str = "\(timeStr) \u{EA86} \(actionStr)\n\(timeStr) \u{F129} \(stateStr)\n"
print(str) print(str)
if isConsoleLoggingEnabled { if isConsoleLoggingEnabled {
NSLog(str) NSLog(str)
@ -30,9 +32,9 @@ let isConsoleLoggingEnabled = false
#endif #endif
enum LogLevels: String { enum LogLevels: String {
case info = "" case info = "\u{F449}"
case warning = "⚠️" case warning = "\u{F071}"
case error = "" case error = "\u{EA76}"
} }
// For database errors logging // For database errors logging

View file

@ -15,6 +15,8 @@ enum MessageContentType: String, Codable, DatabaseValueConvertible {
} }
struct Message: DBStorable, Equatable { struct Message: DBStorable, Equatable {
static let databaseTableName = "messages"
let id: String let id: String
let type: MessageType let type: MessageType
let contentType: MessageContentType let contentType: MessageContentType