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.
- pythonnative/__init__.py +16 -4
- pythonnative/animated.py +2 -2
- pythonnative/cli/pn.py +172 -12
- pythonnative/components.py +59 -0
- pythonnative/diagnostics.py +27 -0
- pythonnative/hooks.py +364 -81
- pythonnative/native_modules/app_state.py +2 -1
- pythonnative/native_modules/battery.py +3 -2
- pythonnative/native_modules/biometrics.py +2 -1
- pythonnative/native_modules/camera.py +16 -7
- pythonnative/native_modules/clipboard.py +3 -2
- pythonnative/native_modules/file_system.py +3 -2
- pythonnative/native_modules/haptics.py +7 -6
- pythonnative/native_modules/linking.py +62 -6
- pythonnative/native_modules/location.py +11 -8
- pythonnative/native_modules/net_info.py +2 -1
- pythonnative/native_modules/notifications.py +132 -9
- pythonnative/native_modules/permissions.py +27 -3
- pythonnative/native_modules/share.py +2 -1
- pythonnative/native_views/android.py +149 -124
- pythonnative/native_views/desktop.py +50 -49
- pythonnative/native_views/ios.py +240 -161
- pythonnative/project/android.py +15 -3
- pythonnative/project/builder.py +172 -70
- pythonnative/project/config.py +28 -6
- pythonnative/project/devices.py +291 -0
- pythonnative/project/doctor.py +5 -4
- pythonnative/project/ios.py +51 -77
- pythonnative/project/permissions.py +19 -1
- pythonnative/project/runtime_assets.py +78 -166
- pythonnative/reconciler.py +518 -37
- pythonnative/runtime.py +407 -215
- pythonnative/screen.py +53 -7
- pythonnative/storage.py +2 -2
- pythonnative/suspense.py +417 -0
- pythonnative/templates/android_template/app/build.gradle +5 -0
- pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +1 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +88 -12
- pythonnative/templates/ios_template/ios_template/AppDelegate.swift +41 -17
- pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
- pythonnative/templates/ios_template/ios_template/Info.plist +0 -2
- pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +397 -0
- pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +31 -20
- pythonnative/templates/ios_template/ios_template/ViewController.swift +77 -198
- pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +72 -47
- {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/METADATA +2 -1
- {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/RECORD +51 -48
- {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/WHEEL +1 -1
- pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -24
- {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.24.0.dist-info → pythonnative-0.26.0.dist-info}/licenses/LICENSE +0 -0
- {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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
258
|
+
diagnostics.swallowed("android._apply_border")
|
|
258
259
|
view.setBackground(drawable)
|
|
259
260
|
try:
|
|
260
261
|
drawable.invalidateSelf()
|
|
261
262
|
except Exception:
|
|
262
|
-
|
|
263
|
+
diagnostics.swallowed("android._apply_border")
|
|
263
264
|
try:
|
|
264
265
|
view.invalidate()
|
|
265
266
|
except Exception:
|
|
266
|
-
|
|
267
|
+
diagnostics.swallowed("android._apply_border")
|
|
267
268
|
except Exception:
|
|
268
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
771
|
+
diagnostics.swallowed("android.AndroidViewHandler.set_frame")
|
|
766
772
|
native_view.setLayoutParams(lp)
|
|
767
773
|
except Exception:
|
|
768
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1254
|
+
diagnostics.swallowed(
|
|
1255
|
+
"android.ScrollViewHandler._bind_scroll_listener._ScrollChangeProxy.onScrollChange"
|
|
1256
|
+
)
|
|
1249
1257
|
|
|
1250
1258
|
sv.setOnScrollChangeListener(_ScrollChangeProxy())
|
|
1251
1259
|
except Exception:
|
|
1252
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1295
|
+
diagnostics.swallowed("android.ScrollViewHandler._apply_refresh")
|
|
1288
1296
|
return
|
|
1289
1297
|
try:
|
|
1290
1298
|
srl.setEnabled(True)
|
|
1291
1299
|
except Exception:
|
|
1292
|
-
|
|
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
|
-
|
|
1305
|
+
diagnostics.swallowed("android.ScrollViewHandler._apply_refresh")
|
|
1298
1306
|
try:
|
|
1299
1307
|
srl.setRefreshing(bool(spec.get("refreshing")))
|
|
1300
1308
|
except Exception:
|
|
1301
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2299
|
+
diagnostics.swallowed("android.TabBarHandler._set_menu")
|
|
2288
2300
|
except Exception:
|
|
2289
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2502
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3278
|
+
diagnostics.swallowed("android.VirtualListHandler.command")
|
|
3254
3279
|
return None
|
|
3255
3280
|
if name == "get_scroll_offset":
|
|
3256
3281
|
try:
|