Added WebP decoding to notification service

This commit is contained in:
Peter 2019-04-09 21:09:16 +01:00
parent 9802f70a80
commit 10c86a102e
9 changed files with 94 additions and 33 deletions

3
.gitmodules vendored
View File

@ -34,3 +34,6 @@ url=../ffmpeg.git
[submodule "submodules/LegacyComponents"]
path = submodules/LegacyComponents
url=../legacycomponents.git
[submodule "submodules/webp"]
path = submodules/webp
url=../webp.git

View File

@ -44,7 +44,7 @@ private func parseFileLocationResource(_ dict: [AnyHashable: Any]) -> TelegramMe
class NotificationViewController: UIViewController, UNNotificationContentExtension {
private let imageNode = TransformImageNode()
private var imageDimensions: CGSize?
private var imageInfo: (isSticker: Bool, dimensions: CGSize)?
private let applyDisposable = MetaDisposable()
private let fetchedDisposable = MetaDisposable()
@ -147,7 +147,7 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
self.view.frame = CGRect(origin: self.view.frame.origin, size: fittedSize)
self.preferredContentSize = fittedSize
self.imageDimensions = dimensions
self.imageInfo = (false, dimensions)
self.updateImageLayout(boundingSize: self.view.bounds.size)
let mediaBoxPath = accountsPath + "/" + accountRecordIdPathName(AccountRecordId(rawValue: accountIdValue)) + "/postbox/media"
@ -211,10 +211,13 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
return
}
let fittedSize = dimensions.fitted(CGSize(width: min(300.0, self.view.bounds.width), height: 300.0))
let fittedSize = dimensions.fitted(CGSize(width: min(256.0, self.view.bounds.width), height: 256.0))
self.view.frame = CGRect(origin: self.view.frame.origin, size: fittedSize)
self.preferredContentSize = fittedSize
self.imageInfo = (true, dimensions)
self.updateImageLayout(boundingSize: self.view.bounds.size)
self.applyDisposable.set((sharedAccountContext.activeAccounts
|> map { _, accounts, _ -> Account? in
return accounts.first(where: { $0.0 == AccountRecordId(rawValue: accountIdValue) })?.1
@ -267,12 +270,18 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
}
private func updateImageLayout(boundingSize: CGSize) {
if let imageDimensions = self.imageDimensions {
if let (isSticker, dimensions) = self.imageInfo {
let makeLayout = self.imageNode.asyncLayout()
let fittedSize = imageDimensions.fitted(CGSize(width: boundingSize.width, height: 1000.0))
let fittedSize: CGSize
if isSticker {
fittedSize = dimensions.fitted(CGSize(width: min(256.0, boundingSize.width), height: 256.0))
} else {
fittedSize = dimensions.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)
let displaySize = isSticker ? fittedSize : boundingSize
self.imageNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - displaySize.width) / 2.0), y: 0.0), size: displaySize)
}
}
}

View File

@ -1,6 +1,7 @@
import Foundation
import UserNotifications
import MtProtoKitDynamic
import WebP
private var sharedLogger: Logger?
@ -324,7 +325,7 @@ class NotificationService: UNNotificationServiceExtension {
let imagesPath = NSTemporaryDirectory() + "aps-data"
let _ = try? FileManager.default.createDirectory(atPath: imagesPath, withIntermediateDirectories: true, attributes: nil)
let accountBasePath = rootPath + "account-\(UInt64(bitPattern: account.id))"
let accountBasePath = rootPath + "/account-\(UInt64(bitPattern: account.id))"
let mediaBoxPath = accountBasePath + "/postbox/media"
@ -333,6 +334,7 @@ class NotificationService: UNNotificationServiceExtension {
var inputFileLocation: (Int32, Api.InputFileLocation)?
var fetchResourceId: String?
var isPng = false
if let attachment = attachment {
switch attachment {
@ -356,14 +358,26 @@ class NotificationService: UNNotificationServiceExtension {
}
case let .document(document):
switch document {
case let .document(_, id, accessHash, fileReference, _, _, _, thumbs, dcId, _):
case let .document(_, id, accessHash, fileReference, _, _, _, thumbs, dcId, attributes):
var isSticker = false
for attribute in attributes {
switch attribute {
case .documentAttributeSticker:
isSticker = true
default:
break
}
}
if let thumbs = thumbs {
loop: for size in thumbs {
switch size {
case let .photoSize(type, _, _, _, _):
if type == "m" {
if (isSticker && type == "s") || type == "m" {
if isSticker {
isPng = true
}
inputFileLocation = (dcId, .inputDocumentFileLocation(id: id, accessHash: accessHash, fileReference: fileReference, thumbSize: type))
fetchResourceId = "telegram-cloud-photo-size-\(dcId)-\(id)-\(type)"
fetchResourceId = "telegram-cloud-document-size-\(dcId)-\(id)-\(type)"
break loop
}
default:
@ -376,8 +390,8 @@ class NotificationService: UNNotificationServiceExtension {
}
if let fetchResourceId = fetchResourceId {
tempImagePath = imagesPath + "/\(fetchResourceId).jpg"
mediaBoxThumbnailImagePath = mediaBoxPath + "/\(fetchResourceId).jpg"
tempImagePath = imagesPath + "/\(fetchResourceId).\(isPng ? "png" : "jpg")"
mediaBoxThumbnailImagePath = mediaBoxPath + "/\(fetchResourceId)"
}
if let aps = dict["aps"] as? [AnyHashable: Any] {
@ -424,26 +438,49 @@ class NotificationService: UNNotificationServiceExtension {
self.cancelFetch?()
if let mediaBoxThumbnailImagePath = mediaBoxThumbnailImagePath, let tempImagePath = tempImagePath, let (datacenterId, inputFileLocation) = inputFileLocation {
self.cancelFetch = fetchImageWithAccount(proxyConnection: accountInfos.proxy, account: account, inputFileLocation: inputFileLocation, datacenterId: datacenterId, completion: { [weak self] data in
DispatchQueue.main.async {
guard let strongSelf = self else {
return
}
strongSelf.cancelFetch?()
strongSelf.cancelFetch = nil
if let data = data {
let _ = try? data.write(to: URL(fileURLWithPath: mediaBoxThumbnailImagePath))
if let _ = try? data.write(to: URL(fileURLWithPath: tempImagePath)) {
if let attachment = try? UNNotificationAttachment(identifier: "image", url: URL(fileURLWithPath: tempImagePath)) {
strongSelf.bestAttemptContent?.attachments = [attachment]
}
}
}
if let bestAttemptContent = strongSelf.bestAttemptContent {
contentHandler(bestAttemptContent)
if let data = try? Data(contentsOf: URL(fileURLWithPath: mediaBoxThumbnailImagePath)) {
var tempData = data
if isPng {
if let image = WebP.convert(fromWebP: data), let imageData = image.pngData() {
tempData = imageData
}
}
})
if let _ = try? tempData.write(to: URL(fileURLWithPath: tempImagePath)) {
if let attachment = try? UNNotificationAttachment(identifier: "image", url: URL(fileURLWithPath: tempImagePath)) {
self.bestAttemptContent?.attachments = [attachment]
}
}
if let bestAttemptContent = self.bestAttemptContent {
contentHandler(bestAttemptContent)
}
} else {
self.cancelFetch = fetchImageWithAccount(proxyConnection: accountInfos.proxy, account: account, inputFileLocation: inputFileLocation, datacenterId: datacenterId, completion: { [weak self] data in
DispatchQueue.main.async {
guard let strongSelf = self else {
return
}
strongSelf.cancelFetch?()
strongSelf.cancelFetch = nil
if let data = data {
let _ = try? data.write(to: URL(fileURLWithPath: mediaBoxThumbnailImagePath))
var tempData = data
if isPng {
if let image = WebP.convert(fromWebP: data), let imageData = image.pngData() {
tempData = imageData
}
}
if let _ = try? tempData.write(to: URL(fileURLWithPath: tempImagePath)) {
if let attachment = try? UNNotificationAttachment(identifier: "image", url: URL(fileURLWithPath: tempImagePath)) {
strongSelf.bestAttemptContent?.attachments = [attachment]
}
}
}
if let bestAttemptContent = strongSelf.bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
})
}
} else {
if let bestAttemptContent = self.bestAttemptContent {
contentHandler(bestAttemptContent)

View File

@ -225,6 +225,9 @@
D00ED75D1FE95287001F38BD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D00ED75B1FE95287001F38BD /* InfoPlist.strings */; };
D015E011225CCEB300CB9E8A /* ReadBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015E010225CCEB300CB9E8A /* ReadBuffer.swift */; };
D015E01F225CDF5100CB9E8A /* Api0.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015E01E225CDF5000CB9E8A /* Api0.swift */; };
D015E04D225D2D8F00CB9E8A /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D015E04C225D2D8F00CB9E8A /* WebP.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
D015E050225D303F00CB9E8A /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D015E04C225D2D8F00CB9E8A /* WebP.framework */; };
D015E051225D303F00CB9E8A /* WebP.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D015E04C225D2D8F00CB9E8A /* WebP.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D01A47551F4DBED700383CC1 /* HockeySDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D01A47541F4DBED700383CC1 /* HockeySDK.framework */; };
D021D4D9219CAEDD0064BEBA /* Config-Fork.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = D021D4D8219CAEDD0064BEBA /* Config-Fork.xcconfig */; };
D02CF5FD215D9ABF00E0F56A /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0AA1A671D568BA400152314 /* UserNotifications.framework */; };
@ -545,6 +548,7 @@
D096C2C21CC3C104006D814E /* Postbox.framework in Embed Frameworks */,
D096C2C51CC3C11A006D814E /* SwiftSignalKit.framework in Embed Frameworks */,
D006CFA021A8D11B00FDCD32 /* ModernProto.framework in Embed Frameworks */,
D015E051225D303F00CB9E8A /* WebP.framework in Embed Frameworks */,
D0CAF3191D763B230011F558 /* MtProtoKitDynamic.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
@ -932,6 +936,7 @@
D00ED75C1FE95287001F38BD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D015E010225CCEB300CB9E8A /* ReadBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadBuffer.swift; sourceTree = "<group>"; };
D015E01E225CDF5000CB9E8A /* Api0.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Api0.swift; sourceTree = "<group>"; };
D015E04C225D2D8F00CB9E8A /* WebP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = WebP.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D01A47521F4DBEB100383CC1 /* libHockeySDK.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libHockeySDK.a; path = "../../build/HockeySDK-iOS/Support/build/Debug-iphoneos/libHockeySDK.a"; sourceTree = "<group>"; };
D01A47541F4DBED700383CC1 /* HockeySDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = HockeySDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D021D4D7219CAEDD0064BEBA /* Telegram-iOS-Fork.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "Telegram-iOS-Fork.entitlements"; sourceTree = "<group>"; };
@ -1214,6 +1219,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D015E04D225D2D8F00CB9E8A /* WebP.framework in Frameworks */,
D0CCD61D222EFFB000EE1E08 /* MtProtoKitDynamic.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -1233,6 +1239,7 @@
D0CD17B51CC3AE14007C5650 /* AsyncDisplayKit.framework in Frameworks */,
D0D17E8A1CAAD66600C4750B /* Accelerate.framework in Frameworks */,
D0F575132083B96B00F1C1E1 /* CloudKit.framework in Frameworks */,
D015E050225D303F00CB9E8A /* WebP.framework in Frameworks */,
D006CF9F21A8D11B00FDCD32 /* ModernProto.framework in Frameworks */,
D0B4AF8F1EC122A700D51FF6 /* TelegramUI.framework in Frameworks */,
D096C2BE1CC3C021006D814E /* Display.framework in Frameworks */,
@ -2042,6 +2049,7 @@
D00859C21B281E0000EAF753 /* Frameworks */ = {
isa = PBXGroup;
children = (
D015E04C225D2D8F00CB9E8A /* WebP.framework */,
D0CCD61C222EFFB000EE1E08 /* MtProtoKitDynamic.framework */,
D0CAD6A121C03BE2001E3055 /* FFMpeg.framework */,
D006CFA121A8D12600FDCD32 /* ModernProto.framework */,

View File

@ -28,6 +28,9 @@
<FileRef
location = "group:submodules/ffmpeg/FFMpeg.xcodeproj">
</FileRef>
<FileRef
location = "group:submodules/webp/WebP.xcodeproj">
</FileRef>
<FileRef
location = "group:submodules/libtgvoip/libtgvoip.xcodeproj">
</FileRef>

@ -1 +1 @@
Subproject commit 73d45d3c87aa5837189521f41e4709a5d3780825
Subproject commit 97a3a77dff3b49d3cb0ec6603b6dba4723f06674

@ -1 +1 @@
Subproject commit 35b9b925fe4f97c735bf8952362b2da42dfdedc8
Subproject commit 03f72c3abd02dbe2fbd6586c880d4ca8f7070c17

@ -1 +1 @@
Subproject commit b4c851cecdad300d2bdd672138345b06785f8e95
Subproject commit a91c3edd4910ff08dbf3b2c8041c171503c47867

1
submodules/webp Submodule

@ -0,0 +1 @@
Subproject commit 11b3a56ae271a55931ae0bccb8b3cf2b8f3ae191