mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
228 lines
11 KiB
Swift
228 lines
11 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Intents
|
|
import Display
|
|
import Postbox
|
|
import TelegramCore
|
|
import SwiftSignalKit
|
|
import TelegramUIPreferences
|
|
import TelegramPresentationData
|
|
import AvatarNode
|
|
import AccountContext
|
|
|
|
private let savedMessagesAvatar: UIImage = {
|
|
return generateImage(CGSize(width: 60.0, height: 60.0), rotatedContext: { size, context in
|
|
var locations: [CGFloat] = [1.0, 0.0]
|
|
|
|
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
|
let gradient = CGGradient(colorsSpace: colorSpace, colors: [UIColor(rgb: 0x2a9ef1).cgColor, UIColor(rgb: 0x72d5fd).cgColor] as CFArray, locations: &locations)!
|
|
|
|
context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
|
|
|
let factor = size.width / 60.0
|
|
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
|
|
context.scaleBy(x: factor, y: -factor)
|
|
context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
|
|
|
|
if let savedMessagesIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/SavedMessagesIcon"), color: .white) {
|
|
context.draw(savedMessagesIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - savedMessagesIcon.size.width) / 2.0), y: floor((size.height - savedMessagesIcon.size.height) / 2.0)), size: savedMessagesIcon.size))
|
|
}
|
|
})!
|
|
}()
|
|
|
|
public enum SendMessageIntentContext {
|
|
case chat
|
|
case share
|
|
}
|
|
|
|
public enum SendMessageIntentSubject: CaseIterable {
|
|
case contact
|
|
case savedMessages
|
|
case privateChat
|
|
case group
|
|
|
|
func toString() -> String {
|
|
switch self {
|
|
case .contact:
|
|
return "contact"
|
|
case .savedMessages:
|
|
return "savedMessages"
|
|
case .privateChat:
|
|
return "privateChat"
|
|
case .group:
|
|
return "group"
|
|
}
|
|
}
|
|
}
|
|
|
|
public func donateSendMessageIntent(account: Account, sharedContext: SharedAccountContext, intentContext: SendMessageIntentContext, peerIds: [PeerId]) {
|
|
if #available(iOSApplicationExtension 13.2, iOS 13.2, *) {
|
|
let _ = (sharedContext.accountManager.transaction { transaction -> Bool in
|
|
if case .none = transaction.getAccessChallengeData() {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|> mapToSignal { unlocked -> Signal<[(Peer, SendMessageIntentSubject, UIImage?)], NoError> in
|
|
if unlocked {
|
|
return sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.intentsSettings])
|
|
|> take(1)
|
|
|> mapToSignal { sharedData -> Signal<[(Peer, SendMessageIntentSubject)], NoError> in
|
|
let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.intentsSettings]?.get(IntentsSettings.self) ?? IntentsSettings.defaultSettings
|
|
if let accountId = settings.account, accountId != account.peerId {
|
|
return .single([])
|
|
}
|
|
if case .chat = intentContext, settings.onlyShared {
|
|
return .single([])
|
|
}
|
|
|
|
return TelegramEngine(account: account).data.get(
|
|
EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init)),
|
|
EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Peer.IsContact.init)),
|
|
EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Messages.ChatListGroup.init))
|
|
)
|
|
|> map { peerMap, isContactMap, chatListGroupMap -> [(Peer, SendMessageIntentSubject)] in
|
|
var peers: [(Peer, SendMessageIntentSubject)] = []
|
|
for peerId in peerIds {
|
|
if peerId.namespace != Namespaces.Peer.SecretChat, let maybePeer = peerMap[peerId], let peer = maybePeer {
|
|
var subject: SendMessageIntentSubject?
|
|
let chatListGroup = chatListGroupMap[peerId]
|
|
if chatListGroup == .archive {
|
|
continue
|
|
}
|
|
if peerId.namespace == Namespaces.Peer.CloudUser {
|
|
if peerId == account.peerId {
|
|
if !settings.savedMessages {
|
|
continue
|
|
}
|
|
subject = .savedMessages
|
|
} else if let isContact = isContactMap[peerId], isContact {
|
|
if !settings.contacts {
|
|
continue
|
|
}
|
|
subject = .contact
|
|
} else {
|
|
if !settings.privateChats {
|
|
continue
|
|
}
|
|
subject = .privateChat
|
|
}
|
|
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
|
|
if !settings.groups {
|
|
continue
|
|
}
|
|
subject = .group
|
|
} else if case let .channel(peer) = peer {
|
|
if case .group = peer.info {
|
|
if !settings.groups {
|
|
continue
|
|
}
|
|
subject = .group
|
|
} else {
|
|
continue
|
|
}
|
|
} else {
|
|
continue
|
|
}
|
|
|
|
if let subject = subject {
|
|
peers.append((peer._asPeer(), subject))
|
|
}
|
|
}
|
|
}
|
|
return peers
|
|
}
|
|
}
|
|
|> mapToSignal { peers -> Signal<[(Peer, SendMessageIntentSubject, UIImage?)], NoError> in
|
|
var signals: [Signal<(Peer, SendMessageIntentSubject, UIImage?), NoError>] = []
|
|
for (peer, subject) in peers {
|
|
if peer.id == account.peerId {
|
|
signals.append(.single((peer, subject, savedMessagesAvatar)))
|
|
} else {
|
|
let peerAndAvatar = (peerAvatarImage(account: account, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.smallProfileImage, clipStyle: .none) ?? .single(nil))
|
|
|> map { imageVersions -> (Peer, SendMessageIntentSubject, UIImage?) in
|
|
var avatarImage: UIImage?
|
|
if let image = imageVersions?.0 {
|
|
avatarImage = image
|
|
} else {
|
|
let avatarFont = avatarPlaceholderFont(size: 26.0)
|
|
let size = CGSize(width: 60.0, height: 60.0)
|
|
if let image = generateImage(size, rotatedContext: { size, context in
|
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
|
|
drawPeerAvatarLetters(context: context, size: CGSize(width: size.width, height: size.height), font: avatarFont, letters: peer.displayLetters, peerId: peer.id, nameColor: peer.nameColor)
|
|
})?.withRenderingMode(.alwaysOriginal) {
|
|
avatarImage = image
|
|
}
|
|
}
|
|
return (peer, subject, avatarImage)
|
|
}
|
|
signals.append(peerAndAvatar)
|
|
}
|
|
}
|
|
return combineLatest(signals)
|
|
}
|
|
} else {
|
|
return .single([])
|
|
}
|
|
}
|
|
|> deliverOnMainQueue).start(next: { peers in
|
|
let presentationData = sharedContext.currentPresentationData.with { $0 }
|
|
|
|
for (peer, _, avatarImage) in peers {
|
|
let recipientHandle = INPersonHandle(value: "tg\(peer.id.toInt64())", type: .unknown)
|
|
let displayTitle: String
|
|
var nameComponents = PersonNameComponents()
|
|
|
|
if let peer = peer as? TelegramUser {
|
|
if peer.botInfo != nil || peer.flags.contains(.isSupport) {
|
|
continue
|
|
}
|
|
|
|
if peer.id == account.peerId {
|
|
displayTitle = presentationData.strings.DialogList_SavedMessages
|
|
nameComponents.givenName = displayTitle
|
|
} else {
|
|
displayTitle = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
|
nameComponents.givenName = peer.firstName
|
|
nameComponents.familyName = peer.lastName
|
|
}
|
|
} else {
|
|
displayTitle = EnginePeer(peer).compactDisplayTitle
|
|
nameComponents.givenName = displayTitle
|
|
}
|
|
|
|
var personImage: INImage?
|
|
if let avatarImage = avatarImage, let avatarImageData = avatarImage.jpegData(compressionQuality: 0.8) {
|
|
personImage = INImage(imageData: avatarImageData)
|
|
}
|
|
|
|
let recipient = INPerson(personHandle: recipientHandle, nameComponents: nameComponents, displayName: displayTitle, image: personImage, contactIdentifier: nil, customIdentifier: "tg\(peer.id.toInt64())")
|
|
|
|
let intent = INSendMessageIntent(recipients: [recipient], content: nil, speakableGroupName: INSpeakableString(spokenPhrase: displayTitle), conversationIdentifier: "tg\(peer.id.toInt64())", serviceName: nil, sender: nil)
|
|
let interaction = INInteraction(intent: intent, response: nil)
|
|
interaction.direction = .outgoing
|
|
interaction.groupIdentifier = "sendMessage_\(peer.id.toInt64())"
|
|
interaction.donate { error in
|
|
if let error = error {
|
|
print(error)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
public func deleteSendMessageIntents(peerId: PeerId) {
|
|
if #available(iOS 10.0, *) {
|
|
INInteraction.delete(with: "sendMessage_\(peerId.toInt64())")
|
|
}
|
|
}
|
|
|
|
public func deleteAllSendMessageIntents() {
|
|
if #available(iOS 10.0, *) {
|
|
INInteraction.deleteAll()
|
|
}
|
|
}
|