react-native-acoustic-connect-beta 18.0.23 → 18.0.25

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 (30) hide show
  1. package/AcousticConnectRN.podspec +24 -4
  2. package/README.md +237 -67
  3. package/android/build.gradle +47 -2
  4. package/android/gradle.properties +3 -3
  5. package/android/src/main/assets/ConnectAdvancedConfig.json +1 -1
  6. package/android/src/main/assets/ConnectBasicConfig.properties +1 -1
  7. package/android/src/main/assets/TealeafAdvancedConfig.json +1 -1
  8. package/android/src/main/java/com/acousticconnectrn/AcousticConnectRNPackage.java +9 -32
  9. package/android/src/main/java/com/acousticconnectrn/HybridAcousticConnectRN.kt +202 -12
  10. package/ios/AcousticConnectRNConfig.json +1 -1
  11. package/ios/HybridAcousticConnectRN.swift +181 -73
  12. package/lib/commonjs/components/Connect.js +3 -0
  13. package/lib/commonjs/components/Connect.js.map +1 -1
  14. package/lib/module/components/Connect.js +3 -0
  15. package/lib/module/components/Connect.js.map +1 -1
  16. package/lib/typescript/src/components/Connect.d.ts.map +1 -1
  17. package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts +62 -0
  18. package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts.map +1 -1
  19. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.cpp +10 -0
  20. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.hpp +2 -0
  21. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/HybridAcousticConnectRNSpec.kt +8 -0
  22. package/nitrogen/generated/ios/c++/HybridAcousticConnectRNSpecSwift.hpp +16 -0
  23. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec.swift +2 -0
  24. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec_cxx.swift +24 -0
  25. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.cpp +2 -0
  26. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.hpp +2 -0
  27. package/package.json +11 -7
  28. package/scripts/ConnectConfig.json +1 -1
  29. package/src/components/Connect.tsx +3 -0
  30. package/src/specs/react-native-acoustic-connect.nitro.ts +63 -0
@@ -64,22 +64,201 @@ import com.tl.uic.util.keyboardview.KeyboardView
64
64
  import java.util.Objects
65
65
 
66
66
 
67
- class HybridAcousticConnectRN(private val reactContext: ReactApplicationContext) : HybridAcousticConnectRNSpec(),
67
+ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
68
68
  LifecycleEventListener {
69
69
 
70
+ // The Nitro C++ factory (`AcousticConnectRNOnLoad.cpp`) instantiates this
71
+ // class with `getConstructor<()>()` — i.e. it expects a zero-arg
72
+ // constructor. The React context can therefore not be passed in at
73
+ // construction time; we resolve it lazily via `NitroModules.applicationContext`
74
+ // (which is nullable until the React context attaches), guard every
75
+ // access, and retry the lifecycle-listener registration on each
76
+ // `enable()` call until it succeeds.
77
+
78
+ // Touched only on the main looper. All read/write goes through
79
+ // `runOnMain { ... }` (called from `init`, `enable()`, etc.), so the
80
+ // unsynchronised access pattern is safe — the field's mutating thread
81
+ // and reading thread are the same.
82
+ private var lifecycleListenerRegistered = false
83
+
70
84
  init {
71
- // Add your listener logic here
72
- Log.v(TAG, "HybridAcousticConnectRNSpec has been initialized")
85
+ Log.v(TAG, "[bridge] HybridAcousticConnectRN constructed")
86
+ runOnMain {
87
+ tryRegisterLifecycleListenerOnMain()
88
+ // Cold-start auto-init: mirrors the iOS bridge's behaviour, where
89
+ // `load()` runs inside the constructor's `Task { @MainActor in … }`
90
+ // and initialises the SDK without waiting for an explicit JS
91
+ // call. Without this, an Android cold start where the first
92
+ // activity `onResume` fires before the lifecycle listener was
93
+ // registered (slow JS bundle, RAM-bundle apps, dev hot reload)
94
+ // would leave the SDK uninitialised until the next resume.
95
+ maybeAutoInitOnMain()
96
+ }
97
+ }
73
98
 
74
- Handler(Looper.getMainLooper()).post {
75
- if (reactContext.hasActiveCatalystInstance()) {
76
- reactContext.addLifecycleEventListener(this)
77
- } else {
78
- Log.v(TAG, "ReactContext is not ready. LifecycleEventListener not registered.")
99
+ /**
100
+ * Posts to the main looper. Used by every operation that touches
101
+ * `lifecycleListenerRegistered`, registers a `LifecycleEventListener`,
102
+ * or calls into `Connect.init`/`Connect.enable`/`Connect.disable` — so
103
+ * all of those operations execute single-threaded on main, eliminating
104
+ * read-then-write races on the registration flag.
105
+ */
106
+ private fun runOnMain(block: () -> Unit) {
107
+ Handler(Looper.getMainLooper()).post(block)
108
+ }
109
+
110
+ /**
111
+ * Idempotent: registers this hybrid as a React lifecycle listener the
112
+ * first time `NitroModules.applicationContext` is non-null, then no-ops.
113
+ *
114
+ * MUST be called on the main looper. Callers funnel through
115
+ * [runOnMain]; the read-then-write of `lifecycleListenerRegistered` is
116
+ * therefore single-threaded by construction.
117
+ */
118
+ private fun tryRegisterLifecycleListenerOnMain() {
119
+ if (lifecycleListenerRegistered) return
120
+ val ctx = applicationContext
121
+ if (ctx == null) {
122
+ Log.v(TAG, "[bridge] React context not ready; lifecycle listener registration deferred")
123
+ return
124
+ }
125
+ ctx.addLifecycleEventListener(this)
126
+ lifecycleListenerRegistered = true
127
+ Log.v(TAG, "[bridge] Lifecycle listener registered")
128
+ }
129
+
130
+ /**
131
+ * Cold-start auto-init helper. Calls `Connect.init` + `Connect.enable`
132
+ * if the SDK isn't already running and the React context is attached.
133
+ * MUST be called on the main looper.
134
+ *
135
+ * Idempotent at every level:
136
+ * - If the SDK is already enabled, returns immediately.
137
+ * - If the context isn't ready, returns without acting (the subsequent
138
+ * `onHostResume` lifecycle callback or an explicit `enable()` from JS
139
+ * will retry).
140
+ * - `Connect.init` and `Connect.enable` are themselves idempotent in
141
+ * the native SDK, so this co-existing with a later JS-driven
142
+ * `enable()` is safe.
143
+ */
144
+ private fun maybeAutoInitOnMain() {
145
+ if (Connect.isEnabled()) return
146
+ val app = resolveApplication() ?: return
147
+ if (Connect.getApplication() == null) {
148
+ Connect.init(app)
149
+ }
150
+ Connect.enable()
151
+ Log.i(TAG, "[bridge] SDK auto-initialised at bridge construction")
152
+ }
153
+
154
+ /**
155
+ * Resolves the host app's `Application` from
156
+ * `NitroModules.applicationContext`. Returns `null` (with a logged
157
+ * warning) when the React context isn't attached yet — callers must
158
+ * bail rather than NPE. Replaces the previous direct deref through a
159
+ * constructor-injected `ReactApplicationContext` field, which was unsafe
160
+ * because Nitro's factory passes a null JNI handle through Kotlin's
161
+ * non-null platform type.
162
+ */
163
+ private fun resolveApplication(): Application? {
164
+ val app = applicationContext?.applicationContext as? Application
165
+ if (app == null) {
166
+ Log.w(TAG, "[bridge] Application not yet available (NitroModules.applicationContext is null or its applicationContext is not an Application)")
167
+ }
168
+ return app
169
+ }
170
+
171
+ // region Gate-keeper API (CA-137696)
172
+
173
+ /**
174
+ * Re-enables the Connect SDK after a prior `disable()`. All configuration
175
+ * comes from `ConnectConfig.json` at the consumer's project root, which
176
+ * `config.gradle` bakes into `ConnectBasicConfig.properties` /
177
+ * `TealeafBasicConfig.properties` at build time.
178
+ *
179
+ * Idempotency is owned by the native SDK. `Connect.init` is safe to call
180
+ * multiple times, and `Connect.enable` short-circuits once the SDK is
181
+ * running. The bridge does not track its own enable signature — subsequent
182
+ * JS calls just post another runnable that the native side will treat as
183
+ * a no-op.
184
+ *
185
+ * Push wiring on Android is gated at build time by `Connect.PushEnabled`
186
+ * in `ConnectConfig.json`, which `android/build.gradle` consults to
187
+ * include the `connect-push-fcm` artifact. Token forwarding to Connect
188
+ * lives in CA-137698 and runs through the host app's
189
+ * `FirebaseMessagingService`.
190
+ *
191
+ * @return true on accepted dispatch, false if no application context.
192
+ */
193
+ override fun enable(): Boolean {
194
+ Log.i(TAG, "[bridge] enable() called from JS")
195
+ logResolvedPushAvailability()
196
+
197
+ // All work happens on the main looper so the lifecycle-listener
198
+ // registration flag is touched single-threaded and we don't race
199
+ // with the `init { runOnMain { … } }` registration path. Returning
200
+ // `true` reflects "accepted dispatch", not "succeeded"; the actual
201
+ // work logs its own success or failure on main.
202
+ runOnMain {
203
+ tryRegisterLifecycleListenerOnMain()
204
+ val application = resolveApplication() ?: run {
205
+ Log.w(TAG, "[bridge] enable() bailed — Application still null on main thread")
206
+ return@runOnMain
79
207
  }
208
+ Connect.init(application)
209
+ Connect.enable()
210
+ Log.i(TAG, "[bridge] SDK initialised")
80
211
  }
212
+ return true
81
213
  }
82
214
 
215
+ /**
216
+ * Disables the Connect SDK. Idempotent — the underlying `Connect.disable()`
217
+ * is safe to call repeatedly on the native side; this override always
218
+ * returns `true` for an accepted dispatch.
219
+ */
220
+ override fun disable(): Boolean {
221
+ Log.i(TAG, "[bridge] disable() called from JS")
222
+ runOnMain {
223
+ Connect.disable()
224
+ Log.i(TAG, "[bridge] SDK disabled")
225
+ }
226
+ return true
227
+ }
228
+
229
+ /**
230
+ * Checks whether the `connect-push-fcm` artifact is on the classpath and
231
+ * logs the result. The artifact is gated by `Connect.PushEnabled` in
232
+ * `ConnectConfig.json` via `android/build.gradle`'s conditional
233
+ * `implementation` clause. A missing artifact when `PushEnabled` was set
234
+ * to true points at a build-pipeline issue (didn't run `config.gradle`
235
+ * or the conditional didn't fire). Once CA-137698 lands the actual
236
+ * Connect push API on Android, this method also gates the wire-up.
237
+ */
238
+ private fun logResolvedPushAvailability() {
239
+ val pushAvailable = isConnectPushFcmAvailable()
240
+ Log.i(TAG, "[config] connect-push-fcm on classpath: $pushAvailable")
241
+ if (!pushAvailable) {
242
+ Log.i(TAG, "[config] Push is not active on Android in this build. To enable, set Connect.PushEnabled=true in ConnectConfig.json and re-sync Gradle to include connect-push-fcm. Token forwarding wires in CA-137698.")
243
+ }
244
+ }
245
+
246
+ private fun isConnectPushFcmAvailable(): Boolean {
247
+ // Probe a known class shipped by the connect-push-fcm artifact. The
248
+ // exact class lives in the Connect Android SDK's push module and is
249
+ // finalised under CA-137698; this Class.forName probe is robust to
250
+ // package-name changes because it falls through silently when the
251
+ // class is missing (which is the default in a no-push build).
252
+ return try {
253
+ Class.forName(CONNECT_PUSH_FCM_PROBE_CLASS)
254
+ true
255
+ } catch (e: ClassNotFoundException) {
256
+ false
257
+ }
258
+ }
259
+
260
+ // endregion
261
+
83
262
  /**
84
263
  * Sets the module's boolean configuration item from AdvancedConfig.json or BasicConfig.properties that matches the specified key.
85
264
  *
@@ -813,7 +992,7 @@ class HybridAcousticConnectRN(private val reactContext: ReactApplicationContext)
813
992
  // }
814
993
 
815
994
  fun onWindowFocusChanged(hasFocus: Boolean) {
816
- if (!reactContext.hasActiveCatalystInstance()) {
995
+ if (applicationContext == null) {
817
996
  // logEvent("WindowFocus", "Context is not ready. Skipping onWindowFocusChanged.")
818
997
  return
819
998
  }
@@ -831,7 +1010,7 @@ class HybridAcousticConnectRN(private val reactContext: ReactApplicationContext)
831
1010
  */
832
1011
  override fun onHostResume() {
833
1012
  // Initialize Connect library, and hook into activity lifecycle events to help detect if app is in background
834
- if (!reactContext.hasActiveCatalystInstance()) {
1013
+ if (applicationContext == null) {
835
1014
  // logEvent("Lifecycle", "onHostResume skipped: ReactContext is not ready")
836
1015
  return
837
1016
  }
@@ -844,9 +1023,13 @@ class HybridAcousticConnectRN(private val reactContext: ReactApplicationContext)
844
1023
 
845
1024
  if (!isEnabled()) {
846
1025
  if (getApplication() == null) {
847
- init((reactContext.applicationContext as Application))
1026
+ val app = resolveApplication() ?: return
1027
+ init(app)
848
1028
  }
849
- enable()
1029
+ // Qualified to bypass the `enable()` override on this class —
1030
+ // call the native SDK's `Connect.enable()` directly so the
1031
+ // log line "called from JS" doesn't fire on lifecycle wake-ups.
1032
+ Connect.enable()
850
1033
  }
851
1034
  onResume(activity, null)
852
1035
  }
@@ -882,5 +1065,12 @@ class HybridAcousticConnectRN(private val reactContext: ReactApplicationContext)
882
1065
  companion object {
883
1066
  const val TAG = "AcousticConnectRN"
884
1067
  const val DIALOG_CAPTURE_DELAY_MS = 500L // Configurable delay for dialog screenshot capture
1068
+
1069
+ // Class probed at runtime to detect whether the connect-push-fcm
1070
+ // artifact was included in the build. Conservative placeholder — the
1071
+ // actual class name is finalised under CA-137698; if that ticket lands
1072
+ // a different fully-qualified name, update this constant.
1073
+ private const val CONNECT_PUSH_FCM_PROBE_CLASS =
1074
+ "com.acoustic.connect.android.push.fcm.ConnectPushFcm"
885
1075
  }
886
1076
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "Connect": {
3
- "AndroidVersion": "11.0.9-beta",
3
+ "AndroidVersion": "11.0.12-beta",
4
4
  "AppKey": "b6c3709b7a4c479bb4b5a9fb8fec324c",
5
5
  "KillSwitchUrl": "https://lib-us-2.brilliantcollector.com/collector/switch/b6c3709b7a4c479bb4b5a9fb8fec324c",
6
6
  "PostMessageUrl": "https://lib-us-2.brilliantcollector.com/collector/collectorPost",
@@ -13,6 +13,27 @@
13
13
  import Foundation
14
14
  import Connect
15
15
  import NitroModules
16
+ import OSLog
17
+
18
+ // Two loggers under one subsystem so developers can filter Console.app / Xcode
19
+ // output by category. `config` covers anything about reading and validating
20
+ // `AcousticConnectRNConfig.bundle`; `bridge` covers SDK lifecycle calls
21
+ // (`enable`, `disable`, the resolved-config summary line).
22
+ private let configLog = Logger(subsystem: "com.acoustic.AcousticConnectRN", category: "config")
23
+ private let bridgeLog = Logger(subsystem: "com.acoustic.AcousticConnectRN", category: "bridge")
24
+
25
+ // Small descriptor on `ConnectPushConfig` so the bridge can log "off" /
26
+ // "automatic" / "manual" without round-tripping through the JS-side enum.
27
+ private extension ConnectPushConfig {
28
+ var modeDescription: String {
29
+ switch self.mode {
30
+ case .off: return "off"
31
+ case .automatic: return "automatic"
32
+ case .manual: return "manual"
33
+ @unknown default: return "unknown"
34
+ }
35
+ }
36
+ }
16
37
 
17
38
  // Single compat entry point for the config-item store. Works against every
18
39
  // shipping iOS SDK variant (Release with separate EOCore/Tealeaf, current merged
@@ -42,86 +63,149 @@ private enum ConnectConfigStore {
42
63
  }
43
64
 
44
65
  class HybridAcousticConnectRN: HybridAcousticConnectRNSpec {
45
-
46
- // Constructor
66
+
67
+ // Constructor — auto-inits the SDK from `ConnectConfig.json`. Matches the
68
+ // pre-CA-137696 behaviour; consumers that need consent-gated init can call
69
+ // `disable()` immediately and `enable()` once they have permission.
47
70
  override init() {
48
- // Call the superclass initializer
49
71
  super.init()
50
-
51
- // init library from ui thread
52
- // This is important to ensure that the library is initialized on the main thread
53
- // as it may involve UI components or other main-thread specific tasks.
54
- DispatchQueue.main.async { [weak self] in
55
- self?.load()
56
- }
57
72
 
58
- // Perform additional setup if needed
59
- print("HybridAcousticConnectRN initialized")
73
+ Task { @MainActor [weak self] in
74
+ self?.load()
75
+ }
76
+
77
+ bridgeLog.info("HybridAcousticConnectRN constructed; load() dispatched on main actor.")
60
78
  }
61
-
79
+
80
+ // `load()` calls into the MainActor-isolated `ConnectSDK.shared` API.
81
+ // Marking the method `@MainActor` means Swift can verify the SDK calls
82
+ // without an inner dispatch, and it makes the contract explicit for any
83
+ // future caller.
84
+ @MainActor
62
85
  func load() {
63
- DispatchQueue.main.async {
64
- let connectData = self.parseConnectConfigJSON()
65
- let appKey = (connectData?["AppKey"] as? String) ?? ""
66
- let postURL = (connectData?["PostMessageUrl"] as? String) ?? ""
67
-
68
- // Skip enable entirely if the consumer's config didn't reach us —
69
- // proceeding with empty strings would let the SDK silently fall back
70
- // to its bundled demo collector, which is exactly the bug this flow
71
- // is designed to prevent. Most likely cause: missing or malformed
72
- // ConnectConfig.json at the consumer's project root, or `pod install`
73
- // didn't run after the file was added.
74
- guard !appKey.isEmpty, !postURL.isEmpty else {
75
- print("[AcousticConnectRN] SDK NOT ENABLED — empty AppKey or PostMessageUrl. " +
76
- "Verify ConnectConfig.json at your project root contains both fields, " +
77
- "then re-run `pod install`.")
78
- return
79
- }
86
+ let connectData = self.parseConnectConfigJSON()
80
87
 
81
- let helper = ConnectApplicationHelper.sharedInstance()
82
- helper.isReactNative(true, wrapNavigationContainer: true)
83
-
84
- // Seed bundle defaults via the new internal selector when available.
85
- // Required on merged Debug 2.1.2+ SDKs where EOCoreSettings.bundle /
86
- // TLFResources.bundle aren't on the app target's resource path; without
87
- // it the SDK fails to enable. Runtime-dispatched so older SDKs that
88
- // don't expose this method skip cleanly.
89
- let applyDefaults = NSSelectorFromString("_connectApplyBundleDefaults")
90
- if helper.responds(to: applyDefaults) {
91
- helper.perform(applyDefaults)
92
- }
88
+ guard let connectData = connectData else {
89
+ configLog.error("AcousticConnectRNConfig.bundle missing or unreadable. SDK not initialised. Verify ConnectConfig.json at your project root and re-run `pod install`.")
90
+ return
91
+ }
92
+ configLog.info("Read AcousticConnectRNConfig.bundle (\(connectData.count) top-level keys).")
93
93
 
94
- // Enable with explicit appKey/postURL via the new internal selector
95
- // when present. The zero-arg `enableFramework()` and the deprecated
96
- // 2-arg public form both empirically ignore explicit values on merged
97
- // SDKs (they re-read from Connect.framework's bundled demo defaults).
98
- // The new `_connectEnableWithAppKey:postURL:` honours the args same
99
- // path the SDK's own ConnectSDK.shared.enable(...) wrapper uses.
100
- // Falls back to the deprecated public 2-arg form on older SDKs.
101
- let connectEnableSel = NSSelectorFromString("_connectEnableWithAppKey:postURL:")
102
- if helper.responds(to: connectEnableSel) {
103
- typealias EnableFn = @convention(c) (AnyObject, Selector, NSString, NSString) -> Bool
104
- let imp = helper.method(for: connectEnableSel)
105
- let fn = unsafeBitCast(imp, to: EnableFn.self)
106
- _ = fn(helper, connectEnableSel, appKey as NSString, postURL as NSString)
107
- } else {
108
- // Older SDK build that doesn't expose the underscored category. The
109
- // deprecated 2-arg public form may not honor explicit values on every
110
- // SDK version — log so the consumer can tell which path fired if they
111
- // see unexpected routing on their dashboard.
112
- print("[AcousticConnectRN] Using deprecated enableFramework(_:withPostMessageUrl:)" +
113
- "the new internal selector is not exposed by this SDK build. " +
114
- "If sessions appear on the wrong dashboard, upgrade the AcousticConnect pod.")
115
- _ = helper.enableFramework(appKey, withPostMessageUrl: postURL)
116
- }
94
+ let appKey = (connectData["AppKey"] as? String) ?? ""
95
+ let postURL = (connectData["PostMessageUrl"] as? String) ?? ""
96
+
97
+ // Skip enable entirely if the consumer's config didn't reach us —
98
+ // proceeding with empty strings would let the SDK silently fall back
99
+ // to its bundled demo collector, which is exactly the bug this flow
100
+ // is designed to prevent. Most likely cause: missing or malformed
101
+ // ConnectConfig.json at the consumer's project root, or `pod install`
102
+ // didn't run after the file was added.
103
+ guard !appKey.isEmpty, !postURL.isEmpty else {
104
+ configLog.error("SDK NOT ENABLED — empty AppKey or PostMessageUrl. Verify ConnectConfig.json at your project root contains both fields, then re-run `pod install`.")
105
+ return
106
+ }
107
+
108
+ // Log every field the bridge consumes so the developer can see in
109
+ // Xcode / Console.app exactly what's in effect, without cross-checking
110
+ // ConnectConfig.json.
111
+ configLog.info("AppKey: \(appKey, privacy: .public) (length=\(appKey.count))")
112
+ configLog.info("PostMessageUrl: \(postURL, privacy: .public)")
113
+ if let killSwitch = connectData["KillSwitchUrl"] as? String, !killSwitch.isEmpty {
114
+ configLog.info("KillSwitchUrl: \(killSwitch, privacy: .public)")
115
+ }
116
+
117
+ let pushConfig = self.resolvePushConfig(from: connectData)
118
+
119
+ let sdk = ConnectSDK.shared
120
+ bridgeLog.info("Calling ConnectSDK.shared.enable(with: ConnectConfig(push: \(pushConfig.modeDescription, privacy: .public)))")
121
+ sdk.enable(with: ConnectConfig(appKey: appKey, postURL: postURL, push: pushConfig))
122
+ _ = sdk.setReactNative(true, wrapNavigationContainer: true)
123
+
124
+ // Apply remaining programmatic overrides (everything other than the
125
+ // two enable parameters) AFTER enable — matches the order in the SDK's
126
+ // own ConnectSDK.shared.enable(with:) implementation.
127
+ self.applyConnectConfig(connectData)
128
+
129
+ bridgeLog.info("SDK initialised: appKey length=\(appKey.count), push=\(pushConfig.modeDescription, privacy: .public), isReactNative=true, wrapNavigationContainer=true")
130
+ }
131
+
132
+ /// Resolves `PushEnabled` + `iOSPushMode` + `iOSAppGroupIdentifier` from the
133
+ /// bundled config into a `ConnectPushConfig`. Validation errors are logged
134
+ /// at `.error`; soft mismatches at `.warning`. The SDK always falls back to
135
+ /// a safe default (`.off`) so an invalid config never crashes the app.
136
+ @MainActor
137
+ private func resolvePushConfig(from connectData: [String: Any]) -> ConnectPushConfig {
138
+ let pushEnabled = self.parsePushEnabled(connectData["PushEnabled"])
139
+ let iOSPushModeRaw = connectData["iOSPushMode"] as? String
140
+ let groupId = connectData["iOSAppGroupIdentifier"] as? String
141
+
142
+ configLog.info("PushEnabled: \(pushEnabled)")
117
143
 
118
- // Apply remaining programmatic overrides (everything other than the
119
- // two enable parameters) AFTER enable matches the order in the SDK's
120
- // own ConnectSDK.shared.enable(with:) implementation.
121
- if let connectData = connectData {
122
- self.applyConnectConfig(connectData)
144
+ // Inconsistency: iOSPushMode is set but PushEnabled is false. The
145
+ // mode value would never take effect; warn the developer so they
146
+ // know to fix one or the other.
147
+ if !pushEnabled, let raw = iOSPushModeRaw, !raw.isEmpty {
148
+ configLog.error("iOSPushMode \"\(raw, privacy: .public)\" is set but PushEnabled is false. Ignoring iOSPushMode; SDK will run with push disabled.")
149
+ return .off
150
+ }
151
+
152
+ guard pushEnabled else {
153
+ configLog.info("iOSPushMode: (not used, PushEnabled is false)")
154
+ configLog.info("iOSAppGroupIdentifier: (not used, PushEnabled is false)")
155
+ return .off
156
+ }
157
+
158
+ let mode = self.parseIOSPushMode(iOSPushModeRaw)
159
+ configLog.info("iOSPushMode: \(mode.descriptor, privacy: .public)")
160
+ if let groupId = groupId, !groupId.isEmpty {
161
+ configLog.info("iOSAppGroupIdentifier: \(groupId, privacy: .public)")
162
+ } else {
163
+ configLog.warning("iOSAppGroupIdentifier is not set. Required if your app uses a Notification Service or Notification Content extension to render rich push payloads.")
164
+ }
165
+
166
+ switch mode {
167
+ case .automatic:
168
+ return ConnectPushConfig(mode: .automatic, appGroupIdentifier: groupId)
169
+ case .manual:
170
+ return ConnectPushConfig(mode: .manual, appGroupIdentifier: groupId)
171
+ }
172
+ }
173
+
174
+ /// Lenient `PushEnabled` parser — accepts a `Bool` directly, or a string
175
+ /// like `"true"`/`"false"`/`"yes"`/`"no"`. Anything else falls back to
176
+ /// `false` with a warning so a typo in the JSON doesn't silently enable
177
+ /// push when the developer thought they'd turned it off.
178
+ private func parsePushEnabled(_ raw: Any?) -> Bool {
179
+ if let b = raw as? Bool { return b }
180
+ if let n = raw as? NSNumber { return n.boolValue }
181
+ if let s = raw as? String {
182
+ switch s.lowercased() {
183
+ case "true", "yes", "1": return true
184
+ case "false", "no", "0", "": return false
185
+ default:
186
+ configLog.warning("PushEnabled string \"\(s, privacy: .public)\" not recognised. Falling back to false.")
187
+ return false
123
188
  }
124
189
  }
190
+ if raw != nil {
191
+ configLog.warning("PushEnabled is set but is neither a Bool nor a recognised string. Falling back to false.")
192
+ }
193
+ return false
194
+ }
195
+
196
+ private enum IOSPushMode { case automatic, manual
197
+ var descriptor: String { self == .automatic ? "automatic" : "manual" } }
198
+
199
+ private func parseIOSPushMode(_ raw: String?) -> IOSPushMode {
200
+ switch raw?.lowercased() {
201
+ case "automatic", "auto", nil, "":
202
+ return .automatic
203
+ case "manual":
204
+ return .manual
205
+ default:
206
+ configLog.error("iOSPushMode \"\(raw ?? "", privacy: .public)\" not recognised. Allowed values: \"automatic\", \"manual\". Falling back to \"automatic\".")
207
+ return .automatic
208
+ }
125
209
  }
126
210
 
127
211
  /// Reads and returns the `Connect` dictionary from the bundled
@@ -196,7 +280,30 @@ class HybridAcousticConnectRN: HybridAcousticConnectRNSpec {
196
280
  }
197
281
  }
198
282
  }
199
-
283
+
284
+ // MARK: - Gate-keeper API
285
+
286
+ /// Re-enables the Connect SDK after a prior `disable()`. All configuration
287
+ /// comes from `ConnectConfig.json` — re-runs `load()` on the main actor,
288
+ /// which the native SDK no-ops if it's already enabled.
289
+ func enable() throws -> Bool {
290
+ bridgeLog.info("enable() called from JS.")
291
+ Task { @MainActor [weak self] in self?.load() }
292
+ return true
293
+ }
294
+
295
+ /// Disables the Connect SDK. Idempotent — the native SDK handles repeat
296
+ /// calls safely. After this call, sessions and push state are released;
297
+ /// a subsequent `enable()` re-initialises from `ConnectConfig.json`.
298
+ func disable() throws -> Bool {
299
+ bridgeLog.info("disable() called from JS.")
300
+ Task { @MainActor in
301
+ ConnectSDK.shared.disable()
302
+ bridgeLog.info("SDK disabled.")
303
+ }
304
+ return true
305
+ }
306
+
200
307
  /// Sets the module's configuration item from AdvancedConfig.json or BasicConfig.plist that matches the specified key as a BOOL value.
201
308
  /// - Parameters:
202
309
  /// - key: Key to update value in configuration settings.
@@ -334,9 +441,10 @@ class HybridAcousticConnectRN: HybridAcousticConnectRNSpec {
334
441
  /// - Returns: Boolean value will return whether it was able to log the click event.
335
442
  func logClickEvent(target: Double, controlId: String) throws -> Bool {
336
443
  var result: Bool = false
337
- DispatchQueue.main.async {
338
- let view:UIView? = nil
444
+ Task { @MainActor in
445
+ let view: UIView? = nil
339
446
  let result = ConnectCustomEvent().logClick(view, controlId: controlId, data: nil)
447
+ _ = result
340
448
  }
341
449
  return result
342
450
  }
@@ -29,6 +29,9 @@ const Connect = ({
29
29
  navigationRef
30
30
  }) => {
31
31
  const child = children;
32
+ // CA-138631: React 19 moved the ref off `element.ref` onto `element.props.ref`.
33
+ // Read `props.ref` first; the legacy `child.ref` fallback is a defensive
34
+ // guard from the React 18 era — kept to avoid a behavioural change.
32
35
  const childProvidedRef = child?.props?.ref ?? child?.ref;
33
36
  const internalRef = (0, _react.useRef)(null);
34
37
 
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_TLTRN","_interopRequireDefault","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","useRef","navigation","shouldInjectRef","React","isValidElement","currentRoute","undefined","initial","useEffect","TLTRN","interceptKeyboardEvents","interceptDialogEvents","current","addListener","getCurrentRoute","console","warn","unsubscribeState","extractName","name","log","Platform","OS","logScreenViewPageName","logScreenLayout","onStartShouldSetResponderCapture","useCallback","event","logClickEvent","onLayout","_event","jsx","View","style","styles","connect_main","cloneElement","routeParams","params","_default","exports","StyleSheet","create","flex"],"sourceRoot":"../../../src","sources":["components/Connect.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_TLTRN","_interopRequireDefault","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","useRef","navigation","shouldInjectRef","React","isValidElement","currentRoute","undefined","initial","useEffect","TLTRN","interceptKeyboardEvents","interceptDialogEvents","current","addListener","getCurrentRoute","console","warn","unsubscribeState","extractName","name","log","Platform","OS","logScreenViewPageName","logScreenLayout","onStartShouldSetResponderCapture","useCallback","event","logClickEvent","onLayout","_event","jsx","View","style","styles","connect_main","cloneElement","routeParams","params","_default","exports","StyleSheet","create","flex"],"sourceRoot":"../../../src","sources":["components/Connect.tsx"],"mappings":"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","ignoreList":[]}
@@ -21,6 +21,9 @@ const Connect = ({
21
21
  navigationRef
22
22
  }) => {
23
23
  const child = children;
24
+ // CA-138631: React 19 moved the ref off `element.ref` onto `element.props.ref`.
25
+ // Read `props.ref` first; the legacy `child.ref` fallback is a defensive
26
+ // guard from the React 18 era — kept to avoid a behavioural change.
24
27
  const childProvidedRef = child?.props?.ref ?? child?.ref;
25
28
  const internalRef = useRef(null);
26
29
 
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useEffect","useRef","View","StyleSheet","Platform","TLTRN","jsx","_jsx","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","navigation","shouldInjectRef","isValidElement","currentRoute","undefined","initial","interceptKeyboardEvents","interceptDialogEvents","current","addListener","getCurrentRoute","console","warn","unsubscribeState","extractName","name","log","OS","logScreenViewPageName","logScreenLayout","onStartShouldSetResponderCapture","event","logClickEvent","onLayout","_event","style","styles","connect_main","cloneElement","routeParams","params","create","flex"],"sourceRoot":"../../../src","sources":["components/Connect.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","useCallback","useEffect","useRef","View","StyleSheet","Platform","TLTRN","jsx","_jsx","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","navigation","shouldInjectRef","isValidElement","currentRoute","undefined","initial","interceptKeyboardEvents","interceptDialogEvents","current","addListener","getCurrentRoute","console","warn","unsubscribeState","extractName","name","log","OS","logScreenViewPageName","logScreenLayout","onStartShouldSetResponderCapture","event","logClickEvent","onLayout","_event","style","styles","connect_main","cloneElement","routeParams","params","create","flex"],"sourceRoot":"../../../src","sources":["components/Connect.tsx"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"Connect.d.ts","sourceRoot":"","sources":["../../../../src/components/Connect.tsx"],"names":[],"mappings":"AAAA;;;;;;;;6FAQ6F;AAC7F,OAAO,KAAyC,MAAM,OAAO,CAAC;AAK9D,UAAU,YAAY;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;CACxC;AAED,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAsGnC,CAAC;AAWF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"Connect.d.ts","sourceRoot":"","sources":["../../../../src/components/Connect.tsx"],"names":[],"mappings":"AAAA;;;;;;;;6FAQ6F;AAC7F,OAAO,KAAyC,MAAM,OAAO,CAAC;AAK9D,UAAU,YAAY;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;CACxC;AAED,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAyGnC,CAAC;AAWF,eAAe,OAAO,CAAC"}