From e1b4a8d85aa971bbdfe75ba57a4a9121bc21ed29 Mon Sep 17 00:00:00 2001 From: Dmytro Date: Fri, 29 Aug 2025 12:32:41 +0200 Subject: [PATCH 1/3] add android `ConsentLibExceptionK.code` to RN --- .../com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt | 7 ++++++- src/NativeReactNativeCmp.ts | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt b/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt index 0a256a6..bf73982 100644 --- a/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt +++ b/android/src/main/java/com/sourcepoint/reactnativecmp/ReactNativeCmpModule.kt @@ -8,6 +8,7 @@ import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import com.sourcepoint.cmplibrary.SpClient import com.sourcepoint.cmplibrary.SpConsentLib +import com.sourcepoint.cmplibrary.exception.ConsentLibExceptionK import com.sourcepoint.cmplibrary.creation.ConfigOption.SUPPORT_LEGACY_USPSTRING import com.sourcepoint.cmplibrary.creation.SpConfigDataBuilder import com.sourcepoint.cmplibrary.creation.makeConsentLib @@ -179,7 +180,11 @@ class ReactNativeCmpModule(reactContext: ReactApplicationContext) : NativeReactN override fun onConsentReady(consent: SPConsents) {} override fun onError(error: Throwable) { - emitInternalOnError(Json.encodeToString(mapOf("description" to error.message))) + val convertedError = error as? ConsentLibExceptionK + emitInternalOnError(Json.encodeToString(mapOf( + "spCode" to convertedError?.code as String, + "description" to convertedError?.message as String + ))) } override fun onNoIntentActivitiesFound(url: String) {} diff --git a/src/NativeReactNativeCmp.ts b/src/NativeReactNativeCmp.ts index a2b821d..99c7f0b 100644 --- a/src/NativeReactNativeCmp.ts +++ b/src/NativeReactNativeCmp.ts @@ -210,6 +210,7 @@ export type SPBuildOptions = { } export type SPError = { + spCode: string; description: string; }; From dec7f376cd79e1953e89b5ca09fcd3d64756dcac Mon Sep 17 00:00:00 2001 From: Dmytro Date: Fri, 29 Aug 2025 12:33:42 +0200 Subject: [PATCH 2/3] pass ios `SPError.spCode` to RN --- ios/RNSourcepointCmp.swift | 27 +++++++++++++++++++++++++-- ios/ReactNativeCmp.mm | 7 ++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ios/RNSourcepointCmp.swift b/ios/RNSourcepointCmp.swift index c74187a..af64ea1 100644 --- a/ios/RNSourcepointCmp.swift +++ b/ios/RNSourcepointCmp.swift @@ -42,13 +42,36 @@ import React } } +@objcMembers public class RNError: NSObject { + public let code: String + public let errorDescription: String + + @objc public init(code: String, description: String) { + self.code = code + self.errorDescription = description + } + + func toDictionary() -> [String: Any] { + ["spCode": code, "description": errorDescription] + } + + @objc public func stringifiedJson() -> String { + if let jsonData = try? JSONSerialization.data(withJSONObject: toDictionary()), + let jsonString = String(data: jsonData, encoding: .utf8) { + return jsonString + } else { + return "{\"code\":\"unknown\"}" + } + } +} + @objc public protocol ReactNativeCmpImplDelegate { func onAction(_ action: RNAction) func onSPUIReady() func onSPUIFinished() func onFinished() func onMessageInactivityTimeout() - func onError(description: String) + func onError(_ error: RNError) } @objcMembers public class ReactNativeCmpImpl: NSObject { @@ -163,7 +186,7 @@ import React public func onError(error: SPError) { print("Something went wrong", error) - delegate?.onError(description: error.description) + delegate?.onError(RNError(code: error.spCode, description: error.description)) } public func dismissMessage() { diff --git a/ios/ReactNativeCmp.mm b/ios/ReactNativeCmp.mm index 9e99601..0df4099 100644 --- a/ios/ReactNativeCmp.mm +++ b/ios/ReactNativeCmp.mm @@ -137,11 +137,8 @@ - (void)onAction:(RNAction*)action { [self emitInternalOnAction: [action stringifiedJson]]; } -- (void)onErrorWithDescription:(NSString * _Nonnull)description { - NSDictionary *dict = @{@"description": description}; - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; - NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - [self emitInternalOnError: json]; +- (void)onError:(RNError*)error { + [self emitInternalOnError: [error stringifiedJson]]; } - (void)onFinished { From 3cad035eb43aa4cc27ead4374b99dfe60f968e39 Mon Sep 17 00:00:00 2001 From: Dmytro Date: Fri, 29 Aug 2025 12:34:05 +0200 Subject: [PATCH 3/3] update example app --- README.md | 2 +- example/src/App.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6a78aac..8285762 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Refer to the table below regarding the different campaigns that can be implement | `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. | +| `onError(callback: (error: SPError) => {})` | Called if something goes wrong. | ### Call `loadMessages` diff --git a/example/src/App.tsx b/example/src/App.tsx index 63f340a..b1b8f71 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -97,9 +97,9 @@ export default function App() { console.log("User inactive"); }); - consentManager.current?.onError((description) => { + consentManager.current?.onError((error) => { setSDKStatus(SDKStatus.Errored); - console.error(description); + console.error(error); }); consentManager.current?.getUserData().then(setUserData);