react-native-acoustic-connect-beta 19.1.3 → 19.1.4

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 19.1.4 (2026-09-30)
2
+
3
+ ### Reverts
4
+
5
+ * Revert "Beta ReactNativeConnect build: 18.0.36" ([609ad7d](https://github.com/aipoweredmarketer/react-native-acoustic-connect-beta/commit/609ad7d3244ec06f27dced5864d40585c5b3c9cf))
1
6
  ## 19.1.3 (2026-09-30)
2
7
 
3
8
  ### Reverts
@@ -1,4 +1,4 @@
1
- #Wed Sep 30 09:13:37 GMT 2026
1
+ #Wed Sep 30 13:22:22 GMT 2026
2
2
  UseWhiteList=true
3
3
  PrintScreen=3
4
4
  UseRandomSample=false
@@ -819,32 +819,23 @@ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
819
819
  /**
820
820
  * Log click events on react native control.
821
821
  *
822
+ * The view lookup and the SDK call both run on the main looper — see
823
+ * [withResolvedView].
824
+ *
822
825
  * @param target Target id of the control.
823
826
  * @param controlId Accessibility ID(virtual id).
824
- * @return True if the operation was successful, false otherwise.
827
+ * @return True if the event was handed to the main looper, false without a
828
+ * React context. It cannot report whether the view resolved.
825
829
  */
826
830
  override fun logClickEvent(target: Double, controlId: String): Boolean {
827
- val viewTag = target.toInt()
828
- return try {
829
- val ctx = applicationContext ?: return false
830
- val uiManager = UIManagerHelper.getUIManagerForReactTag(ctx, viewTag)
831
- ?: return false
832
- val view = uiManager.resolveView(viewTag) ?: return false
833
-
834
- Handler(Looper.getMainLooper()).post {
835
- val activity = getCurrentActivity() ?: return@post
836
- if (view is EditText) {
837
- addFocusAndRegister(view, null, activity)
838
- } else if (TextUtils.isEmpty(controlId)) {
839
- logEvent(view, "click")
840
- } else {
841
- logEvent(view, "click", controlId)
842
- }
831
+ return withResolvedView(target.toInt(), "logClickEvent") { view, activity ->
832
+ if (view is EditText) {
833
+ addFocusAndRegister(view, null, activity)
834
+ } else if (TextUtils.isEmpty(controlId)) {
835
+ logEvent(view, "click")
836
+ } else {
837
+ logEvent(view, "click", controlId)
843
838
  }
844
- true
845
- } catch (e: Exception) {
846
- Log.v(TAG, "logClickEvent error: ${e.message}", e)
847
- false
848
839
  }
849
840
  }
850
841
 
@@ -852,28 +843,16 @@ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
852
843
  * Log click events on react native control.
853
844
  *
854
845
  * @param target Target id of the control.
855
- * @return True if the operation was successful, false otherwise.
846
+ * @return True if the event was handed to the main looper, false without a
847
+ * React context. It cannot report whether the view resolved.
856
848
  */
857
849
  fun logClickEvent(target: Double): Boolean {
858
- val viewTag = target.toInt()
859
- return try {
860
- val ctx = applicationContext ?: return false
861
- val uiManager = UIManagerHelper.getUIManagerForReactTag(ctx, viewTag)
862
- ?: return false
863
- val view = uiManager.resolveView(viewTag) ?: return false
864
-
865
- Handler(Looper.getMainLooper()).post {
866
- val activity = getCurrentActivity() ?: return@post
867
- if (view is EditText) {
868
- addFocusAndRegister(view, null, activity)
869
- } else {
870
- logEvent(view, "click")
871
- }
850
+ return withResolvedView(target.toInt(), "logClickEvent") { view, activity ->
851
+ if (view is EditText) {
852
+ addFocusAndRegister(view, null, activity)
853
+ } else {
854
+ logEvent(view, "click")
872
855
  }
873
- true
874
- } catch (e: Exception) {
875
- Log.v(TAG, "logClickEvent error: ${e.message}")
876
- false
877
856
  }
878
857
  }
879
858
 
@@ -883,30 +862,59 @@ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
883
862
  * @param target A valid native View Id for lookup.
884
863
  * @param controlId Accessibility ID(virtual id).
885
864
  * @param text The input string.
886
- * @return True if the operation was successful, false otherwise.
865
+ * @return True if the event was handed to the main looper, false without a
866
+ * React context. It cannot report whether the view resolved.
887
867
  */
888
868
  override fun logTextChangeEvent(target: Double, controlId: String, text: Variant_NullType_String?): Boolean {
889
- val viewTag = target.toInt()
890
- return try {
891
- val ctx = applicationContext ?: return false
892
- val uiManager = UIManagerHelper.getUIManagerForReactTag(ctx, viewTag)
893
- ?: return false
894
- val view = uiManager.resolveView(viewTag) ?: return false
895
-
896
- Handler(Looper.getMainLooper()).post {
897
- val activity = getCurrentActivity() ?: return@post
898
- if (view is EditText && view.onFocusChangeListener == null) {
899
- logEvent(view, TLF_ON_FOCUS_CHANGE_IN, controlId)
900
- addFocusAndRegister(view, controlId, activity)
901
- }
869
+ return withResolvedView(target.toInt(), "logTextChangeEvent") { view, activity ->
870
+ if (view is EditText && view.onFocusChangeListener == null) {
871
+ logEvent(view, TLF_ON_FOCUS_CHANGE_IN, controlId)
872
+ addFocusAndRegister(view, controlId, activity)
902
873
  }
903
- true
904
- } catch (e: Exception) {
905
- Log.v(TAG, "logTextChangeEvent error: ${e.message}")
906
- false
907
874
  }
908
875
  }
909
876
 
877
+ /**
878
+ * Resolves the native view behind a React tag and hands it to [block], with
879
+ * the lookup and the block both running on the main looper.
880
+ *
881
+ * Nitro calls arrive on the JS thread, and Fabric's `resolveView` must run
882
+ * on the UI thread. The bridge used to resolve first and post second, so
883
+ * every tap logged `AssertionException: Expected to run on UI thread!` in
884
+ * debug builds. That assertion is soft — the view still came back — but
885
+ * the lookup was reading the mounting layer's view map while the UI thread
886
+ * mutates it.
887
+ *
888
+ * The whole block is guarded, not just the lookup. `getView` throws when
889
+ * the view was unmounted between the tap and this post running, and an
890
+ * exception escaping a posted block is uncaught on the main thread — a
891
+ * crash, where the old off-thread lookup only returned false.
892
+ *
893
+ * @param viewTag React tag of the touched view.
894
+ * @param api Name of the bridge method, for the log line.
895
+ * @param block Work to do with the resolved view and current activity;
896
+ * skipped when either is unavailable.
897
+ * @return False without a React context, true once the work is posted.
898
+ */
899
+ private fun withResolvedView(
900
+ viewTag: Int,
901
+ api: String,
902
+ block: (View, Activity) -> Unit
903
+ ): Boolean {
904
+ val ctx = applicationContext ?: return false
905
+ runOnMain {
906
+ try {
907
+ val view = UIManagerHelper.getUIManagerForReactTag(ctx, viewTag)
908
+ ?.resolveView(viewTag) ?: return@runOnMain
909
+ val activity = getCurrentActivity() ?: return@runOnMain
910
+ block(view, activity)
911
+ } catch (e: Exception) {
912
+ Log.v(TAG, "$api error: ${e.message}", e)
913
+ }
914
+ }
915
+ return true
916
+ }
917
+
910
918
  /**
911
919
  * Whether the bridge may touch capture at all.
912
920
  *
package/package.json CHANGED
@@ -228,7 +228,7 @@
228
228
  "source": "src/index",
229
229
  "summary": "react-native ios android tealeaf connect cxa wxca er enhanced-replay",
230
230
  "types": "./lib/typescript/src/index.d.ts",
231
- "version": "19.1.3",
231
+ "version": "19.1.4",
232
232
  "workspaces": [
233
233
  "example",
234
234
  "Examples/bare-workflow"