react-native-acoustic-connect-beta 18.0.26 → 18.0.28

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 (61) hide show
  1. package/AcousticConnectRN.podspec +7 -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 +221 -13
  8. package/ios/Bridge.h +1 -1
  9. package/ios/HybridAcousticConnectRN.swift +179 -2
  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 +109 -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/AcousticConnectRN+autolinking.cmake +1 -0
  29. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.cpp +137 -1
  30. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.hpp +7 -0
  31. package/nitrogen/generated/android/c++/JPushErrorInfo.hpp +66 -0
  32. package/nitrogen/generated/android/c++/JPushPermissionResult.hpp +66 -0
  33. package/nitrogen/generated/android/c++/JVariant_NullType_Boolean.cpp +26 -0
  34. package/nitrogen/generated/android/c++/JVariant_NullType_Boolean.hpp +69 -0
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/HybridAcousticConnectRNSpec.kt +30 -0
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/PushErrorInfo.kt +61 -0
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/PushPermissionResult.kt +56 -0
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/Variant_NullType_Boolean.kt +62 -0
  39. package/nitrogen/generated/ios/AcousticConnectRN-Swift-Cxx-Bridge.cpp +32 -0
  40. package/nitrogen/generated/ios/AcousticConnectRN-Swift-Cxx-Bridge.hpp +249 -0
  41. package/nitrogen/generated/ios/AcousticConnectRN-Swift-Cxx-Umbrella.hpp +8 -0
  42. package/nitrogen/generated/ios/c++/HybridAcousticConnectRNSpecSwift.hpp +67 -1
  43. package/nitrogen/generated/ios/swift/Func_void_PushPermissionResult.swift +46 -0
  44. package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
  45. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  46. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__bool_.swift +58 -0
  47. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec.swift +7 -0
  48. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec_cxx.swift +205 -0
  49. package/nitrogen/generated/ios/swift/PushErrorInfo.swift +65 -0
  50. package/nitrogen/generated/ios/swift/PushPermissionResult.swift +66 -0
  51. package/nitrogen/generated/ios/swift/Variant_NullType_Bool.swift +30 -0
  52. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.cpp +7 -0
  53. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.hpp +15 -1
  54. package/nitrogen/generated/shared/c++/PushErrorInfo.hpp +92 -0
  55. package/nitrogen/generated/shared/c++/PushPermissionResult.hpp +90 -0
  56. package/package.json +5 -5
  57. package/src/TLTRN.ts +31 -11
  58. package/src/components/Connect.tsx +1 -1
  59. package/src/index.ts +19 -2
  60. package/src/specs/react-native-acoustic-connect.nitro.ts +129 -1
  61. package/src/utils/withAcousticAutoDialog.tsx +1 -1
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'
@@ -20,6 +20,38 @@ export type KeyValueObject = {
20
20
 
21
21
  export type ConnectMonitoringLevelType = 'Ignore' | 'CellularAndWiFi' | 'WiFi'
22
22
 
23
+ /**
24
+ * Structured error describing an APNs / permission failure.
25
+ *
26
+ * Mirrors the `firebase-messaging` / `notifee` ecosystem convention so callers
27
+ * can forward a native error object without string-encoding it. The native
28
+ * bridge reconstructs an `NSError` (iOS) from these fields.
29
+ */
30
+ export interface PushErrorInfo {
31
+ /** Platform error code, when available (maps to `NSError.code`). */
32
+ code?: number
33
+ /** Platform error domain, when available (maps to `NSError.domain`). */
34
+ domain?: string
35
+ /** Human-readable failure description (maps to `NSLocalizedDescriptionKey`). */
36
+ message: string
37
+ }
38
+
39
+ /**
40
+ * Result of a permission request.
41
+ *
42
+ * The Promise from {@link AcousticConnectRN.pushRequestPermission} always
43
+ * resolves with this shape and never rejects. `error` is `null` on success or
44
+ * a denial with no system error; a non-null string carries the system error's
45
+ * localized description, or `'permission-prompt-abandoned'` if the host was
46
+ * destroyed mid-prompt.
47
+ */
48
+ export interface PushPermissionResult {
49
+ /** `true` if the user granted permission, `false` otherwise. */
50
+ granted: boolean
51
+ /** `null` on success/clean denial; otherwise a description of the error. */
52
+ error?: string | null
53
+ }
54
+
23
55
  export interface AcousticConnectRN extends HybridObject<{ ios: 'swift', android: 'kotlin' }> {
24
56
  /**
25
57
  * Re-enables the Connect SDK after a prior {@link disable} call.
@@ -107,4 +139,100 @@ export interface AcousticConnectRN extends HybridObject<{ ios: 'swift', android:
107
139
  logDialogDismissEvent(dialogId: string, dismissReason: string): boolean
108
140
  logDialogButtonClickEvent(dialogId: string, buttonText: string, buttonIndex: number): boolean
109
141
  logDialogCustomEvent(dialogId: string, eventName: string, values: Record<string, string | number | boolean>): boolean
142
+
143
+ // ── Push: APNs lifecycle (iOS) ──────────────────────────────────────────
144
+ //
145
+ // Push mode (automatic / manual / off) is configured in `ConnectConfig.json`
146
+ // and enforced by the native SDK — there is no JS-side mode argument. In
147
+ // automatic mode the SDK's swizzled delegate handles everything and these
148
+ // forwarding calls are redundant-but-safe; in manual mode they are the only
149
+ // path for events to reach the SDK.
150
+
151
+ /**
152
+ * Forwards the raw APNs device token to the Connect SDK (manual mode).
153
+ *
154
+ * Nitro maps `ArrayBuffer` ↔ `Data` natively; the bridge forwards the bytes
155
+ * unchanged with no hex conversion and no validation.
156
+ *
157
+ * @param deviceToken Raw APNs device-token bytes from
158
+ * `didRegisterForRemoteNotificationsWithDeviceToken`.
159
+ * @returns A promise resolving to `true` once the SDK accepted the token,
160
+ * or `false` if the SDK rejected the call (e.g. push not enabled). Never
161
+ * rejects.
162
+ */
163
+ pushDidRegisterWithToken(deviceToken: ArrayBuffer): Promise<boolean>
164
+
165
+ /**
166
+ * Forwards an APNs registration failure to the Connect SDK (manual mode).
167
+ *
168
+ * @param error Structured error; the bridge builds an `NSError` from it.
169
+ * @returns A promise resolving to `true` once forwarded, `false` on failure.
170
+ * Never rejects.
171
+ */
172
+ pushDidFailToRegister(error: PushErrorInfo): Promise<boolean>
173
+
174
+ /**
175
+ * Forwards a received notification to the Connect SDK so it can log a
176
+ * `pushReceived` signal (manual mode).
177
+ *
178
+ * The bridge branches on the push mode resolved from `ConnectConfig.json`:
179
+ * manual mode forwards to the SDK and returns `true`; automatic/off mode
180
+ * returns `false` (bridge error `EAC-RN-007`) without forwarding, because
181
+ * the SDK's own delegate already handles delivery in automatic mode and
182
+ * forwarding would double-log.
183
+ *
184
+ * @param userInfo The notification `userInfo` payload.
185
+ * @returns A promise resolving to `true` if processed (manual mode), or
186
+ * `false` in automatic/off mode (`EAC-RN-007`). Never rejects.
187
+ */
188
+ pushDidReceiveNotification(userInfo: Record<string, string | number | boolean>): Promise<boolean>
189
+
190
+ /**
191
+ * Forwards a notification response (tap / action) to the Connect SDK so it
192
+ * can run the built-in action and log a `pushAction` signal (manual mode).
193
+ *
194
+ * Same `EAC-RN-007` (`false`) behaviour in automatic mode as
195
+ * {@link pushDidReceiveNotification}.
196
+ *
197
+ * @param actionIdentifier The response action identifier.
198
+ * @param userInfo The notification `userInfo` payload.
199
+ * @returns A promise resolving to `true` if processed (manual mode), or
200
+ * `false` in automatic/off mode (`EAC-RN-007`). Never rejects.
201
+ */
202
+ pushDidReceiveResponse(actionIdentifier: string, userInfo: Record<string, string | number | boolean>): Promise<boolean>
203
+
204
+ // ── Push: permission management (cross-platform) ────────────────────────
205
+
206
+ /**
207
+ * Forwards externally-obtained permission state to the SDK.
208
+ *
209
+ * Tri-state `granted`: `true` granted, `false` denied, `null` not yet
210
+ * determined. For `null` the bridge records the state but does not call the
211
+ * SDK (it has no notion of forwarding "unknown").
212
+ *
213
+ * @param granted Tri-state permission value.
214
+ * @param error Optional structured error accompanying a denial.
215
+ * @returns A promise resolving to `true` once handled — including the
216
+ * `null`/not-determined case, which is intentionally accepted without
217
+ * forwarding to the SDK. `false` only if the SDK rejected a forwarded
218
+ * state. Never rejects.
219
+ */
220
+ pushDidReceiveAuthorization(granted: boolean | null, error?: PushErrorInfo): Promise<boolean>
221
+
222
+ /**
223
+ * Requests notification permission via the SDK, presenting the system prompt
224
+ * when undetermined.
225
+ *
226
+ * Always resolves, never rejects — see {@link PushPermissionResult}.
227
+ *
228
+ * @returns The permission result.
229
+ */
230
+ pushRequestPermission(): Promise<PushPermissionResult>
231
+
232
+ /**
233
+ * Reads the current notification permission state without prompting.
234
+ *
235
+ * @returns Tri-state: `true` granted, `false` denied, `null` not determined.
236
+ */
237
+ pushGetPermissionState(): Promise<boolean | null>
110
238
  }
@@ -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