From 9cf386d9856753bf97b83c3df2ec552af246199e Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Sun, 30 Dec 2018 18:24:16 -0500 Subject: picture messaging for iOS initial support --- www/external/NotificationService.swift | 109 +++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 www/external/NotificationService.swift (limited to 'www/external') diff --git a/www/external/NotificationService.swift b/www/external/NotificationService.swift new file mode 100644 index 00000000..1fa81558 --- /dev/null +++ b/www/external/NotificationService.swift @@ -0,0 +1,109 @@ +// Credit: https://github.com/phonegap/phonegap-plugin-push/issues/1347#issuecomment-450206184 +import UserNotifications + +class NotificationService: UNNotificationServiceExtension { + + var contentHandler: ((UNNotificationContent) -> Void)? + var bestAttemptContent: UNMutableNotificationContent? + + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.contentHandler = contentHandler + self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) + guard let content = bestAttemptContent else { + #if DEBUG + exitGracefully("bestAttemptContent not a UNMutableNotificationContent") + #endif + return + } + + DispatchQueue.main.async { [weak self] in + let userInfo: [AnyHashable: Any] = request.content.userInfo + content.attachments = self?.attachmentsFor(userInfo) ?? [] + guard let copy = self?.bestAttemptContent else { + #if DEBUG + self?.exitGracefully("bestAttemptContent is nil") + #endif + return + } + contentHandler(copy) + } + } + + override func serviceExtensionTimeWillExpire() { + if let contentHandler = contentHandler, let content = self.bestAttemptContent { + contentHandler(content) + } + } + + /// Helper function to extract Attachments from an userInfo object + /// + /// - Attribute userInfo: The user info extracted from the notification, + /// which should contain one of the available keys to create + /// a rich push notification. + private func attachmentsFor(_ userInfo: [AnyHashable: Any]) -> [UNNotificationAttachment] { + if let attachmentURLString = userInfo["image_url_png"] as? String { + guard let attachmentURL = URL(string: attachmentURLString), + let imageData = try? Data(contentsOf: attachmentURL), + let attachment = self.save("image.png", data: imageData, options: nil) else { + #if DEBUG + self.exitGracefully("PNG was not saved properly") + #endif + return [] + } + return [attachment] + } else if let attachmentURLString = userInfo["image_url_jpg"] as? String { + guard let attachmentURL = URL(string: attachmentURLString), + let imageData = try? Data(contentsOf: attachmentURL), + let attachment = self.save("image.jpg", data: imageData, options: nil) else { + #if DEBUG + self.exitGracefully("JPG was not saved properly") + #endif + return [] + } + return [attachment] + } else if let attachmentURLString = userInfo["image_url_gif"] as? String { + guard let attachmentURL = URL(string: attachmentURLString), + let imageData = try? Data(contentsOf: attachmentURL), + let attachment = self.save("image.gif", data: imageData, options: nil) else { + #if DEBUG + self.exitGracefully("GIF was not saved properly") + #endif + return [] + } + return [attachment] + } + + return [] + } + + /// Save data object onto disk and return an optional attachment linked to this path. + /// + /// - Attributes: + /// - identifier: The unique identifier of the attachment. + /// Use this string to identify the attachment later. If you specify an + /// empty string, this method creates a unique identifier string for you. + /// - data: The data stored onto disk. + /// - options: A dictionary of options related to the attached file. + /// Use the options to specify meta information about the attachment, + /// such as the clipping rectangle to use for the resulting thumbnail. + private func save(_ identifier: String, data: Data, options: [AnyHashable: Any]?) -> UNNotificationAttachment? { + // Create paths + let directory = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString, isDirectory: true) + let fileURL = directory.appendingPathComponent(identifier) + // Write data on disk + try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil) + try? data.write(to: fileURL, options: []) + // Create Notification attachment + return try? UNNotificationAttachment(identifier: identifier, url: fileURL, options: options) + } + + /// Something went wrong, so maybe we want to clean up and present a fallback to the user. + /// + /// - Attribute reason: The reason why something went wrong. + private func exitGracefully(_ reason: String = "") { + guard let copy = bestAttemptContent?.mutableCopy() as? UNMutableNotificationContent else { return } + copy.title = reason + contentHandler?(copy) + } + +} -- cgit v1.2.3