mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
91 lines
3.4 KiB
Swift
91 lines
3.4 KiB
Swift
import Foundation
|
|
import Contacts
|
|
import SwiftSignalKit
|
|
import Postbox
|
|
import TelegramCore
|
|
|
|
private func authorizedContacts() -> Signal<Bool, NoError> {
|
|
return Signal { subscriber in
|
|
if #available(iOSApplicationExtension 9.0, *) {
|
|
if CNContactStore.authorizationStatus(for: .contacts) == .notDetermined {
|
|
let store = CNContactStore()
|
|
store.requestAccess(for: .contacts, completionHandler: { authorized, _ in
|
|
subscriber.putNext(authorized)
|
|
subscriber.putCompletion()
|
|
})
|
|
} else if CNContactStore.authorizationStatus(for: .contacts) == .authorized {
|
|
subscriber.putNext(true)
|
|
subscriber.putCompletion()
|
|
}
|
|
} else {
|
|
|
|
}
|
|
|
|
return EmptyDisposable
|
|
}
|
|
}
|
|
|
|
@available(iOSApplicationExtension 9.0, *)
|
|
private func retrieveContactsWithStore(_ store: CNContactStore) -> [DeviceContact] {
|
|
let keysToFetch: [CNKeyDescriptor] = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey as CNKeyDescriptor]
|
|
|
|
let request = CNContactFetchRequest(keysToFetch: keysToFetch)
|
|
request.unifyResults = true
|
|
|
|
var result: [DeviceContact] = []
|
|
let _ = try? store.enumerateContacts(with: request, usingBlock: { contact, _ in
|
|
var phoneNumbers: [DeviceContactPhoneNumber] = []
|
|
for number in contact.phoneNumbers {
|
|
phoneNumbers.append(DeviceContactPhoneNumber(label: number.label ?? "", number: number.value.stringValue))
|
|
}
|
|
result.append(DeviceContact(id: contact.identifier, firstName: contact.givenName, lastName: contact.familyName, phoneNumbers: phoneNumbers))
|
|
})
|
|
return result
|
|
}
|
|
|
|
@available(iOSApplicationExtension 9.0, *)
|
|
private func modernContacts() -> Signal<[DeviceContact], NoError> {
|
|
return authorizedContacts()
|
|
|> mapToSignal { authorized -> Signal<[DeviceContact], NoError> in
|
|
return Signal { subscriber in
|
|
let queue = Queue()
|
|
let disposable = MetaDisposable()
|
|
queue.async {
|
|
let store = CNContactStore()
|
|
var current = retrieveContactsWithStore(store)
|
|
subscriber.putNext(current)
|
|
|
|
let handle = NotificationCenter.default.addObserver(forName: NSNotification.Name.CNContactStoreDidChange, object: nil, queue: nil, using: { _ in
|
|
queue.async {
|
|
let updated = retrieveContactsWithStore(store)
|
|
if current != updated {
|
|
current = updated
|
|
subscriber.putNext(updated)
|
|
}
|
|
}
|
|
})
|
|
|
|
disposable.set(ActionDisposable {
|
|
NotificationCenter.default.removeObserver(handle)
|
|
})
|
|
}
|
|
return disposable
|
|
}
|
|
}
|
|
}
|
|
|
|
public final class DeviceContactsManager {
|
|
private let contactsValue = Promise<[DeviceContact]>()
|
|
public var contacts: Signal<[DeviceContact], NoError> {
|
|
return self.contactsValue.get()
|
|
}
|
|
|
|
init() {
|
|
if #available(iOSApplicationExtension 9.0, *) {
|
|
self.contactsValue.set(modernContacts())
|
|
} else {
|
|
|
|
}
|
|
}
|
|
}
|