diff --git a/Example/BasicExample/BasicExample.xcodeproj/project.pbxproj b/Example/BasicExample/BasicExample.xcodeproj/project.pbxproj index 840ada4..8177d7d 100644 --- a/Example/BasicExample/BasicExample.xcodeproj/project.pbxproj +++ b/Example/BasicExample/BasicExample.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 46EDC72127C6B92C00B870D7 /* Segment in Frameworks */ = {isa = PBXBuildFile; productRef = 46EDC72027C6B92C00B870D7 /* Segment */; }; 82A3C7672B0D32F60036DF9A /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82A3C7662B0D32F60036DF9A /* NotificationService.swift */; }; 82A3C76B2B0D32F60036DF9A /* TwilioEngageExampleNotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 82A3C7642B0D32F60036DF9A /* TwilioEngageExampleNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 82D44CB02B0D56CC0055CF7F /* TwilioEngage in Frameworks */ = {isa = PBXBuildFile; productRef = 82D44CAF2B0D56CC0055CF7F /* TwilioEngage */; }; 82F9C4732A8177A200E580E3 /* DeepLinkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F9C4722A8177A200E580E3 /* DeepLinkViewController.swift */; }; 9BC924392A5C9C840003637C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC924382A5C9C840003637C /* AppDelegate.swift */; }; 9BC9243B2A5C9D130003637C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC9243A2A5C9D130003637C /* SceneDelegate.swift */; }; @@ -54,15 +55,9 @@ 46EDC70627C6B8D200B870D7 /* BasicExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicExampleTests.swift; sourceTree = ""; }; 46EDC71027C6B8D200B870D7 /* BasicExampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicExampleUITests.swift; sourceTree = ""; }; 46EDC71227C6B8D200B870D7 /* BasicExampleUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicExampleUITestsLaunchTests.swift; sourceTree = ""; }; - 82A3C7562B0D321B0036DF9A /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; - 82A3C7582B0D321B0036DF9A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 82A3C75F2B0D32270036DF9A /* TwilioEngageExmpleNotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TwilioEngageExmpleNotificationServiceExtension.entitlements; sourceTree = ""; }; 82A3C7642B0D32F60036DF9A /* TwilioEngageExampleNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = TwilioEngageExampleNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 82A3C7662B0D32F60036DF9A /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 82A3C7682B0D32F60036DF9A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 82D179FA2A8166A700318017 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; - 82D179FC2A8166A700318017 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 82D209802A840559005118D1 /* TwiliEngageExampleNotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TwiliEngageExampleNotificationService.entitlements; sourceTree = ""; }; 82D44CAE2B0D3CF80055CF7F /* TwilioEngageExampleNotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TwilioEngageExampleNotificationServiceExtension.entitlements; sourceTree = ""; }; 82F9C4722A8177A200E580E3 /* DeepLinkViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeepLinkViewController.swift; sourceTree = ""; }; 9BC924352A5C9AE20003637C /* BasicExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BasicExample.entitlements; sourceTree = ""; }; @@ -91,6 +86,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 82D44CB02B0D56CC0055CF7F /* TwilioEngage in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -104,8 +100,6 @@ 46EDC6F427C6B8D100B870D7 /* BasicExample */, 46EDC70527C6B8D200B870D7 /* BasicExampleTests */, 46EDC70F27C6B8D200B870D7 /* BasicExampleUITests */, - 82D179F92A8166A700318017 /* TwiliEngageExampleNotificationService */, - 82A3C7552B0D321B0036DF9A /* TwilioEngageExmpleNotificationServiceExtension */, 82A3C7652B0D32F60036DF9A /* TwilioEngageExampleNotificationServiceExtension */, 46EDC6F327C6B8D100B870D7 /* Products */, 9BC9244A2A5CA6540003637C /* Frameworks */, @@ -165,16 +159,6 @@ path = BasicExampleUITests; sourceTree = ""; }; - 82A3C7552B0D321B0036DF9A /* TwilioEngageExmpleNotificationServiceExtension */ = { - isa = PBXGroup; - children = ( - 82A3C75F2B0D32270036DF9A /* TwilioEngageExmpleNotificationServiceExtension.entitlements */, - 82A3C7562B0D321B0036DF9A /* NotificationService.swift */, - 82A3C7582B0D321B0036DF9A /* Info.plist */, - ); - path = TwilioEngageExmpleNotificationServiceExtension; - sourceTree = ""; - }; 82A3C7652B0D32F60036DF9A /* TwilioEngageExampleNotificationServiceExtension */ = { isa = PBXGroup; children = ( @@ -185,16 +169,6 @@ path = TwilioEngageExampleNotificationServiceExtension; sourceTree = ""; }; - 82D179F92A8166A700318017 /* TwiliEngageExampleNotificationService */ = { - isa = PBXGroup; - children = ( - 82D209802A840559005118D1 /* TwiliEngageExampleNotificationService.entitlements */, - 82D179FA2A8166A700318017 /* NotificationService.swift */, - 82D179FC2A8166A700318017 /* Info.plist */, - ); - path = TwiliEngageExampleNotificationService; - sourceTree = ""; - }; 9BC924472A5CA3E30003637C /* Packages */ = { isa = PBXGroup; children = ( @@ -249,6 +223,9 @@ dependencies = ( ); name = TwilioEngageExampleNotificationServiceExtension; + packageProductDependencies = ( + 82D44CAF2B0D56CC0055CF7F /* TwilioEngage */, + ); productName = TwilioEngageExampleNotificationServiceExtension; productReference = 82A3C7642B0D32F60036DF9A /* TwilioEngageExampleNotificationServiceExtension.appex */; productType = "com.apple.product-type.app-extension"; @@ -674,6 +651,10 @@ package = 46EDC71F27C6B92C00B870D7 /* XCRemoteSwiftPackageReference "analytics-swift" */; productName = Segment; }; + 82D44CAF2B0D56CC0055CF7F /* TwilioEngage */ = { + isa = XCSwiftPackageProductDependency; + productName = TwilioEngage; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 46EDC6EA27C6B8D100B870D7 /* Project object */; diff --git a/Example/BasicExample/BasicExample/AppDelegate.swift b/Example/BasicExample/BasicExample/AppDelegate.swift index 5dc20de..b7d740a 100644 --- a/Example/BasicExample/BasicExample/AppDelegate.swift +++ b/Example/BasicExample/BasicExample/AppDelegate.swift @@ -39,7 +39,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD let customCategory = TwilioEngage.CustomCategory(title: "customized_push", acceptActionTitle: "Accept Title", dismissActionTitle: "Dismiss Title") let categories = engage.createDefaultCategories(customCategory: customCategory) - + UNUserNotificationCenter.current() .setNotificationCategories(categories) diff --git a/Example/BasicExample/TwilioEngageExampleNotificationServiceExtension/NotificationService.swift b/Example/BasicExample/TwilioEngageExampleNotificationServiceExtension/NotificationService.swift index ecb2b38..9e98af6 100644 --- a/Example/BasicExample/TwilioEngageExampleNotificationServiceExtension/NotificationService.swift +++ b/Example/BasicExample/TwilioEngageExampleNotificationServiceExtension/NotificationService.swift @@ -6,66 +6,23 @@ // import UserNotifications +import TwilioEngage class NotificationService: UNNotificationServiceExtension { + let engage = TwilioEngageServiceExtension() var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? - let userDefaults = UserDefaults(suiteName: "group.com.segment.twilioEngage") override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) - + if let bestAttemptContent = bestAttemptContent { - // set badge - let badgeAmount = bestAttemptContent.userInfo["badgeAmount"] as? Int ?? 1 - let badgeStrategy = bestAttemptContent.userInfo["badgeStrategy"] as? String - var currentBadge = 2 - - print("****CURRENTBADGE******\(currentBadge)") - switch badgeStrategy { - case "inc": - currentBadge += badgeAmount - case "dec": - currentBadge -= badgeAmount - case "set": - currentBadge = badgeAmount - default: - currentBadge = badgeAmount - } - - userDefaults?.set(currentBadge, forKey: "Count") - bestAttemptContent.badge = NSNumber(value: currentBadge) - - // handle media - var urlString: String? = nil - if let mediaArray: NSArray = bestAttemptContent.userInfo["media"] as? NSArray { - - if let mediaURLString = mediaArray[0] as? String { - urlString = mediaURLString - } - - if urlString != nil, let fileURL = URL(string: urlString!){ - - guard let mediaData = NSData(contentsOf: fileURL) else { - contentHandler(bestAttemptContent) - return - } - - guard let mediaAttachment = UNNotificationAttachment.saveImageToDisk(fileIdentifier: "engage-image.png", data: mediaData, options: nil) else { - contentHandler(bestAttemptContent) - return - } - - bestAttemptContent.attachments = [ mediaAttachment ] - } - } - + + engage.handleNotification(content: bestAttemptContent, contentHandler) - contentHandler(bestAttemptContent) } - } override func serviceExtensionTimeWillExpire() { @@ -77,25 +34,3 @@ class NotificationService: UNNotificationServiceExtension { } } - -@available(iOSApplicationExtension 10.0, *) -extension UNNotificationAttachment { - - static func saveImageToDisk(fileIdentifier: String, data: NSData, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? { - let fileManager = FileManager.default - let folderName = ProcessInfo.processInfo.globallyUniqueString - let folderURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(folderName, isDirectory: true) - - do { - try fileManager.createDirectory(at: folderURL!, withIntermediateDirectories: true, attributes: nil) - let fileURL = folderURL?.appendingPathComponent(fileIdentifier) - try data.write(to: fileURL!, options: []) - let attachment = try UNNotificationAttachment(identifier: fileIdentifier, url: fileURL!, options: options) - return attachment - } catch let error { - print("error \(error)") - } - - return nil - } -} diff --git a/README.md b/README.md index bc7df48..bbb75bd 100644 --- a/README.md +++ b/README.md @@ -247,7 +247,7 @@ func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive respo //an extension for logic for displaying different notification types: extension AppDelegate { - //Handle the notification bacsed on the `tapAction` + //Handle the notification based on the `tapAction` func handleNotificiation(notification: [AnyHashable: Any], shouldAsk: Bool) { if let aps = notification["aps"] as? NSDictionary { if let tapAction = aps["category"] as? String { diff --git a/Sources/TwilioEngage/TwilioEngageServiceExtension.swift b/Sources/TwilioEngage/TwilioEngageServiceExtension.swift new file mode 100644 index 0000000..e862b85 --- /dev/null +++ b/Sources/TwilioEngage/TwilioEngageServiceExtension.swift @@ -0,0 +1,91 @@ +// +// TwilioEngageServiceExtension.swift +// +// Created by Alan Charles on 11/21/23. +// + +import Foundation +import Segment +import UserNotifications + +public class TwilioEngageServiceExtension: UtilityPlugin { + public var type = PluginType.utility + public weak var analytics: Analytics? = nil + let userDefaults = UserDefaults(suiteName: "group.com.segment.twilioEngage") + + public init() { + } + + public func configure(analytics: Analytics) { + self.analytics = analytics + } + + public func handleNotification(content: UNMutableNotificationContent, _ contentHandler: @escaping (UNNotificationContent) -> Void) { + + // set badge + let badgeAmount = content.userInfo["badgeAmount"] as? Int ?? 1 + let badgeStrategy = content.userInfo["badgeStrategy"] as? String + var currentBadge = 2 + + switch badgeStrategy { + case "inc": + currentBadge += badgeAmount + case "dec": + currentBadge -= badgeAmount + case "set": + currentBadge = badgeAmount + default: + currentBadge = badgeAmount + } + + userDefaults?.set(currentBadge, forKey: "Count") + content.badge = NSNumber(value: currentBadge) + + // handle media + var urlString: String? = nil + if let mediaArray: NSArray = content.userInfo["media"] as? NSArray { + + if let mediaURLString = mediaArray[0] as? String { + urlString = mediaURLString + } + + if urlString != nil, let fileURL = URL(string: urlString!){ + + guard let mediaData = NSData(contentsOf: fileURL) else { + contentHandler(content) + return + } + + guard let mediaAttachment = UNNotificationAttachment.saveImageToDisk(fileIdentifier: "engage-image.png", data: mediaData, options: nil) else { + contentHandler(content) + return + } + + content.attachments = [ mediaAttachment ] + } + } + } +} + +@available(iOSApplicationExtension 10.0, *) +extension UNNotificationAttachment { + + static func saveImageToDisk(fileIdentifier: String, data: NSData, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? { + let fileManager = FileManager.default + let folderName = ProcessInfo.processInfo.globallyUniqueString + let folderURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(folderName, isDirectory: true) + + do { + try fileManager.createDirectory(at: folderURL!, withIntermediateDirectories: true, attributes: nil) + let fileURL = folderURL?.appendingPathComponent(fileIdentifier) + try data.write(to: fileURL!, options: []) + let attachment = try UNNotificationAttachment(identifier: fileIdentifier, url: fileURL!, options: options) + return attachment + } catch let error { + print("error \(error)") + } + + return nil + } +} +