Donate send message intents when posting from share controller

Clear donated send message intents on logout
This commit is contained in:
Ilya Laktyushin 2019-11-07 18:31:36 +04:00
parent f3120ee918
commit 8ca47c3aef
8 changed files with 151 additions and 42 deletions

View File

@ -0,0 +1,23 @@
load("//Config:buck_rule_macros.bzl", "static_library")
static_library(
name = "AppIntents",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/TelegramCore:TelegramCore#shared",
"//submodules/SyncCore:SyncCore#shared",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#shared",
"//submodules/Display:Display#shared",
"//submodules/AccountContext:AccountContext",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/AvatarNode:AvatarNode",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
],
weak_frameworks = [
"Intents",
],
)

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>

View File

@ -0,0 +1,67 @@
import Foundation
import UIKit
import Intents
import Display
import Postbox
import TelegramCore
import SyncCore
import SwiftSignalKit
import TelegramPresentationData
import AvatarNode
import AccountContext
public func donateSendMessageIntent(account: Account, sharedContext: SharedAccountContext, peerIds: [PeerId]) {
if #available(iOSApplicationExtension 13.2, iOS 13.2, *) {
let _ = (account.postbox.transaction { transaction -> [Peer] in
var peers: [Peer] = []
for peerId in peerIds {
if peerId.namespace == Namespaces.Peer.CloudUser && peerId != account.peerId, let peer = transaction.getPeer(peerId) {
peers.append(peer)
}
}
return peers
}
|> mapToSignal { peers -> Signal<[(Peer, UIImage?)], NoError> in
var signals: [Signal<(Peer, UIImage?), NoError>] = []
for peer in peers {
let peerAndAvatar = (peerAvatarImage(account: account, peer: peer, authorOfMessage: nil, representation: peer.smallProfileImage, round: false) ?? .single(nil))
|> map { avatarImage in
return (peer, avatarImage)
}
signals.append(peerAndAvatar)
}
return combineLatest(signals)
}
|> deliverOnMainQueue).start(next: { peers in
for (peer, avatarImage) in peers {
guard let peer = peer as? TelegramUser, peer.botInfo == nil && !peer.flags.contains(.isSupport) else {
continue
}
let presentationData = sharedContext.currentPresentationData.with { $0 }
let recipientHandle = INPersonHandle(value: "tg\(peer.id.id)", type: .unknown)
var nameComponents = PersonNameComponents()
nameComponents.givenName = peer.firstName
nameComponents.familyName = peer.lastName
let displayTitle = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let recipient = INPerson(personHandle: recipientHandle, nameComponents: nameComponents, displayName: displayTitle, image: nil, contactIdentifier: nil, customIdentifier: "tg\(peer.id.id)")
let intent = INSendMessageIntent(recipients: [recipient], content: nil, speakableGroupName: INSpeakableString(spokenPhrase: displayTitle), conversationIdentifier: "tg\(peer.id.id)", serviceName: nil, sender: nil)
if let avatarImage = avatarImage, let avatarImageData = avatarImage.jpegData(compressionQuality: 0.8) {
intent.setImage(INImage(imageData: avatarImageData), forParameterNamed: \.groupName)
}
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .outgoing
interaction.groupIdentifier = "sendMessage_\(account.peerId.toInt64())"
interaction.donate()
}
})
}
}
public func deleteAllSendMessageIntents(accountPeerId: PeerId) {
if #available(iOS 10.0, *) {
INInteraction.delete(with: "sendMessage_\(accountPeerId.toInt64())")
}
}

View File

@ -23,6 +23,7 @@ static_library(
"//submodules/ActivityIndicator:ActivityIndicator",
"//submodules/AppBundle:AppBundle",
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
"//submodules/AppIntents:AppIntents",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -8,6 +8,7 @@ import TelegramCore
import SyncCore
import TelegramPresentationData
import AccountContext
import AppIntents
enum ShareState {
case preparing
@ -26,6 +27,7 @@ func openExternalShare(state: () -> Signal<ShareExternalState, NoError>) {
final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate {
private let sharedContext: SharedAccountContext
private var account: Account?
private var presentationData: PresentationData
private let externalShare: Bool
private let immediateExternalShare: Bool
@ -537,6 +539,10 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
peerIds = self.controllerInteraction!.selectedPeers.map { $0.peerId }
}
if let account = self.account {
donateSendMessageIntent(account: account, sharedContext: self.sharedContext, peerIds: peerIds)
}
if let signal = self.share?(self.inputFieldNode.text, peerIds) {
self.transitionToContentNode(ShareLoadingContainerNode(theme: self.presentationData.theme, forceNativeAppearance: true), fastOut: true)
let timestamp = CACurrentMediaTime()
@ -629,6 +635,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
}
func updatePeers(account: Account, switchableAccounts: [AccountWithInfo], peers: [(RenderedPeer, PeerPresence?)], accountPeer: Peer, defaultAction: ShareControllerAction?) {
self.account = account
if let peersContentNode = self.peersContentNode, peersContentNode.accountPeer.id == accountPeer.id {
peersContentNode.peersValue.set(.single(peers))
return

View File

@ -197,6 +197,7 @@ framework(
"//submodules/AppLock:AppLock",
"//submodules/NotificationsPresentationData:NotificationsPresentationData",
"//submodules/UrlWhitelist:UrlWhitelist",
"//submodules/AppIntents:AppIntents",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -33,6 +33,7 @@ import WalletCore
import OpenSSLEncryptionProvider
import AppLock
import PresentationDataUtils
import AppIntents
#if canImport(BackgroundTasks)
import BackgroundTasks
@ -179,6 +180,8 @@ final class SharedApplicationContext {
private let authContext = Promise<UnauthorizedApplicationContext?>()
private let authContextDisposable = MetaDisposable()
private let logoutDisposable = MetaDisposable()
private let openChatWhenReadyDisposable = MetaDisposable()
private let openUrlWhenReadyDisposable = MetaDisposable()
@ -1155,7 +1158,8 @@ final class SharedApplicationContext {
}
|> take(1)
|> timeout(4.0, queue: .mainQueue(), alternate: .complete())
|> deliverOnMainQueue).start(completed: { authContextValue.rootController.view.endEditing(true)
|> deliverOnMainQueue).start(completed: {
authContextValue.rootController.view.endEditing(true)
authContextValue.rootController.dismiss()
})
} else {
@ -1174,12 +1178,32 @@ final class SharedApplicationContext {
|> take(1)
|> deliverOnMainQueue).start(next: { _ in
statusController.dismiss()
self.mainWindow.present(context.rootController, on: .root) }))
self.mainWindow.present(context.rootController, on: .root)
}))
} else {
authContextReadyDisposable.set(nil)
}
}))
self.logoutDisposable.set((self.sharedContextPromise.get()
|> take(1)
|> mapToSignal { sharedContext -> Signal<Set<PeerId>, NoError> in
return sharedContext.sharedContext.activeAccounts
|> map { _, accounts, _ -> Set<PeerId> in
return Set(accounts.map { $0.1.peerId })
}
|> reduceLeft(value: Set<PeerId>()) { current, updated, emit in
if !current.isEmpty {
emit(current.subtracting(current.intersection(updated)))
}
return updated
}
}).start(next: { loggedOutAccountPeerIds in
for peerId in loggedOutAccountPeerIds {
deleteAllSendMessageIntents(accountPeerId: peerId)
}
}))
self.watchCommunicationManagerPromise.set(watchCommunicationManager(context: self.context.get() |> flatMap { WatchCommunicationManagerContext(context: $0.context) }, allowBackgroundTimeExtension: { timeout in
let _ = (self.sharedContextPromise.get()
|> take(1)).start(next: { sharedContext in

View File

@ -55,6 +55,7 @@ import LocalizedPeerData
import PhoneNumberFormat
import SettingsUI
import UrlWhitelist
import AppIntents
public enum ChatControllerPeekActions {
case standard
@ -2798,7 +2799,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
})
strongSelf.donateSendMessageIntent()
donateSendMessageIntent(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, peerIds: [peerId])
}
}
@ -5994,7 +5995,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
})
self.donateSendMessageIntent()
donateSendMessageIntent(account: self.context.account, sharedContext: self.context.sharedContext, peerIds: [peerId])
} else {
let mode: ChatScheduleTimeControllerMode
if peerId == self.context.account.peerId {
@ -8067,44 +8068,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
private func donateSendMessageIntent() {
guard case let .peer(peerId) = self.chatLocation, peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId else {
return
}
if #available(iOSApplicationExtension 13.2, iOS 13.2, *) {
let _ = (self.context.account.postbox.loadedPeerWithId(peerId)
|> mapToSignal { peer -> Signal<(Peer, UIImage?), NoError> in
let avatarImage = peerAvatarImage(account: self.context.account, peer: peer, authorOfMessage: nil, representation: peer.smallProfileImage, round: false) ?? .single(nil)
return avatarImage
|> map { avatarImage in
return (peer, avatarImage)
}
}
|> deliverOnMainQueue).start(next: { [weak self] peer, avatarImage in
if let strongSelf = self, let peer = peer as? TelegramUser, peer.botInfo == nil && !peer.flags.contains(.isSupport) {
let recipientHandle = INPersonHandle(value: "tg\(peerId.id)", type: .unknown)
var nameComponents = PersonNameComponents()
nameComponents.givenName = peer.firstName
nameComponents.familyName = peer.lastName
let displayTitle = peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)
let recipient = INPerson(personHandle: recipientHandle, nameComponents: nameComponents, displayName: displayTitle, image: nil, contactIdentifier: nil, customIdentifier: "tg\(peerId.id)")
let intent = INSendMessageIntent(recipients: [recipient], content: nil, speakableGroupName: INSpeakableString(spokenPhrase: displayTitle), conversationIdentifier: "tg\(peerId.id)", serviceName: nil, sender: nil)
if #available(iOS 12.0, *), let avatarImage = avatarImage, let avatarImageData = avatarImage.jpegData(compressionQuality: 0.8) {
intent.setImage(INImage(imageData: avatarImageData), forParameterNamed: \.groupName)
}
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .outgoing
interaction.groupIdentifier = "sendMessage_\(strongSelf.context.account.peerId.toInt64())"
interaction.donate { error in
if let error = error {
print(error.localizedDescription)
}
}
}
})
}
}
private func updateReminderActivity() {
if self.isReminderActivityEnabled && false {
if #available(iOS 9.0, *) {