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

166 lines
5.7 KiB
Swift
Raw Normal View History

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()
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
}
}
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-06 07:55:59 +00:00
func chat(with: Contact) -> WrapperChat? {
2024-12-06 12:34:31 +00:00
guard let account = accounts.first(where: { $0.id == with.ownerId }) else { return nil }
return WrapperChat(with: with, account: account)
2024-11-23 23:22:07 +00:00
}
2024-11-25 10:51:00 +00:00
2024-12-02 15:50:23 +00:00
func chat(with: Chat) -> WrapperChat? {
2024-12-06 12:34:31 +00:00
guard let account = accounts.first(where: { $0.id == with.accountId }) else { return nil }
return WrapperChat(with: with, account: account)
2024-11-25 10:51:00 +00:00
}
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
2024-12-05 17:14:22 +00:00
self?.processEvent(kMonalRefresh, notification.userInfo?["contact"])
2024-12-04 15:00:37 +00:00
}
)
notificationObservers.append(
NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRefresh), object: nil, queue: .main) { [weak self] notification in
2024-12-05 17:14:22 +00:00
self?.processEvent(kMonalContactRefresh, notification.userInfo?["contact"])
2024-12-04 15:00:37 +00:00
}
)
notificationObservers.append(
NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRemoved), object: nil, queue: .main) { [weak self] notification in
2024-12-05 17:14:22 +00:00
self?.processEvent(kMonalContactRemoved, notification.userInfo?["contact"])
}
)
notificationObservers.append(
NotificationCenter.default.addObserver(forName: Notification.Name(kMLResourceBoundNotice), object: nil, queue: .main) { [weak self] _ in
self?.processOnStart()
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// }
2024-12-04 15:00:37 +00:00
}
)
}
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:
2024-12-05 17:14:22 +00:00
if let mlContact = object as? MLContact, !mlContact.isSelfChat {
if let contact = Contact(mlContact) {
if let index = contacts.firstIndex(where: { $0.id == mlContact.id }) {
contacts[index] = contact
} else {
contacts.append(contact)
contacts.sort { $0.name < $1.name }
}
2024-12-04 15:03:20 +00:00
}
}
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
}