diff --git a/README.md b/README.md index d539928..97221c8 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Refer to the table below regarding the different campaigns that can be implement | `onAction(callback: (action: string) => {})` | Called when the user takes an action (e.g. Accept All) within the consent message. `action: string` is going to be replaced with an enum. | | `onSPUIFinished(callback: () => {})` | Called when the native SDKs is done removing the consent UI from the foreground. | | `onFinished(callback: () => {})` | Called when all UI and network processes are finished. User consent is stored on the local storage of each platform (`UserDefaults` for iOS and `SharedPrefs` for Android). And it is safe to retrieve consent data with `getUserData` | +| `onMessageInactivityTimeout(callback: () => {})` | Called when the user becomes inactive while viewing a consent message. This allows your app to respond to user inactivity events. | | `onError(callback: (description: string) => {})` | Called if something goes wrong. | ### Call `loadMessages` @@ -255,6 +256,9 @@ export default function App() { consentManager.current?.onAction(({ actionType }) => { console.log(`User took action ${actionType}`) }); + consentManager.current?.onMessageInactivityTimeout(() => { + console.log("User became inactive") + }); consentManager.current?.onError(console.error) consentManager.current?.loadMessage(); diff --git a/ReactNativeCmp.podspec b/ReactNativeCmp.podspec index 830416e..475b84c 100644 --- a/ReactNativeCmp.podspec +++ b/ReactNativeCmp.podspec @@ -15,7 +15,7 @@ Pod::Spec.new do |s| s.platforms = { :ios => min_ios_version_supported } s.source = { :git => "https://github.com/SourcePointUSA/react-native-sourcepoint-cmp.git", :tag => "#{s.version}" } - s.dependency "ConsentViewController", "7.11.1" + s.dependency "ConsentViewController", "7.12.0" s.source_files = "ios/**/*.{h,m,mm,cpp,swift}" s.private_header_files = "ios/**/*.h" diff --git a/android/build.gradle b/android/build.gradle index 7cc89e1..49efee2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -77,7 +77,7 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3" implementation "org.jetbrains.kotlinx:kotlinx-datetime:0.6.1" - implementation "com.sourcepoint.cmplibrary:cmplibrary:7.15.2" + implementation "com.sourcepoint.cmplibrary:cmplibrary:7.15.3" } react { diff --git a/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt b/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt index 97bd4a7..b9b8656 100644 --- a/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt +++ b/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt @@ -5,14 +5,10 @@ import com.facebook.react.bridge.Arguments.createMap import com.facebook.react.bridge.Callback import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactMethod -import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.ReadableArray -import com.facebook.react.module.annotations.ReactModule -import com.sourcepoint.cmplibrary.NativeMessageController +import com.facebook.react.bridge.ReadableMap import com.sourcepoint.cmplibrary.SpClient import com.sourcepoint.cmplibrary.SpConsentLib -import com.sourcepoint.cmplibrary.core.nativemessage.MessageStructure import com.sourcepoint.cmplibrary.creation.ConfigOption.SUPPORT_LEGACY_USPSTRING import com.sourcepoint.cmplibrary.creation.SpConfigDataBuilder import com.sourcepoint.cmplibrary.creation.makeConsentLib @@ -23,22 +19,19 @@ import com.sourcepoint.cmplibrary.util.clearAllData import com.sourcepoint.cmplibrary.util.userConsents import com.sourcepoint.reactnativecmp.arguments.BuildOptions import com.sourcepoint.reactnativecmp.arguments.toList -import com.sourcepoint.reactnativecmp.consents.RNSPUserData import com.sourcepoint.reactnativecmp.consents.RNSPGDPRConsent -import org.json.JSONObject +import com.sourcepoint.reactnativecmp.consents.RNSPUserData data class SPLoadMessageParams(val authId: String?) { constructor(fromReadableMap: ReadableMap?) : this(authId = fromReadableMap?.getString("authId")) } -@ReactModule(name = ReactNativeCmpModule.NAME) class ReactNativeCmpModule(reactContext: ReactApplicationContext) : NativeReactNativeCmpSpec(reactContext), SpClient { private var spConsentLib: SpConsentLib? = null override fun getName() = NAME - @ReactMethod override fun build( accountId: Double, propertyId: Double, @@ -84,7 +77,6 @@ class ReactNativeCmpModule(reactContext: ReactApplicationContext) : NativeReactN reactApplicationContext.runOnUiQueueThread(runnable) } - @ReactMethod override fun loadMessage(params: ReadableMap?) { val parsedParams = SPLoadMessageParams(fromReadableMap = params) @@ -93,22 +85,18 @@ class ReactNativeCmpModule(reactContext: ReactApplicationContext) : NativeReactN } } - @ReactMethod override fun clearLocalData() { clearAllData(reactApplicationContext) } - @ReactMethod override fun getUserData(promise: Promise) { promise.resolve(userConsentsToWriteableMap(userConsents(reactApplicationContext))) } - @ReactMethod override fun loadGDPRPrivacyManager(pmId: String) { runOnMainThread { spConsentLib?.loadPrivacyManager(pmId, GDPR) } } - @ReactMethod override fun loadUSNatPrivacyManager(pmId: String) { runOnMainThread { spConsentLib?.loadPrivacyManager(pmId, USNAT) } } @@ -125,7 +113,12 @@ class ReactNativeCmpModule(reactContext: ReactApplicationContext) : NativeReactN runOnMainThread { spConsentLib?.dismissMessage() } } - override fun postCustomConsentGDPR(vendors: ReadableArray, categories: ReadableArray, legIntCategories: ReadableArray, callback: Callback) { + override fun postCustomConsentGDPR( + vendors: ReadableArray, + categories: ReadableArray, + legIntCategories: ReadableArray, + callback: Callback + ) { runOnMainThread { spConsentLib?.customConsentGDPR( vendors.toList(), @@ -142,7 +135,12 @@ class ReactNativeCmpModule(reactContext: ReactApplicationContext) : NativeReactN } } - override fun postDeleteCustomConsentGDPR(vendors: ReadableArray, categories: ReadableArray, legIntCategories: ReadableArray, callback: Callback) { + override fun postDeleteCustomConsentGDPR( + vendors: ReadableArray, + categories: ReadableArray, + legIntCategories: ReadableArray, + callback: Callback) + { runOnMainThread { spConsentLib?.deleteCustomConsentTo( vendors.toList(), @@ -177,20 +175,16 @@ class ReactNativeCmpModule(reactContext: ReactApplicationContext) : NativeReactN emitOnError(createMap().apply { putString("description", error.message) }) } - @Deprecated("onMessageReady callback will be removed in favor of onUIReady. Currently this callback is disabled.") - override fun onMessageReady(message: JSONObject) {} - - override fun onNativeMessageReady( - message: MessageStructure, - messageController: NativeMessageController - ) {} - override fun onNoIntentActivitiesFound(url: String) {} override fun onSpFinished(sPConsents: SPConsents) { emitOnFinished() } + override fun onMessageInactivityTimeout() { + emitOnMessageInactivityTimeout() + } + override fun onUIFinished(view: View) { spConsentLib?.removeView(view) emitOnSPUIFinished() diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f0c6024..8467a58 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,6 +1,6 @@ PODS: - boost (1.84.0) - - ConsentViewController (7.11.1): + - ConsentViewController (7.12.0): - Down (~> 0.11.0) - SPMobileCore (= 0.1.11) - DoubleConversion (1.1.6) @@ -1660,7 +1660,7 @@ PODS: - React-perflogger (= 0.79.2) - React-utils (= 0.79.2) - ReactNativeCmp (1.0.4): - - ConsentViewController (= 7.11.1) + - ConsentViewController (= 7.12.0) - DoubleConversion - glog - hermes-engine @@ -1919,7 +1919,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - ConsentViewController: 6cd17ebf78b80e7d32bf3d6b0b46d20a40e8cad9 + ConsentViewController: 9adf0d8de93022115c3a398e2b465870ee951a1d DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 84b955f7b4da8b895faf5946f73748267347c975 @@ -1989,7 +1989,7 @@ SPEC CHECKSUMS: ReactAppDependencyProvider: 04d5eb15eb46be6720e17a4a7fa92940a776e584 ReactCodegen: c63eda03ba1d94353fb97b031fc84f75a0d125ba ReactCommon: 76d2dc87136d0a667678668b86f0fca0c16fdeb0 - ReactNativeCmp: 8502676551832d19d227fa2b161b4c7354cd686c + ReactNativeCmp: 5d2aee1d86992ceb88690649e0bdcf55920ca62a SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 SPMobileCore: 220d109e404cb17169f7e26f2a34c6022b80079a Yoga: c758bfb934100bb4bf9cbaccb52557cee35e8bdf diff --git a/example/src/App.tsx b/example/src/App.tsx index 84c6b5f..0e8a93d 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -88,6 +88,10 @@ export default function App() { console.log(`action: ${actionType}`) ); + consentManager.current?.onMessageInactivityTimeout(() => { + console.log("User inactive"); + }); + consentManager.current?.onError((description) => { setSDKStatus(SDKStatus.Errored); console.error(description); diff --git a/ios/RNSourcepointCmp.swift b/ios/RNSourcepointCmp.swift index a7e5491..6266f58 100644 --- a/ios/RNSourcepointCmp.swift +++ b/ios/RNSourcepointCmp.swift @@ -38,6 +38,7 @@ import React func onSPUIReady() func onSPUIFinished() func onFinished() + func onMessageInactivityTimeout() func onError(description: String) } @@ -143,6 +144,10 @@ import React delegate?.onFinished() } + public func onMessageInactivityTimeout() { + delegate?.onMessageInactivityTimeout() + } + public func onError(error: SPError) { print("Something went wrong", error) delegate?.onError(description: error.description) @@ -176,6 +181,10 @@ private class CMPDelegateHandler: NSObject, SPDelegate { parent?.onSPFinished(userData: userData) } + func onMessageInactivityTimeout() { + parent?.onMessageInactivityTimeout() + } + func onError(error: SPError) { parent?.onError(error: error) } diff --git a/ios/ReactNativeCmp.mm b/ios/ReactNativeCmp.mm index 83c76b0..0be03e3 100644 --- a/ios/ReactNativeCmp.mm +++ b/ios/ReactNativeCmp.mm @@ -136,6 +136,10 @@ - (void)onFinished { [self emitOnFinished]; } +- (void)onMessageInactivityTimeout { + [self emitOnMessageInactivityTimeout]; +} + - (void)onSPUIFinished { [self emitOnSPUIFinished]; } diff --git a/src/NativeReactNativeCmp.ts b/src/NativeReactNativeCmp.ts index a81d0d2..3e4f74d 100644 --- a/src/NativeReactNativeCmp.ts +++ b/src/NativeReactNativeCmp.ts @@ -233,6 +233,7 @@ export interface Spec extends TurboModule { readonly onSPUIReady: EventEmitter; readonly onSPUIFinished: EventEmitter; readonly onFinished: EventEmitter; + readonly onMessageInactivityTimeout: EventEmitter; readonly onError: EventEmitter<{ description: string }>; } diff --git a/src/index.tsx b/src/index.tsx index e219ae3..56fdf35 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -82,5 +82,6 @@ export default class SPConsentManager implements Spec { onSPUIReady: EventEmitter = ReactNativeCmp.onSPUIReady; onSPUIFinished: EventEmitter = ReactNativeCmp.onSPUIFinished; onFinished: EventEmitter = ReactNativeCmp.onFinished; + onMessageInactivityTimeout: EventEmitter = ReactNativeCmp.onMessageInactivityTimeout; onError: EventEmitter<{ description: string }> = ReactNativeCmp.onError; }