another.im-ios/Monal/another.im/XMPP/Wrappers/WrapperChat.swift

167 lines
5.5 KiB
Swift
Raw Normal View History

2024-12-02 15:50:23 +00:00
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
2024-12-06 12:34:31 +00:00
let account: Account
2024-12-02 15:50:23 +00:00
private let xmpp: MLXMPPManager
private let db: DataLayer
2024-12-06 07:55:59 +00:00
private let monalContact: MLContact
2024-12-02 15:50:23 +00:00
private var notificationObservers: [AnyObject] = []
2024-12-06 12:34:31 +00:00
init?(with: Contact, account: Account) {
2024-12-06 07:55:59 +00:00
contact = with
xmpp = MLXMPPManager.sharedInstance()
db = DataLayer.sharedInstance()
2024-12-06 12:34:31 +00:00
self.account = account
2024-12-02 15:50:23 +00:00
2024-12-06 07:55:59 +00:00
guard
let monalContact = db.contactList()
.first(where: {
2024-12-06 23:30:27 +00:00
$0.accountID.intValue == with.ownerId &&
$0.contactJid == with.contactJid
2024-12-06 07:55:59 +00:00
})
else { return nil }
self.monalContact = monalContact
2024-12-02 15:50:23 +00:00
isOmemoEnabled = monalContact.isEncrypted
2024-12-06 11:56:09 +00:00
subscribe()
2024-12-06 19:32:41 +00:00
reloadMessages()
2024-12-06 07:55:59 +00:00
}
2024-12-02 15:50:23 +00:00
2024-12-06 12:34:31 +00:00
init?(with: Chat, account: Account) {
2024-12-06 11:56:09 +00:00
xmpp = MLXMPPManager.sharedInstance()
db = DataLayer.sharedInstance()
2024-12-06 12:34:31 +00:00
self.account = account
2024-12-06 11:56:09 +00:00
guard
let monalContact = db.contactList()
.first(where: {
2024-12-06 23:30:27 +00:00
$0.accountID.intValue == with.accountId &&
$0.contactJid == with.participantJid
2024-12-06 11:56:09 +00:00
})
else { return nil }
self.monalContact = monalContact
isOmemoEnabled = monalContact.isEncrypted
guard let contact = Contact(monalContact) else { return nil }
self.contact = contact
subscribe()
2024-12-06 19:32:41 +00:00
reloadMessages()
2024-12-02 15:50:23 +00:00
}
deinit {
notificationObservers.forEach { NotificationCenter.default.removeObserver($0) }
}
var chatTitle: String {
contact.name
}
func sendText(_ text: String) {
let newMessageId = UUID().uuidString
2024-12-06 21:57:59 +00:00
let histId = db.addMessageHistory(
2024-12-02 15:50:23 +00:00
to: contact.contactJid,
forAccount: monalContact.accountID,
withMessage: text,
2024-12-06 12:34:31 +00:00
actuallyFrom: account.jid,
2024-12-02 15:50:23 +00:00
withId: newMessageId,
encrypted: monalContact.isEncrypted,
messageType: kMessageTypeText,
mimeType: nil,
size: nil
)
2024-12-06 21:57:59 +00:00
if let newMlMessage = db.message(forHistoryID: histId), let message = Message(newMlMessage) {
messages.insert(message, at: 0)
}
2024-12-02 15:50:23 +00:00
xmpp.sendMessage(text, to: monalContact, isEncrypted: monalContact.isEncrypted, isUpload: false, messageId: newMessageId)
}
func requestMAM() {
2024-12-06 11:56:09 +00:00
guard let acc = monalContact.account else { return }
2024-12-02 15:50:23 +00:00
if mamRequestInProgress { return }
mamRequestInProgress = true
2024-12-06 23:30:27 +00:00
let lastStanzaId = messages.last?.messageId // last here because list is reversed
2024-12-06 11:56:09 +00:00
?? db.lastStanzaId(forAccount: NSNumber(value: contact.ownerId))
2024-12-02 15:50:23 +00:00
acc.setMAMQueryMostRecentFor(monalContact, before: lastStanzaId) { [weak self] msgs, _ in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
self?.mamRequestInProgress = false
2024-12-06 23:30:27 +00:00
if let msgs, !msgs.isEmpty {
print(msgs)
self?.reloadMessages()
}
2024-12-02 15:50:23 +00:00
}
}
}
}
private extension WrapperChat {
func subscribe() {
2024-12-06 19:32:41 +00:00
let notificationNames = [
kMonalNewMessageNotice,
2024-12-06 21:32:17 +00:00
kMonalHistoryMessagesNotice,
2024-12-06 23:09:49 +00:00
kMonalMessageDisplayedNotice,
kMonalMessageErrorNotice,
kMonalSentMessageNotice,
2024-12-06 21:32:17 +00:00
kMonalMessageDisplayedNotice
2024-12-06 19:32:41 +00:00
]
notificationObservers = notificationNames.map { name in
NotificationCenter.default.addObserver(forName: Notification.Name(name), object: nil, queue: .main) { [weak self] notification in
self?.processEvent(notification: notification)
}
2024-12-02 15:50:23 +00:00
}
2024-12-06 19:32:41 +00:00
}
2024-12-02 15:50:23 +00:00
2024-12-06 19:32:41 +00:00
func processEvent(notification: Notification) {
2024-12-06 23:09:49 +00:00
switch notification.name.rawValue {
case kMonalSentMessageNotice:
if let stanza = notification.userInfo?["message"] as? XMPPStanza, let id = stanza.id {
2024-12-06 23:30:27 +00:00
if let index = messages.firstIndex(where: { $0.messageId == id }) {
var message = messages[index]
message.status = .sent
messages[index] = message
2024-12-06 23:09:49 +00:00
}
}
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 }
}
2024-12-02 15:50:23 +00:00
}
}
2024-12-06 19:32:41 +00:00
func reloadMessages() {
2024-12-02 15:50:23 +00:00
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)
}
}
}