wip
This commit is contained in:
parent
9f91741354
commit
8ce21712b7
|
@ -10,4 +10,5 @@ enum AppAction: Codable {
|
|||
case rostersAction(_ action: RostersAction)
|
||||
case chatsAction(_ action: ChatsAction)
|
||||
case conversationAction(_ action: ConversationAction)
|
||||
case messagesAction(_ action: MessagesAction)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
enum MessagesAction: Codable {
|
||||
case newMessageReceived(Message)
|
||||
case messageDraftUpdate(Message)
|
||||
}
|
|
@ -52,6 +52,7 @@ extension Database {
|
|||
table.column("toJid", .text).notNull()
|
||||
table.column("timestamp", .datetime).notNull()
|
||||
table.column("body", .text)
|
||||
table.column("type", .text).notNull()
|
||||
// table.column("isReaded", .boolean).notNull().defaults(to: false)
|
||||
// table.column("subject", .text)
|
||||
// table.column("threadId", .text)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import Combine
|
||||
|
||||
final class MessagesMiddleware {
|
||||
static let shared = MessagesMiddleware()
|
||||
|
||||
func middleware(state _: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {
|
||||
switch action {
|
||||
default:
|
||||
return Empty().eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,26 @@ final class XMPPMiddleware {
|
|||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
service.clientMessages.sink { client, martinMessage in
|
||||
print("---")
|
||||
print("Message received: \(martinMessage)")
|
||||
print("In client: \(client)")
|
||||
print("---")
|
||||
// guard let message = Message.mapMartinMessage(martinMessage) else {
|
||||
// return
|
||||
// }
|
||||
// if message.type == .writingProcessUpdate {
|
||||
// DispatchQueue.main.async {
|
||||
// store.dispatch(.messagesAction(.messageDraftUpdate(message)))
|
||||
// }
|
||||
// } else {
|
||||
// DispatchQueue.main.async {
|
||||
// store.dispatch(.messagesAction(.newMessageReceived(message)))
|
||||
// }
|
||||
// }
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func middleware(state: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {
|
||||
|
|
|
@ -1,30 +1,98 @@
|
|||
import Foundation
|
||||
import GRDB
|
||||
import Martin
|
||||
|
||||
enum MessageType: String, Codable, DatabaseValueConvertible {
|
||||
case chat
|
||||
case channel
|
||||
case groupchat
|
||||
}
|
||||
|
||||
enum MessageContentType: String, Codable, DatabaseValueConvertible {
|
||||
case text
|
||||
case image
|
||||
case video
|
||||
case audio
|
||||
case file
|
||||
case location
|
||||
case typing
|
||||
case invite
|
||||
}
|
||||
|
||||
struct Message: DBStorable, Equatable {
|
||||
static let databaseTableName = "messages"
|
||||
|
||||
struct MessageContainer: Stateable, DatabaseValueConvertible {
|
||||
let id: String
|
||||
let chatId: String
|
||||
let fromJid: String
|
||||
let toJid: String
|
||||
let timestamp: Date
|
||||
let body: String?
|
||||
// var isReaded: Bool
|
||||
// let subject: String?
|
||||
// let threadId: String?
|
||||
// let errorType: String?
|
||||
|
||||
var type: MessageType {
|
||||
.text
|
||||
}
|
||||
let type: MessageType
|
||||
let content: any MessageContent
|
||||
}
|
||||
|
||||
protocol MessageContent: Stateable, DatabaseValueConvertible {
|
||||
var type: MessageContentType { get }
|
||||
}
|
||||
|
||||
//
|
||||
// enum MessageType: String, Codable, DatabaseValueConvertible {
|
||||
// case text
|
||||
// case image
|
||||
// case video
|
||||
// case audio
|
||||
// case file
|
||||
// case location
|
||||
// case writingProcessUpdate
|
||||
// }
|
||||
//
|
||||
// struct Message: DBStorable, Equatable {
|
||||
// static let databaseTableName = "messages"
|
||||
//
|
||||
// let id: String
|
||||
// let chatId: String
|
||||
// let fromJid: String
|
||||
// let toJid: String
|
||||
// let timestamp: Date
|
||||
// let body: String?
|
||||
// let type: MessageType
|
||||
// }
|
||||
//
|
||||
// // Special extnesion for mapping Martin.Message to Message
|
||||
// extension Message {
|
||||
// static func mapMartinMessage(_ martinMessage: Martin.Message) -> Message? {
|
||||
// // for draft messages
|
||||
// if martinMessage.hints.contains(.noStore) {
|
||||
// return Message(
|
||||
// id: martinMessage.id ?? UUID().uuidString,
|
||||
// chatId: "none", // chat id will be filled later
|
||||
// fromJid: martinMessage.from?.bareJid.stringValue ?? "",
|
||||
// toJid: martinMessage.to?.bareJid.stringValue ?? "",
|
||||
// timestamp: Date(),
|
||||
// body: nil,
|
||||
// type: .writingProcessUpdate
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// // if regular message contains no body - return nil
|
||||
// guard let body = martinMessage.body else {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// print("Message received: \(martinMessage)")
|
||||
// print("From: \(martinMessage.from)")
|
||||
// print("To: \(martinMessage.to)")
|
||||
// print("Body: \(martinMessage.body)")
|
||||
// print("Type: \(martinMessage.type)")
|
||||
// print("Id: \(martinMessage.id)")
|
||||
// print("Subject: \(martinMessage.subject)")
|
||||
// print("----")
|
||||
// print("!!!!!-----Message body: \(body)")
|
||||
//
|
||||
// // parse regular message
|
||||
// return nil
|
||||
// // Message(
|
||||
// // id: message.id,
|
||||
// // chatId: message.chatId,
|
||||
// // fromJid: message.from,
|
||||
// // toJid: message.to,
|
||||
// // timestamp: message.timestamp,
|
||||
// // body: message.body,
|
||||
// // type: MessageType(rawValue: message.type) ?? .text
|
||||
// // )
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -27,6 +27,9 @@ extension AppState {
|
|||
|
||||
case .conversationAction(let action):
|
||||
ConversationState.reducer(state: &state.conversationsState, action: action)
|
||||
|
||||
case .messagesAction:
|
||||
break // messages actions are processed by MessagesMiddleware, and other components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
struct ConversationState: Stateable {
|
||||
var currentChat: Chat?
|
||||
var dumb: Bool
|
||||
var currentMessages: [Message]
|
||||
}
|
||||
|
||||
// MARK: Init
|
||||
extension ConversationState {
|
||||
init() {
|
||||
dumb = false
|
||||
currentMessages = []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,19 @@ protocol MartinsManager: Martin.RosterManager & Martin.ChatManager {}
|
|||
final class XMPPService: ObservableObject {
|
||||
private let manager: MartinsManager
|
||||
private let clientStatePublisher = PassthroughSubject<(XMPPClient, XMPPClient.State), Never>()
|
||||
private var clientStateCancellables: [AnyCancellable] = []
|
||||
private let clientMessagesPublisher = PassthroughSubject<(XMPPClient, Martin.Message), Never>()
|
||||
private var clientStateCancellables: Set<AnyCancellable> = []
|
||||
private var clientMessagesCancellables: Set<AnyCancellable> = []
|
||||
|
||||
@Published private(set) var clients: [XMPPClient] = []
|
||||
var clientState: AnyPublisher<(XMPPClient, XMPPClient.State), Never> {
|
||||
clientStatePublisher.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
var clientMessages: AnyPublisher<(XMPPClient, Martin.Message), Never> {
|
||||
clientMessagesPublisher.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(manager: MartinsManager) {
|
||||
self.manager = manager
|
||||
}
|
||||
|
@ -29,14 +35,24 @@ final class XMPPService: ObservableObject {
|
|||
|
||||
// init and add clients
|
||||
for account in forAdd {
|
||||
// add client
|
||||
let client = makeClient(for: account, with: manager)
|
||||
clients.append(client)
|
||||
let cancellable = client.$state
|
||||
|
||||
// subscribe to client state
|
||||
client.$state
|
||||
.sink { [weak self] state in
|
||||
self?.clientStatePublisher.send((client, state))
|
||||
}
|
||||
.store(in: &clientStateCancellables)
|
||||
|
||||
// subscribe to client messages
|
||||
client.module(MessageModule.self).messagesPublisher
|
||||
.sink { [weak self] message in
|
||||
self?.clientMessagesPublisher.send((client, message.message))
|
||||
}
|
||||
.store(in: &clientMessagesCancellables)
|
||||
|
||||
clientStateCancellables.append(cancellable)
|
||||
client.login()
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@ let store = AppStore(
|
|||
XMPPMiddleware.shared.middleware,
|
||||
RostersMiddleware.shared.middleware,
|
||||
ChatsMiddleware.shared.middleware,
|
||||
ConversationMiddleware.shared.middleware
|
||||
ConversationMiddleware.shared.middleware,
|
||||
MessagesMiddleware.shared.middleware
|
||||
]
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue