import UIKit import UserNotifications import UserNotificationsUI import Display import TelegramCore import TelegramUI import SwiftSignalKit import Postbox private enum NotificationContentAuthorizationError { case unauthorized } private var sharedAccountContext: SharedAccountContext? private var installedSharedLogger = false private func setupSharedLogger(_ path: String) { if !installedSharedLogger { installedSharedLogger = true Logger.setSharedLogger(Logger(basePath: path)) } } private func parseFileLocationResource(_ dict: [AnyHashable: Any]) -> TelegramMediaResource? { guard let datacenterId = dict["datacenterId"] as? Int32 else { return nil } guard let volumeId = dict["volumeId"] as? Int64 else { return nil } guard let localId = dict["localId"] as? Int32 else { return nil } guard let secret = dict["secret"] as? Int64 else { return nil } var fileReference: Data? if let fileReferenceString = dict["fileReference"] as? String { fileReference = dataWithHexString(fileReferenceString) } return CloudFileMediaResource(datacenterId: Int(datacenterId), volumeId: volumeId, localId: localId, secret: secret, size: nil, fileReference: fileReference) } class NotificationViewController: UIViewController, UNNotificationContentExtension { private let imageNode = TransformImageNode() private var imageDimensions: CGSize? private let applyDisposable = MetaDisposable() private let fetchedDisposable = MetaDisposable() deinit { self.applyDisposable.dispose() self.fetchedDisposable.dispose() } override func viewDidLoad() { super.viewDidLoad() self.view.addSubnode(self.imageNode) let appBundleIdentifier = Bundle.main.bundleIdentifier! guard let lastDotRange = appBundleIdentifier.range(of: ".", options: [.backwards]) else { return } let apiId: Int32 = BuildConfig.shared().apiId let languagesCategory = "ios" let appGroupName = "group.\(appBundleIdentifier[.. map { $0.1 }) return } if let path = thumbnailInfo["path"] as? String, let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { self.imageNode.setSignal(chatMessagePhotoInternal(photoData: .single((data, nil, false))) |> map { $0.1 }) } guard let sharedAccountContext = sharedAccountContext else { return } self.applyDisposable.set((sharedAccountContext.activeAccounts |> map { _, accounts, _ -> Account? in return accounts[AccountRecordId(rawValue: accountIdValue)] } |> filter { account in return account != nil } |> take(1) |> mapToSignal { account -> Signal<(Account, ImageMediaReference?), NoError> in guard let account = account else { return .complete() } return account.postbox.messageAtId(messageId) |> take(1) |> map { message in var imageReference: ImageMediaReference? if let message = message, false { for media in message.media { if let image = media as? TelegramMediaImage { imageReference = .message(message: MessageReference(message), media: image) } } } else { if let thumbnailFileLocation = thumbnailInfo["fileLocation"] as? [AnyHashable: Any], let thumbnailResource = parseFileLocationResource(thumbnailFileLocation), let fileLocation = fullSizeInfo["fileLocation"] as? [AnyHashable: Any], let resource = parseFileLocationResource(fileLocation) { imageReference = .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudImage, id: 1), representations: [TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(width), height: CGFloat(height)).fitted(CGSize(width: 320.0, height: 320.0)), resource: thumbnailResource), TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(width), height: CGFloat(height)), resource: resource)], immediateThumbnailData: nil, reference: nil, partialReference: nil)) } } return (account, imageReference) } } |> deliverOnMainQueue).start(next: { [weak self] accountAndImage in guard let strongSelf = self else { return } if let imageReference = accountAndImage.1 { strongSelf.imageNode.setSignal(chatMessagePhoto(postbox: accountAndImage.0.postbox, photoReference: imageReference)) accountAndImage.0.network.shouldExplicitelyKeepWorkerConnections.set(.single(true)) strongSelf.fetchedDisposable.set(standaloneChatMessagePhotoInteractiveFetched(account: accountAndImage.0, photoReference: imageReference).start()) } })) } } } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) self.updateImageLayout(boundingSize: size) } private func updateImageLayout(boundingSize: CGSize) { if let imageDimensions = self.imageDimensions { let makeLayout = self.imageNode.asyncLayout() let fittedSize = imageDimensions.fitted(CGSize(width: boundingSize.width, height: 1000.0)) let apply = makeLayout(TransformImageArguments(corners: ImageCorners(radius: 0.0), imageSize: fittedSize, boundingSize: fittedSize, intrinsicInsets: UIEdgeInsets())) apply() self.imageNode.frame = CGRect(origin: CGPoint(), size: boundingSize) } } }