react-native-acoustic-connect-beta 18.0.27 → 18.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/AcousticConnectRN.podspec +4 -4
  2. package/README.md +36 -7
  3. package/android/CMakeLists.txt +1 -1
  4. package/android/build.gradle +1 -1
  5. package/android/src/main/assets/ConnectBasicConfig.properties +1 -1
  6. package/android/src/main/java/com/acousticconnectrn/AcousticConnectRNPackage.java +1 -1
  7. package/android/src/main/java/com/acousticconnectrn/HybridAcousticConnectRN.kt +237 -37
  8. package/ios/Bridge.h +1 -1
  9. package/ios/HybridAcousticConnectRN.swift +36 -6
  10. package/lib/commonjs/TLTRN.js +23 -3
  11. package/lib/commonjs/TLTRN.js.map +1 -1
  12. package/lib/commonjs/components/Connect.js +1 -1
  13. package/lib/commonjs/index.js +13 -2
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/commonjs/utils/withAcousticAutoDialog.js +1 -1
  16. package/lib/module/TLTRN.js +23 -3
  17. package/lib/module/TLTRN.js.map +1 -1
  18. package/lib/module/components/Connect.js +1 -1
  19. package/lib/module/index.js +14 -2
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/utils/withAcousticAutoDialog.js +1 -1
  22. package/lib/typescript/src/TLTRN.d.ts.map +1 -1
  23. package/lib/typescript/src/index.d.ts +2 -2
  24. package/lib/typescript/src/index.d.ts.map +1 -1
  25. package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts +40 -0
  26. package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts.map +1 -1
  27. package/lib/typescript/src/utils/withAcousticAutoDialog.d.ts +1 -1
  28. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.cpp +22 -0
  29. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.hpp +1 -0
  30. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/HybridAcousticConnectRNSpec.kt +4 -0
  31. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/PushErrorInfo.kt +17 -0
  32. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/PushPermissionResult.kt +15 -0
  33. package/nitrogen/generated/ios/AcousticConnectRN-Swift-Cxx-Bridge.hpp +54 -14
  34. package/nitrogen/generated/ios/c++/HybridAcousticConnectRNSpecSwift.hpp +8 -0
  35. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec.swift +1 -0
  36. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec_cxx.swift +41 -0
  37. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.cpp +1 -0
  38. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.hpp +1 -0
  39. package/package.json +5 -5
  40. package/src/TLTRN.ts +31 -11
  41. package/src/components/Connect.tsx +1 -1
  42. package/src/index.ts +19 -2
  43. package/src/specs/react-native-acoustic-connect.nitro.ts +47 -1
  44. package/src/utils/withAcousticAutoDialog.tsx +1 -1
@@ -37,6 +37,7 @@ public protocol HybridAcousticConnectRNSpec_protocol: HybridObject {
37
37
  func logDialogDismissEvent(dialogId: String, dismissReason: String) throws -> Bool
38
38
  func logDialogButtonClickEvent(dialogId: String, buttonText: String, buttonIndex: Double) throws -> Bool
39
39
  func logDialogCustomEvent(dialogId: String, eventName: String, values: Dictionary<String, Variant_Bool_String_Double>) throws -> Bool
40
+ func logIdentity(identifierName: String, identifierValue: String, signalType: String?, additionalParameters: Dictionary<String, String>?) throws -> Promise<Bool>
40
41
  func pushDidRegisterWithToken(deviceToken: ArrayBuffer) throws -> Promise<Bool>
41
42
  func pushDidFailToRegister(error: PushErrorInfo) throws -> Promise<Bool>
42
43
  func pushDidReceiveNotification(userInfo: Dictionary<String, Variant_Bool_String_Double>) throws -> Promise<Bool>
@@ -604,6 +604,47 @@ open class HybridAcousticConnectRNSpec_cxx {
604
604
  }
605
605
  }
606
606
 
607
+ @inline(__always)
608
+ public final func logIdentity(identifierName: std.string, identifierValue: std.string, signalType: bridge.std__optional_std__string_, additionalParameters: bridge.std__optional_std__unordered_map_std__string__std__string__) -> bridge.Result_std__shared_ptr_Promise_bool___ {
609
+ do {
610
+ let __result = try self.__implementation.logIdentity(identifierName: String(identifierName), identifierValue: String(identifierValue), signalType: { () -> String? in
611
+ if bridge.has_value_std__optional_std__string_(signalType) {
612
+ let __unwrapped = bridge.get_std__optional_std__string_(signalType)
613
+ return String(__unwrapped)
614
+ } else {
615
+ return nil
616
+ }
617
+ }(), additionalParameters: { () -> Dictionary<String, String>? in
618
+ if bridge.has_value_std__optional_std__unordered_map_std__string__std__string__(additionalParameters) {
619
+ let __unwrapped = bridge.get_std__optional_std__unordered_map_std__string__std__string__(additionalParameters)
620
+ return { () -> Dictionary<String, String> in
621
+ var __dictionary = Dictionary<String, String>(minimumCapacity: __unwrapped.size())
622
+ let __keys = bridge.get_std__unordered_map_std__string__std__string__keys(__unwrapped)
623
+ for __key in __keys {
624
+ let __value = bridge.get_std__unordered_map_std__string__std__string__value(__unwrapped, __key)
625
+ __dictionary[String(__key)] = String(__value)
626
+ }
627
+ return __dictionary
628
+ }()
629
+ } else {
630
+ return nil
631
+ }
632
+ }())
633
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_bool__ in
634
+ let __promise = bridge.create_std__shared_ptr_Promise_bool__()
635
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_bool__(__promise)
636
+ __result
637
+ .then({ __result in __promiseHolder.resolve(__result) })
638
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
639
+ return __promise
640
+ }()
641
+ return bridge.create_Result_std__shared_ptr_Promise_bool___(__resultCpp)
642
+ } catch (let __error) {
643
+ let __exceptionPtr = __error.toCpp()
644
+ return bridge.create_Result_std__shared_ptr_Promise_bool___(__exceptionPtr)
645
+ }
646
+ }
647
+
607
648
  @inline(__always)
608
649
  public final func pushDidRegisterWithToken(deviceToken: ArrayBuffer) -> bridge.Result_std__shared_ptr_Promise_bool___ {
609
650
  do {
@@ -38,6 +38,7 @@ namespace margelo::nitro::acousticconnectrn {
38
38
  prototype.registerHybridMethod("logDialogDismissEvent", &HybridAcousticConnectRNSpec::logDialogDismissEvent);
39
39
  prototype.registerHybridMethod("logDialogButtonClickEvent", &HybridAcousticConnectRNSpec::logDialogButtonClickEvent);
40
40
  prototype.registerHybridMethod("logDialogCustomEvent", &HybridAcousticConnectRNSpec::logDialogCustomEvent);
41
+ prototype.registerHybridMethod("logIdentity", &HybridAcousticConnectRNSpec::logIdentity);
41
42
  prototype.registerHybridMethod("pushDidRegisterWithToken", &HybridAcousticConnectRNSpec::pushDidRegisterWithToken);
42
43
  prototype.registerHybridMethod("pushDidFailToRegister", &HybridAcousticConnectRNSpec::pushDidFailToRegister);
43
44
  prototype.registerHybridMethod("pushDidReceiveNotification", &HybridAcousticConnectRNSpec::pushDidReceiveNotification);
@@ -83,6 +83,7 @@ namespace margelo::nitro::acousticconnectrn {
83
83
  virtual bool logDialogDismissEvent(const std::string& dialogId, const std::string& dismissReason) = 0;
84
84
  virtual bool logDialogButtonClickEvent(const std::string& dialogId, const std::string& buttonText, double buttonIndex) = 0;
85
85
  virtual bool logDialogCustomEvent(const std::string& dialogId, const std::string& eventName, const std::unordered_map<std::string, std::variant<bool, std::string, double>>& values) = 0;
86
+ virtual std::shared_ptr<Promise<bool>> logIdentity(const std::string& identifierName, const std::string& identifierValue, const std::optional<std::string>& signalType, const std::optional<std::unordered_map<std::string, std::string>>& additionalParameters) = 0;
86
87
  virtual std::shared_ptr<Promise<bool>> pushDidRegisterWithToken(const std::shared_ptr<ArrayBuffer>& deviceToken) = 0;
87
88
  virtual std::shared_ptr<Promise<bool>> pushDidFailToRegister(const PushErrorInfo& error) = 0;
88
89
  virtual std::shared_ptr<Promise<bool>> pushDidReceiveNotification(const std::unordered_map<std::string, std::variant<bool, std::string, double>>& userInfo) = 0;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "author": "Acoustic, L.P., Omar Hernandez, Chang Jie Yang",
2
+ "author": "Acoustic, L.P., Radoslaw Serek, Aksana Naskalava",
3
3
  "dependencies": {
4
4
  "@prettier/plugin-xml": "^2.2.0",
5
5
  "fast-xml-parser": "^4.0.8",
@@ -14,12 +14,12 @@
14
14
  "@types/jest": "^29.5.12",
15
15
  "@types/react": "^19.0.10",
16
16
  "jetifier": "^1.6.3",
17
- "nitrogen": "0.35.4",
17
+ "nitrogen": "0.35.9",
18
18
  "prettier-plugin-kotlin": "^2.1.0",
19
19
  "react": "19.1.1",
20
20
  "react-native": "0.82.1",
21
21
  "react-native-builder-bob": "^0.37.0",
22
- "react-native-nitro-modules": "0.35.4",
22
+ "react-native-nitro-modules": "0.35.9",
23
23
  "release-it": "^19.0.2",
24
24
  "typescript": "5.0.4"
25
25
  },
@@ -99,7 +99,7 @@
99
99
  "peerDependencies": {
100
100
  "react": ">=19.1.1 <20.0.0",
101
101
  "react-native": ">=0.82.0 <0.86.0",
102
- "react-native-nitro-modules": ">=0.35.0 <0.37.0"
102
+ "react-native-nitro-modules": "0.35.9"
103
103
  },
104
104
  "prettier": {
105
105
  "quoteProps": "consistent",
@@ -195,7 +195,7 @@
195
195
  "source": "src/index",
196
196
  "summary": "react-native ios android tealeaf connect cxa wxca er enhanced-replay",
197
197
  "types": "./lib/typescript/src/index.d.ts",
198
- "version": "18.0.27",
198
+ "version": "18.0.29",
199
199
  "workspaces": [
200
200
  "example",
201
201
  "Examples/bare-workflow"
package/src/TLTRN.ts CHANGED
@@ -16,13 +16,29 @@ import DialogListener from "./utils/DialogListener";
16
16
  import type { DialogEvent, DialogButtonClickEvent, DialogDismissEvent } from "./utils/DialogListener";
17
17
  import AcousticConnectRN from './index';
18
18
 
19
+ // Preserve any previously-installed handler (e.g. React Native's red-box
20
+ // handler) so we augment rather than replace it.
19
21
  // @ts-ignore
20
- global.ErrorUtils.setGlobalHandler((e: any, _isFatal: boolean) => {
21
- AcousticConnectRN.logExceptionEvent(
22
- JSON.stringify(e),
23
- JSON.stringify(e),
24
- true
25
- );
22
+ const previousGlobalErrorHandler = global.ErrorUtils?.getGlobalHandler?.();
23
+
24
+ // @ts-ignore
25
+ global.ErrorUtils?.setGlobalHandler?.((e: any, isFatal: boolean) => {
26
+ // A global error handler must never throw — otherwise it masks the ORIGINAL
27
+ // error. `AcousticConnectRN` can be undefined here (e.g. the native module
28
+ // failed to load, or during the module-load circular import), so guard the
29
+ // call and always forward to the previous handler so the real error still
30
+ // surfaces and fatals still crash.
31
+ try {
32
+ AcousticConnectRN?.logExceptionEvent?.(
33
+ JSON.stringify(e),
34
+ JSON.stringify(e),
35
+ true
36
+ );
37
+ } catch (loggingError: Error | any) {
38
+ console.warn('TLTRN: failed to log uncaught exception:', loggingError?.message);
39
+ } finally {
40
+ previousGlobalErrorHandler?.(e, isFatal);
41
+ }
26
42
  });
27
43
 
28
44
  class TLTRN {
@@ -294,11 +310,15 @@ class TLTRN {
294
310
  }
295
311
 
296
312
  if (message.module === "ExceptionsManager") {
297
- AcousticConnectRN.logExceptionEvent(
298
- message.args[0],
299
- JSON.stringify(message.args[1]),
300
- true
301
- );
313
+ try {
314
+ AcousticConnectRN?.logExceptionEvent?.(
315
+ message.args[0],
316
+ JSON.stringify(message.args[1]),
317
+ true
318
+ );
319
+ } catch (error: Error | any) {
320
+ console.log('logExceptionEvent (bridge) error: ', error?.message);
321
+ }
302
322
  }
303
323
  };
304
324
 
@@ -37,7 +37,7 @@ const Connect: React.FC<ConnectProps> = ({
37
37
  navigationRef,
38
38
  }) => {
39
39
  const child = children as any;
40
- // CA-138631: React 19 moved the ref off `element.ref` onto `element.props.ref`.
40
+ // React 19 moved the ref off `element.ref` onto `element.props.ref`.
41
41
  // Read `props.ref` first; the legacy `child.ref` fallback is a defensive
42
42
  // guard from the React 18 era — kept to avoid a behavioural change.
43
43
  const childProvidedRef = child?.props?.ref ?? child?.ref;
package/src/index.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
8
8
  * prohibited.
9
9
  *
10
- * Created by Omar Hernandez on 5/9/25.
10
+ * Created on 5/9/25.
11
11
  *
12
12
  ********************************************************************************************/
13
13
 
@@ -21,7 +21,24 @@ import { withAcousticAutoDialog } from './utils/withAcousticAutoDialog'
21
21
  import DialogDebugger from './utils/DialogDebugger'
22
22
  import TLTRN from './TLTRN'
23
23
 
24
- const AcousticConnectRN = NitroModules.createHybridObject<AcousticConnectRNSpec>('AcousticConnectRN')
24
+ // Instantiating the native HybridObject is the first thing that fails when the
25
+ // app's `react-native-nitro-modules` runtime does not match the version this SDK
26
+ // was generated against (the generated registration is tightly coupled to the
27
+ // Nitro version — see peerDependencies). Without this guard the failure surfaces
28
+ // as an opaque `ClassNotFoundException` and an `undefined` module far from the
29
+ // cause. Re-throw with an actionable message instead.
30
+ let AcousticConnectRN: AcousticConnectRNSpec
31
+ try {
32
+ AcousticConnectRN = NitroModules.createHybridObject<AcousticConnectRNSpec>('AcousticConnectRN')
33
+ } catch (error) {
34
+ throw new Error(
35
+ '[AcousticConnectRN] Failed to load the native HybridObject. This almost ' +
36
+ 'always means a `react-native-nitro-modules` version mismatch: this SDK is ' +
37
+ 'built against the exact version declared in its peerDependencies, so your ' +
38
+ 'app must resolve that same version (check `npm ls react-native-nitro-modules`). ' +
39
+ `Original error: ${String(error)}`
40
+ )
41
+ }
25
42
 
26
43
  export { Connect, TLTRN, KeyboardListener, DialogListener, useDialogTracking, DialogDebugger, withAcousticAutoDialog }
27
44
  export default AcousticConnectRN
@@ -7,7 +7,7 @@
7
7
  // prohibited.
8
8
  //
9
9
  //
10
- // Created by Omar Hernandez on 5/9/25.
10
+ // Created on 5/9/25.
11
11
  //
12
12
 
13
13
  import { type HybridObject } from 'react-native-nitro-modules'
@@ -140,6 +140,52 @@ export interface AcousticConnectRN extends HybridObject<{ ios: 'swift', android:
140
140
  logDialogButtonClickEvent(dialogId: string, buttonText: string, buttonIndex: number): boolean
141
141
  logDialogCustomEvent(dialogId: string, eventName: string, values: Record<string, string | number | boolean>): boolean
142
142
 
143
+ /**
144
+ * Logs a user identity so the current device/session can be associated with
145
+ * a known Connect contact — the foundation for audience building and
146
+ * cross-channel engagement. Wraps the native identity loggers
147
+ * (`ConnectSDK.shared.identity.log` on iOS, `Connect.logIdentificationEvent`
148
+ * on Android).
149
+ *
150
+ * Unlike the synchronous analytics loggers above, this returns a `Promise`:
151
+ * `ConnectSDK.shared` (iOS) is `@MainActor`-isolated, so the bridge hops to the
152
+ * main actor and resolves with the *real* success/failure value rather than
153
+ * firing and forgetting.
154
+ *
155
+ * The native APIs return `false` — and emit no signal — when either
156
+ * `identifierName` or `identifierValue` is empty/blank after trimming.
157
+ *
158
+ * @param identifierName Identifier name, e.g. `'Email'`.
159
+ * @param identifierValue Identifier value, e.g. `'user@example.com'`.
160
+ * @param signalType Optional signal type; the bridge supplies
161
+ * `'loggedIn'` when omitted (identity logging typically marks a sign-in),
162
+ * overriding the native SDKs' own `'pageView'` default.
163
+ * @param additionalParameters Optional extra key/value pairs merged into the
164
+ * signal payload. Only when omitted (`undefined`) does the bridge supply
165
+ * the default `{ registrationMethod: 'email' }`; an explicitly-provided
166
+ * map is used as-is, so passing an empty `{}` sends no extra parameters
167
+ * (the default is not merged in). A `'url'` entry is honoured uniformly on
168
+ * both platforms: on Android it is routed to the SDK's explicit `url`
169
+ * parameter, on iOS it rides inside the parameter map (where the native
170
+ * API expects it).
171
+ * @returns A promise resolving to `true` if the identity signal was
172
+ * dispatched, `false` otherwise (including the blank-identifier case).
173
+ * Never rejects.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * import AcousticConnectRN from 'react-native-acoustic-connect-beta'
178
+ *
179
+ * await AcousticConnectRN.logIdentity('Email', 'user@example.com')
180
+ * ```
181
+ */
182
+ logIdentity(
183
+ identifierName: string,
184
+ identifierValue: string,
185
+ signalType?: string,
186
+ additionalParameters?: Record<string, string>
187
+ ): Promise<boolean>
188
+
143
189
  // ── Push: APNs lifecycle (iOS) ──────────────────────────────────────────
144
190
  //
145
191
  // Push mode (automatic / manual / off) is configured in `ConnectConfig.json`
@@ -7,7 +7,7 @@
7
7
  * Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
8
8
  * prohibited.
9
9
  *
10
- * Created by Omar Hernandez on 5/9/25.
10
+ * Created on 5/9/25.
11
11
  *
12
12
  ********************************************************************************************/
13
13