diff --git a/ConversationsClassic/AppCore/Actions/DatabaseActions.swift b/ConversationsClassic/AppCore/Actions/DatabaseActions.swift index 5381970..1b2793c 100644 --- a/ConversationsClassic/AppCore/Actions/DatabaseActions.swift +++ b/ConversationsClassic/AppCore/Actions/DatabaseActions.swift @@ -5,4 +5,6 @@ enum DatabaseAction: Codable { case storedRostersLoaded(rosters: [Roster]) case storedChatsLoaded(chats: [Chat]) + + case storeMessageFailed(reason: String) } diff --git a/ConversationsClassic/AppCore/Middlewares/ConversationMiddleware.swift b/ConversationsClassic/AppCore/Middlewares/ConversationMiddleware.swift index 943a191..cd08b92 100644 --- a/ConversationsClassic/AppCore/Middlewares/ConversationMiddleware.swift +++ b/ConversationsClassic/AppCore/Middlewares/ConversationMiddleware.swift @@ -16,25 +16,6 @@ final class ConversationMiddleware { case .conversationAction(.makeConversationActive): return Just(AppAction.changeFlow(.conversation)).eraseToAnyPublisher() - // case .xmppAction(.xmppMessageReceived(let message)): - // return Future { 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 { promise in - // var currentMessages = state.conversationsState.currentMessages - // currentMessages.append(message) - // promise(.success(.conversationAction(.messagesUpdated(messages: currentMessages)))) - // } - // .eraseToAnyPublisher() - default: return Empty().eraseToAnyPublisher() } diff --git a/ConversationsClassic/AppCore/Middlewares/DatabaseMiddleware.swift b/ConversationsClassic/AppCore/Middlewares/DatabaseMiddleware.swift index e97518b..e5002ba 100644 --- a/ConversationsClassic/AppCore/Middlewares/DatabaseMiddleware.swift +++ b/ConversationsClassic/AppCore/Middlewares/DatabaseMiddleware.swift @@ -34,6 +34,7 @@ final class DatabaseMiddleware { .store(in: &cancellables) } + // swiftlint:disable:next function_body_length func middleware(state _: AppState, action: AppAction) -> AnyPublisher { switch action { // MARK: Accounts @@ -156,52 +157,27 @@ final class DatabaseMiddleware { // MARK: Conversation and messages case .conversationAction(.makeConversationActive(let chat, _)): - return Future { [weak self] promise in - guard let wSelf = self else { - 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() + subscribeToMessages(chat: chat) + return Empty().eraseToAnyPublisher() case .xmppAction(.xmppMessageReceived(let message)): return Future { promise in Task(priority: .background) { [weak self] in guard let database = self?.database else { + promise(.success(.databaseAction(.storeMessageFailed(reason: L10n.Global.Error.genericDbError)))) + return + } + guard message.contentType != .typing else { promise(.success(.empty)) return } do { try database._db.write { db in try message.insert(db) - promise(.success(.empty)) } + promise(.success(.empty)) } 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) + } +} diff --git a/ConversationsClassic/AppCore/Middlewares/LoggerMiddleware.swift b/ConversationsClassic/AppCore/Middlewares/LoggerMiddleware.swift index 272f319..2c9d5ed 100644 --- a/ConversationsClassic/AppCore/Middlewares/LoggerMiddleware.swift +++ b/ConversationsClassic/AppCore/Middlewares/LoggerMiddleware.swift @@ -1,5 +1,6 @@ import Combine import Foundation +import SwiftUI let isConsoleLoggingEnabled = false @@ -13,7 +14,8 @@ let isConsoleLoggingEnabled = false var stateStr = "\(state)" 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) if isConsoleLoggingEnabled { NSLog(str) @@ -30,9 +32,9 @@ let isConsoleLoggingEnabled = false #endif enum LogLevels: String { - case info = "ℹ️" - case warning = "⚠️" - case error = "❌" + case info = "\u{F449}" + case warning = "\u{F071}" + case error = "\u{EA76}" } // For database errors logging diff --git a/ConversationsClassic/AppCore/Models/Message.swift b/ConversationsClassic/AppCore/Models/Message.swift index 6c0c101..482fed4 100644 --- a/ConversationsClassic/AppCore/Models/Message.swift +++ b/ConversationsClassic/AppCore/Models/Message.swift @@ -15,6 +15,8 @@ enum MessageContentType: String, Codable, DatabaseValueConvertible { } struct Message: DBStorable, Equatable { + static let databaseTableName = "messages" + let id: String let type: MessageType let contentType: MessageContentType