import Foundation import monalxmpp final class WrapperChat: ObservableObject { @Published private(set) var messages: [Message] = [] @Published var replyText: String = "" @Published private(set) var mamRequestInProgress = false @Published var isOmemoEnabled: Bool { didSet { toggleOmemo(isOmemoEnabled) } } let contact: Contact let account: Account private let xmpp: MLXMPPManager private let db: DataLayer private let monalContact: MLContact private var notificationObservers: [AnyObject] = [] init?(with: Contact, account: Account) { contact = with xmpp = MLXMPPManager.sharedInstance() db = DataLayer.sharedInstance() self.account = account guard let monalContact = db.contactList() .first(where: { $0.accountID.intValue == with.ownerId }) else { return nil } self.monalContact = monalContact isOmemoEnabled = monalContact.isEncrypted subscribe() reloadMessages() } init?(with: Chat, account: Account) { xmpp = MLXMPPManager.sharedInstance() db = DataLayer.sharedInstance() self.account = account guard let monalContact = db.contactList() .first(where: { $0.accountID.intValue == with.accountId }) else { return nil } self.monalContact = monalContact isOmemoEnabled = monalContact.isEncrypted guard let contact = Contact(monalContact) else { return nil } self.contact = contact subscribe() reloadMessages() // guard let account = accounts.first(where: { $0.id == with.accountId }) else { return nil } // // var contact = contacts.first(where: { $0.ownerId == with.accountId && $0.contactJid == with.participantJid }) // if contact == nil { // let semaphore = DispatchSemaphore(value: 0) // Task { // await addContact(contactJid: with.participantJid, forAccountID: with.accountId) // semaphore.signal() // } // semaphore.wait() // contact = contacts.first(where: { $0.ownerId == with.accountId && $0.contactJid == with.participantJid }) // } // // guard let contact else { return nil } // let chatModel = WrapperChat(account: account, contact: contact, db: db, xmpp: xmpp) // return chatModel } deinit { notificationObservers.forEach { NotificationCenter.default.removeObserver($0) } } var chatTitle: String { contact.name } func sendText(_ text: String) { let newMessageId = UUID().uuidString let histId = db.addMessageHistory( to: contact.contactJid, forAccount: monalContact.accountID, withMessage: text, actuallyFrom: account.jid, withId: newMessageId, encrypted: monalContact.isEncrypted, messageType: kMessageTypeText, mimeType: nil, size: nil ) if let newMlMessage = db.message(forHistoryID: histId), let message = Message(newMlMessage) { messages.insert(message, at: 0) } print("CCCCC", newMessageId) xmpp.sendMessage(text, to: monalContact, isEncrypted: monalContact.isEncrypted, isUpload: false, messageId: newMessageId) } func requestMAM() { guard let acc = monalContact.account else { return } if mamRequestInProgress { return } mamRequestInProgress = true let lastStanzaId = messages.last?.stanzaId // last here because list is reversed ?? db.lastStanzaId(forAccount: NSNumber(value: contact.ownerId)) acc.setMAMQueryMostRecentFor(monalContact, before: lastStanzaId) { [weak self] msgs, _ in DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in self?.mamRequestInProgress = false print(msgs ?? []) } } } } private extension WrapperChat { func subscribe() { let notificationNames = [ kMonalNewMessageNotice, kMonalHistoryMessagesNotice, kMonalMessageDisplayedNotice, kMonalMessageErrorNotice, kMonalSentMessageNotice, kMonalMessageDisplayedNotice ] notificationObservers = notificationNames.map { name in NotificationCenter.default.addObserver(forName: Notification.Name(name), object: nil, queue: .main) { [weak self] notification in self?.processEvent(notification: notification) } } } func processEvent(notification: Notification) { switch notification.name.rawValue { case kMonalSentMessageNotice: if let stanza = notification.userInfo?["message"] as? XMPPStanza, let id = stanza.id { if let index = messages.firstIndex(where: { $0.stanzaId == id }) { print(index) } } default: guard let mlMessage = notification.userInfo?["message"] as? MLMessage else { return } guard let message = Message(mlMessage) else { return } if let index = messages.firstIndex(where: { $0.id == message.id }) { messages[index] = message } else { messages.append(message) messages.sort { $0.timestamp > $1.timestamp } } } } func reloadMessages() { let messages = db.messages(forContact: contact.contactJid, forAccount: NSNumber(value: contact.ownerId)) .compactMap { obj -> Message? in guard let message = obj as? MLMessage else { return nil } return Message(message) } .sorted { $0.timestamp > $1.timestamp } self.messages = messages } func toggleOmemo(_ new: Bool) { if monalContact.isEncrypted != new { monalContact.toggleEncryption(new) } } }