pythonnative 0.10.0__tar.gz → 0.12.0__tar.gz
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-0.10.0/src/pythonnative.egg-info → pythonnative-0.12.0}/PKG-INFO +2 -1
- {pythonnative-0.10.0 → pythonnative-0.12.0}/README.md +1 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/pyproject.toml +2 -1
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/__init__.py +35 -1
- pythonnative-0.12.0/src/pythonnative/alerts.py +112 -0
- pythonnative-0.12.0/src/pythonnative/animated.py +667 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/cli/pn.py +85 -11
- pythonnative-0.12.0/src/pythonnative/components.py +1215 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/hooks.py +145 -7
- pythonnative-0.12.0/src/pythonnative/layout.py +949 -0
- pythonnative-0.12.0/src/pythonnative/native_modules/camera.py +331 -0
- pythonnative-0.12.0/src/pythonnative/native_modules/location.py +245 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/native_views/__init__.py +39 -3
- pythonnative-0.12.0/src/pythonnative/native_views/android.py +1602 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/native_views/base.py +87 -42
- pythonnative-0.12.0/src/pythonnative/native_views/ios.py +2497 -0
- pythonnative-0.12.0/src/pythonnative/page.py +1193 -0
- pythonnative-0.12.0/src/pythonnative/platform.py +152 -0
- pythonnative-0.12.0/src/pythonnative/platform_metrics.py +249 -0
- pythonnative-0.12.0/src/pythonnative/reconciler.py +868 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/build.gradle +1 -0
- pythonnative-0.12.0/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNVirtualListView.java +129 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/ViewController.swift +44 -3
- {pythonnative-0.10.0 → pythonnative-0.12.0/src/pythonnative.egg-info}/PKG-INFO +2 -1
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative.egg-info/SOURCES.txt +14 -0
- pythonnative-0.12.0/tests/test_alert.py +68 -0
- pythonnative-0.12.0/tests/test_animated.py +168 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_cli.py +54 -0
- pythonnative-0.12.0/tests/test_layout.py +773 -0
- pythonnative-0.12.0/tests/test_metric_hooks.py +167 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_native_views.py +65 -27
- pythonnative-0.12.0/tests/test_new_components.py +185 -0
- pythonnative-0.12.0/tests/test_page.py +189 -0
- pythonnative-0.12.0/tests/test_platform.py +63 -0
- pythonnative-0.12.0/tests/test_platform_metrics.py +119 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_reconciler.py +285 -1
- pythonnative-0.12.0/tests/test_ref.py +130 -0
- pythonnative-0.10.0/src/pythonnative/components.py +0 -649
- pythonnative-0.10.0/src/pythonnative/native_modules/camera.py +0 -121
- pythonnative-0.10.0/src/pythonnative/native_modules/location.py +0 -84
- pythonnative-0.10.0/src/pythonnative/native_views/android.py +0 -839
- pythonnative-0.10.0/src/pythonnative/native_views/ios.py +0 -784
- pythonnative-0.10.0/src/pythonnative/page.py +0 -680
- pythonnative-0.10.0/src/pythonnative/reconciler.py +0 -384
- pythonnative-0.10.0/tests/test_page.py +0 -68
- {pythonnative-0.10.0 → pythonnative-0.12.0}/LICENSE +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/setup.cfg +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/_ios_log.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/cli/__init__.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/element.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/hot_reload.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/native_modules/__init__.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/native_modules/file_system.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/native_modules/notifications.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/navigation.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/style.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/proguard-rules.pro +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/Navigator.kt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PageFragment.kt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/values/colors.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/values/strings.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/values/themes.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/build.gradle +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/gradle.properties +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/gradlew +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/gradlew.bat +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/android_template/settings.gradle +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/AppDelegate.swift +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/Info.plist +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative/utils.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative.egg-info/dependency_links.txt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative.egg-info/entry_points.txt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative.egg-info/requires.txt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/src/pythonnative.egg-info/top_level.txt +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_components.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_element.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_hooks.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_hot_reload.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_ios_log.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_navigation.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_smoke.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_style.py +0 -0
- {pythonnative-0.10.0 → pythonnative-0.12.0}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonnative
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
4
4
|
Summary: Cross-platform native UI toolkit for Android and iOS
|
|
5
5
|
Author: Owen Carey
|
|
6
6
|
License: MIT License
|
|
@@ -97,6 +97,7 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
|
|
|
97
97
|
- **Declarative UI:** Describe *what* your UI should look like with element functions (`Text`, `Button`, `Column`, `Row`, etc.). PythonNative creates and updates native views automatically.
|
|
98
98
|
- **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect`, and navigation with `use_navigation`, all through one consistent pattern.
|
|
99
99
|
- **`style` prop:** Pass all visual and layout properties through a single `style` dict, composable via `StyleSheet`.
|
|
100
|
+
- **Cross-platform flexbox engine:** A pure-Python, Yoga-style layout engine computes frames once and applies them to native views, so `flex`, `padding`, `aspect_ratio`, and `position: "absolute"` produce the same geometry on Android and iOS.
|
|
100
101
|
- **Virtual view tree + reconciler:** Element trees are diffed and patched with minimal native mutations, similar to React's reconciliation.
|
|
101
102
|
- **Direct native bindings:** Python calls platform APIs directly through Chaquopy and rubicon-objc, with no JavaScript bridge.
|
|
102
103
|
- **CLI scaffolding:** `pn init` creates a ready-to-run project; `pn run android` and `pn run ios` build and launch your app.
|
|
@@ -33,6 +33,7 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
|
|
|
33
33
|
- **Declarative UI:** Describe *what* your UI should look like with element functions (`Text`, `Button`, `Column`, `Row`, etc.). PythonNative creates and updates native views automatically.
|
|
34
34
|
- **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect`, and navigation with `use_navigation`, all through one consistent pattern.
|
|
35
35
|
- **`style` prop:** Pass all visual and layout properties through a single `style` dict, composable via `StyleSheet`.
|
|
36
|
+
- **Cross-platform flexbox engine:** A pure-Python, Yoga-style layout engine computes frames once and applies them to native views, so `flex`, `padding`, `aspect_ratio`, and `position: "absolute"` produce the same geometry on Android and iOS.
|
|
36
37
|
- **Virtual view tree + reconciler:** Element trees are diffed and patched with minimal native mutations, similar to React's reconciliation.
|
|
37
38
|
- **Direct native bindings:** Python calls platform APIs directly through Chaquopy and rubicon-objc, with no JavaScript bridge.
|
|
38
39
|
- **CLI scaffolding:** `pn init` creates a ready-to-run project; `pn run android` and `pn run ios` build and launch your app.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pythonnative"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.12.0"
|
|
8
8
|
description = "Cross-platform native UI toolkit for Android and iOS"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Owen Carey" }
|
|
@@ -60,6 +60,7 @@ Repository = "https://github.com/pythonnative/pythonnative"
|
|
|
60
60
|
Issues = "https://github.com/pythonnative/pythonnative/issues"
|
|
61
61
|
Documentation = "https://docs.pythonnative.com/"
|
|
62
62
|
|
|
63
|
+
|
|
63
64
|
[tool.setuptools.packages.find]
|
|
64
65
|
where = ["src"]
|
|
65
66
|
|
|
@@ -23,6 +23,8 @@ Key building blocks:
|
|
|
23
23
|
factories.
|
|
24
24
|
- **Styling** uses a single ``style`` dict per element (or a list of
|
|
25
25
|
dicts), composable via [`StyleSheet`][pythonnative.StyleSheet].
|
|
26
|
+
- **Animations** use the ``Animated`` namespace, modeled on React
|
|
27
|
+
Native's animation API.
|
|
26
28
|
|
|
27
29
|
Example:
|
|
28
30
|
```python
|
|
@@ -39,8 +41,10 @@ Example:
|
|
|
39
41
|
```
|
|
40
42
|
"""
|
|
41
43
|
|
|
42
|
-
__version__ = "0.
|
|
44
|
+
__version__ = "0.12.0"
|
|
43
45
|
|
|
46
|
+
from .alerts import Alert
|
|
47
|
+
from .animated import Animated, AnimatedValue
|
|
44
48
|
from .components import (
|
|
45
49
|
ActivityIndicator,
|
|
46
50
|
Button,
|
|
@@ -48,14 +52,19 @@ from .components import (
|
|
|
48
52
|
ErrorBoundary,
|
|
49
53
|
FlatList,
|
|
50
54
|
Image,
|
|
55
|
+
KeyboardAvoidingView,
|
|
51
56
|
Modal,
|
|
57
|
+
Picker,
|
|
52
58
|
Pressable,
|
|
53
59
|
ProgressBar,
|
|
60
|
+
RefreshControl,
|
|
54
61
|
Row,
|
|
55
62
|
SafeAreaView,
|
|
56
63
|
ScrollView,
|
|
64
|
+
SectionList,
|
|
57
65
|
Slider,
|
|
58
66
|
Spacer,
|
|
67
|
+
StatusBar,
|
|
59
68
|
Switch,
|
|
60
69
|
Text,
|
|
61
70
|
TextInput,
|
|
@@ -71,12 +80,16 @@ from .hooks import (
|
|
|
71
80
|
use_callback,
|
|
72
81
|
use_context,
|
|
73
82
|
use_effect,
|
|
83
|
+
use_keyboard_height,
|
|
74
84
|
use_memo,
|
|
75
85
|
use_navigation,
|
|
76
86
|
use_reducer,
|
|
77
87
|
use_ref,
|
|
88
|
+
use_safe_area_insets,
|
|
78
89
|
use_state,
|
|
90
|
+
use_window_dimensions,
|
|
79
91
|
)
|
|
92
|
+
from .native_modules import Camera, FileSystem, Location, Notifications
|
|
80
93
|
from .navigation import (
|
|
81
94
|
NavigationContainer,
|
|
82
95
|
create_drawer_navigator,
|
|
@@ -86,6 +99,7 @@ from .navigation import (
|
|
|
86
99
|
use_route,
|
|
87
100
|
)
|
|
88
101
|
from .page import create_page
|
|
102
|
+
from .platform import Platform
|
|
89
103
|
from .style import StyleSheet, ThemeContext
|
|
90
104
|
|
|
91
105
|
__all__ = [
|
|
@@ -96,14 +110,19 @@ __all__ = [
|
|
|
96
110
|
"ErrorBoundary",
|
|
97
111
|
"FlatList",
|
|
98
112
|
"Image",
|
|
113
|
+
"KeyboardAvoidingView",
|
|
99
114
|
"Modal",
|
|
115
|
+
"Picker",
|
|
100
116
|
"Pressable",
|
|
101
117
|
"ProgressBar",
|
|
118
|
+
"RefreshControl",
|
|
102
119
|
"Row",
|
|
103
120
|
"SafeAreaView",
|
|
104
121
|
"ScrollView",
|
|
122
|
+
"SectionList",
|
|
105
123
|
"Slider",
|
|
106
124
|
"Spacer",
|
|
125
|
+
"StatusBar",
|
|
107
126
|
"Switch",
|
|
108
127
|
"Text",
|
|
109
128
|
"TextInput",
|
|
@@ -120,12 +139,15 @@ __all__ = [
|
|
|
120
139
|
"use_context",
|
|
121
140
|
"use_effect",
|
|
122
141
|
"use_focus_effect",
|
|
142
|
+
"use_keyboard_height",
|
|
123
143
|
"use_memo",
|
|
124
144
|
"use_navigation",
|
|
125
145
|
"use_reducer",
|
|
126
146
|
"use_ref",
|
|
127
147
|
"use_route",
|
|
148
|
+
"use_safe_area_insets",
|
|
128
149
|
"use_state",
|
|
150
|
+
"use_window_dimensions",
|
|
129
151
|
"Provider",
|
|
130
152
|
# Navigation
|
|
131
153
|
"NavigationContainer",
|
|
@@ -135,4 +157,16 @@ __all__ = [
|
|
|
135
157
|
# Styling
|
|
136
158
|
"StyleSheet",
|
|
137
159
|
"ThemeContext",
|
|
160
|
+
# Animation
|
|
161
|
+
"Animated",
|
|
162
|
+
"AnimatedValue",
|
|
163
|
+
# Imperative
|
|
164
|
+
"Alert",
|
|
165
|
+
# Native modules
|
|
166
|
+
"Camera",
|
|
167
|
+
"FileSystem",
|
|
168
|
+
"Location",
|
|
169
|
+
"Notifications",
|
|
170
|
+
# Platform
|
|
171
|
+
"Platform",
|
|
138
172
|
]
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Imperative system alerts.
|
|
2
|
+
|
|
3
|
+
Modeled on React Native's `Alert.alert()`. Alerts are not part of
|
|
4
|
+
the element tree — they're imperative, fire-and-forget calls that
|
|
5
|
+
trigger a native dialog.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
```python
|
|
9
|
+
import pythonnative as pn
|
|
10
|
+
|
|
11
|
+
def confirm_delete():
|
|
12
|
+
pn.Alert.show(
|
|
13
|
+
title="Delete item?",
|
|
14
|
+
message="This action cannot be undone.",
|
|
15
|
+
buttons=[
|
|
16
|
+
{"label": "Cancel", "style": "cancel"},
|
|
17
|
+
{
|
|
18
|
+
"label": "Delete",
|
|
19
|
+
"style": "destructive",
|
|
20
|
+
"on_press": delete_item,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
)
|
|
24
|
+
```
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
30
|
+
|
|
31
|
+
from .platform import Platform
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Alert:
|
|
35
|
+
"""Imperative alert / action-sheet helper.
|
|
36
|
+
|
|
37
|
+
All methods are static. Use `Alert.show()` for an alert dialog
|
|
38
|
+
and pass ``style="action_sheet"`` for an iOS-style action sheet.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def show(
|
|
43
|
+
*,
|
|
44
|
+
title: str,
|
|
45
|
+
message: Optional[str] = None,
|
|
46
|
+
buttons: Optional[List[Dict[str, Any]]] = None,
|
|
47
|
+
style: str = "alert",
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Present a native alert dialog or action sheet.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
title: Dialog title (required).
|
|
53
|
+
message: Optional body text.
|
|
54
|
+
buttons: Each button is ``{"label": str, "style":
|
|
55
|
+
"default"|"cancel"|"destructive", "on_press": callable}``.
|
|
56
|
+
Defaults to a single "OK" button.
|
|
57
|
+
style: ``"alert"`` (default) or ``"action_sheet"``.
|
|
58
|
+
|
|
59
|
+
On iOS this uses ``UIAlertController``; on Android it uses
|
|
60
|
+
``AlertDialog.Builder``. On the test backend the call is a
|
|
61
|
+
no-op so unit tests don't need to mock UIKit/AndroidX.
|
|
62
|
+
"""
|
|
63
|
+
if Platform.is_ios:
|
|
64
|
+
try:
|
|
65
|
+
from .native_views.ios import _present_alert as _ios_present_alert
|
|
66
|
+
|
|
67
|
+
_ios_present_alert(title=title, message=message, buttons=buttons or [], style=style)
|
|
68
|
+
except Exception:
|
|
69
|
+
pass
|
|
70
|
+
return
|
|
71
|
+
if Platform.is_android:
|
|
72
|
+
try:
|
|
73
|
+
from .native_views.android import _present_alert as _android_present_alert
|
|
74
|
+
|
|
75
|
+
_android_present_alert(title=title, message=message, buttons=buttons or [], style=style)
|
|
76
|
+
except Exception:
|
|
77
|
+
pass
|
|
78
|
+
return
|
|
79
|
+
# Test environment: record the call so unit tests can assert on it.
|
|
80
|
+
Alert._test_log.append(
|
|
81
|
+
{
|
|
82
|
+
"title": title,
|
|
83
|
+
"message": message,
|
|
84
|
+
"buttons": list(buttons or []),
|
|
85
|
+
"style": style,
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def confirm(
|
|
91
|
+
*,
|
|
92
|
+
title: str,
|
|
93
|
+
message: Optional[str] = None,
|
|
94
|
+
confirm_label: str = "OK",
|
|
95
|
+
cancel_label: str = "Cancel",
|
|
96
|
+
on_confirm: Optional[Callable[[], None]] = None,
|
|
97
|
+
on_cancel: Optional[Callable[[], None]] = None,
|
|
98
|
+
) -> None:
|
|
99
|
+
"""Convenience wrapper for two-button confirm/cancel dialogs."""
|
|
100
|
+
Alert.show(
|
|
101
|
+
title=title,
|
|
102
|
+
message=message,
|
|
103
|
+
buttons=[
|
|
104
|
+
{"label": cancel_label, "style": "cancel", "on_press": on_cancel},
|
|
105
|
+
{"label": confirm_label, "style": "default", "on_press": on_confirm},
|
|
106
|
+
],
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
#: Records every Alert.show call when running off-device. Tests
|
|
110
|
+
#: should reset this list between cases via
|
|
111
|
+
#: ``Alert._test_log.clear()``.
|
|
112
|
+
_test_log: List[Dict[str, Any]] = []
|