Skip to content

Commit

Permalink
♻️ Determine push attachment file type using file mime type
Browse files Browse the repository at this point in the history
  • Loading branch information
mmaatttt authored and iujames committed Sep 17, 2024
1 parent f5f50a0 commit 6611a28
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 25 deletions.
2 changes: 0 additions & 2 deletions Sources/AppcuesKit/Push/ParsedNotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ internal struct ParsedNotification {
let deepLinkURL: URL?
let experienceID: String?
let attachmentURL: URL?
let attachmentType: String?
let isTest: Bool
let isInternal: Bool

Expand All @@ -41,7 +40,6 @@ internal struct ParsedNotification {
self.experienceID = userInfo["appcues_experience_id"] as? String
self.attachmentURL = (userInfo["appcues_attachment_url"] as? String)
.flatMap { URL(string: $0) }
self.attachmentType = userInfo["appcues_attachment_type"] as? String
self.isTest = userInfo["appcues_test"] != nil
self.isInternal = userInfo["_appcues_internal"] as? Bool ?? false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//

import UserNotifications
import UniformTypeIdentifiers
import CoreServices

/// `UNNotificationServiceExtension` subclass that implements Appcues functionality.
///
Expand All @@ -28,11 +30,9 @@ open class AppcuesNotificationServiceExtension: UNNotificationServiceExtension {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

if let attachment = request.attachment {
bestAttemptContent?.attachments = [attachment]
if let bestAttemptContent = bestAttemptContent {
processAttachment(bestAttemptContent, contentHandler)
}

contentHandler(bestAttemptContent ?? request.content)
}

override public func serviceExtensionTimeWillExpire() {
Expand All @@ -42,32 +42,57 @@ open class AppcuesNotificationServiceExtension: UNNotificationServiceExtension {
contentHandler(bestAttemptContent)
}
}
}

extension UNNotificationRequest {
var attachment: UNNotificationAttachment? {
func processAttachment(_ content: UNMutableNotificationContent, _ contentHandler: @escaping (UNNotificationContent) -> Void) {
guard let attachment = content.userInfo["appcues_attachment_url"] as? String,
let attachmentType = content.userInfo["appcues_attachment_type"] as? String,
let attachmentURL = URL(string: attachment),
let imageData = try? Data(contentsOf: attachmentURL) else {
return nil
let attachmentURL = URL(string: attachment) else {
contentHandler(content)
return
}
return try? UNNotificationAttachment(data: imageData, dataType: attachmentType, options: nil)
}
}

extension UNNotificationAttachment {
convenience init(data: Data, dataType: String, options: [NSObject: AnyObject]?) throws {
let temporaryFolderName = ProcessInfo.processInfo.globallyUniqueString
let temporaryFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(temporaryFolderName, isDirectory: true)
let dataTask = URLSession.shared.downloadTask(with: attachmentURL) { url, response, error in
guard let downloadedURL = url, error == nil else {
contentHandler(content)
return
}

let temporaryFolderURL = URL(fileURLWithPath: NSTemporaryDirectory())
let imageFileIdentifier = UUID().uuidString
let fileType = response?.fileType ?? "tmp"

let tmpFileURL = temporaryFolderURL
.appendingPathComponent(imageFileIdentifier)
.appendingPathExtension(fileType)

try FileManager.default.createDirectory(at: temporaryFolderURL, withIntermediateDirectories: true, attributes: nil)
do {
try FileManager.default.moveItem(at: downloadedURL, to: tmpFileURL)
let attachment = try UNNotificationAttachment(identifier: imageFileIdentifier, url: tmpFileURL)
content.attachments = [attachment]
} catch {
print(error)
}

let imageFileIdentifier = UUID().uuidString + "." + dataType
let fileURL = temporaryFolderURL.appendingPathComponent(imageFileIdentifier)
contentHandler(content)
}

dataTask.resume()
}
}

try data.write(to: fileURL)
extension URLResponse {
var fileType: String? {
guard let mimeType = self.mimeType else {
return self.url?.pathExtension
}

try self.init(identifier: imageFileIdentifier, url: fileURL, options: options)
if #available(iOS 14.0, *) {
return UTType(mimeType: mimeType)?.preferredFilenameExtension
} else {
guard let mimeUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType as CFString, nil)?.takeUnretainedValue(),
let extUTI = UTTypeCopyPreferredTagWithClass(mimeUTI, kUTTagClassFilenameExtension)

else { return nil }
return extUTI.takeUnretainedValue() as String
}
}
}

0 comments on commit 6611a28

Please sign in to comment.