SiriIntents: Added support for new recipient resolving

This commit is contained in:
Ilya Laktyushin 2019-08-05 21:26:50 +03:00
parent 8109a71d19
commit 199f65dde2

View File

@ -135,14 +135,48 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
return self return self
} }
private func resolve(persons: [INPerson]?, with completion: @escaping ([INPersonResolutionResult]) -> Void) { enum ResolveResult {
guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else { case success(INPerson)
completion([INPersonResolutionResult.notRequired()]) case disambiguation([INPerson])
return case needsValue
case noResult
case skip
@available(iOSApplicationExtension 11.0, *)
var sendMessageRecipientResulutionResult: INSendMessageRecipientResolutionResult {
switch self {
case let .success(person):
return .success(with: person)
case let .disambiguation(persons):
return .disambiguation(with: persons)
case .needsValue:
return .needsValue()
case .noResult:
return .unsupported()
case .skip:
return .notRequired()
}
} }
var personResolutionResult: INPersonResolutionResult {
switch self {
case let .success(person):
return .success(with: person)
case let .disambiguation(persons):
return .disambiguation(with: persons)
case .needsValue:
return .needsValue()
case .noResult:
return .unsupported()
case .skip:
return .notRequired()
}
}
}
private func resolve(persons: [INPerson]?, with completion: @escaping ([ResolveResult]) -> Void) {
guard let initialPersons = persons, !initialPersons.isEmpty else { guard let initialPersons = persons, !initialPersons.isEmpty else {
completion([INPersonResolutionResult.needsValue()]) completion([.needsValue])
return return
} }
@ -164,12 +198,12 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
} }
if filteredPersons.isEmpty { if filteredPersons.isEmpty {
completion([INPersonResolutionResult.needsValue()]) completion([.noResult])
return return
} }
if filteredPersons.count > 1 { if filteredPersons.count > 1 {
completion([INPersonResolutionResult.disambiguation(with: filteredPersons)]) completion([.disambiguation(filteredPersons)])
return return
} }
@ -182,7 +216,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
} }
if allPersonsAlreadyMatched { if allPersonsAlreadyMatched {
completion([INPersonResolutionResult.success(with: filteredPersons[0])]) completion([.success(filteredPersons[0])])
return return
} }
@ -221,30 +255,37 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
self.resolvePersonsDisposable.set((signal self.resolvePersonsDisposable.set((signal
|> deliverOnMainQueue).start(next: { peers in |> deliverOnMainQueue).start(next: { peers in
if peers.isEmpty { if peers.isEmpty {
completion([INPersonResolutionResult.needsValue()]) completion([.needsValue])
} else { } else {
completion(peers.map { stableId, user in completion(peers.map { .success(personWithUser(stableId: $0, user: $1)) })
let person = personWithUser(stableId: stableId, user: user)
return INPersonResolutionResult.success(with: person)
})
} }
}, error: { error in }, error: { error in
completion([INPersonResolutionResult.unsupported()]) completion([.skip])
})) }))
} }
// MARK: - INSendMessageIntentHandling // MARK: - INSendMessageIntentHandling
func resolveRecipients(for intent: INSendMessageIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) { func resolveRecipients(for intent: INSendMessageIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
if #available(iOSApplicationExtension 11.0, *) { guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
if let peerId = intent.conversationIdentifier.flatMap(Int64.init) { completion([INPersonResolutionResult.notRequired()])
let account = self.accountPromise.get() return
}
let signal = account self.resolve(persons: intent.recipients, with: { result in
|> introduceError(IntentHandlingError.self) completion(result.map { $0.personResolutionResult })
|> mapToSignal { account -> Signal<INPerson?, IntentHandlingError> in })
if let account = account { }
return matchingCloudContact(postbox: account.postbox, peerId: PeerId(peerId))
@available(iOSApplicationExtension 11.0, *)
func resolveRecipients(for intent: INSendMessageIntent, with completion: @escaping ([INSendMessageRecipientResolutionResult]) -> Void) {
if let peerId = intent.conversationIdentifier.flatMap(Int64.init) {
let account = self.accountPromise.get()
let signal = account
|> introduceError(IntentHandlingError.self)
|> mapToSignal { account -> Signal<INPerson?, IntentHandlingError> in
if let account = account {
return matchingCloudContact(postbox: account.postbox, peerId: PeerId(peerId))
|> introduceError(IntentHandlingError.self) |> introduceError(IntentHandlingError.self)
|> map { user -> INPerson? in |> map { user -> INPerson? in
if let user = user { if let user = user {
@ -252,27 +293,30 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
} else { } else {
return nil return nil
} }
}
} else {
return .fail(.generic)
} }
} else {
return .fail(.generic)
} }
self.resolvePersonsDisposable.set((signal
|> deliverOnMainQueue).start(next: { person in
if let person = person {
completion([INPersonResolutionResult.success(with: person)])
} else {
completion([INPersonResolutionResult.needsValue()])
}
}, error: { error in
completion([INPersonResolutionResult.notRequired()])
}))
} else {
self.resolve(persons: intent.recipients, with: completion)
} }
self.resolvePersonsDisposable.set((signal
|> deliverOnMainQueue).start(next: { person in
if let person = person {
completion([INSendMessageRecipientResolutionResult.success(with: person)])
} else {
completion([INSendMessageRecipientResolutionResult.needsValue()])
}
}, error: { error in
completion([INSendMessageRecipientResolutionResult.unsupported(forReason: .noAccount)])
}))
} else { } else {
self.resolve(persons: intent.recipients, with: completion) guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
completion([INSendMessageRecipientResolutionResult.notRequired()])
return
}
self.resolve(persons: intent.recipients, with: { result in
completion(result.map { $0.sendMessageRecipientResulutionResult })
})
} }
} }
@ -468,9 +512,15 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
// MARK: - INStartAudioCallIntentHandling // MARK: - INStartAudioCallIntentHandling
func resolveContacts(for intent: INStartAudioCallIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) { func resolveContacts(for intent: INStartAudioCallIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
self.resolve(persons: intent.contacts, with: completion) guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
completion([INPersonResolutionResult.notRequired()])
return
}
self.resolve(persons: intent.contacts, with: { result in
completion(result.map { $0.personResolutionResult })
})
} }
func handle(intent: INStartAudioCallIntent, completion: @escaping (INStartAudioCallIntentResponse) -> Void) { func handle(intent: INStartAudioCallIntent, completion: @escaping (INStartAudioCallIntentResponse) -> Void) {
self.actionDisposable.set((self.accountPromise.get() self.actionDisposable.set((self.accountPromise.get()
|> take(1) |> take(1)