diff --git a/ios/wrappers/CioRctWrapper.mm b/ios/wrappers/CioRctWrapper.mm index 8a0d6b8a..b3cf4aca 100644 --- a/ios/wrappers/CioRctWrapper.mm +++ b/ios/wrappers/CioRctWrapper.mm @@ -1,16 +1,15 @@ #import +@interface RCT_EXTERN_REMAP_MODULE (NativeCustomerIO, CioRctWrapper, NSObject) -@interface RCT_EXTERN_REMAP_MODULE(NativeCustomerIO, CioRctWrapper, NSObject) - -RCT_EXTERN_METHOD(initialize:(id)config args:(id)args) -RCT_EXTERN_METHOD(identify:(NSString *)identify traits:(NSDictionary *)traits) +RCT_EXTERN_METHOD(initialize : (id)config args : (id _Nullable)args) +RCT_EXTERN_METHOD(identify : (NSString* _Nullable)userId traits : (NSDictionary* _Nullable)traits) RCT_EXTERN_METHOD(clearIdentify) -RCT_EXTERN_METHOD(track:(NSString *)name properties:(NSDictionary *)properties) -RCT_EXTERN_METHOD(screen:(NSString *)title properties:(NSDictionary *)) -RCT_EXTERN_METHOD(setProfileAttributes: (NSDictionary *)attributes) -RCT_EXTERN_METHOD(setDeviceAttributes: (NSDictionary *)attributes) -RCT_EXTERN_METHOD(registerDeviceToken: (NSString *)token) +RCT_EXTERN_METHOD(track : (NSString*)name properties : (NSDictionary* _Nullable)properties) +RCT_EXTERN_METHOD(screen : (NSString*)title properties : (NSDictionary* _Nullable)properties) +RCT_EXTERN_METHOD(setProfileAttributes : (NSDictionary*)attributes) +RCT_EXTERN_METHOD(setDeviceAttributes : (NSDictionary*)attributes) +RCT_EXTERN_METHOD(registerDeviceToken : (NSString*)token) RCT_EXTERN_METHOD(deleteDeviceToken) + (BOOL)requiresMainQueueSetup diff --git a/ios/wrappers/CioRctWrapper.swift b/ios/wrappers/CioRctWrapper.swift index 861024ac..6ed8a8fe 100644 --- a/ios/wrappers/CioRctWrapper.swift +++ b/ios/wrappers/CioRctWrapper.swift @@ -1,17 +1,16 @@ -import CioInternalCommon +import CioAnalytics import CioDataPipelines +import CioInternalCommon import CioMessagingInApp import CioMessagingPush -import UserNotifications import React -import CioAnalytics +import UserNotifications @objc(CioRctWrapper) class CioRctWrapper: NSObject { - @objc var moduleRegistry: RCTModuleRegistry! private let logger: CioInternalCommon.Logger = DIGraphShared.shared.logger - + @objc(initialize:args:) func initialize(_ configJson: AnyObject, _ sdkArgs: AnyObject?) { do { @@ -22,14 +21,14 @@ class CioRctWrapper: NSObject { let sdkParams = sdkArgs as? [String: Any?] let packageSource = sdkParams?["packageSource"] as? String let packageVersion = sdkParams?["packageVersion"] as? String - + if let source = packageSource, let sdkVersion = packageVersion { DIGraphShared.shared.override(value: CustomerIOSdkClient(source: source, sdkVersion: sdkVersion), forType: SdkClient.self) } let sdkConfigBuilder = try SDKConfigBuilder.create(from: sdkConfig) CustomerIO.initialize(withConfig: sdkConfigBuilder.build()) - + if let inAppConfig = try? MessagingInAppConfigBuilder.build(from: sdkConfig) { MessagingInApp.initialize(withConfig: inAppConfig) MessagingInApp.shared.setEventListener(self) @@ -39,9 +38,9 @@ class CioRctWrapper: NSObject { logger.error("Initializing Customer.io SDK failed with error: \(error)") } } - - @objc - func identify(_ userId: String? = nil, traits: [String: Any]? = nil) { + + @objc(identify:traits:) + func identify(_ userId: String?, _ traits: [String: Any]?) { if let userId = userId { CustomerIO.shared.identify(userId: userId, traits: traits) } else if traits != nil { @@ -54,39 +53,39 @@ class CioRctWrapper: NSObject { logger.error("Provide id or traits to identify a user profile.") } } - - @objc + + @objc(clearIdentify) func clearIdentify() { CustomerIO.shared.clearIdentify() } - - @objc + + @objc(track:properties:) func track(_ name: String, properties: [String: Any]?) { CustomerIO.shared.track(name: name, properties: properties) } - - @objc + + @objc(screen:properties:) func screen(_ title: String, properties: [String: Any]?) { CustomerIO.shared.screen(title: title, properties: properties) } - - @objc + + @objc(setProfileAttributes:) func setProfileAttributes(_ attrs: [String: Any]) { CustomerIO.shared.profileAttributes = attrs } - - @objc + + @objc(setDeviceAttributes:) func setDeviceAttributes(_ attrs: [String: Any]) { CustomerIO.shared.deviceAttributes = attrs } - - @objc - func registerDeviceToken(_ token: String){ + + @objc(registerDeviceToken:) + func registerDeviceToken(_ token: String) { CustomerIO.shared.registerDeviceToken(token) } - - @objc - func deleteDeviceToken(){ + + @objc(deleteDeviceToken) + func deleteDeviceToken() { CustomerIO.shared.deleteDeviceToken() } } @@ -109,19 +108,19 @@ extension CioRctWrapper: InAppEventListener { body: body ) } - + func messageShown(message: InAppMessage) { sendEvent(eventType: CustomerioConstants.messageShown, message: message) } - + func messageDismissed(message: InAppMessage) { sendEvent(eventType: CustomerioConstants.messageDismissed, message: message) } - + func errorWithMessage(message: InAppMessage) { sendEvent(eventType: CustomerioConstants.errorWithMessage, message: message) } - + func messageActionTaken(message: InAppMessage, actionValue: String, actionName: String) { sendEvent(eventType: CustomerioConstants.messageActionTaken, message: message, actionValue: actionValue, actionName: actionName) } diff --git a/ios/wrappers/inapp/CioRctInAppMessaging.mm b/ios/wrappers/inapp/CioRctInAppMessaging.mm index fc45fba0..f8a54a74 100644 --- a/ios/wrappers/inapp/CioRctInAppMessaging.mm +++ b/ios/wrappers/inapp/CioRctInAppMessaging.mm @@ -1,6 +1,6 @@ #import -@interface RCT_EXTERN_REMAP_MODULE(CioRctInAppMessaging, CioRctInAppMessaging, RCTEventEmitter) +@interface RCT_EXTERN_REMAP_MODULE (CioRctInAppMessaging, CioRctInAppMessaging, RCTEventEmitter) RCT_EXTERN_METHOD(supportedEvents) diff --git a/ios/wrappers/inapp/CioRctInAppMessaging.swift b/ios/wrappers/inapp/CioRctInAppMessaging.swift index 3da2be6e..ce18677f 100644 --- a/ios/wrappers/inapp/CioRctInAppMessaging.swift +++ b/ios/wrappers/inapp/CioRctInAppMessaging.swift @@ -1,6 +1,6 @@ +import CioMessagingInApp import Foundation import React -import CioMessagingInApp @objc(CioRctInAppMessaging) class CioRctInAppMessaging: RCTEventEmitter { @@ -21,8 +21,8 @@ class CioRctInAppMessaging: RCTEventEmitter { * Overriding supportedEvents method to return an array of supported event names. * We are combining in-app events against single name so only one event is added. */ - open override func supportedEvents() -> [String]! { - return [CustomerioConstants.inAppEventListener] + override open func supportedEvents() -> [String]! { + [CustomerioConstants.inAppEventListener] } /** diff --git a/ios/wrappers/logging/CioLoggingEmitter.mm b/ios/wrappers/logging/CioLoggingEmitter.mm index 779e1a32..38e27e69 100644 --- a/ios/wrappers/logging/CioLoggingEmitter.mm +++ b/ios/wrappers/logging/CioLoggingEmitter.mm @@ -1,4 +1,5 @@ #import -@interface RCT_EXTERN_REMAP_MODULE(CioLoggingEmitter, CioLoggingEmitter, RCTEventEmitter) +@interface RCT_EXTERN_REMAP_MODULE (CioLoggingEmitter, CioLoggingEmitter, RCTEventEmitter) + @end diff --git a/ios/wrappers/logging/CioLoggingEmitter.swift b/ios/wrappers/logging/CioLoggingEmitter.swift index 73beaf80..05844510 100644 --- a/ios/wrappers/logging/CioLoggingEmitter.swift +++ b/ios/wrappers/logging/CioLoggingEmitter.swift @@ -1,51 +1,49 @@ - -import React import CioInternalCommon +import React @objc(CioLoggingEmitter) class CioLoggingEmitter: RCTEventEmitter { - fileprivate static var eventName = "CioLogEvent" - + fileprivate var hasObservers = false - + // Requires adding requiresMainQueueSetup method // since it overrides init - @objc static override func requiresMainQueueSetup() -> Bool { - return true // Return true if the module must be initialized on the main queue + @objc override static func requiresMainQueueSetup() -> Bool { + true // Return true if the module must be initialized on the main queue } - + override init() { super.init() DIGraphShared.shared.logger.setLogDispatcher { [weak self] level, message in guard let self else { return } - + emit(level: level, message: message) } } - + deinit { // Clear log dispatcher if the emitter has been deallocated DIGraphShared.shared.logger.setLogDispatcher(nil) } - + override func startObserving() { hasObservers = true } - + override func stopObserving() { hasObservers = false } - + override func supportedEvents() -> [String] { [Self.eventName] } - + override var methodQueue: dispatch_queue_t! { DispatchQueue(label: Self.moduleName()) } - + private var emitter: CioLoggingEmitter? { moduleRegistry?.module(forName: "CioLoggingEmitter") as? CioLoggingEmitter } diff --git a/ios/wrappers/push/CioRctPushMessaging.mm b/ios/wrappers/push/CioRctPushMessaging.mm index cead07a1..80536a6f 100644 --- a/ios/wrappers/push/CioRctPushMessaging.mm +++ b/ios/wrappers/push/CioRctPushMessaging.mm @@ -1,19 +1,22 @@ #import -@interface RCT_EXTERN_REMAP_MODULE(CioRctPushMessaging, CioRctPushMessaging, NSObject) +@interface RCT_EXTERN_REMAP_MODULE (CioRctPushMessaging, CioRctPushMessaging, NSObject) -RCT_EXTERN_METHOD(trackNotificationResponseReceived : (nonnull NSDictionary *) payload]) +RCT_EXTERN_METHOD(trackNotificationResponseReceived : (NSDictionary*)payload) -RCT_EXTERN_METHOD(trackNotificationReceived : (nonnull NSDictionary *) payload]) +RCT_EXTERN_METHOD(trackNotificationReceived : (NSDictionary*)payload) -RCT_EXTERN_METHOD(getRegisteredDeviceToken: (RCTPromiseResolveBlock) resolver - rejecter:(RCTPromiseRejectBlock)rejecter) +RCT_EXTERN_METHOD(getRegisteredDeviceToken + : (RCTPromiseResolveBlock)resolver rejecter + : (RCTPromiseRejectBlock)rejecter) -RCT_EXTERN_METHOD(showPromptForPushNotifications: (nonnull NSDictionary *) options - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(showPromptForPushNotifications + : (NSDictionary*)options resolver + : (RCTPromiseResolveBlock)resolve rejecter + : (RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(getPushPermissionStatus: (RCTPromiseResolveBlock) resolver - rejecter:(RCTPromiseRejectBlock)rejecter) +RCT_EXTERN_METHOD(getPushPermissionStatus + : (RCTPromiseResolveBlock)resolver rejecter + : (RCTPromiseRejectBlock)reject) -@end \ No newline at end of file +@end diff --git a/ios/wrappers/push/CioRctPushMessaging.swift b/ios/wrappers/push/CioRctPushMessaging.swift index 49359656..e501d131 100644 --- a/ios/wrappers/push/CioRctPushMessaging.swift +++ b/ios/wrappers/push/CioRctPushMessaging.swift @@ -1,6 +1,6 @@ -import Foundation import CioInternalCommon import CioMessagingPush +import Foundation enum PushPermissionStatus: String, CaseIterable { case denied @@ -8,51 +8,47 @@ enum PushPermissionStatus: String, CaseIterable { case granted var value: String { - return rawValue.uppercased() + rawValue.uppercased() } } @objc(CioRctPushMessaging) class CioRctPushMessaging: NSObject { - @objc static func requiresMainQueueSetup() -> Bool { false /// false because our native module's initialization does not require access to UIKit } // Tracks `opened` push metrics when a push notification is interacted with. - @objc + @objc(trackNotificationResponseReceived:) func trackNotificationResponseReceived(_ payload: NSDictionary) { trackPushMetrics(payload: payload, event: .opened) } // Tracks `delivered` push metrics when a push notification is received. - @objc + @objc(trackNotificationReceived:) func trackNotificationReceived(_ payload: NSDictionary) { - trackPushMetrics(payload: payload, event: .delivered) } // Get the currently registered device token for the app @objc(getRegisteredDeviceToken:rejecter:) - func getRegisteredDeviceToken(resolver resolve: @escaping(RCTPromiseResolveBlock), rejecter reject: @escaping(RCTPromiseRejectBlock)) -> Void { - - guard let token = CustomerIO.shared.registeredDeviceToken else { + func getRegisteredDeviceToken(resolver resolve: @escaping (RCTPromiseResolveBlock), rejecter reject: @escaping (RCTPromiseRejectBlock)) { + guard let token = CustomerIO.shared.registeredDeviceToken else { reject(CustomerioConstants.cioTag, CustomerioConstants.showDeviceTokenFailureError, nil) - return + return } resolve(token) } - private func trackPushMetrics(payload: NSDictionary, event : Metric) { - guard let deliveryId = payload[CustomerioConstants.CioDeliveryId] as? String, let deviceToken = payload[CustomerioConstants.CioDeliveryToken] as? String else - {return} + private func trackPushMetrics(payload: NSDictionary, event: Metric) { + guard let deliveryId = payload[CustomerioConstants.CioDeliveryId] as? String, let deviceToken = payload[CustomerioConstants.CioDeliveryToken] as? String + else { return } MessagingPush.shared.trackMetric(deliveryID: deliveryId, event: event, deviceToken: deviceToken) } @objc(showPromptForPushNotifications:resolver:rejecter:) - func showPromptForPushNotifications(options : Dictionary, resolver resolve: @escaping(RCTPromiseResolveBlock), rejecter reject: @escaping(RCTPromiseRejectBlock)) -> Void { - + func showPromptForPushNotifications(options: [String: AnyHashable], resolver resolve: @escaping (RCTPromiseResolveBlock), rejecter reject: @escaping (RCTPromiseRejectBlock)) { // Show prompt if status is not determined getPushNotificationPermissionStatus { status in if status == .notDetermined { @@ -71,39 +67,37 @@ class CioRctPushMessaging: NSObject { } @objc(getPushPermissionStatus:rejecter:) - func getPushPermissionStatus(resolver resolve: @escaping(RCTPromiseResolveBlock), rejecter reject: @escaping(RCTPromiseRejectBlock)) -> Void { + func getPushPermissionStatus(resolver resolve: @escaping (RCTPromiseResolveBlock), rejecter _: @escaping (RCTPromiseRejectBlock)) { getPushNotificationPermissionStatus { status in resolve(status.value) } } - private func requestPushAuthorization(options: [String: Any], onComplete : @escaping(Any) -> Void - ) { - let current = UNUserNotificationCenter.current() - var notificationOptions : UNAuthorizationOptions = [.alert] - if let ios = options[CustomerioConstants.platformiOS] as? [String: Any] { - - if let soundOption = ios[CustomerioConstants.sound] as? Bool, soundOption { - notificationOptions.insert(.sound) - } - if let badgeOption = ios[CustomerioConstants.badge] as? Bool, badgeOption { - notificationOptions.insert(.badge) - } + private func requestPushAuthorization(options: [String: Any], onComplete: @escaping (Any) -> Void) { + let current = UNUserNotificationCenter.current() + var notificationOptions: UNAuthorizationOptions = [.alert] + if let ios = options[CustomerioConstants.platformiOS] as? [String: Any] { + if let soundOption = ios[CustomerioConstants.sound] as? Bool, soundOption { + notificationOptions.insert(.sound) } - current.requestAuthorization(options: notificationOptions) { isGranted, error in - if let error = error { - onComplete(error) - return - } - onComplete(isGranted) + if let badgeOption = ios[CustomerioConstants.badge] as? Bool, badgeOption { + notificationOptions.insert(.badge) } } + current.requestAuthorization(options: notificationOptions) { isGranted, error in + if let error = error { + onComplete(error) + return + } + onComplete(isGranted) + } + } - private func getPushNotificationPermissionStatus(completionHandler: @escaping(PushPermissionStatus) -> Void) { + private func getPushNotificationPermissionStatus(completionHandler: @escaping (PushPermissionStatus) -> Void) { var status = PushPermissionStatus.notDetermined let current = UNUserNotificationCenter.current() current.getNotificationSettings(completionHandler: { permission in - switch permission.authorizationStatus { + switch permission.authorizationStatus { case .authorized, .provisional, .ephemeral: status = .granted case .denied: diff --git a/ios/wrappers/utils/CioConfigUtils.swift b/ios/wrappers/utils/CioConfigUtils.swift index 0e386ef6..25399a11 100644 --- a/ios/wrappers/utils/CioConfigUtils.swift +++ b/ios/wrappers/utils/CioConfigUtils.swift @@ -56,7 +56,7 @@ extension RawRepresentable where RawValue == String { thenPassItTo handler: (Transformed) -> Any, transformingBy transform: (Raw) -> Transformed? ) { - if let value = config?[self.rawValue] as? Raw, let result = transform(value) { + if let value = config?[rawValue] as? Raw, let result = transform(value) { _ = handler(result) } } diff --git a/ios/wrappers/utils/CioConstants.swift b/ios/wrappers/utils/CioConstants.swift index c12e2586..87df4c2b 100644 --- a/ios/wrappers/utils/CioConstants.swift +++ b/ios/wrappers/utils/CioConstants.swift @@ -1,4 +1,4 @@ -struct CustomerioConstants { +enum CustomerioConstants { // InApp Messaging static let inAppEventListener = "InAppEventListener" static let eventType = "eventType" @@ -10,7 +10,7 @@ struct CustomerioConstants { static let messageDismissed = "messageDismissed" static let errorWithMessage = "errorWithMessage" static let messageActionTaken = "messageActionTaken" - + // Push Messaging static let CioDeliveryId = "CIO-Delivery-ID" static let CioDeliveryToken = "CIO-Delivery-Token" @@ -19,7 +19,7 @@ struct CustomerioConstants { static let platformiOS = "ios" static let sound = "sound" static let badge = "badge" - + // Logging static let cioTag = "[CIO]" }