2024-11-19 12:59:22 +00:00
|
|
|
import Foundation
|
|
|
|
import monalxmpp
|
|
|
|
|
2024-11-29 17:35:20 +00:00
|
|
|
enum AccountsAvailability {
|
|
|
|
case noAccounts
|
|
|
|
case allDisabled
|
|
|
|
case someEnabled
|
|
|
|
}
|
|
|
|
|
2024-12-02 15:50:23 +00:00
|
|
|
final class WrapperXMPP: ObservableObject {
|
2024-11-21 16:03:55 +00:00
|
|
|
@Published private(set) var accountsAvailability: AccountsAvailability = .noAccounts
|
|
|
|
@Published private(set) var accounts: [Account] = []
|
|
|
|
@Published private(set) var contacts: [Contact] = []
|
2024-11-23 16:23:56 +00:00
|
|
|
@Published private(set) var activeChats: [Chat] = []
|
2024-11-19 12:59:22 +00:00
|
|
|
|
2024-11-20 15:52:49 +00:00
|
|
|
private let xmpp: MLXMPPManager
|
|
|
|
private let db: DataLayer
|
2024-11-19 12:59:22 +00:00
|
|
|
|
2024-11-21 16:03:55 +00:00
|
|
|
private var notificationObservers: [AnyObject] = []
|
|
|
|
|
2024-11-19 12:59:22 +00:00
|
|
|
init() {
|
2024-11-21 13:32:38 +00:00
|
|
|
// init monalxmpp components
|
|
|
|
xmpp = MLXMPPManager.sharedInstance()
|
|
|
|
db = DataLayer.sharedInstance()
|
|
|
|
|
2024-11-21 16:03:55 +00:00
|
|
|
// subscribe to monalxmpp notifications and fire notification for update
|
|
|
|
subscribeToUpdates()
|
2024-12-04 15:00:37 +00:00
|
|
|
processOnStart()
|
|
|
|
// xmpp.reconnectAll()
|
|
|
|
// NotificationCenter.default.post(name: Notification.Name(kMonalRefresh), object: nil)
|
2024-11-21 16:03:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
deinit {
|
|
|
|
notificationObservers.forEach { NotificationCenter.default.removeObserver($0) }
|
2024-11-19 12:59:22 +00:00
|
|
|
}
|
2024-11-22 14:45:38 +00:00
|
|
|
}
|
2024-11-20 15:52:49 +00:00
|
|
|
|
2024-11-22 14:45:38 +00:00
|
|
|
// MARK: - Public
|
2024-12-02 15:50:23 +00:00
|
|
|
extension WrapperXMPP {
|
2024-11-20 15:52:49 +00:00
|
|
|
func tryLogin(_ login: String, _ password: String) async throws {
|
2024-11-29 17:43:27 +00:00
|
|
|
let scenario = ScenarioLogIn()
|
|
|
|
let result = await scenario.tryLogin(login, password)
|
2024-11-20 15:52:49 +00:00
|
|
|
if !result {
|
|
|
|
throw AimErrors.loginError
|
2024-11-19 12:59:22 +00:00
|
|
|
} else {
|
2024-12-04 15:00:37 +00:00
|
|
|
processOnStart()
|
2024-11-19 12:59:22 +00:00
|
|
|
}
|
|
|
|
}
|
2024-11-22 14:45:38 +00:00
|
|
|
|
2024-11-22 16:34:56 +00:00
|
|
|
func addContact(contactJid: String, forAccountID: Int) async {
|
2024-11-22 16:54:07 +00:00
|
|
|
let contact = MLContact.createContact(fromJid: contactJid, andAccountID: NSNumber(value: forAccountID))
|
|
|
|
xmpp.add(contact)
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteContact(_ contact: Contact) async throws {
|
|
|
|
if let mlContact = db.contactList().first(where: { $0.contactJid == contact.contactJid }) {
|
|
|
|
xmpp.remove(mlContact)
|
|
|
|
} else {
|
|
|
|
throw AimErrors.contactRemoveError
|
2024-11-22 16:34:56 +00:00
|
|
|
}
|
2024-11-22 14:45:38 +00:00
|
|
|
}
|
2024-11-23 23:22:07 +00:00
|
|
|
|
2024-12-02 15:50:23 +00:00
|
|
|
func chat(with: Contact) -> WrapperChat {
|
2024-11-25 13:14:23 +00:00
|
|
|
// swiftlint:disable:next force_unwrapping
|
|
|
|
let account = accounts.first { $0.id == with.ownerId }!
|
2024-12-02 15:50:23 +00:00
|
|
|
let chatModel = WrapperChat(account: account, contact: with, db: db, xmpp: xmpp)
|
2024-11-23 23:22:07 +00:00
|
|
|
return chatModel
|
|
|
|
}
|
2024-11-25 10:51:00 +00:00
|
|
|
|
2024-12-02 15:50:23 +00:00
|
|
|
func chat(with: Chat) -> WrapperChat? {
|
2024-11-25 13:14:23 +00:00
|
|
|
guard let account = accounts.first(where: { $0.id == with.accountId }) else { return nil }
|
2024-11-28 16:34:41 +00:00
|
|
|
|
|
|
|
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()
|
|
|
|
refreshChats()
|
|
|
|
refreshContacts()
|
|
|
|
contact = contacts.first(where: { $0.ownerId == with.accountId && $0.contactJid == with.participantJid })
|
|
|
|
}
|
|
|
|
|
|
|
|
guard let contact else { return nil }
|
2024-12-02 15:50:23 +00:00
|
|
|
let chatModel = WrapperChat(account: account, contact: contact, db: db, xmpp: xmpp)
|
2024-11-25 10:51:00 +00:00
|
|
|
return chatModel
|
|
|
|
}
|
2024-11-19 12:59:22 +00:00
|
|
|
}
|
2024-11-20 15:52:49 +00:00
|
|
|
|
2024-11-21 16:03:55 +00:00
|
|
|
// MARK: - Handle notifications
|
2024-12-02 15:50:23 +00:00
|
|
|
private extension WrapperXMPP {
|
2024-12-04 15:00:37 +00:00
|
|
|
// Subsribe to monalxmpp events
|
2024-11-21 16:03:55 +00:00
|
|
|
func subscribeToUpdates() {
|
2024-12-04 15:00:37 +00:00
|
|
|
notificationObservers.append(
|
|
|
|
NotificationCenter.default.addObserver(forName: Notification.Name(kMonalRefresh), object: nil, queue: .main) { [weak self] notification in
|
|
|
|
self?.processEvent(kMonalRefresh, notification.object)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
notificationObservers.append(
|
|
|
|
NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRefresh), object: nil, queue: .main) { [weak self] notification in
|
|
|
|
self?.processEvent(kMonalContactRefresh, notification.object)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
notificationObservers.append(
|
|
|
|
NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRemoved), object: nil, queue: .main) { [weak self] notification in
|
|
|
|
self?.processEvent(kMonalContactRemoved, notification.object)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
2024-11-21 16:03:55 +00:00
|
|
|
|
2024-12-04 15:00:37 +00:00
|
|
|
// Process monalxmpp events
|
|
|
|
func processEvent(_ notificationName: String, _ object: Any?) {
|
2024-12-04 15:03:20 +00:00
|
|
|
switch notificationName {
|
|
|
|
case kMonalRefresh:
|
|
|
|
print("refresh?")
|
|
|
|
|
|
|
|
case kMonalContactRefresh:
|
|
|
|
if let mlContact = object as? MLContact {
|
|
|
|
if let updated = Contact(mlContact), let index = contacts.firstIndex(where: { $0.id == mlContact.id }) {
|
|
|
|
contacts[index] = updated
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case kMonalContactRemoved:
|
|
|
|
if let mlContact = object as? MLContact {
|
|
|
|
contacts = contacts.filter { $0.id != mlContact.id }
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break
|
|
|
|
}
|
2024-11-22 13:12:09 +00:00
|
|
|
}
|
2024-11-21 16:03:55 +00:00
|
|
|
|
2024-12-04 15:00:37 +00:00
|
|
|
// Initital monalxmpp db fetch
|
|
|
|
func processOnStart() {
|
|
|
|
// get all accounts and contacts once
|
2024-11-22 13:12:09 +00:00
|
|
|
let accounts = db.accountList()
|
|
|
|
.compactMap { dict -> Account? in
|
|
|
|
guard let dict = dict as? NSDictionary else { return nil }
|
|
|
|
return Account(dict)
|
|
|
|
}
|
|
|
|
self.accounts = accounts
|
|
|
|
|
2024-12-04 15:00:37 +00:00
|
|
|
// check if active accounts existed
|
2024-11-22 13:12:09 +00:00
|
|
|
if accounts.isEmpty {
|
|
|
|
accountsAvailability = .noAccounts
|
|
|
|
} else if accounts.filter({ $0.isEnabled }).isEmpty {
|
|
|
|
accountsAvailability = .allDisabled
|
|
|
|
} else {
|
|
|
|
accountsAvailability = .someEnabled
|
2024-11-21 16:03:55 +00:00
|
|
|
}
|
2024-11-23 16:23:56 +00:00
|
|
|
|
2024-12-04 15:00:37 +00:00
|
|
|
// get all contacts
|
|
|
|
if !accounts.isEmpty {
|
|
|
|
contacts = db.contactList()
|
|
|
|
.filter { $0.isSubscribedTo || $0.hasOutgoingContactRequest || $0.isSubscribedFrom }
|
|
|
|
.filter { !$0.isSelfChat } // removed for now
|
|
|
|
.compactMap { Contact($0) }
|
|
|
|
|
|
|
|
// get active chats
|
|
|
|
if !contacts.isEmpty {
|
|
|
|
activeChats = db.activeContacts(withPinned: false)
|
|
|
|
.compactMap {
|
|
|
|
guard let contact = $0 as? MLContact else { return nil }
|
|
|
|
return Chat(contact)
|
|
|
|
}
|
2024-11-23 16:23:56 +00:00
|
|
|
}
|
2024-12-04 15:00:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// try reconnect active clients
|
|
|
|
xmpp.connectIfNecessary()
|
2024-11-23 16:23:56 +00:00
|
|
|
}
|
2024-11-21 16:03:55 +00:00
|
|
|
}
|