pythonnative 0.40.0__cp313-cp313-win_amd64.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 +411 -0
- pythonnative/_ios_log.py +92 -0
- pythonnative/_yoga.cp313-win_amd64.pyd +0 -0
- pythonnative/alerts.py +236 -0
- pythonnative/animated.py +1687 -0
- pythonnative/animation_graph.py +78 -0
- pythonnative/appearance.py +124 -0
- pythonnative/bootstrap.py +100 -0
- pythonnative/bridge/__init__.py +302 -0
- pythonnative/bridge/android.py +78 -0
- pythonnative/bridge/codec.py +170 -0
- pythonnative/bridge/commits.py +114 -0
- pythonnative/bridge/fake.py +243 -0
- pythonnative/bridge/ios.py +138 -0
- pythonnative/bridge/web.py +489 -0
- pythonnative/cli/__init__.py +7 -0
- pythonnative/cli/pn.py +1214 -0
- pythonnative/component.py +271 -0
- pythonnative/components/__init__.py +111 -0
- pythonnative/components/_base.py +166 -0
- pythonnative/components/controls.py +521 -0
- pythonnative/components/layout.py +518 -0
- pythonnative/components/lists.py +785 -0
- pythonnative/components/media.py +204 -0
- pythonnative/components/overlays.py +107 -0
- pythonnative/components/pressable.py +252 -0
- pythonnative/components/structural.py +167 -0
- pythonnative/components/text.py +291 -0
- pythonnative/devclient.py +824 -0
- pythonnative/devserver/__init__.py +34 -0
- pythonnative/devserver/server.py +718 -0
- pythonnative/devserver/static/animation_graph.js +82 -0
- pythonnative/devserver/static/bridge.js +147 -0
- pythonnative/devserver/static/colors.js +70 -0
- pythonnative/devserver/static/host.js +552 -0
- pythonnative/devserver/static/index.html +60 -0
- pythonnative/devserver/static/layout.js +85 -0
- pythonnative/devserver/static/preview.css +415 -0
- pythonnative/devserver/static/renderer.js +1994 -0
- pythonnative/devserver/static/shell.js +345 -0
- pythonnative/devserver/static/yoga/LICENSE +21 -0
- pythonnative/devserver/static/yoga/binaries/yoga-wasm-base64-esm.js +75 -0
- pythonnative/devserver/static/yoga/src/generated/YGEnums.d.ts +189 -0
- pythonnative/devserver/static/yoga/src/generated/YGEnums.js +211 -0
- pythonnative/devserver/static/yoga/src/generated/YGEnums.js.map +1 -0
- pythonnative/devserver/static/yoga/src/index.d.ts +12 -0
- pythonnative/devserver/static/yoga/src/index.js +16 -0
- pythonnative/devserver/static/yoga/src/index.js.map +1 -0
- pythonnative/devserver/static/yoga/src/load.d.ts +11 -0
- pythonnative/devserver/static/yoga/src/load.js +17 -0
- pythonnative/devserver/static/yoga/src/load.js.map +1 -0
- pythonnative/devserver/static/yoga/src/wrapAssembly.d.ts +155 -0
- pythonnative/devserver/static/yoga/src/wrapAssembly.js +125 -0
- pythonnative/devserver/static/yoga/src/wrapAssembly.js.map +1 -0
- pythonnative/devserver/watcher.py +267 -0
- pythonnative/devserver/ws.py +421 -0
- pythonnative/diagnostics.py +241 -0
- pythonnative/element.py +159 -0
- pythonnative/equality.py +19 -0
- pythonnative/events.py +231 -0
- pythonnative/gestures.py +1333 -0
- pythonnative/hooks.py +1621 -0
- pythonnative/hosts/__init__.py +63 -0
- pythonnative/hosts/base.py +596 -0
- pythonnative/hosts/native.py +302 -0
- pythonnative/hot_reload.py +585 -0
- pythonnative/layout.py +328 -0
- pythonnative/mutations.py +142 -0
- pythonnative/native/android/build.gradle +52 -0
- pythonnative/native/android/gradle.properties +3 -0
- pythonnative/native/android/settings.gradle +12 -0
- pythonnative/native/android/src/main/AndroidManifest.xml +11 -0
- pythonnative/native/android/src/main/cpp/CMakeLists.txt +9 -0
- pythonnative/native/android/src/main/cpp/yoga_jni.cpp +52 -0
- pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeModules.kt +5 -0
- pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeProps.kt +3705 -0
- pythonnative/native/android/src/main/java/com/pythonnative/generated/PNContracts.kt +129 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/PNBridge.kt +261 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/PythonHost.kt +20 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationGraph.kt +108 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationSpecs.kt +141 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/PNAnimator.kt +257 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/CommitState.kt +106 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/JsonUtil.kt +175 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/MainThread.kt +40 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNLog.kt +33 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNRegistry.kt +82 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNTransaction.kt +80 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt +117 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/ViewRegistry.kt +74 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt +37 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt +32 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt +213 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ContainerManagers.kt +69 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ControlManagers.kt +186 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/DatePickerManager.kt +123 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageLoader.kt +141 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageManager.kt +162 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ModalManager.kt +134 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PNColor.kt +201 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PickerManager.kt +86 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PortalManager.kt +55 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PressableManager.kt +122 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScreenStackManager.kt +110 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScrollViewManager.kt +214 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/SegmentedControlManager.kt +113 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/StatusBarManager.kt +52 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TabBarManager.kt +131 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextInputManager.kt +250 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextManager.kt +233 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ViewStyler.kt +355 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/VirtualListManager.kt +159 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/WebViewManager.kt +149 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureArbiter.kt +233 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureCoordinator.kt +127 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureRecognizers.kt +527 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/NativeLayout.kt +145 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/YogaNode.kt +29 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/BuiltinModules.kt +73 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/DeviceModules.kt +316 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/HostModule.kt +61 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/MediaModules.kt +200 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NativeModule.kt +158 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NotificationsModule.kt +100 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +99 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/StorageModules.kt +89 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/SystemModules.kt +178 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/plugins/GeneratedPlugins.kt +16 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/PNScreenFragment.kt +188 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/ScreenRegistry.kt +80 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNAccessibilityDelegate.kt +48 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNBorderDrawable.kt +76 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNEditText.kt +18 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNFrameLayout.kt +49 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/AnimationSpecsTest.kt +75 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/GestureArbiterTest.kt +197 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNColorTest.kt +47 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNTransactionTest.kt +78 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/PromiseTest.kt +89 -0
- pythonnative/native/ios/Package.swift +23 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimationGraph.swift +199 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimator.swift +312 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNBridge.swift +255 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNCommit.swift +104 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNRegistry.swift +142 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNTransaction.swift +166 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNViewRegistry.swift +53 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNButtonManagers.swift +207 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNColor.swift +173 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNComponentManager.swift +183 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNContainerView.swift +56 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNControlManagers.swift +281 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNImageManager.swift +222 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNOverlayManagers.swift +243 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNPressableManager.swift +114 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScreenStackManager.swift +107 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScrollViewManager.swift +197 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTabBarManager.swift +106 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextInputManager.swift +297 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextManager.swift +230 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTransform.swift +82 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewManager.swift +86 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewState.swift +87 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewStyler.swift +340 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNVirtualListManager.swift +155 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNWebViewManager.swift +124 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeModules.swift +1 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeProps.swift +3775 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Generated/PNContracts.swift +46 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Gestures/PNGestureCoordinator.swift +260 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Layout/PNLayout.swift +173 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/AlertModule.swift +92 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/HostModule.swift +80 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/LifecycleModules.swift +174 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/MediaModules.swift +177 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/PNNativeModule.swift +168 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/PermissionModules.swift +266 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/SystemModules.swift +251 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Plugins/PNPluginRegistration.swift +8 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNScreenRegistry.swift +46 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNViewController.swift +237 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNCompat.swift +46 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNJSON.swift +173 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNLog.swift +47 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNWindow.swift +51 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNAnimationGraphTests.swift +26 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNColorTests.swift +50 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNCommitTests.swift +86 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNGestureTests.swift +101 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNManagerTests.swift +126 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNModuleTests.swift +111 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNTransactionTests.swift +91 -0
- pythonnative/native/yoga/LICENSE +21 -0
- pythonnative/native/yoga/Package.swift +9 -0
- pythonnative/native/yoga/VENDORED.md +2 -0
- pythonnative/native/yoga/include/PNStyle.h +10 -0
- pythonnative/native/yoga/include/module.modulemap +5 -0
- pythonnative/native/yoga/include/yoga/YGConfig.h +158 -0
- pythonnative/native/yoga/include/yoga/YGEnums.h +142 -0
- pythonnative/native/yoga/include/yoga/YGMacros.h +99 -0
- pythonnative/native/yoga/include/yoga/YGNode.h +304 -0
- pythonnative/native/yoga/include/yoga/YGNodeLayout.h +35 -0
- pythonnative/native/yoga/include/yoga/YGNodeStyle.h +130 -0
- pythonnative/native/yoga/include/yoga/YGPixelGrid.h +29 -0
- pythonnative/native/yoga/include/yoga/YGValue.h +84 -0
- pythonnative/native/yoga/include/yoga/Yoga.h +21 -0
- pythonnative/native/yoga/python.cpp +16 -0
- pythonnative/native/yoga/style.cpp +272 -0
- pythonnative/native/yoga/yoga/CMakeLists.txt +41 -0
- pythonnative/native/yoga/yoga/YGConfig.cpp +92 -0
- pythonnative/native/yoga/yoga/YGConfig.h +158 -0
- pythonnative/native/yoga/yoga/YGEnums.cpp +262 -0
- pythonnative/native/yoga/yoga/YGEnums.h +142 -0
- pythonnative/native/yoga/yoga/YGMacros.h +99 -0
- pythonnative/native/yoga/yoga/YGNode.cpp +366 -0
- pythonnative/native/yoga/yoga/YGNode.h +304 -0
- pythonnative/native/yoga/yoga/YGNodeLayout.cpp +92 -0
- pythonnative/native/yoga/yoga/YGNodeLayout.h +35 -0
- pythonnative/native/yoga/yoga/YGNodeStyle.cpp +405 -0
- pythonnative/native/yoga/yoga/YGNodeStyle.h +130 -0
- pythonnative/native/yoga/yoga/YGPixelGrid.cpp +22 -0
- pythonnative/native/yoga/yoga/YGPixelGrid.h +29 -0
- pythonnative/native/yoga/yoga/YGValue.cpp +20 -0
- pythonnative/native/yoga/yoga/YGValue.h +84 -0
- pythonnative/native/yoga/yoga/Yoga.h +21 -0
- pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.cpp +563 -0
- pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.h +41 -0
- pythonnative/native/yoga/yoga/algorithm/Align.h +72 -0
- pythonnative/native/yoga/yoga/algorithm/Baseline.cpp +78 -0
- pythonnative/native/yoga/yoga/algorithm/Baseline.h +21 -0
- pythonnative/native/yoga/yoga/algorithm/BoundAxis.h +79 -0
- pythonnative/native/yoga/yoga/algorithm/Cache.cpp +121 -0
- pythonnative/native/yoga/yoga/algorithm/Cache.h +30 -0
- pythonnative/native/yoga/yoga/algorithm/CalculateLayout.cpp +2428 -0
- pythonnative/native/yoga/yoga/algorithm/CalculateLayout.h +38 -0
- pythonnative/native/yoga/yoga/algorithm/FlexDirection.h +120 -0
- pythonnative/native/yoga/yoga/algorithm/FlexLine.cpp +124 -0
- pythonnative/native/yoga/yoga/algorithm/FlexLine.h +75 -0
- pythonnative/native/yoga/yoga/algorithm/PixelGrid.cpp +132 -0
- pythonnative/native/yoga/yoga/algorithm/PixelGrid.h +29 -0
- pythonnative/native/yoga/yoga/algorithm/SizingMode.h +73 -0
- pythonnative/native/yoga/yoga/algorithm/TrailingPosition.h +44 -0
- pythonnative/native/yoga/yoga/config/Config.cpp +135 -0
- pythonnative/native/yoga/yoga/config/Config.h +92 -0
- pythonnative/native/yoga/yoga/debug/AssertFatal.cpp +53 -0
- pythonnative/native/yoga/yoga/debug/AssertFatal.h +29 -0
- pythonnative/native/yoga/yoga/debug/Log.cpp +107 -0
- pythonnative/native/yoga/yoga/debug/Log.h +34 -0
- pythonnative/native/yoga/yoga/enums/Align.h +47 -0
- pythonnative/native/yoga/yoga/enums/BoxSizing.h +40 -0
- pythonnative/native/yoga/yoga/enums/Dimension.h +40 -0
- pythonnative/native/yoga/yoga/enums/Direction.h +41 -0
- pythonnative/native/yoga/yoga/enums/Display.h +41 -0
- pythonnative/native/yoga/yoga/enums/Edge.h +47 -0
- pythonnative/native/yoga/yoga/enums/Errata.h +41 -0
- pythonnative/native/yoga/yoga/enums/ExperimentalFeature.h +39 -0
- pythonnative/native/yoga/yoga/enums/FlexDirection.h +42 -0
- pythonnative/native/yoga/yoga/enums/Gutter.h +41 -0
- pythonnative/native/yoga/yoga/enums/Justify.h +44 -0
- pythonnative/native/yoga/yoga/enums/LogLevel.h +44 -0
- pythonnative/native/yoga/yoga/enums/MeasureMode.h +41 -0
- pythonnative/native/yoga/yoga/enums/NodeType.h +40 -0
- pythonnative/native/yoga/yoga/enums/Overflow.h +41 -0
- pythonnative/native/yoga/yoga/enums/PhysicalEdge.h +21 -0
- pythonnative/native/yoga/yoga/enums/PositionType.h +41 -0
- pythonnative/native/yoga/yoga/enums/Unit.h +42 -0
- pythonnative/native/yoga/yoga/enums/Wrap.h +41 -0
- pythonnative/native/yoga/yoga/enums/YogaEnums.h +85 -0
- pythonnative/native/yoga/yoga/event/event.cpp +87 -0
- pythonnative/native/yoga/yoga/event/event.h +130 -0
- pythonnative/native/yoga/yoga/module.modulemap +21 -0
- pythonnative/native/yoga/yoga/node/CachedMeasurement.h +53 -0
- pythonnative/native/yoga/yoga/node/LayoutResults.cpp +48 -0
- pythonnative/native/yoga/yoga/node/LayoutResults.h +122 -0
- pythonnative/native/yoga/yoga/node/LayoutableChildren.h +148 -0
- pythonnative/native/yoga/yoga/node/Node.cpp +443 -0
- pythonnative/native/yoga/yoga/node/Node.h +337 -0
- pythonnative/native/yoga/yoga/numeric/Comparison.h +81 -0
- pythonnative/native/yoga/yoga/numeric/FloatOptional.h +93 -0
- pythonnative/native/yoga/yoga/style/SmallValueBuffer.h +133 -0
- pythonnative/native/yoga/yoga/style/Style.h +757 -0
- pythonnative/native/yoga/yoga/style/StyleLength.h +107 -0
- pythonnative/native/yoga/yoga/style/StyleValueHandle.h +98 -0
- pythonnative/native/yoga/yoga/style/StyleValuePool.h +127 -0
- pythonnative/native_modules/__init__.py +124 -0
- pythonnative/native_modules/app_state.py +99 -0
- pythonnative/native_modules/battery.py +75 -0
- pythonnative/native_modules/biometrics.py +42 -0
- pythonnative/native_modules/camera.py +65 -0
- pythonnative/native_modules/clipboard.py +46 -0
- pythonnative/native_modules/fallback.py +324 -0
- pythonnative/native_modules/file_system.py +145 -0
- pythonnative/native_modules/haptics.py +75 -0
- pythonnative/native_modules/linking.py +123 -0
- pythonnative/native_modules/location.py +75 -0
- pythonnative/native_modules/net_info.py +112 -0
- pythonnative/native_modules/notifications.py +129 -0
- pythonnative/native_modules/permissions.py +108 -0
- pythonnative/native_modules/registry.py +526 -0
- pythonnative/native_modules/secure_store.py +52 -0
- pythonnative/native_modules/share.py +51 -0
- pythonnative/native_views/__init__.py +375 -0
- pythonnative/native_views/base.py +316 -0
- pythonnative/native_views/bridge_backend.py +277 -0
- pythonnative/navigation/__init__.py +103 -0
- pythonnative/navigation/container.py +154 -0
- pythonnative/navigation/handle.py +540 -0
- pythonnative/navigation/hooks.py +133 -0
- pythonnative/navigation/host.py +58 -0
- pythonnative/navigation/linking.py +200 -0
- pythonnative/navigation/navigators.py +659 -0
- pythonnative/navigation/screen.py +149 -0
- pythonnative/navigation/state.py +269 -0
- pythonnative/net.py +248 -0
- pythonnative/platform.py +166 -0
- pythonnative/platform_metrics.py +252 -0
- pythonnative/preview.py +287 -0
- pythonnative/profiling.py +101 -0
- pythonnative/project/__init__.py +68 -0
- pythonnative/project/android.py +557 -0
- pythonnative/project/builder.py +817 -0
- pythonnative/project/config.py +773 -0
- pythonnative/project/deps.py +719 -0
- pythonnative/project/devices.py +304 -0
- pythonnative/project/doctor.py +283 -0
- pythonnative/project/fingerprint.py +171 -0
- pythonnative/project/icons.py +247 -0
- pythonnative/project/ios.py +325 -0
- pythonnative/project/lockfile.py +100 -0
- pythonnative/project/permissions.py +361 -0
- pythonnative/project/plugins.py +519 -0
- pythonnative/project/runtime_assets.py +183 -0
- pythonnative/py.typed +0 -0
- pythonnative/query.py +153 -0
- pythonnative/reconciler/__init__.py +29 -0
- pythonnative/reconciler/boundaries.py +375 -0
- pythonnative/reconciler/children.py +88 -0
- pythonnative/reconciler/core.py +1165 -0
- pythonnative/reconciler/layout_pass.py +393 -0
- pythonnative/reconciler/vnode.py +266 -0
- pythonnative/refresh.py +55 -0
- pythonnative/runtime.py +306 -0
- pythonnative/scheduler.py +159 -0
- pythonnative/sdk/__init__.py +153 -0
- pythonnative/sdk/_components.py +427 -0
- pythonnative/sdk/builtins.py +91 -0
- pythonnative/sdk/codegen.py +149 -0
- pythonnative/sdk/module_codegen.py +184 -0
- pythonnative/sdk/schema.py +224 -0
- pythonnative/sdk/templates/contracts.kt +46 -0
- pythonnative/sdk/templates/contracts.swift +46 -0
- pythonnative/storage.py +184 -0
- pythonnative/style.py +841 -0
- pythonnative/suspense.py +183 -0
- pythonnative/templates/android_template/app/build.gradle +75 -0
- pythonnative/templates/android_template/app/proguard-rules.pro +21 -0
- pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +24 -0
- pythonnative/templates/android_template/app/src/debug/AndroidManifest.xml +7 -0
- pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +32 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +130 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +13 -0
- pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
- pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +30 -0
- pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +10 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +22 -0
- pythonnative/templates/android_template/app/src/main/res/values/colors.xml +5 -0
- pythonnative/templates/android_template/app/src/main/res/values/strings.xml +5 -0
- pythonnative/templates/android_template/app/src/main/res/values/themes.xml +9 -0
- pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +7 -0
- pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +13 -0
- pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +19 -0
- pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +17 -0
- pythonnative/templates/android_template/build.gradle +10 -0
- pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
- pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +6 -0
- pythonnative/templates/android_template/gradle.properties +23 -0
- pythonnative/templates/android_template/gradlew +185 -0
- pythonnative/templates/android_template/gradlew.bat +89 -0
- pythonnative/templates/android_template/settings.gradle +17 -0
- pythonnative/templates/ios_template/ios_template/AppDelegate.swift +51 -0
- pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +13 -0
- pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +6 -0
- pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +25 -0
- pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
- pythonnative/templates/ios_template/ios_template/Info.plist +28 -0
- pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +390 -0
- pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +61 -0
- pythonnative/templates/ios_template/ios_template/ViewController.swift +23 -0
- pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +745 -0
- pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +36 -0
- pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +41 -0
- pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +32 -0
- pythonnative/testing/__init__.py +53 -0
- pythonnative/testing/backend.py +276 -0
- pythonnative/testing/harness.py +369 -0
- pythonnative/utils.py +145 -0
- pythonnative-0.40.0.dist-info/DELVEWHEEL +2 -0
- pythonnative-0.40.0.dist-info/METADATA +150 -0
- pythonnative-0.40.0.dist-info/RECORD +418 -0
- pythonnative-0.40.0.dist-info/WHEEL +5 -0
- pythonnative-0.40.0.dist-info/entry_points.txt +2 -0
- pythonnative-0.40.0.dist-info/licenses/LICENSE +21 -0
- pythonnative-0.40.0.dist-info/top_level.txt +1 -0
- pythonnative.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package com.pythonnative.runtime.bridge
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.pythonnative.runtime.components.BuiltinComponents
|
|
5
|
+
import com.pythonnative.runtime.components.ComponentManager
|
|
6
|
+
import com.pythonnative.runtime.modules.BuiltinModules
|
|
7
|
+
import com.pythonnative.runtime.modules.NativeModule
|
|
8
|
+
import com.pythonnative.runtime.plugins.GeneratedPlugins
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A native extension: registers component managers and native modules.
|
|
12
|
+
*
|
|
13
|
+
* `pn build` generates a call to each plugin entry's `register` in
|
|
14
|
+
* `plugins/GeneratedPlugins.kt`.
|
|
15
|
+
*/
|
|
16
|
+
interface PNPlugin {
|
|
17
|
+
fun register(registry: PNRegistry)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Registry of component managers (by element type) and native modules
|
|
22
|
+
* (by module name). Built-ins are registered on first use, followed by
|
|
23
|
+
* the generated plugin registrations.
|
|
24
|
+
*/
|
|
25
|
+
object PNRegistry {
|
|
26
|
+
private val componentFactories = HashMap<String, () -> ComponentManager>()
|
|
27
|
+
private val managers = HashMap<String, ComponentManager>()
|
|
28
|
+
private val moduleFactories = HashMap<String, () -> NativeModule>()
|
|
29
|
+
private val modules = HashMap<String, NativeModule>()
|
|
30
|
+
private var builtinsRegistered = false
|
|
31
|
+
|
|
32
|
+
/** Register (or override) the manager factory for element type `name`. */
|
|
33
|
+
fun registerComponent(name: String, factory: () -> ComponentManager) {
|
|
34
|
+
componentFactories[name] = factory
|
|
35
|
+
managers.remove(name)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Register a native module. The factory is invoked once to read the
|
|
40
|
+
* module's `name`; the same instance then serves every call.
|
|
41
|
+
*/
|
|
42
|
+
fun registerModule(factory: () -> NativeModule) {
|
|
43
|
+
val module = factory()
|
|
44
|
+
moduleFactories[module.name] = factory
|
|
45
|
+
modules[module.name] = module
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The manager for element type `name`, or `null` when unknown. */
|
|
49
|
+
fun managerFor(name: String): ComponentManager? {
|
|
50
|
+
ensureBuiltins()
|
|
51
|
+
managers[name]?.let { return it }
|
|
52
|
+
val factory = componentFactories[name] ?: return null
|
|
53
|
+
val manager = factory()
|
|
54
|
+
managers[name] = manager
|
|
55
|
+
return manager
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The module named `name`, or `null`. */
|
|
59
|
+
fun module(name: String): NativeModule? {
|
|
60
|
+
ensureBuiltins()
|
|
61
|
+
return modules[name]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Registered element type names. */
|
|
65
|
+
fun componentNames(): Set<String> {
|
|
66
|
+
ensureBuiltins()
|
|
67
|
+
return componentFactories.keys
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Register built-in components and modules plus generated plugins (idempotent). */
|
|
71
|
+
fun ensureBuiltins() {
|
|
72
|
+
if (builtinsRegistered) return
|
|
73
|
+
builtinsRegistered = true
|
|
74
|
+
BuiltinComponents.register(this)
|
|
75
|
+
BuiltinModules.register(this)
|
|
76
|
+
try {
|
|
77
|
+
GeneratedPlugins.registerAll(this)
|
|
78
|
+
} catch (e: Exception) {
|
|
79
|
+
Log.e(PNLog.TAG, "plugin registration failed", e)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
package com.pythonnative.runtime.bridge
|
|
2
|
+
|
|
3
|
+
import org.json.JSONArray
|
|
4
|
+
import org.json.JSONException
|
|
5
|
+
import org.json.JSONObject
|
|
6
|
+
|
|
7
|
+
/** One decoded mutation op. Geometry is in dp (points). */
|
|
8
|
+
sealed class Op {
|
|
9
|
+
/** `["c", tag, "Type", {props}]` */
|
|
10
|
+
data class Create(val tag: Long, val typeName: String, val props: JSONObject) : Op()
|
|
11
|
+
|
|
12
|
+
/** `["u", tag, {changed}]` (a `null` value means the prop was removed) */
|
|
13
|
+
data class Update(val tag: Long, val changed: JSONObject) : Op()
|
|
14
|
+
|
|
15
|
+
/** `["i", parent, child, index]` (move-aware) */
|
|
16
|
+
data class Insert(val parent: Long, val child: Long, val index: Int) : Op()
|
|
17
|
+
|
|
18
|
+
/** `["d", tag]` */
|
|
19
|
+
data class Destroy(val tag: Long) : Op()
|
|
20
|
+
|
|
21
|
+
/** `["f", tag, x, y, w, h]` relative to the parent's content origin */
|
|
22
|
+
data class Frame(val tag: Long, val x: Double, val y: Double, val width: Double, val height: Double) : Op()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Decoder for the transaction wire format: a JSON array of ops, each an
|
|
27
|
+
* array whose first element is a one-letter opcode.
|
|
28
|
+
*
|
|
29
|
+
* Decoding is isolated per op: a malformed entry is reported through
|
|
30
|
+
* `onError` and skipped so the rest of the commit still applies.
|
|
31
|
+
*/
|
|
32
|
+
object PNTransaction {
|
|
33
|
+
/** Decode `json`; invalid ops are skipped after `onError(index, error)`. */
|
|
34
|
+
fun decode(json: String, onError: (Int, Throwable) -> Unit = { _, _ -> }): List<Op> {
|
|
35
|
+
val array = JSONArray(json)
|
|
36
|
+
val ops = ArrayList<Op>(array.length())
|
|
37
|
+
for (i in 0 until array.length()) {
|
|
38
|
+
try {
|
|
39
|
+
val raw = array.get(i) as? JSONArray
|
|
40
|
+
?: throw JSONException("op $i is not an array")
|
|
41
|
+
ops.add(decodeOp(raw))
|
|
42
|
+
} catch (e: Exception) {
|
|
43
|
+
onError(i, e)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return ops
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Decode a single op array. */
|
|
50
|
+
fun decodeOp(raw: JSONArray): Op {
|
|
51
|
+
val code = raw.optString(0, "")
|
|
52
|
+
return when (code) {
|
|
53
|
+
"c" -> Op.Create(
|
|
54
|
+
tag(raw, 1),
|
|
55
|
+
raw.optString(2, ""),
|
|
56
|
+
raw.optJSONObject(3) ?: JSONObject(),
|
|
57
|
+
)
|
|
58
|
+
"u" -> Op.Update(tag(raw, 1), raw.optJSONObject(2) ?: JSONObject())
|
|
59
|
+
"i" -> Op.Insert(tag(raw, 1), tag(raw, 2), JsonUtil.toInt(raw.opt(3), 0))
|
|
60
|
+
"d" -> Op.Destroy(tag(raw, 1))
|
|
61
|
+
"f" -> Op.Frame(
|
|
62
|
+
tag(raw, 1),
|
|
63
|
+
JsonUtil.toDouble(raw.opt(2)),
|
|
64
|
+
JsonUtil.toDouble(raw.opt(3)),
|
|
65
|
+
JsonUtil.toDouble(raw.opt(4)),
|
|
66
|
+
JsonUtil.toDouble(raw.opt(5)),
|
|
67
|
+
)
|
|
68
|
+
else -> throw JSONException("unknown opcode '$code'")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private fun tag(raw: JSONArray, index: Int): Long {
|
|
73
|
+
val v = raw.opt(index) ?: throw JSONException("missing tag at $index")
|
|
74
|
+
return when (v) {
|
|
75
|
+
is Number -> v.toLong()
|
|
76
|
+
is String -> v.toLongOrNull() ?: throw JSONException("bad tag '$v'")
|
|
77
|
+
else -> throw JSONException("bad tag $v")
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
package com.pythonnative.runtime.bridge
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.pythonnative.runtime.PNBridge
|
|
5
|
+
import com.pythonnative.runtime.components.ComponentManager
|
|
6
|
+
import com.pythonnative.runtime.components.PlaceholderManager
|
|
7
|
+
import com.pythonnative.runtime.gestures.GestureCoordinator
|
|
8
|
+
import org.json.JSONObject
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Applies decoded transactions to the view tree, in order, with per-op
|
|
12
|
+
* error isolation. Unknown element types create a placeholder view and
|
|
13
|
+
* log once.
|
|
14
|
+
*/
|
|
15
|
+
class TransactionApplier(private val registry: ViewRegistry) {
|
|
16
|
+
private val placeholder = PlaceholderManager()
|
|
17
|
+
|
|
18
|
+
/** Decode and apply `transactionJson`. */
|
|
19
|
+
fun apply(transactionJson: String) {
|
|
20
|
+
val ops = try {
|
|
21
|
+
PNTransaction.decode(transactionJson) { index, error ->
|
|
22
|
+
PNLog.rateLimited("decode", "transaction op $index could not be decoded", error)
|
|
23
|
+
}
|
|
24
|
+
} catch (e: Exception) {
|
|
25
|
+
PNLog.rateLimited("decode-top", "transaction is not a JSON array", e)
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
for (op in ops) {
|
|
29
|
+
try {
|
|
30
|
+
applyOp(op)
|
|
31
|
+
} catch (e: Exception) {
|
|
32
|
+
PNLog.rateLimited("op:" + op.javaClass.simpleName, "failed to apply $op", e)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Apply a single op. */
|
|
38
|
+
fun applyOp(op: Op) {
|
|
39
|
+
when (op) {
|
|
40
|
+
is Op.Create -> create(op)
|
|
41
|
+
is Op.Update -> update(op)
|
|
42
|
+
is Op.Insert -> insert(op)
|
|
43
|
+
is Op.Destroy -> destroy(op)
|
|
44
|
+
is Op.Frame -> frame(op)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private fun create(op: Op.Create) {
|
|
49
|
+
registry.get(op.tag)?.let {
|
|
50
|
+
PNLog.rateLimited("dup-create", "tag ${op.tag} already exists (${it.typeName}); replacing")
|
|
51
|
+
destroyRecord(it)
|
|
52
|
+
}
|
|
53
|
+
val manager = PNRegistry.managerFor(op.typeName) ?: run {
|
|
54
|
+
PNLog.once("unknown-type:" + op.typeName, "unknown element type '${op.typeName}'; using a placeholder view")
|
|
55
|
+
placeholder
|
|
56
|
+
}
|
|
57
|
+
val view = manager.createView(PNBridge.context(), op.tag, op.props)
|
|
58
|
+
val record = ViewRecord(op.tag, op.typeName, view, manager)
|
|
59
|
+
JsonUtil.merge(record.props, op.props)
|
|
60
|
+
registry.register(record)
|
|
61
|
+
try {
|
|
62
|
+
manager.applyProps(view, op.props, true)
|
|
63
|
+
} finally {
|
|
64
|
+
record.initialized = true
|
|
65
|
+
}
|
|
66
|
+
if (op.props.has("gestures")) {
|
|
67
|
+
GestureCoordinator.bind(record, op.props.opt("gestures"))
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private fun update(op: Op.Update) {
|
|
72
|
+
val record = registry.get(op.tag) ?: throw IllegalStateException("update: unknown tag ${op.tag}")
|
|
73
|
+
JsonUtil.merge(record.props, op.changed)
|
|
74
|
+
record.manager.update(record.view, op.changed)
|
|
75
|
+
if (op.changed.has("gestures")) {
|
|
76
|
+
GestureCoordinator.bind(record, op.changed.opt("gestures"))
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private fun insert(op: Op.Insert) {
|
|
81
|
+
val parent = registry.get(op.parent) ?: throw IllegalStateException("insert: unknown parent ${op.parent}")
|
|
82
|
+
val child = registry.get(op.child) ?: throw IllegalStateException("insert: unknown child ${op.child}")
|
|
83
|
+
parent.manager.insertChild(parent.view, child.view, op.index)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private fun destroy(op: Op.Destroy) {
|
|
87
|
+
val record = registry.get(op.tag) ?: return
|
|
88
|
+
destroyRecord(record)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private fun destroyRecord(record: ViewRecord) {
|
|
92
|
+
com.pythonnative.runtime.animation.AnimationGraph.forget(record.tag)
|
|
93
|
+
GestureCoordinator.unbind(record)
|
|
94
|
+
try {
|
|
95
|
+
val parentRecord = com.pythonnative.runtime.layout.NativeLayout.parent(record.tag)?.let { registry.get(it) }
|
|
96
|
+
?: (record.view.parent as? View)?.let { registry.recordFor(it) }
|
|
97
|
+
if (parentRecord != null) {
|
|
98
|
+
parentRecord.manager.removeChild(parentRecord.view, record.view)
|
|
99
|
+
}
|
|
100
|
+
record.manager.destroy(record.view)
|
|
101
|
+
} finally {
|
|
102
|
+
registry.unregister(record.tag)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private fun frame(op: Op.Frame) {
|
|
107
|
+
val record = registry.get(op.tag) ?: throw IllegalStateException("frame: unknown tag ${op.tag}")
|
|
108
|
+
record.frame = doubleArrayOf(op.x, op.y, op.width, op.height)
|
|
109
|
+
record.manager.setFrame(record.view, op.x, op.y, op.width, op.height)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Whether `manager` is the fallback placeholder manager. */
|
|
113
|
+
fun isPlaceholder(manager: ComponentManager): Boolean = manager === placeholder
|
|
114
|
+
|
|
115
|
+
/** The props recorded for `tag`, mainly for diagnostics. */
|
|
116
|
+
fun propsOf(tag: Long): JSONObject? = registry.get(tag)?.props
|
|
117
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
package com.pythonnative.runtime.bridge
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.pythonnative.runtime.components.ComponentManager
|
|
5
|
+
import org.json.JSONArray
|
|
6
|
+
import org.json.JSONObject
|
|
7
|
+
import java.util.IdentityHashMap
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Per-view bookkeeping: the reconciler tag, the element type, the
|
|
11
|
+
* manager that owns it, the merged props, and free-form manager state.
|
|
12
|
+
*/
|
|
13
|
+
class ViewRecord(
|
|
14
|
+
val tag: Long,
|
|
15
|
+
val typeName: String,
|
|
16
|
+
val view: View,
|
|
17
|
+
val manager: ComponentManager,
|
|
18
|
+
) {
|
|
19
|
+
/** Every prop applied so far (removed props stay as JSON null). */
|
|
20
|
+
val props = JSONObject()
|
|
21
|
+
|
|
22
|
+
/** Manager-private state (suppress flags, wrapped widgets, etc.). */
|
|
23
|
+
val state = HashMap<String, Any?>()
|
|
24
|
+
|
|
25
|
+
/** Last frame applied by `setFrame`, in dp (`x, y, w, h`). */
|
|
26
|
+
var frame: DoubleArray? = null
|
|
27
|
+
|
|
28
|
+
/** Whether the initial props have been applied. */
|
|
29
|
+
var initialized = false
|
|
30
|
+
|
|
31
|
+
/** Whether the element wired a callback named `name` this render. */
|
|
32
|
+
fun hasEvent(name: String): Boolean {
|
|
33
|
+
val events = props.opt("_pn_events") as? JSONArray ?: return false
|
|
34
|
+
for (i in 0 until events.length()) {
|
|
35
|
+
if (events.optString(i) == name) return true
|
|
36
|
+
}
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Tag to [ViewRecord] map with a reverse index by view identity. */
|
|
42
|
+
class ViewRegistry {
|
|
43
|
+
private val byTag = HashMap<Long, ViewRecord>()
|
|
44
|
+
private val byView = IdentityHashMap<View, ViewRecord>()
|
|
45
|
+
|
|
46
|
+
/** Number of live records. */
|
|
47
|
+
val size: Int get() = byTag.size
|
|
48
|
+
|
|
49
|
+
/** Register `record`; replaces any earlier record with the same tag. */
|
|
50
|
+
fun register(record: ViewRecord) {
|
|
51
|
+
byTag.remove(record.tag)?.let { byView.remove(it.view) }
|
|
52
|
+
byTag[record.tag] = record
|
|
53
|
+
byView[record.view] = record
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Remove and return the record for `tag`. */
|
|
57
|
+
fun unregister(tag: Long): ViewRecord? {
|
|
58
|
+
val record = byTag.remove(tag) ?: return null
|
|
59
|
+
byView.remove(record.view)
|
|
60
|
+
return record
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The record for `tag`, or `null`. */
|
|
64
|
+
fun get(tag: Long): ViewRecord? = byTag[tag]
|
|
65
|
+
|
|
66
|
+
/** The record whose view is `view`, or `null`. */
|
|
67
|
+
fun recordFor(view: View): ViewRecord? = byView[view]
|
|
68
|
+
|
|
69
|
+
/** The tag of `view`, or `null` when it is not a PythonNative view. */
|
|
70
|
+
fun tagOf(view: View): Long? = byView[view]?.tag
|
|
71
|
+
|
|
72
|
+
/** Snapshot of all records. */
|
|
73
|
+
fun all(): List<ViewRecord> = ArrayList(byTag.values)
|
|
74
|
+
}
|
pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package com.pythonnative.runtime.components
|
|
2
|
+
|
|
3
|
+
import com.pythonnative.runtime.bridge.PNRegistry
|
|
4
|
+
|
|
5
|
+
/** Registers the built-in element types with the registry. */
|
|
6
|
+
object BuiltinComponents {
|
|
7
|
+
fun register(registry: PNRegistry) {
|
|
8
|
+
registry.registerComponent("View") { ViewManager() }
|
|
9
|
+
registry.registerComponent("Screen") { ScreenManager() }
|
|
10
|
+
registry.registerComponent("ScreenStack") { ScreenStackManager() }
|
|
11
|
+
registry.registerComponent("Column") { ViewManager() }
|
|
12
|
+
registry.registerComponent("Row") { ViewManager() }
|
|
13
|
+
registry.registerComponent("Text") { TextManager() }
|
|
14
|
+
registry.registerComponent("Button") { ButtonManager() }
|
|
15
|
+
registry.registerComponent("TextInput") { TextInputManager() }
|
|
16
|
+
registry.registerComponent("Image") { ImageManager() }
|
|
17
|
+
registry.registerComponent("Switch") { SwitchManager() }
|
|
18
|
+
registry.registerComponent("Checkbox") { CheckboxManager() }
|
|
19
|
+
registry.registerComponent("ProgressBar") { ProgressBarManager() }
|
|
20
|
+
registry.registerComponent("ActivityIndicator") { ActivityIndicatorManager() }
|
|
21
|
+
registry.registerComponent("Slider") { SliderManager() }
|
|
22
|
+
registry.registerComponent("WebView") { WebViewManager() }
|
|
23
|
+
registry.registerComponent("Spacer") { SpacerManager() }
|
|
24
|
+
registry.registerComponent("ScrollView") { ScrollViewManager() }
|
|
25
|
+
registry.registerComponent("SafeAreaView") { SafeAreaViewManager() }
|
|
26
|
+
registry.registerComponent("KeyboardAvoidingView") { KeyboardAvoidingViewManager() }
|
|
27
|
+
registry.registerComponent("Modal") { ModalManager() }
|
|
28
|
+
registry.registerComponent("Portal") { PortalManager() }
|
|
29
|
+
registry.registerComponent("TabBar") { TabBarManager() }
|
|
30
|
+
registry.registerComponent("Pressable") { PressableManager() }
|
|
31
|
+
registry.registerComponent("StatusBar") { StatusBarManager() }
|
|
32
|
+
registry.registerComponent("Picker") { PickerManager() }
|
|
33
|
+
registry.registerComponent("SegmentedControl") { SegmentedControlManager() }
|
|
34
|
+
registry.registerComponent("DatePicker") { DatePickerManager() }
|
|
35
|
+
registry.registerComponent("VirtualList") { VirtualListManager() }
|
|
36
|
+
}
|
|
37
|
+
}
|
pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package com.pythonnative.runtime.components
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.View
|
|
5
|
+
import android.widget.Button
|
|
6
|
+
import com.pythonnative.runtime.bridge.JsonUtil
|
|
7
|
+
import com.pythonnative.runtime.bridge.num
|
|
8
|
+
import com.pythonnative.runtime.bridge.str
|
|
9
|
+
import com.pythonnative.runtime.bridge.value
|
|
10
|
+
import org.json.JSONObject
|
|
11
|
+
|
|
12
|
+
/** `Button` element: a platform `Button` firing `on_press`. */
|
|
13
|
+
class ButtonManager : ComponentManager() {
|
|
14
|
+
override fun createView(context: Context, tag: Long, props: JSONObject): View {
|
|
15
|
+
val button = Button(context)
|
|
16
|
+
button.setOnClickListener { fire(it, "on_press") }
|
|
17
|
+
return button
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override fun applyProps(view: View, props: JSONObject, initial: Boolean) {
|
|
21
|
+
val button = view as Button
|
|
22
|
+
if (props.has("title")) button.text = props.str("title") ?: ""
|
|
23
|
+
props.num("font_size")?.let { button.textSize = it.toFloat() }
|
|
24
|
+
PNColor.parse(props.value("color"))?.let { button.setTextColor(it) }
|
|
25
|
+
if (props.has("disabled")) button.isEnabled = !JsonUtil.truthy(props.value("disabled"))
|
|
26
|
+
if (props.has("all_caps")) button.isAllCaps = JsonUtil.truthy(props.value("all_caps"))
|
|
27
|
+
if (listOf("font_family", "font_weight", "italic", "bold").any { props.has(it) }) {
|
|
28
|
+
TextStyle.applyTypeface(button, propsOf(button))
|
|
29
|
+
}
|
|
30
|
+
ViewStyler.apply(button, props)
|
|
31
|
+
}
|
|
32
|
+
}
|
pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
package com.pythonnative.runtime.components
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.view.ViewGroup
|
|
7
|
+
import android.widget.FrameLayout
|
|
8
|
+
import com.pythonnative.runtime.PNBridge
|
|
9
|
+
import com.pythonnative.runtime.animation.PNAnimator
|
|
10
|
+
import com.pythonnative.runtime.bridge.JsonUtil
|
|
11
|
+
import com.pythonnative.runtime.bridge.ViewRecord
|
|
12
|
+
import com.pythonnative.runtime.bridge.present
|
|
13
|
+
import org.json.JSONArray
|
|
14
|
+
import org.json.JSONObject
|
|
15
|
+
import kotlin.math.max
|
|
16
|
+
import kotlin.math.min
|
|
17
|
+
import kotlin.math.roundToInt
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Base class for one element type's native implementation.
|
|
21
|
+
*
|
|
22
|
+
* Subclasses implement [createView] (construct the widget) and
|
|
23
|
+
* [applyProps] (apply visual props); the base class owns frame
|
|
24
|
+
* application, intrinsic measurement, child management, and the
|
|
25
|
+
* animation hooks. All geometry crossing this API is in dp.
|
|
26
|
+
*/
|
|
27
|
+
abstract class ComponentManager {
|
|
28
|
+
/** Construct the widget for `tag`; `props` may be consulted for creation-time choices. */
|
|
29
|
+
abstract fun createView(context: Context, tag: Long, props: JSONObject): View
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Apply `props` to `view`. `initial` is `true` for the create op;
|
|
33
|
+
* on updates `props` holds only the changed keys (JSON null means
|
|
34
|
+
* removed). The merged props are always available via [propsOf].
|
|
35
|
+
*/
|
|
36
|
+
open fun applyProps(view: View, props: JSONObject, initial: Boolean) {
|
|
37
|
+
ViewStyler.apply(view, props)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Apply changed props (the `u` op). */
|
|
41
|
+
fun update(view: View, changed: JSONObject) = applyProps(view, changed, false)
|
|
42
|
+
|
|
43
|
+
/** Ensure `child` sits at `index` under `parent` (move-aware, clamped). */
|
|
44
|
+
open fun insertChild(parent: View, child: View, index: Int) {
|
|
45
|
+
val group = parent as? ViewGroup ?: return
|
|
46
|
+
ViewChildren.insert(group, child, index)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Detach `child` from `parent` without destroying it. */
|
|
50
|
+
open fun removeChild(parent: View, child: View) {
|
|
51
|
+
(parent as? ViewGroup)?.removeView(child)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Release resources and detach from the parent. */
|
|
55
|
+
open fun destroy(view: View) {
|
|
56
|
+
try {
|
|
57
|
+
teardown(view)
|
|
58
|
+
} catch (e: Exception) {
|
|
59
|
+
Log.d(PNBridge.TAG, "teardown failed for ${view.javaClass.simpleName}", e)
|
|
60
|
+
}
|
|
61
|
+
(view.parent as? ViewGroup)?.removeView(view)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Subclass hook for extra cleanup before the view is released. */
|
|
65
|
+
protected open fun teardown(view: View) {}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Position `view` inside its parent's `FrameLayout` via margin layout
|
|
69
|
+
* params. Non-finite values are clamped; sizes are never negative.
|
|
70
|
+
*/
|
|
71
|
+
open fun setFrame(view: View, x: Double, y: Double, width: Double, height: Double) {
|
|
72
|
+
val pxX = px(finite(x))
|
|
73
|
+
val pxY = px(finite(y))
|
|
74
|
+
val pxW = max(0, px(finite(width)))
|
|
75
|
+
val pxH = max(0, px(finite(height)))
|
|
76
|
+
val lp = view.layoutParams
|
|
77
|
+
val params: ViewGroup.LayoutParams = if (lp == null) {
|
|
78
|
+
FrameLayout.LayoutParams(pxW, pxH)
|
|
79
|
+
} else {
|
|
80
|
+
lp.width = pxW
|
|
81
|
+
lp.height = pxH
|
|
82
|
+
lp
|
|
83
|
+
}
|
|
84
|
+
if (params is ViewGroup.MarginLayoutParams) {
|
|
85
|
+
params.leftMargin = pxX
|
|
86
|
+
params.topMargin = pxY
|
|
87
|
+
params.rightMargin = 0
|
|
88
|
+
params.bottomMargin = 0
|
|
89
|
+
}
|
|
90
|
+
view.layoutParams = params
|
|
91
|
+
val record = recordOf(view)
|
|
92
|
+
if (record != null) {
|
|
93
|
+
record.frame = doubleArrayOf(x, y, width, height)
|
|
94
|
+
if (record.props.present("hit_slop") || record.state["hit_slop_active"] == true) {
|
|
95
|
+
ViewStyler.updateHitSlop(view)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Natural size of `view` under the constraints, in dp. Either
|
|
102
|
+
* constraint may be `1e6` or infinite meaning unconstrained.
|
|
103
|
+
*/
|
|
104
|
+
open fun measure(view: View, maxWidth: Double, maxHeight: Double): FloatArray {
|
|
105
|
+
val density = PNBridge.density()
|
|
106
|
+
val wSpec = measureSpec(maxWidth, density)
|
|
107
|
+
val hSpec = measureSpec(maxHeight, density)
|
|
108
|
+
view.measure(wSpec, hSpec)
|
|
109
|
+
return floatArrayOf(view.measuredWidth / density, view.measuredHeight / density)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Run an imperative command; unknown names return `null`. */
|
|
113
|
+
open fun command(view: View, name: String, args: JSONObject): Any? = null
|
|
114
|
+
|
|
115
|
+
/** Apply one Python-driven animation frame immediately. */
|
|
116
|
+
open fun setAnimatedProperty(view: View, prop: String, value: Any?) {
|
|
117
|
+
PNAnimator.setProperty(view, prop, value)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Start a natively driven animation; `false` asks Python to tick it instead. */
|
|
121
|
+
open fun startAnimation(view: View, id: Long, prop: String, spec: JSONObject): Boolean =
|
|
122
|
+
PNAnimator.start(view, id, prop, spec)
|
|
123
|
+
|
|
124
|
+
/** Cancel a native animation and return the presentation value, if readable. */
|
|
125
|
+
open fun cancelAnimation(view: View, id: Long): Any? = PNAnimator.cancel(id)
|
|
126
|
+
|
|
127
|
+
// ------------------------------------------------------------------
|
|
128
|
+
// Helpers for subclasses
|
|
129
|
+
// ------------------------------------------------------------------
|
|
130
|
+
|
|
131
|
+
/** The registry record for `view`, or `null` for foreign views. */
|
|
132
|
+
protected fun recordOf(view: View): ViewRecord? = PNBridge.registry.recordFor(view)
|
|
133
|
+
|
|
134
|
+
/** Merged props for `view` (empty for foreign views). */
|
|
135
|
+
protected fun propsOf(view: View): JSONObject = recordOf(view)?.props ?: JSONObject()
|
|
136
|
+
|
|
137
|
+
/** Manager-private state map for `view`. */
|
|
138
|
+
protected fun stateOf(view: View): MutableMap<String, Any?> = recordOf(view)?.state ?: HashMap()
|
|
139
|
+
|
|
140
|
+
/** Dispatch event `name` with positional `args` for `view`'s tag. */
|
|
141
|
+
protected fun fire(view: View, name: String, vararg args: Any?): Boolean = PNEvents.fire(view, name, *args)
|
|
142
|
+
|
|
143
|
+
/** Dispatch event `name` and return Python's (JSON) reply. */
|
|
144
|
+
protected fun fireForResult(view: View, name: String, vararg args: Any?): String? =
|
|
145
|
+
PNEvents.fireForResult(view, name, *args)
|
|
146
|
+
|
|
147
|
+
/** Whether the element wired a callback named `name`. */
|
|
148
|
+
protected fun hasEvent(view: View, name: String): Boolean = recordOf(view)?.hasEvent(name) ?: false
|
|
149
|
+
|
|
150
|
+
/** dp to whole pixels. */
|
|
151
|
+
protected fun px(dp: Double): Int = (dp * PNBridge.density()).roundToInt()
|
|
152
|
+
|
|
153
|
+
/** dp to pixels as a float. */
|
|
154
|
+
protected fun pxF(dp: Double): Float = (dp * PNBridge.density()).toFloat()
|
|
155
|
+
|
|
156
|
+
/** pixels to dp. */
|
|
157
|
+
protected fun dp(px: Number): Double = px.toDouble() / PNBridge.density()
|
|
158
|
+
|
|
159
|
+
private fun finite(v: Double): Double = if (v.isNaN() || v.isInfinite()) 0.0 else v
|
|
160
|
+
|
|
161
|
+
private fun measureSpec(limit: Double, density: Float): Int {
|
|
162
|
+
if (limit.isNaN() || limit.isInfinite() || limit >= 1e6) {
|
|
163
|
+
return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
|
164
|
+
}
|
|
165
|
+
val px = min((max(0.0, limit) * density).toInt(), (1 shl 29))
|
|
166
|
+
return View.MeasureSpec.makeMeasureSpec(px, View.MeasureSpec.AT_MOST)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Move-aware indexed insertion into any `ViewGroup`. */
|
|
171
|
+
object ViewChildren {
|
|
172
|
+
fun insert(parent: ViewGroup, child: View, index: Int) {
|
|
173
|
+
val current = child.parent as? ViewGroup
|
|
174
|
+
if (current === parent) {
|
|
175
|
+
val currentIndex = parent.indexOfChild(child)
|
|
176
|
+
val target = max(0, min(index, parent.childCount - 1))
|
|
177
|
+
if (currentIndex == target) return
|
|
178
|
+
parent.removeView(child)
|
|
179
|
+
parent.addView(child, max(0, min(target, parent.childCount)))
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
current?.removeView(child)
|
|
183
|
+
if (child.layoutParams == null) {
|
|
184
|
+
child.layoutParams = FrameLayout.LayoutParams(0, 0)
|
|
185
|
+
}
|
|
186
|
+
parent.addView(child, max(0, min(index, parent.childCount)))
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Event dispatch keyed by view identity. */
|
|
191
|
+
object PNEvents {
|
|
192
|
+
/** Dispatch `name` for `view` with positional `args`; `false` when the view is unknown. */
|
|
193
|
+
fun fire(view: View, name: String, vararg args: Any?): Boolean {
|
|
194
|
+
val tag = PNBridge.registry.tagOf(view) ?: return false
|
|
195
|
+
fireTag(tag, name, JsonUtil.args(*args))
|
|
196
|
+
return true
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Dispatch `name` for `view` and return Python's JSON reply. */
|
|
200
|
+
fun fireForResult(view: View, name: String, vararg args: Any?): String? {
|
|
201
|
+
val tag = PNBridge.registry.tagOf(view) ?: return null
|
|
202
|
+
return fireTag(tag, name, JsonUtil.args(*args))
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Dispatch `name` for `tag` with an already built argument array. */
|
|
206
|
+
fun fireTag(tag: Long, name: String, args: JSONArray): String? =
|
|
207
|
+
PNBridge.callPython("event", tag, name, args.toString())
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Fallback for unknown element types: an empty container that hosts children. */
|
|
211
|
+
class PlaceholderManager : ComponentManager() {
|
|
212
|
+
override fun createView(context: Context, tag: Long, props: JSONObject): View = FrameLayout(context)
|
|
213
|
+
}
|