pythonnative 0.24.0__py3-none-any.whl → 0.26.0__py3-none-any.whl

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 (52) hide show
  1. pythonnative/__init__.py +16 -4
  2. pythonnative/animated.py +2 -2
  3. pythonnative/cli/pn.py +172 -12
  4. pythonnative/components.py +59 -0
  5. pythonnative/diagnostics.py +27 -0
  6. pythonnative/hooks.py +364 -81
  7. pythonnative/native_modules/app_state.py +2 -1
  8. pythonnative/native_modules/battery.py +3 -2
  9. pythonnative/native_modules/biometrics.py +2 -1
  10. pythonnative/native_modules/camera.py +16 -7
  11. pythonnative/native_modules/clipboard.py +3 -2
  12. pythonnative/native_modules/file_system.py +3 -2
  13. pythonnative/native_modules/haptics.py +7 -6
  14. pythonnative/native_modules/linking.py +62 -6
  15. pythonnative/native_modules/location.py +11 -8
  16. pythonnative/native_modules/net_info.py +2 -1
  17. pythonnative/native_modules/notifications.py +132 -9
  18. pythonnative/native_modules/permissions.py +27 -3
  19. pythonnative/native_modules/share.py +2 -1
  20. pythonnative/native_views/android.py +149 -124
  21. pythonnative/native_views/desktop.py +50 -49
  22. pythonnative/native_views/ios.py +240 -161
  23. pythonnative/project/android.py +15 -3
  24. pythonnative/project/builder.py +172 -70
  25. pythonnative/project/config.py +28 -6
  26. pythonnative/project/devices.py +291 -0
  27. pythonnative/project/doctor.py +5 -4
  28. pythonnative/project/ios.py +51 -77
  29. pythonnative/project/permissions.py +19 -1
  30. pythonnative/project/runtime_assets.py +78 -166
  31. pythonnative/reconciler.py +518 -37
  32. pythonnative/runtime.py +407 -215
  33. pythonnative/screen.py +53 -7
  34. pythonnative/storage.py +2 -2
  35. pythonnative/suspense.py +417 -0
  36. pythonnative/templates/android_template/app/build.gradle +5 -0
  37. pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +1 -0
  38. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +88 -12
  39. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +41 -17
  40. pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
  41. pythonnative/templates/ios_template/ios_template/Info.plist +0 -2
  42. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +397 -0
  43. pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +31 -20
  44. pythonnative/templates/ios_template/ios_template/ViewController.swift +77 -198
  45. pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +72 -47
  46. {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/METADATA +2 -1
  47. {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/RECORD +51 -48
  48. {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/WHEEL +1 -1
  49. pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -24
  50. {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/entry_points.txt +0 -0
  51. {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/licenses/LICENSE +0 -0
  52. {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/top_level.txt +0 -0
@@ -40,6 +40,7 @@ from typing import Any, Callable, Dict, Optional, Tuple
40
40
 
41
41
  from java import dynamic_proxy, jclass
42
42
 
43
+ from .. import diagnostics
43
44
  from ..events import dispatch_event, event_names
44
45
  from ..gestures import make_arbiter
45
46
  from ..utils import get_android_context
@@ -206,7 +207,7 @@ def _apply_side_border(view: Any, props: Dict[str, Any]) -> bool:
206
207
  try:
207
208
  view.invalidate()
208
209
  except Exception:
209
- pass
210
+ diagnostics.swallowed("android._apply_side_border")
210
211
  return True
211
212
  except Exception:
212
213
  return False
@@ -237,12 +238,12 @@ def _apply_border(view: Any, props: Dict[str, Any]) -> None:
237
238
  try:
238
239
  drawable.setColor(parse_color_int(props["background_color"]))
239
240
  except Exception:
240
- pass
241
+ diagnostics.swallowed("android._apply_border")
241
242
  if "border_radius" in props and props["border_radius"] is not None:
242
243
  try:
243
244
  drawable.setCornerRadius(float(_dp(float(props["border_radius"]))))
244
245
  except Exception:
245
- pass
246
+ diagnostics.swallowed("android._apply_border")
246
247
  if ("border_width" in props and props["border_width"] is not None) or (
247
248
  "border_color" in props and props["border_color"] is not None
248
249
  ):
@@ -254,18 +255,18 @@ def _apply_border(view: Any, props: Dict[str, Any]) -> None:
254
255
  parse_color_int(color or "#000000"),
255
256
  )
256
257
  except Exception:
257
- pass
258
+ diagnostics.swallowed("android._apply_border")
258
259
  view.setBackground(drawable)
259
260
  try:
260
261
  drawable.invalidateSelf()
261
262
  except Exception:
262
- pass
263
+ diagnostics.swallowed("android._apply_border")
263
264
  try:
264
265
  view.invalidate()
265
266
  except Exception:
266
- pass
267
+ diagnostics.swallowed("android._apply_border")
267
268
  except Exception:
268
- pass
269
+ diagnostics.swallowed("android._apply_border")
269
270
 
270
271
 
271
272
  def _apply_shadow(view: Any, props: Dict[str, Any]) -> None:
@@ -291,7 +292,7 @@ def _apply_shadow(view: Any, props: Dict[str, Any]) -> None:
291
292
  try:
292
293
  view.setElevation(float(_dp(float(elevation))))
293
294
  except Exception:
294
- pass
295
+ diagnostics.swallowed("android._apply_shadow")
295
296
  color = props.get("shadow_color")
296
297
  if color is None:
297
298
  return
@@ -308,7 +309,7 @@ def _apply_shadow(view: Any, props: Dict[str, Any]) -> None:
308
309
  view.setOutlineAmbientShadowColor(signed)
309
310
  view.setOutlineSpotShadowColor(signed)
310
311
  except Exception:
311
- pass
312
+ diagnostics.swallowed("android._apply_shadow")
312
313
 
313
314
 
314
315
  def _apply_transform(view: Any, props: Dict[str, Any]) -> None:
@@ -324,7 +325,7 @@ def _apply_transform(view: Any, props: Dict[str, Any]) -> None:
324
325
  view.setTranslationX(0.0)
325
326
  view.setTranslationY(0.0)
326
327
  except Exception:
327
- pass
328
+ diagnostics.swallowed("android._apply_transform")
328
329
  return
329
330
  entries = spec if isinstance(spec, list) else [spec]
330
331
  for entry in entries:
@@ -353,7 +354,7 @@ def _apply_transform(view: Any, props: Dict[str, Any]) -> None:
353
354
  if "translate_y" in entry:
354
355
  view.setTranslationY(float(_dp(float(entry["translate_y"]))))
355
356
  except Exception:
356
- pass
357
+ diagnostics.swallowed("android._apply_transform")
357
358
 
358
359
 
359
360
  def _apply_accessibility(view: Any, props: Dict[str, Any]) -> None:
@@ -365,13 +366,13 @@ def _apply_accessibility(view: Any, props: Dict[str, Any]) -> None:
365
366
  View.IMPORTANT_FOR_ACCESSIBILITY_YES if props["accessible"] else View.IMPORTANT_FOR_ACCESSIBILITY_NO
366
367
  )
367
368
  except Exception:
368
- pass
369
+ diagnostics.swallowed("android._apply_accessibility")
369
370
  if "accessibility_label" in props:
370
371
  try:
371
372
  label = props["accessibility_label"]
372
373
  view.setContentDescription(str(label) if label is not None else None)
373
374
  except Exception:
374
- pass
375
+ diagnostics.swallowed("android._apply_accessibility")
375
376
  if "accessibility_live_region" in props:
376
377
  try:
377
378
  mode = {"none": 0, "polite": 1, "assertive": 2}.get(
@@ -379,14 +380,14 @@ def _apply_accessibility(view: Any, props: Dict[str, Any]) -> None:
379
380
  )
380
381
  view.setAccessibilityLiveRegion(mode)
381
382
  except Exception:
382
- pass
383
+ diagnostics.swallowed("android._apply_accessibility")
383
384
 
384
385
  state = props.get("accessibility_state")
385
386
  if isinstance(state, dict) and "selected" in state:
386
387
  try:
387
388
  view.setSelected(bool(state["selected"]))
388
389
  except Exception:
389
- pass
390
+ diagnostics.swallowed("android._apply_accessibility")
390
391
  test_id = props.get("test_id")
391
392
  if test_id is None and not isinstance(state, dict):
392
393
  return
@@ -413,7 +414,7 @@ def _apply_accessibility(view: Any, props: Dict[str, Any]) -> None:
413
414
  delegate.setStateBusy(state.get("busy"))
414
415
  delegate.setStateExpanded(state.get("expanded"))
415
416
  except Exception:
416
- pass
417
+ diagnostics.swallowed("android._apply_accessibility")
417
418
 
418
419
 
419
420
  def _apply_common_visual(view: Any, props: Dict[str, Any]) -> None:
@@ -433,12 +434,12 @@ def _apply_common_visual(view: Any, props: Dict[str, Any]) -> None:
433
434
  view.setClipChildren(clip)
434
435
  view.setClipToPadding(clip)
435
436
  except Exception:
436
- pass
437
+ diagnostics.swallowed("android._apply_common_visual")
437
438
  if "opacity" in props and props["opacity"] is not None:
438
439
  try:
439
440
  view.setAlpha(float(props["opacity"]))
440
441
  except Exception:
441
- pass
442
+ diagnostics.swallowed("android._apply_common_visual")
442
443
  _apply_shadow(view, props)
443
444
  _apply_transform(view, props)
444
445
  _apply_accessibility(view, props)
@@ -501,7 +502,7 @@ def _schedule_arbiter_poll(view: Any, state: Dict[str, Any]) -> None:
501
502
 
502
503
  handler.postDelayed(_PollRunnable(), delay_ms)
503
504
  except Exception:
504
- pass
505
+ diagnostics.swallowed("android._schedule_arbiter_poll")
505
506
 
506
507
 
507
508
  def _bind_touch_stream(view: Any, state: Dict[str, Any]) -> None:
@@ -515,7 +516,7 @@ def _bind_touch_stream(view: Any, state: Dict[str, Any]) -> None:
515
516
 
516
517
  view.setOnTouchListener(_GestureTouchProxy())
517
518
  except Exception:
518
- pass
519
+ diagnostics.swallowed("android._bind_touch_stream")
519
520
 
520
521
 
521
522
  def _feed_motion_event(view: Any, state: Dict[str, Any], event: Any) -> bool:
@@ -546,7 +547,7 @@ def _feed_motion_event(view: Any, state: Dict[str, Any], event: Any) -> bool:
546
547
  if parent is not None:
547
548
  parent.requestDisallowInterceptTouchEvent(True)
548
549
  except Exception:
549
- pass
550
+ diagnostics.swallowed("android._feed_motion_event")
550
551
  elif action in (1, 6): # UP / POINTER_UP
551
552
  idx = int(event.getActionIndex())
552
553
  pid = int(event.getPointerId(idx))
@@ -603,7 +604,7 @@ def _read_animated_value(view: Any, prop_name: str) -> Any:
603
604
  if prop_name == "rotate":
604
605
  return float(view.getRotation())
605
606
  except Exception:
606
- pass
607
+ diagnostics.swallowed("android._read_animated_value")
607
608
  return None
608
609
 
609
610
 
@@ -612,11 +613,16 @@ def _make_end_listener(anim_id: int) -> Any:
612
613
  AnimatorListener = jclass("android.animation.Animator$AnimatorListener")
613
614
 
614
615
  class _EndProxy(dynamic_proxy(AnimatorListener)):
616
+ # ``onAnimationStart`` / ``onAnimationEnd`` accept an optional
617
+ # ``isReverse``: API 26 added default two-arg overloads to
618
+ # ``AnimatorListener``, and ``ValueAnimator`` invokes those, so
619
+ # the java.lang.reflect.Proxy forwards two arguments here.
620
+
615
621
  def __init__(self) -> None:
616
622
  super().__init__()
617
623
  self._cancelled = False
618
624
 
619
- def onAnimationStart(self, animation: Any) -> None:
625
+ def onAnimationStart(self, animation: Any, isReverse: bool = False) -> None:
620
626
  pass
621
627
 
622
628
  def onAnimationRepeat(self, animation: Any) -> None:
@@ -625,7 +631,7 @@ def _make_end_listener(anim_id: int) -> Any:
625
631
  def onAnimationCancel(self, animation: Any) -> None:
626
632
  self._cancelled = True
627
633
 
628
- def onAnimationEnd(self, animation: Any) -> None:
634
+ def onAnimationEnd(self, animation: Any, isReverse: bool = False) -> None:
629
635
  entry = _native_anims.pop(anim_id, None)
630
636
  if entry is None:
631
637
  return
@@ -634,7 +640,7 @@ def _make_end_listener(anim_id: int) -> Any:
634
640
 
635
641
  native_animation_completed(anim_id, not self._cancelled)
636
642
  except Exception:
637
- pass
643
+ diagnostics.swallowed("android._make_end_listener._EndProxy.onAnimationEnd")
638
644
 
639
645
  return _EndProxy()
640
646
 
@@ -726,7 +732,7 @@ class AndroidViewHandler(ViewHandler):
726
732
  if parent is not None:
727
733
  parent.removeView(native_view)
728
734
  except Exception:
729
- pass
735
+ diagnostics.swallowed("android.AndroidViewHandler.destroy")
730
736
  _forget(native_view)
731
737
 
732
738
  def _build(self, props: Dict[str, Any]) -> Any:
@@ -755,17 +761,17 @@ class AndroidViewHandler(ViewHandler):
755
761
  lp.width = px_w
756
762
  lp.height = px_h
757
763
  except Exception:
758
- pass
764
+ diagnostics.swallowed("android.AndroidViewHandler.set_frame")
759
765
  try:
760
766
  lp.leftMargin = px_x
761
767
  lp.topMargin = px_y
762
768
  lp.rightMargin = 0
763
769
  lp.bottomMargin = 0
764
770
  except Exception:
765
- pass
771
+ diagnostics.swallowed("android.AndroidViewHandler.set_frame")
766
772
  native_view.setLayoutParams(lp)
767
773
  except Exception:
768
- pass
774
+ diagnostics.swallowed("android.AndroidViewHandler.set_frame")
769
775
 
770
776
  def measure_intrinsic(
771
777
  self,
@@ -818,7 +824,7 @@ class AndroidViewHandler(ViewHandler):
818
824
  elif prop_name == "background_color":
819
825
  native_view.setBackgroundColor(parse_color_int(value))
820
826
  except Exception:
821
- pass
827
+ diagnostics.swallowed("android.AndroidViewHandler.set_animated_property")
822
828
 
823
829
  def start_animation(
824
830
  self,
@@ -846,7 +852,7 @@ class AndroidViewHandler(ViewHandler):
846
852
  try:
847
853
  entry["animator"].cancel()
848
854
  except Exception:
849
- pass
855
+ diagnostics.swallowed("android.AndroidViewHandler.cancel_animation")
850
856
  return _read_animated_value(entry.get("view"), str(entry.get("prop", "")))
851
857
 
852
858
 
@@ -874,7 +880,7 @@ class FlexContainerHandler(AndroidViewHandler):
874
880
  try:
875
881
  parent.removeView(child)
876
882
  except Exception:
877
- pass
883
+ diagnostics.swallowed("android.FlexContainerHandler.remove_child")
878
884
 
879
885
 
880
886
  def _insert_view(parent: Any, child: Any, index: int) -> None:
@@ -900,7 +906,7 @@ def _insert_view(parent: Any, child: Any, index: int) -> None:
900
906
  try:
901
907
  parent.addView(child)
902
908
  except Exception:
903
- pass
909
+ diagnostics.swallowed("android._insert_view")
904
910
 
905
911
 
906
912
  # ======================================================================
@@ -988,7 +994,7 @@ def _build_spannable(spans: Any) -> Any:
988
994
  StrikethroughSpan = jclass("android.text.style.StrikethroughSpan")
989
995
  _set(StrikethroughSpan())
990
996
  except Exception:
991
- pass
997
+ diagnostics.swallowed("android._build_spannable")
992
998
  return builder
993
999
 
994
1000
 
@@ -1030,7 +1036,7 @@ class TextHandler(AndroidViewHandler):
1030
1036
  else:
1031
1037
  tv.setTypeface(tv.getTypeface(), style)
1032
1038
  except Exception:
1033
- pass
1039
+ diagnostics.swallowed("android.TextHandler._apply")
1034
1040
  if "max_lines" in props and props["max_lines"] is not None:
1035
1041
  tv.setMaxLines(int(props["max_lines"]))
1036
1042
  if "text_align" in props:
@@ -1045,14 +1051,14 @@ class TextHandler(AndroidViewHandler):
1045
1051
  size = float(merged.get("font_size") or 16.0)
1046
1052
  tv.setLetterSpacing(float(props["letter_spacing"]) / max(size, 1.0))
1047
1053
  except Exception:
1048
- pass
1054
+ diagnostics.swallowed("android.TextHandler._apply")
1049
1055
  if "line_height" in props and props["line_height"] is not None:
1050
1056
  try:
1051
1057
  merged = _state_of(tv).get("props") or props
1052
1058
  size = float(merged.get("font_size") or 16.0)
1053
1059
  tv.setLineSpacing(0.0, float(props["line_height"]) / max(size, 1.0))
1054
1060
  except Exception:
1055
- pass
1061
+ diagnostics.swallowed("android.TextHandler._apply")
1056
1062
  if "text_decoration" in props:
1057
1063
  try:
1058
1064
  Paint = jclass("android.graphics.Paint")
@@ -1063,7 +1069,7 @@ class TextHandler(AndroidViewHandler):
1063
1069
  flags |= Paint.STRIKE_THRU_TEXT_FLAG
1064
1070
  tv.setPaintFlags(flags)
1065
1071
  except Exception:
1066
- pass
1072
+ diagnostics.swallowed("android.TextHandler._apply")
1067
1073
  _apply_common_visual(tv, props)
1068
1074
 
1069
1075
 
@@ -1142,7 +1148,7 @@ class ScrollViewHandler(AndroidViewHandler):
1142
1148
  try:
1143
1149
  outer.setEnabled(False)
1144
1150
  except Exception:
1145
- pass
1151
+ diagnostics.swallowed("android.ScrollViewHandler.create")
1146
1152
  self._bind_scroll_listener(outer, sv)
1147
1153
  self._apply(outer, props, initial=True)
1148
1154
  if props.get("gestures"):
@@ -1160,7 +1166,7 @@ class ScrollViewHandler(AndroidViewHandler):
1160
1166
  sv.setVerticalScrollBarEnabled(show)
1161
1167
  sv.setHorizontalScrollBarEnabled(show)
1162
1168
  except Exception:
1163
- pass
1169
+ diagnostics.swallowed("android.ScrollViewHandler._apply")
1164
1170
  if "bounces" in props:
1165
1171
  # ``bounces`` is only present when ``False``; map it to the
1166
1172
  # closest analogue, the over-scroll (glow) mode.
@@ -1169,7 +1175,7 @@ class ScrollViewHandler(AndroidViewHandler):
1169
1175
  mode = View.OVER_SCROLL_NEVER if props["bounces"] is False else View.OVER_SCROLL_IF_CONTENT_SCROLLS
1170
1176
  sv.setOverScrollMode(mode)
1171
1177
  except Exception:
1172
- pass
1178
+ diagnostics.swallowed("android.ScrollViewHandler._apply")
1173
1179
  if "refresh_control" in props and state.get("refresh") is not None:
1174
1180
  self._apply_refresh(outer, props)
1175
1181
  # ``paging_enabled`` and ``keyboard_dismiss_mode`` have no clean
@@ -1185,7 +1191,7 @@ class ScrollViewHandler(AndroidViewHandler):
1185
1191
  try:
1186
1192
  sv.removeView(child)
1187
1193
  except Exception:
1188
- pass
1194
+ diagnostics.swallowed("android.ScrollViewHandler.remove_child")
1189
1195
 
1190
1196
  def command(self, native_view: Any, name: str, args: Dict[str, Any]) -> Any:
1191
1197
  state = _state_of(native_view)
@@ -1201,7 +1207,7 @@ class ScrollViewHandler(AndroidViewHandler):
1201
1207
  else:
1202
1208
  sv.scrollTo(x_px, y_px)
1203
1209
  except Exception:
1204
- pass
1210
+ diagnostics.swallowed("android.ScrollViewHandler.command")
1205
1211
  return None
1206
1212
  if name == "scroll_to_end":
1207
1213
  try:
@@ -1215,7 +1221,7 @@ class ScrollViewHandler(AndroidViewHandler):
1215
1221
  target_y = max(0, int(child.getHeight()) - int(sv.getHeight()))
1216
1222
  sv.smoothScrollTo(0, target_y)
1217
1223
  except Exception:
1218
- pass
1224
+ diagnostics.swallowed("android.ScrollViewHandler.command")
1219
1225
  return None
1220
1226
  if name == "get_scroll_offset":
1221
1227
  try:
@@ -1245,11 +1251,13 @@ class ScrollViewHandler(AndroidViewHandler):
1245
1251
  density = _density() or 1.0
1246
1252
  _fire(outer, "on_scroll", {"x": scroll_x / density, "y": scroll_y / density})
1247
1253
  except Exception:
1248
- pass
1254
+ diagnostics.swallowed(
1255
+ "android.ScrollViewHandler._bind_scroll_listener._ScrollChangeProxy.onScrollChange"
1256
+ )
1249
1257
 
1250
1258
  sv.setOnScrollChangeListener(_ScrollChangeProxy())
1251
1259
  except Exception:
1252
- pass
1260
+ diagnostics.swallowed("android.ScrollViewHandler._bind_scroll_listener")
1253
1261
 
1254
1262
  def _wrap_in_refresh(self, sv: Any) -> Any:
1255
1263
  try:
@@ -1273,7 +1281,7 @@ class ScrollViewHandler(AndroidViewHandler):
1273
1281
 
1274
1282
  srl.setOnRefreshListener(_RefreshProxy())
1275
1283
  except Exception:
1276
- pass
1284
+ diagnostics.swallowed("android.ScrollViewHandler._bind_refresh_listener")
1277
1285
 
1278
1286
  def _apply_refresh(self, outer: Any, props: Dict[str, Any]) -> None:
1279
1287
  srl = _state_of(outer).get("refresh")
@@ -1284,21 +1292,21 @@ class ScrollViewHandler(AndroidViewHandler):
1284
1292
  try:
1285
1293
  srl.setEnabled(False)
1286
1294
  except Exception:
1287
- pass
1295
+ diagnostics.swallowed("android.ScrollViewHandler._apply_refresh")
1288
1296
  return
1289
1297
  try:
1290
1298
  srl.setEnabled(True)
1291
1299
  except Exception:
1292
- pass
1300
+ diagnostics.swallowed("android.ScrollViewHandler._apply_refresh")
1293
1301
  if spec.get("tint_color"):
1294
1302
  try:
1295
1303
  srl.setColorSchemeColors([parse_color_int(spec["tint_color"])])
1296
1304
  except Exception:
1297
- pass
1305
+ diagnostics.swallowed("android.ScrollViewHandler._apply_refresh")
1298
1306
  try:
1299
1307
  srl.setRefreshing(bool(spec.get("refreshing")))
1300
1308
  except Exception:
1301
- pass
1309
+ diagnostics.swallowed("android.ScrollViewHandler._apply_refresh")
1302
1310
 
1303
1311
 
1304
1312
  class TextInputHandler(AndroidViewHandler):
@@ -1311,7 +1319,7 @@ class TextInputHandler(AndroidViewHandler):
1311
1319
  if not props.get("multiline"):
1312
1320
  et.setSingleLine(True)
1313
1321
  except Exception:
1314
- pass
1322
+ diagnostics.swallowed("android.TextInputHandler._build")
1315
1323
  self._bind_listeners(et, props)
1316
1324
  return et
1317
1325
 
@@ -1337,7 +1345,7 @@ class TextInputHandler(AndroidViewHandler):
1337
1345
 
1338
1346
  et.addTextChangedListener(ChangeProxy())
1339
1347
  except Exception:
1340
- pass
1348
+ diagnostics.swallowed("android.TextInputHandler._bind_listeners")
1341
1349
  try:
1342
1350
 
1343
1351
  class _FocusProxy(dynamic_proxy(jclass("android.view.View").OnFocusChangeListener)):
@@ -1346,7 +1354,7 @@ class TextInputHandler(AndroidViewHandler):
1346
1354
 
1347
1355
  et.setOnFocusChangeListener(_FocusProxy())
1348
1356
  except Exception:
1349
- pass
1357
+ diagnostics.swallowed("android.TextInputHandler._bind_listeners")
1350
1358
 
1351
1359
  def _apply(self, et: Any, props: Dict[str, Any], initial: bool) -> None:
1352
1360
  state = _state_of(et)
@@ -1363,7 +1371,7 @@ class TextInputHandler(AndroidViewHandler):
1363
1371
  selection_start = et.getSelectionStart()
1364
1372
  selection_end = et.getSelectionEnd()
1365
1373
  except Exception:
1366
- pass
1374
+ diagnostics.swallowed("android.TextInputHandler._apply")
1367
1375
  state["suppress"] = True
1368
1376
  try:
1369
1377
  et.setText(incoming)
@@ -1376,7 +1384,7 @@ class TextInputHandler(AndroidViewHandler):
1376
1384
  else:
1377
1385
  et.setSelection(start, end)
1378
1386
  except Exception:
1379
- pass
1387
+ diagnostics.swallowed("android.TextInputHandler._apply")
1380
1388
  finally:
1381
1389
  state["suppress"] = False
1382
1390
  if "placeholder" in props:
@@ -1385,7 +1393,7 @@ class TextInputHandler(AndroidViewHandler):
1385
1393
  try:
1386
1394
  et.setHintTextColor(parse_color_int(props["placeholder_color"]))
1387
1395
  except Exception:
1388
- pass
1396
+ diagnostics.swallowed("android.TextInputHandler._apply")
1389
1397
  if "font_size" in props and props["font_size"] is not None:
1390
1398
  et.setTextSize(float(props["font_size"]))
1391
1399
  if "color" in props and props["color"] is not None:
@@ -1423,18 +1431,18 @@ class TextInputHandler(AndroidViewHandler):
1423
1431
  et.setSingleLine(True)
1424
1432
  et.setInputType(base)
1425
1433
  except Exception:
1426
- pass
1434
+ diagnostics.swallowed("android.TextInputHandler._apply")
1427
1435
  if "max_length" in props and props["max_length"] is not None:
1428
1436
  try:
1429
1437
  InputFilter = jclass("android.text.InputFilter$LengthFilter")
1430
1438
  et.setFilters([InputFilter(int(props["max_length"]))])
1431
1439
  except Exception:
1432
- pass
1440
+ diagnostics.swallowed("android.TextInputHandler._apply")
1433
1441
  if "auto_focus" in props and props["auto_focus"]:
1434
1442
  try:
1435
1443
  et.requestFocus()
1436
1444
  except Exception:
1437
- pass
1445
+ diagnostics.swallowed("android.TextInputHandler._apply")
1438
1446
  if "editable" in props:
1439
1447
  # ``editable`` is only present when ``False`` (read-only); a
1440
1448
  # removal (``None``) restores editing. We keep the field
@@ -1447,12 +1455,12 @@ class TextInputHandler(AndroidViewHandler):
1447
1455
  et.setCursorVisible(editable)
1448
1456
  et.setLongClickable(editable)
1449
1457
  except Exception:
1450
- pass
1458
+ diagnostics.swallowed("android.TextInputHandler._apply")
1451
1459
  if "selection_color" in props and props["selection_color"] is not None:
1452
1460
  try:
1453
1461
  et.setHighlightColor(parse_color_int(props["selection_color"]))
1454
1462
  except Exception:
1455
- pass
1463
+ diagnostics.swallowed("android.TextInputHandler._apply")
1456
1464
  if "text_content_type" in props and props["text_content_type"] is not None:
1457
1465
  self._apply_autofill(et, str(props["text_content_type"]))
1458
1466
  if "clear_button" in props:
@@ -1480,7 +1488,7 @@ class TextInputHandler(AndroidViewHandler):
1480
1488
  action = rkt_mapping.get(props["return_key_type"], EditorInfo.IME_ACTION_DONE)
1481
1489
  et.setImeOptions(action)
1482
1490
  except Exception:
1483
- pass
1491
+ diagnostics.swallowed("android.TextInputHandler._apply")
1484
1492
  if initial or "multiline" in props:
1485
1493
  self._apply_editor_action(et)
1486
1494
  _apply_common_visual(et, props)
@@ -1509,7 +1517,9 @@ class TextInputHandler(AndroidViewHandler):
1509
1517
  try:
1510
1518
  _fire(view, "on_submit", str(view.getText()))
1511
1519
  except Exception:
1512
- pass
1520
+ diagnostics.swallowed(
1521
+ "android.TextInputHandler._apply_editor_action.SubmitProxy.onEditorAction"
1522
+ )
1513
1523
  if not multiline:
1514
1524
  try:
1515
1525
  view.clearFocus()
@@ -1517,12 +1527,14 @@ class TextInputHandler(AndroidViewHandler):
1517
1527
  imm = ctx.getSystemService(Context.INPUT_METHOD_SERVICE)
1518
1528
  imm.hideSoftInputFromWindow(view.getWindowToken(), 0)
1519
1529
  except Exception:
1520
- pass
1530
+ diagnostics.swallowed(
1531
+ "android.TextInputHandler._apply_editor_action.SubmitProxy.onEditorAction"
1532
+ )
1521
1533
  return True
1522
1534
 
1523
1535
  et.setOnEditorActionListener(SubmitProxy())
1524
1536
  except Exception:
1525
- pass
1537
+ diagnostics.swallowed("android.TextInputHandler._apply_editor_action")
1526
1538
 
1527
1539
  @staticmethod
1528
1540
  def _autofill_hint(content_type: str) -> Optional[str]:
@@ -1554,7 +1566,7 @@ class TextInputHandler(AndroidViewHandler):
1554
1566
  if hint:
1555
1567
  et.setAutofillHints([hint])
1556
1568
  except Exception:
1557
- pass
1569
+ diagnostics.swallowed("android.TextInputHandler._apply_autofill")
1558
1570
 
1559
1571
  def _apply_clear_button(self, et: Any, enabled: bool) -> None:
1560
1572
  # Best-effort drawableEnd "X": shows a system clear icon and wires
@@ -1583,12 +1595,12 @@ class TextInputHandler(AndroidViewHandler):
1583
1595
  view.setText("")
1584
1596
  return True
1585
1597
  except Exception:
1586
- pass
1598
+ diagnostics.swallowed("android.TextInputHandler._apply_clear_button._ClearTouchProxy.onTouch")
1587
1599
  return False
1588
1600
 
1589
1601
  et.setOnTouchListener(_ClearTouchProxy())
1590
1602
  except Exception:
1591
- pass
1603
+ diagnostics.swallowed("android.TextInputHandler._apply_clear_button")
1592
1604
 
1593
1605
 
1594
1606
  class ImageHandler(AndroidViewHandler):
@@ -1601,12 +1613,12 @@ class ImageHandler(AndroidViewHandler):
1601
1613
  ColorStateList = jclass("android.content.res.ColorStateList")
1602
1614
  iv.setImageTintList(ColorStateList.valueOf(parse_color_int(props["tint_color"])))
1603
1615
  except Exception:
1604
- pass
1616
+ diagnostics.swallowed("android.ImageHandler._apply")
1605
1617
  if "placeholder_color" in props and props["placeholder_color"] is not None:
1606
1618
  try:
1607
1619
  iv.setBackgroundColor(parse_color_int(props["placeholder_color"]))
1608
1620
  except Exception:
1609
- pass
1621
+ diagnostics.swallowed("android.ImageHandler._apply")
1610
1622
  if "source" in props and props["source"]:
1611
1623
  self._load_source(iv, str(props["source"]))
1612
1624
  if "scale_type" in props and props["scale_type"]:
@@ -1643,7 +1655,7 @@ class ImageHandler(AndroidViewHandler):
1643
1655
  iv.setImageBitmap(bitmap)
1644
1656
  _fire(iv, "on_load")
1645
1657
  except Exception:
1646
- pass
1658
+ diagnostics.swallowed("android.ImageHandler._load_source._on_ready")
1647
1659
 
1648
1660
  def _on_error(message: str) -> None:
1649
1661
  if _state_of(iv).get("pending_uri") == source:
@@ -1669,7 +1681,7 @@ class ImageHandler(AndroidViewHandler):
1669
1681
  else:
1670
1682
  _fire(iv, "on_error", f"drawable {res_name!r} not found")
1671
1683
  except Exception:
1672
- pass
1684
+ diagnostics.swallowed("android.ImageHandler._load_source")
1673
1685
 
1674
1686
  def _load_data_uri(self, iv: Any, source: str) -> None:
1675
1687
  """Decode an inline ``data:`` URI (base64 payload) into the view."""
@@ -1714,7 +1726,7 @@ class ImageHandler(AndroidViewHandler):
1714
1726
  target_w = int(iv.getWidth())
1715
1727
  target_h = int(iv.getHeight())
1716
1728
  except Exception:
1717
- pass
1729
+ diagnostics.swallowed("android.ImageHandler._decode_downsampled")
1718
1730
  if target_w <= 0:
1719
1731
  try:
1720
1732
  metrics = _ctx().getResources().getDisplayMetrics()
@@ -1775,7 +1787,7 @@ class ProgressBarHandler(AndroidViewHandler):
1775
1787
  ColorStateList = jclass("android.content.res.ColorStateList")
1776
1788
  pb.setProgressTintList(ColorStateList.valueOf(parse_color_int(props["color"])))
1777
1789
  except Exception:
1778
- pass
1790
+ diagnostics.swallowed("android.ProgressBarHandler._apply")
1779
1791
  if "track_color" in props and props["track_color"] is not None:
1780
1792
  try:
1781
1793
  ColorStateList = jclass("android.content.res.ColorStateList")
@@ -1783,12 +1795,12 @@ class ProgressBarHandler(AndroidViewHandler):
1783
1795
  pb.setProgressBackgroundTintList(track)
1784
1796
  pb.setSecondaryProgressTintList(track)
1785
1797
  except Exception:
1786
- pass
1798
+ diagnostics.swallowed("android.ProgressBarHandler._apply")
1787
1799
  if "indeterminate" in props:
1788
1800
  try:
1789
1801
  pb.setIndeterminate(bool(props["indeterminate"]))
1790
1802
  except Exception:
1791
- pass
1803
+ diagnostics.swallowed("android.ProgressBarHandler._apply")
1792
1804
 
1793
1805
 
1794
1806
  class ActivityIndicatorHandler(AndroidViewHandler):
@@ -1804,7 +1816,7 @@ class ActivityIndicatorHandler(AndroidViewHandler):
1804
1816
  ColorStateList = jclass("android.content.res.ColorStateList")
1805
1817
  pb.setIndeterminateTintList(ColorStateList.valueOf(parse_color_int(props["color"])))
1806
1818
  except Exception:
1807
- pass
1819
+ diagnostics.swallowed("android.ActivityIndicatorHandler._apply")
1808
1820
  if "size" in props and props["size"] is not None:
1809
1821
  # The framework ProgressBar has no runtime size switch, so
1810
1822
  # approximate "large" by scaling the indeterminate drawable.
@@ -1813,7 +1825,7 @@ class ActivityIndicatorHandler(AndroidViewHandler):
1813
1825
  pb.setScaleX(scale)
1814
1826
  pb.setScaleY(scale)
1815
1827
  except Exception:
1816
- pass
1828
+ diagnostics.swallowed("android.ActivityIndicatorHandler._apply")
1817
1829
 
1818
1830
 
1819
1831
  def _make_web_client(wv: Any) -> Any:
@@ -1849,13 +1861,13 @@ def _make_web_client(wv: Any) -> Any:
1849
1861
  )
1850
1862
  view.evaluateJavascript(shim, None)
1851
1863
  except Exception:
1852
- pass
1864
+ diagnostics.swallowed("android._make_web_client._WebClientProxy.onPageFinished")
1853
1865
  inject_js = (_state_of(wv).get("props") or {}).get("inject_javascript")
1854
1866
  if inject_js:
1855
1867
  try:
1856
1868
  view.evaluateJavascript(str(inject_js), None)
1857
1869
  except Exception:
1858
- pass
1870
+ diagnostics.swallowed("android._make_web_client._WebClientProxy.onPageFinished")
1859
1871
 
1860
1872
  def shouldOverrideUrlLoading(self, view: Any, request: Any) -> bool:
1861
1873
  try:
@@ -1868,7 +1880,7 @@ def _make_web_client(wv: Any) -> Any:
1868
1880
 
1869
1881
  _fire(wv, "on_message", unquote(url[len(scheme) :]))
1870
1882
  except Exception:
1871
- pass
1883
+ diagnostics.swallowed("android._make_web_client._WebClientProxy.shouldOverrideUrlLoading")
1872
1884
  return True
1873
1885
  return False
1874
1886
 
@@ -1888,7 +1900,7 @@ class WebViewHandler(AndroidViewHandler):
1888
1900
  try:
1889
1901
  wv.getSettings().setJavaScriptEnabled(True)
1890
1902
  except Exception:
1891
- pass
1903
+ diagnostics.swallowed("android.WebViewHandler._apply")
1892
1904
 
1893
1905
  if initial:
1894
1906
  client = _make_web_client(wv)
@@ -1896,19 +1908,19 @@ class WebViewHandler(AndroidViewHandler):
1896
1908
  try:
1897
1909
  wv.setWebViewClient(client)
1898
1910
  except Exception:
1899
- pass
1911
+ diagnostics.swallowed("android.WebViewHandler._apply")
1900
1912
 
1901
1913
  # ``html`` takes precedence over ``url`` when both are present.
1902
1914
  if "html" in props and props["html"]:
1903
1915
  try:
1904
1916
  wv.loadDataWithBaseURL(None, str(props["html"]), "text/html", "utf-8", None)
1905
1917
  except Exception:
1906
- pass
1918
+ diagnostics.swallowed("android.WebViewHandler._apply")
1907
1919
  elif "url" in props and props["url"]:
1908
1920
  try:
1909
1921
  wv.loadUrl(str(props["url"]))
1910
1922
  except Exception:
1911
- pass
1923
+ diagnostics.swallowed("android.WebViewHandler._apply")
1912
1924
 
1913
1925
  if "scroll_enabled" in props:
1914
1926
  self._apply_scroll_enabled(wv, props["scroll_enabled"])
@@ -1925,7 +1937,7 @@ class WebViewHandler(AndroidViewHandler):
1925
1937
  else:
1926
1938
  wv.setOnTouchListener(None)
1927
1939
  except Exception:
1928
- pass
1940
+ diagnostics.swallowed("android.WebViewHandler._apply_scroll_enabled")
1929
1941
 
1930
1942
 
1931
1943
  class SpacerHandler(AndroidViewHandler):
@@ -1990,7 +2002,7 @@ class ModalHandler(AndroidViewHandler):
1990
2002
  try:
1991
2003
  dialog.setCanceledOnTouchOutside(props["dismiss_on_backdrop"] is not False)
1992
2004
  except Exception:
1993
- pass
2005
+ diagnostics.swallowed("android.ModalHandler._apply")
1994
2006
 
1995
2007
  def insert_child(self, parent: Any, child: Any, index: int) -> None:
1996
2008
  state = _state_of(parent)
@@ -2007,7 +2019,7 @@ class ModalHandler(AndroidViewHandler):
2007
2019
  try:
2008
2020
  content.removeView(child)
2009
2021
  except Exception:
2010
- pass
2022
+ diagnostics.swallowed("android.ModalHandler.remove_child")
2011
2023
  else:
2012
2024
  buf = state.get("pending")
2013
2025
  if buf and child in buf:
@@ -2052,18 +2064,18 @@ class ModalHandler(AndroidViewHandler):
2052
2064
  WMLP = jclass("android.view.WindowManager$LayoutParams")
2053
2065
  window.setLayout(WMLP.MATCH_PARENT, WMLP.MATCH_PARENT)
2054
2066
  except Exception:
2055
- pass
2067
+ diagnostics.swallowed("android.ModalHandler._present")
2056
2068
  try:
2057
2069
  dialog.setCanceledOnTouchOutside(props.get("dismiss_on_backdrop") is not False)
2058
2070
  except Exception:
2059
- pass
2071
+ diagnostics.swallowed("android.ModalHandler._present")
2060
2072
  state["dialog"] = dialog
2061
2073
  state["content_view"] = content
2062
2074
  for child in state.pop("pending", []):
2063
2075
  try:
2064
2076
  content.addView(child)
2065
2077
  except Exception:
2066
- pass
2078
+ diagnostics.swallowed("android.ModalHandler._present")
2067
2079
 
2068
2080
  OnShowListener = jclass("android.content.DialogInterface$OnShowListener")
2069
2081
 
@@ -2082,7 +2094,7 @@ class ModalHandler(AndroidViewHandler):
2082
2094
  dialog.setOnDismissListener(_DismissProxy())
2083
2095
  dialog.show()
2084
2096
  except Exception:
2085
- pass
2097
+ diagnostics.swallowed("android.ModalHandler._present")
2086
2098
 
2087
2099
  def _dismiss(self, placeholder: Any, state: Dict[str, Any]) -> None:
2088
2100
  dialog = state.pop("dialog", None)
@@ -2091,7 +2103,7 @@ class ModalHandler(AndroidViewHandler):
2091
2103
  try:
2092
2104
  dialog.dismiss()
2093
2105
  except Exception:
2094
- pass
2106
+ diagnostics.swallowed("android.ModalHandler._dismiss")
2095
2107
 
2096
2108
 
2097
2109
  # ======================================================================
@@ -2143,7 +2155,7 @@ class PortalHandler(AndroidViewHandler):
2143
2155
  lp = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
2144
2156
  container.addView(overlay, lp)
2145
2157
  except Exception:
2146
- pass
2158
+ diagnostics.swallowed("android.PortalHandler._ensure_attached")
2147
2159
 
2148
2160
  def insert_child(self, parent: Any, child: Any, index: int) -> None:
2149
2161
  self._ensure_attached(parent)
@@ -2153,7 +2165,7 @@ class PortalHandler(AndroidViewHandler):
2153
2165
  try:
2154
2166
  parent.removeView(child)
2155
2167
  except Exception:
2156
- pass
2168
+ diagnostics.swallowed("android.PortalHandler.remove_child")
2157
2169
 
2158
2170
  def set_frame(self, native_view: Any, x: float, y: float, width: float, height: float) -> None:
2159
2171
  # The overlay fills its container via MATCH_PARENT layout params;
@@ -2166,7 +2178,7 @@ class PortalHandler(AndroidViewHandler):
2166
2178
  if parent is not None:
2167
2179
  parent.removeView(overlay)
2168
2180
  except Exception:
2169
- pass
2181
+ diagnostics.swallowed("android.PortalHandler._teardown")
2170
2182
 
2171
2183
 
2172
2184
  class SliderHandler(AndroidViewHandler):
@@ -2220,7 +2232,7 @@ class TabBarHandler(AndroidViewHandler):
2220
2232
  try:
2221
2233
  bnv.setLabelVisibilityMode(self._LABEL_VISIBILITY_LABELED)
2222
2234
  except Exception:
2223
- pass
2235
+ diagnostics.swallowed("android.TabBarHandler._build")
2224
2236
  return bnv
2225
2237
  except Exception:
2226
2238
  LinearLayout = jclass("android.widget.LinearLayout")
@@ -2270,7 +2282,7 @@ class TabBarHandler(AndroidViewHandler):
2270
2282
 
2271
2283
  bnv.setOnItemSelectedListener(_TabSelectProxy())
2272
2284
  except Exception:
2273
- pass
2285
+ diagnostics.swallowed("android.TabBarHandler._bind_material_listener")
2274
2286
 
2275
2287
  def _set_menu(self, bnv: Any, items: list) -> None:
2276
2288
  try:
@@ -2284,9 +2296,9 @@ class TabBarHandler(AndroidViewHandler):
2284
2296
  try:
2285
2297
  menu_item.setIcon(res_id)
2286
2298
  except Exception:
2287
- pass
2299
+ diagnostics.swallowed("android.TabBarHandler._set_menu")
2288
2300
  except Exception:
2289
- pass
2301
+ diagnostics.swallowed("android.TabBarHandler._set_menu")
2290
2302
 
2291
2303
  def _resolve_icon(self, icon: Any) -> int:
2292
2304
  """Resolve a tab icon spec to an `android.R.drawable.*` res id.
@@ -2320,7 +2332,7 @@ class TabBarHandler(AndroidViewHandler):
2320
2332
  try:
2321
2333
  bnv.setSelectedItemId(i)
2322
2334
  except Exception:
2323
- pass
2335
+ diagnostics.swallowed("android.TabBarHandler._set_active")
2324
2336
  break
2325
2337
 
2326
2338
  def _apply_fallback(self, ll: Any, props: Dict[str, Any]) -> None:
@@ -2420,7 +2432,9 @@ class PressableHandler(FlexContainerHandler):
2420
2432
  try:
2421
2433
  view.animate().alpha(opacity).setDuration(50).start()
2422
2434
  except Exception:
2423
- pass
2435
+ diagnostics.swallowed(
2436
+ "android.PressableHandler._bind_press_stream._PressTouchProxy.onTouch"
2437
+ )
2424
2438
  if _has_event(view, "on_long_press"):
2425
2439
  seq = press["seq"]
2426
2440
 
@@ -2451,7 +2465,9 @@ class PressableHandler(FlexContainerHandler):
2451
2465
  try:
2452
2466
  view.animate().alpha(1.0).setDuration(100).start()
2453
2467
  except Exception:
2454
- pass
2468
+ diagnostics.swallowed(
2469
+ "android.PressableHandler._bind_press_stream._PressTouchProxy.onTouch"
2470
+ )
2455
2471
  if action == 1 and not press["moved"] and not press["long_fired"]:
2456
2472
  _fire(view, "on_press")
2457
2473
  return True
@@ -2459,7 +2475,7 @@ class PressableHandler(FlexContainerHandler):
2459
2475
 
2460
2476
  fl.setOnTouchListener(_PressTouchProxy())
2461
2477
  except Exception:
2462
- pass
2478
+ diagnostics.swallowed("android.PressableHandler._bind_press_stream")
2463
2479
 
2464
2480
 
2465
2481
  # ======================================================================
@@ -2486,20 +2502,29 @@ class StatusBarHandler(AndroidViewHandler):
2486
2502
  return
2487
2503
  if "background_color" in props and props["background_color"] is not None:
2488
2504
  window.setStatusBarColor(parse_color_int(props["background_color"]))
2505
+ View = jclass("android.view.View")
2506
+ decor = window.getDecorView()
2489
2507
  if "bar_style" in props and props["bar_style"] is not None:
2490
2508
  # API 23+: setSystemUiVisibility with SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
2491
2509
  # for dark-content (light backgrounds), 0 for light-content.
2492
- View = jclass("android.view.View")
2493
2510
  bar_style = props["bar_style"]
2494
- decor = window.getDecorView()
2495
2511
  flags = decor.getSystemUiVisibility()
2496
2512
  if bar_style in ("dark", "default"):
2497
2513
  flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
2498
2514
  else:
2499
2515
  flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
2500
2516
  decor.setSystemUiVisibility(flags)
2501
- except Exception:
2502
- pass
2517
+ if "hidden" in props and props["hidden"] is not None:
2518
+ flags = decor.getSystemUiVisibility()
2519
+ if props["hidden"]:
2520
+ flags |= View.SYSTEM_UI_FLAG_FULLSCREEN
2521
+ else:
2522
+ flags &= ~View.SYSTEM_UI_FLAG_FULLSCREEN
2523
+ decor.setSystemUiVisibility(flags)
2524
+ except Exception as exc:
2525
+ from .. import diagnostics
2526
+
2527
+ diagnostics.warn_once(f"StatusBar: could not apply props on Android: {exc!r}")
2503
2528
 
2504
2529
 
2505
2530
  class KeyboardAvoidingViewHandler(FlexContainerHandler):
@@ -2547,7 +2572,7 @@ def _present_alert(
2547
2572
  try:
2548
2573
  on_result(index)
2549
2574
  except Exception:
2550
- pass
2575
+ diagnostics.swallowed("android._present_alert._deliver")
2551
2576
 
2552
2577
  def _present_on_main() -> None:
2553
2578
  try:
@@ -2733,7 +2758,7 @@ class CheckboxHandler(AndroidViewHandler):
2733
2758
  ColorStateList = jclass("android.content.res.ColorStateList")
2734
2759
  cb.setButtonTintList(ColorStateList.valueOf(parse_color_int(props["color"])))
2735
2760
  except Exception:
2736
- pass
2761
+ diagnostics.swallowed("android.CheckboxHandler._apply")
2737
2762
  _apply_accessibility(cb, props)
2738
2763
 
2739
2764
 
@@ -2793,7 +2818,7 @@ class SegmentedControlHandler(AndroidViewHandler):
2793
2818
  try:
2794
2819
  ll.removeAllViews()
2795
2820
  except Exception:
2796
- pass
2821
+ diagnostics.swallowed("android.SegmentedControlHandler._rebuild")
2797
2822
  state["buttons"] = []
2798
2823
  LL_LP = jclass("android.widget.LinearLayout$LayoutParams")
2799
2824
  restyle = self._restyle
@@ -2803,7 +2828,7 @@ class SegmentedControlHandler(AndroidViewHandler):
2803
2828
  try:
2804
2829
  btn.setAllCaps(False)
2805
2830
  except Exception:
2806
- pass
2831
+ diagnostics.swallowed("android.SegmentedControlHandler._rebuild")
2807
2832
  # Equal-width segments: zero base width + weight 1, full height.
2808
2833
  btn.setLayoutParams(LL_LP(0, LL_LP.MATCH_PARENT, 1.0))
2809
2834
  enabled = (state.get("props") or {}).get("enabled") is not False
@@ -2851,7 +2876,7 @@ class SegmentedControlHandler(AndroidViewHandler):
2851
2876
  btn.setBackground(drawable)
2852
2877
  btn.setEnabled(enabled)
2853
2878
  except Exception:
2854
- pass
2879
+ diagnostics.swallowed("android.SegmentedControlHandler._style_segment")
2855
2880
 
2856
2881
  def measure_intrinsic(
2857
2882
  self,
@@ -2906,7 +2931,7 @@ class DatePickerHandler(AndroidViewHandler):
2906
2931
  try:
2907
2932
  btn.setAllCaps(False)
2908
2933
  except Exception:
2909
- pass
2934
+ diagnostics.swallowed("android.DatePickerHandler._build")
2910
2935
  open_dialog = self._open_dialog
2911
2936
 
2912
2937
  class _DateTriggerProxy(dynamic_proxy(jclass("android.view.View").OnClickListener)):
@@ -3016,7 +3041,7 @@ class DatePickerHandler(AndroidViewHandler):
3016
3041
  if maximum:
3017
3042
  picker.setMaxDate(self._parse_to_calendar(maximum, mode).getTimeInMillis())
3018
3043
  except Exception:
3019
- pass
3044
+ diagnostics.swallowed("android.DatePickerHandler._apply_min_max")
3020
3045
 
3021
3046
  def _parse_to_calendar(self, value: Any, mode: str) -> Any:
3022
3047
  Calendar = jclass("java.util.Calendar")
@@ -3028,7 +3053,7 @@ class DatePickerHandler(AndroidViewHandler):
3028
3053
  fmt = SimpleDateFormat(self._PATTERNS.get(mode, self._PATTERNS["date"]), Locale.US)
3029
3054
  cal.setTime(fmt.parse(str(value)))
3030
3055
  except Exception:
3031
- pass
3056
+ diagnostics.swallowed("android.DatePickerHandler._parse_to_calendar")
3032
3057
  return cal
3033
3058
 
3034
3059
  def _format_calendar(self, cal: Any, mode: str) -> str:
@@ -3048,7 +3073,7 @@ class DatePickerHandler(AndroidViewHandler):
3048
3073
  try:
3049
3074
  btn.setText(iso)
3050
3075
  except Exception:
3051
- pass
3076
+ diagnostics.swallowed("android.DatePickerHandler._commit")
3052
3077
  _fire(btn, "on_change", iso)
3053
3078
 
3054
3079
 
@@ -3148,7 +3173,7 @@ class VirtualListHandler(AndroidViewHandler):
3148
3173
  try:
3149
3174
  info["pool"].release(_java_id(container))
3150
3175
  except Exception:
3151
- pass
3176
+ diagnostics.swallowed("android.VirtualListHandler._build._Delegate.onRowRecycled")
3152
3177
 
3153
3178
  def onScrolled(self, offset_dp: float, extent_dp: float, range_dp: float) -> None:
3154
3179
  view = info.get("view")
@@ -3197,12 +3222,12 @@ class VirtualListHandler(AndroidViewHandler):
3197
3222
  try:
3198
3223
  view.setVerticalScrollBarEnabled(show)
3199
3224
  except Exception:
3200
- pass
3225
+ diagnostics.swallowed("android.VirtualListHandler._apply")
3201
3226
  if data_changed and not initial:
3202
3227
  try:
3203
3228
  view.notifyDataChanged()
3204
3229
  except Exception:
3205
- pass
3230
+ diagnostics.swallowed("android.VirtualListHandler._apply")
3206
3231
 
3207
3232
  def _teardown(self, native_view: Any) -> None:
3208
3233
  info = _pn_vlist_info.pop(_java_id(native_view), None)
@@ -3233,7 +3258,7 @@ class VirtualListHandler(AndroidViewHandler):
3233
3258
  args.get("animated", True) is not False,
3234
3259
  )
3235
3260
  except Exception:
3236
- pass
3261
+ diagnostics.swallowed("android.VirtualListHandler.command")
3237
3262
  return None
3238
3263
  if name == "scroll_to_index":
3239
3264
  try:
@@ -3242,7 +3267,7 @@ class VirtualListHandler(AndroidViewHandler):
3242
3267
  args.get("animated", True) is not False,
3243
3268
  )
3244
3269
  except Exception:
3245
- pass
3270
+ diagnostics.swallowed("android.VirtualListHandler.command")
3246
3271
  return None
3247
3272
  if name == "scroll_to_end":
3248
3273
  info = _pn_vlist_info.get(_java_id(native_view))
@@ -3250,7 +3275,7 @@ class VirtualListHandler(AndroidViewHandler):
3250
3275
  try:
3251
3276
  native_view.scrollToIndex(max(0, count - 1), args.get("animated", True) is not False)
3252
3277
  except Exception:
3253
- pass
3278
+ diagnostics.swallowed("android.VirtualListHandler.command")
3254
3279
  return None
3255
3280
  if name == "get_scroll_offset":
3256
3281
  try: