mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-31 07:30:40 +00:00
Merge commit 'd1bcfbc670080b90e187aa42075670febd43685e'
This commit is contained in:
commit
558bf41c4a
@ -135,14 +135,48 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
return self
|
||||
}
|
||||
|
||||
private func resolve(persons: [INPerson]?, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
|
||||
guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
|
||||
completion([INPersonResolutionResult.notRequired()])
|
||||
return
|
||||
enum ResolveResult {
|
||||
case success(INPerson)
|
||||
case disambiguation([INPerson])
|
||||
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 {
|
||||
completion([INPersonResolutionResult.needsValue()])
|
||||
completion([.needsValue])
|
||||
return
|
||||
}
|
||||
|
||||
@ -164,12 +198,12 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
}
|
||||
|
||||
if filteredPersons.isEmpty {
|
||||
completion([INPersonResolutionResult.needsValue()])
|
||||
completion([.noResult])
|
||||
return
|
||||
}
|
||||
|
||||
if filteredPersons.count > 1 {
|
||||
completion([INPersonResolutionResult.disambiguation(with: filteredPersons)])
|
||||
completion([.disambiguation(filteredPersons)])
|
||||
return
|
||||
}
|
||||
|
||||
@ -182,7 +216,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
}
|
||||
|
||||
if allPersonsAlreadyMatched {
|
||||
completion([INPersonResolutionResult.success(with: filteredPersons[0])])
|
||||
completion([.success(filteredPersons[0])])
|
||||
return
|
||||
}
|
||||
|
||||
@ -221,22 +255,29 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
self.resolvePersonsDisposable.set((signal
|
||||
|> deliverOnMainQueue).start(next: { peers in
|
||||
if peers.isEmpty {
|
||||
completion([INPersonResolutionResult.needsValue()])
|
||||
completion([.needsValue])
|
||||
} else {
|
||||
completion(peers.map { stableId, user in
|
||||
let person = personWithUser(stableId: stableId, user: user)
|
||||
return INPersonResolutionResult.success(with: person)
|
||||
})
|
||||
completion(peers.map { .success(personWithUser(stableId: $0, user: $1)) })
|
||||
}
|
||||
}, error: { error in
|
||||
completion([INPersonResolutionResult.unsupported()])
|
||||
completion([.skip])
|
||||
}))
|
||||
}
|
||||
|
||||
// MARK: - INSendMessageIntentHandling
|
||||
|
||||
func resolveRecipients(for intent: INSendMessageIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
|
||||
if #available(iOSApplicationExtension 11.0, *) {
|
||||
guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
|
||||
completion([INPersonResolutionResult.notRequired()])
|
||||
return
|
||||
}
|
||||
self.resolve(persons: intent.recipients, with: { result in
|
||||
completion(result.map { $0.personResolutionResult })
|
||||
})
|
||||
}
|
||||
|
||||
@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()
|
||||
|
||||
@ -261,18 +302,21 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
self.resolvePersonsDisposable.set((signal
|
||||
|> deliverOnMainQueue).start(next: { person in
|
||||
if let person = person {
|
||||
completion([INPersonResolutionResult.success(with: person)])
|
||||
completion([INSendMessageRecipientResolutionResult.success(with: person)])
|
||||
} else {
|
||||
completion([INPersonResolutionResult.needsValue()])
|
||||
completion([INSendMessageRecipientResolutionResult.needsValue()])
|
||||
}
|
||||
}, error: { error in
|
||||
completion([INPersonResolutionResult.notRequired()])
|
||||
completion([INSendMessageRecipientResolutionResult.unsupported(forReason: .noAccount)])
|
||||
}))
|
||||
} else {
|
||||
self.resolve(persons: intent.recipients, with: completion)
|
||||
guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
|
||||
completion([INSendMessageRecipientResolutionResult.notRequired()])
|
||||
return
|
||||
}
|
||||
} else {
|
||||
self.resolve(persons: intent.recipients, with: completion)
|
||||
self.resolve(persons: intent.recipients, with: { result in
|
||||
completion(result.map { $0.sendMessageRecipientResulutionResult })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,7 +512,13 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
||||
// MARK: - INStartAudioCallIntentHandling
|
||||
|
||||
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) {
|
||||
|
@ -95,14 +95,17 @@ final class AlertControllerNode: ASDisplayNode {
|
||||
self.bottomDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.leftDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.rightDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.containerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { [weak self] _ in
|
||||
self.containerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { [weak self] finished in
|
||||
if finished {
|
||||
self?.centerDimView.backgroundColor = nil
|
||||
self?.centerDimView.image = generateStretchableFilledCircleImage(radius: 16.0, color: nil, backgroundColor: UIColor(white: 0.0, alpha: 0.5))
|
||||
}
|
||||
})
|
||||
self.containerNode.layer.animateSpring(from: 0.8 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, removeOnCompletion: true, additive: false, completion: nil)
|
||||
}
|
||||
|
||||
func animateOut(completion: @escaping () -> Void) {
|
||||
self.containerNode.layer.removeAllAnimations()
|
||||
self.centerDimView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
||||
self.centerDimView.image = nil
|
||||
|
||||
|
@ -1121,13 +1121,13 @@ final class SharedApplicationContext {
|
||||
Logger.shared.log("App \(self.episodeId)", "isActive = \(value)")
|
||||
})
|
||||
|
||||
/*if let url = launchOptions?[.url] {
|
||||
if let url = launchOptions?[.url] {
|
||||
if let url = url as? URL, url.scheme == "tg" {
|
||||
self.openUrlWhenReady(url: url.absoluteString)
|
||||
} else if let url = url as? String, url.lowercased().hasPrefix("tg://") {
|
||||
self.openUrlWhenReady(url: url)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if application.applicationState == .active {
|
||||
self.isInForegroundValue = true
|
||||
@ -1845,7 +1845,7 @@ final class SharedApplicationContext {
|
||||
notificationCenter.getNotificationSettings(completionHandler: { settings in
|
||||
switch (settings.authorizationStatus, authorize) {
|
||||
case (.authorized, _), (.notDetermined, true):
|
||||
notificationCenter.requestAuthorization(options: [.badge, .sound, .alert, .carPlay], completionHandler: { result, _ in
|
||||
notificationCenter.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: { result, _ in
|
||||
completion(result)
|
||||
if result {
|
||||
Queue.mainQueue().async {
|
||||
@ -1867,7 +1867,7 @@ final class SharedApplicationContext {
|
||||
}
|
||||
|
||||
var carPlayOptions = options
|
||||
carPlayOptions.insert(.allowInCarPlay)
|
||||
//carPlayOptions.insert(.allowInCarPlay)
|
||||
|
||||
unknownMessageCategory = UNNotificationCategory(identifier: "unknown", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
replyMessageCategory = UNNotificationCategory(identifier: "withReply", actions: [reply], intentIdentifiers: [INSearchForMessagesIntentIdentifier], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: carPlayOptions)
|
||||
@ -1878,7 +1878,7 @@ final class SharedApplicationContext {
|
||||
muteMessageCategory = UNNotificationCategory(identifier: "withMute", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
muteMediaMessageCategory = UNNotificationCategory(identifier: "withMuteMedia", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
} else {
|
||||
let carPlayOptions: UNNotificationCategoryOptions = [.allowInCarPlay]
|
||||
let carPlayOptions: UNNotificationCategoryOptions = [] //[.allowInCarPlay]
|
||||
|
||||
unknownMessageCategory = UNNotificationCategory(identifier: "unknown", actions: [], intentIdentifiers: [], options: [])
|
||||
replyMessageCategory = UNNotificationCategory(identifier: "withReply", actions: [reply], intentIdentifiers: [INSearchForMessagesIntentIdentifier], options: carPlayOptions)
|
||||
|
@ -15,7 +15,7 @@ private func timerValueString(days: Int32, hours: Int32, minutes: Int32, color:
|
||||
|
||||
var hoursString = ""
|
||||
if hours > 0 || days > 0 {
|
||||
daysString = strings.MessageTimer_Hours(hours) + " "
|
||||
hoursString = strings.MessageTimer_Hours(hours) + " "
|
||||
}
|
||||
|
||||
let minutesString = strings.MessageTimer_Minutes(minutes)
|
||||
|
@ -846,6 +846,14 @@ public class ChatListController: TelegramBaseController, UIViewControllerPreview
|
||||
}
|
||||
}
|
||||
|
||||
self.chatListDisplayNode.isEmptyUpdated = { [weak self] isEmpty in
|
||||
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode, let validLayout = strongSelf.validLayout {
|
||||
if isEmpty {
|
||||
searchContentNode.updateListVisibleContentOffset(.known(0.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.chatListDisplayNode.toolbarActionSelected = { [weak self] action in
|
||||
self?.toolbarActionSelected(action: action)
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ final class ChatListControllerNode: ASDisplayNode {
|
||||
var requestOpenMessageFromSearch: ((Peer, MessageId) -> Void)?
|
||||
var requestAddContact: ((String) -> Void)?
|
||||
var dismissSelf: (() -> Void)?
|
||||
var isEmptyUpdated: ((Bool) -> Void)?
|
||||
|
||||
let debugListView = ListView()
|
||||
|
||||
@ -99,6 +100,7 @@ final class ChatListControllerNode: ASDisplayNode {
|
||||
if let (layout, navigationHeight, visualNavigationHeight) = strongSelf.containerLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, visualNavigationHeight: visualNavigationHeight, transition: .immediate)
|
||||
}
|
||||
strongSelf.isEmptyUpdated?(true)
|
||||
}
|
||||
case .notEmpty(false):
|
||||
if case .group = strongSelf.groupId {
|
||||
|
@ -19,6 +19,8 @@ extension UnicodeScalar {
|
||||
return true
|
||||
case 0x1f004:
|
||||
return true
|
||||
case 0x2764:
|
||||
return true
|
||||
case 0x270b, 0x2728:
|
||||
return true
|
||||
default:
|
||||
|
@ -294,7 +294,9 @@ public class ShareRootControllerImpl {
|
||||
}
|
||||
|
||||
cancelImpl = { [weak shareController] in
|
||||
shareController?.dismiss()
|
||||
shareController?.dismiss(completion: { [weak self] in
|
||||
self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||
})
|
||||
}
|
||||
|
||||
if let strongSelf = self {
|
||||
|
Loading…
x
Reference in New Issue
Block a user