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.
Files changed (418) hide show
  1. pythonnative/__init__.py +411 -0
  2. pythonnative/_ios_log.py +92 -0
  3. pythonnative/_yoga.cp313-win_amd64.pyd +0 -0
  4. pythonnative/alerts.py +236 -0
  5. pythonnative/animated.py +1687 -0
  6. pythonnative/animation_graph.py +78 -0
  7. pythonnative/appearance.py +124 -0
  8. pythonnative/bootstrap.py +100 -0
  9. pythonnative/bridge/__init__.py +302 -0
  10. pythonnative/bridge/android.py +78 -0
  11. pythonnative/bridge/codec.py +170 -0
  12. pythonnative/bridge/commits.py +114 -0
  13. pythonnative/bridge/fake.py +243 -0
  14. pythonnative/bridge/ios.py +138 -0
  15. pythonnative/bridge/web.py +489 -0
  16. pythonnative/cli/__init__.py +7 -0
  17. pythonnative/cli/pn.py +1214 -0
  18. pythonnative/component.py +271 -0
  19. pythonnative/components/__init__.py +111 -0
  20. pythonnative/components/_base.py +166 -0
  21. pythonnative/components/controls.py +521 -0
  22. pythonnative/components/layout.py +518 -0
  23. pythonnative/components/lists.py +785 -0
  24. pythonnative/components/media.py +204 -0
  25. pythonnative/components/overlays.py +107 -0
  26. pythonnative/components/pressable.py +252 -0
  27. pythonnative/components/structural.py +167 -0
  28. pythonnative/components/text.py +291 -0
  29. pythonnative/devclient.py +824 -0
  30. pythonnative/devserver/__init__.py +34 -0
  31. pythonnative/devserver/server.py +718 -0
  32. pythonnative/devserver/static/animation_graph.js +82 -0
  33. pythonnative/devserver/static/bridge.js +147 -0
  34. pythonnative/devserver/static/colors.js +70 -0
  35. pythonnative/devserver/static/host.js +552 -0
  36. pythonnative/devserver/static/index.html +60 -0
  37. pythonnative/devserver/static/layout.js +85 -0
  38. pythonnative/devserver/static/preview.css +415 -0
  39. pythonnative/devserver/static/renderer.js +1994 -0
  40. pythonnative/devserver/static/shell.js +345 -0
  41. pythonnative/devserver/static/yoga/LICENSE +21 -0
  42. pythonnative/devserver/static/yoga/binaries/yoga-wasm-base64-esm.js +75 -0
  43. pythonnative/devserver/static/yoga/src/generated/YGEnums.d.ts +189 -0
  44. pythonnative/devserver/static/yoga/src/generated/YGEnums.js +211 -0
  45. pythonnative/devserver/static/yoga/src/generated/YGEnums.js.map +1 -0
  46. pythonnative/devserver/static/yoga/src/index.d.ts +12 -0
  47. pythonnative/devserver/static/yoga/src/index.js +16 -0
  48. pythonnative/devserver/static/yoga/src/index.js.map +1 -0
  49. pythonnative/devserver/static/yoga/src/load.d.ts +11 -0
  50. pythonnative/devserver/static/yoga/src/load.js +17 -0
  51. pythonnative/devserver/static/yoga/src/load.js.map +1 -0
  52. pythonnative/devserver/static/yoga/src/wrapAssembly.d.ts +155 -0
  53. pythonnative/devserver/static/yoga/src/wrapAssembly.js +125 -0
  54. pythonnative/devserver/static/yoga/src/wrapAssembly.js.map +1 -0
  55. pythonnative/devserver/watcher.py +267 -0
  56. pythonnative/devserver/ws.py +421 -0
  57. pythonnative/diagnostics.py +241 -0
  58. pythonnative/element.py +159 -0
  59. pythonnative/equality.py +19 -0
  60. pythonnative/events.py +231 -0
  61. pythonnative/gestures.py +1333 -0
  62. pythonnative/hooks.py +1621 -0
  63. pythonnative/hosts/__init__.py +63 -0
  64. pythonnative/hosts/base.py +596 -0
  65. pythonnative/hosts/native.py +302 -0
  66. pythonnative/hot_reload.py +585 -0
  67. pythonnative/layout.py +328 -0
  68. pythonnative/mutations.py +142 -0
  69. pythonnative/native/android/build.gradle +52 -0
  70. pythonnative/native/android/gradle.properties +3 -0
  71. pythonnative/native/android/settings.gradle +12 -0
  72. pythonnative/native/android/src/main/AndroidManifest.xml +11 -0
  73. pythonnative/native/android/src/main/cpp/CMakeLists.txt +9 -0
  74. pythonnative/native/android/src/main/cpp/yoga_jni.cpp +52 -0
  75. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeModules.kt +5 -0
  76. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeProps.kt +3705 -0
  77. pythonnative/native/android/src/main/java/com/pythonnative/generated/PNContracts.kt +129 -0
  78. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PNBridge.kt +261 -0
  79. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PythonHost.kt +20 -0
  80. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationGraph.kt +108 -0
  81. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationSpecs.kt +141 -0
  82. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/PNAnimator.kt +257 -0
  83. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/CommitState.kt +106 -0
  84. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/JsonUtil.kt +175 -0
  85. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/MainThread.kt +40 -0
  86. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNLog.kt +33 -0
  87. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNRegistry.kt +82 -0
  88. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNTransaction.kt +80 -0
  89. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt +117 -0
  90. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/ViewRegistry.kt +74 -0
  91. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt +37 -0
  92. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt +32 -0
  93. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt +213 -0
  94. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ContainerManagers.kt +69 -0
  95. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ControlManagers.kt +186 -0
  96. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/DatePickerManager.kt +123 -0
  97. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageLoader.kt +141 -0
  98. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageManager.kt +162 -0
  99. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ModalManager.kt +134 -0
  100. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PNColor.kt +201 -0
  101. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PickerManager.kt +86 -0
  102. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PortalManager.kt +55 -0
  103. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PressableManager.kt +122 -0
  104. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScreenStackManager.kt +110 -0
  105. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScrollViewManager.kt +214 -0
  106. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/SegmentedControlManager.kt +113 -0
  107. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/StatusBarManager.kt +52 -0
  108. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TabBarManager.kt +131 -0
  109. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextInputManager.kt +250 -0
  110. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextManager.kt +233 -0
  111. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ViewStyler.kt +355 -0
  112. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/VirtualListManager.kt +159 -0
  113. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/WebViewManager.kt +149 -0
  114. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureArbiter.kt +233 -0
  115. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureCoordinator.kt +127 -0
  116. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureRecognizers.kt +527 -0
  117. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/NativeLayout.kt +145 -0
  118. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/YogaNode.kt +29 -0
  119. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/BuiltinModules.kt +73 -0
  120. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/DeviceModules.kt +316 -0
  121. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/HostModule.kt +61 -0
  122. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/MediaModules.kt +200 -0
  123. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NativeModule.kt +158 -0
  124. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NotificationsModule.kt +100 -0
  125. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +99 -0
  126. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/StorageModules.kt +89 -0
  127. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/SystemModules.kt +178 -0
  128. pythonnative/native/android/src/main/java/com/pythonnative/runtime/plugins/GeneratedPlugins.kt +16 -0
  129. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/PNScreenFragment.kt +188 -0
  130. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/ScreenRegistry.kt +80 -0
  131. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNAccessibilityDelegate.kt +48 -0
  132. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNBorderDrawable.kt +76 -0
  133. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNEditText.kt +18 -0
  134. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNFrameLayout.kt +49 -0
  135. pythonnative/native/android/src/test/java/com/pythonnative/runtime/AnimationSpecsTest.kt +75 -0
  136. pythonnative/native/android/src/test/java/com/pythonnative/runtime/GestureArbiterTest.kt +197 -0
  137. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNColorTest.kt +47 -0
  138. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNTransactionTest.kt +78 -0
  139. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PromiseTest.kt +89 -0
  140. pythonnative/native/ios/Package.swift +23 -0
  141. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimationGraph.swift +199 -0
  142. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimator.swift +312 -0
  143. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNBridge.swift +255 -0
  144. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNCommit.swift +104 -0
  145. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNRegistry.swift +142 -0
  146. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNTransaction.swift +166 -0
  147. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNViewRegistry.swift +53 -0
  148. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNButtonManagers.swift +207 -0
  149. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNColor.swift +173 -0
  150. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNComponentManager.swift +183 -0
  151. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNContainerView.swift +56 -0
  152. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNControlManagers.swift +281 -0
  153. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNImageManager.swift +222 -0
  154. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNOverlayManagers.swift +243 -0
  155. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNPressableManager.swift +114 -0
  156. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScreenStackManager.swift +107 -0
  157. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScrollViewManager.swift +197 -0
  158. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTabBarManager.swift +106 -0
  159. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextInputManager.swift +297 -0
  160. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextManager.swift +230 -0
  161. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTransform.swift +82 -0
  162. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewManager.swift +86 -0
  163. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewState.swift +87 -0
  164. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewStyler.swift +340 -0
  165. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNVirtualListManager.swift +155 -0
  166. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNWebViewManager.swift +124 -0
  167. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeModules.swift +1 -0
  168. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeProps.swift +3775 -0
  169. pythonnative/native/ios/Sources/PythonNativeKit/Generated/PNContracts.swift +46 -0
  170. pythonnative/native/ios/Sources/PythonNativeKit/Gestures/PNGestureCoordinator.swift +260 -0
  171. pythonnative/native/ios/Sources/PythonNativeKit/Layout/PNLayout.swift +173 -0
  172. pythonnative/native/ios/Sources/PythonNativeKit/Modules/AlertModule.swift +92 -0
  173. pythonnative/native/ios/Sources/PythonNativeKit/Modules/HostModule.swift +80 -0
  174. pythonnative/native/ios/Sources/PythonNativeKit/Modules/LifecycleModules.swift +174 -0
  175. pythonnative/native/ios/Sources/PythonNativeKit/Modules/MediaModules.swift +177 -0
  176. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PNNativeModule.swift +168 -0
  177. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PermissionModules.swift +266 -0
  178. pythonnative/native/ios/Sources/PythonNativeKit/Modules/SystemModules.swift +251 -0
  179. pythonnative/native/ios/Sources/PythonNativeKit/Plugins/PNPluginRegistration.swift +8 -0
  180. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNScreenRegistry.swift +46 -0
  181. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNViewController.swift +237 -0
  182. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNCompat.swift +46 -0
  183. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNJSON.swift +173 -0
  184. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNLog.swift +47 -0
  185. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNWindow.swift +51 -0
  186. pythonnative/native/ios/Tests/PythonNativeKitTests/PNAnimationGraphTests.swift +26 -0
  187. pythonnative/native/ios/Tests/PythonNativeKitTests/PNColorTests.swift +50 -0
  188. pythonnative/native/ios/Tests/PythonNativeKitTests/PNCommitTests.swift +86 -0
  189. pythonnative/native/ios/Tests/PythonNativeKitTests/PNGestureTests.swift +101 -0
  190. pythonnative/native/ios/Tests/PythonNativeKitTests/PNManagerTests.swift +126 -0
  191. pythonnative/native/ios/Tests/PythonNativeKitTests/PNModuleTests.swift +111 -0
  192. pythonnative/native/ios/Tests/PythonNativeKitTests/PNTransactionTests.swift +91 -0
  193. pythonnative/native/yoga/LICENSE +21 -0
  194. pythonnative/native/yoga/Package.swift +9 -0
  195. pythonnative/native/yoga/VENDORED.md +2 -0
  196. pythonnative/native/yoga/include/PNStyle.h +10 -0
  197. pythonnative/native/yoga/include/module.modulemap +5 -0
  198. pythonnative/native/yoga/include/yoga/YGConfig.h +158 -0
  199. pythonnative/native/yoga/include/yoga/YGEnums.h +142 -0
  200. pythonnative/native/yoga/include/yoga/YGMacros.h +99 -0
  201. pythonnative/native/yoga/include/yoga/YGNode.h +304 -0
  202. pythonnative/native/yoga/include/yoga/YGNodeLayout.h +35 -0
  203. pythonnative/native/yoga/include/yoga/YGNodeStyle.h +130 -0
  204. pythonnative/native/yoga/include/yoga/YGPixelGrid.h +29 -0
  205. pythonnative/native/yoga/include/yoga/YGValue.h +84 -0
  206. pythonnative/native/yoga/include/yoga/Yoga.h +21 -0
  207. pythonnative/native/yoga/python.cpp +16 -0
  208. pythonnative/native/yoga/style.cpp +272 -0
  209. pythonnative/native/yoga/yoga/CMakeLists.txt +41 -0
  210. pythonnative/native/yoga/yoga/YGConfig.cpp +92 -0
  211. pythonnative/native/yoga/yoga/YGConfig.h +158 -0
  212. pythonnative/native/yoga/yoga/YGEnums.cpp +262 -0
  213. pythonnative/native/yoga/yoga/YGEnums.h +142 -0
  214. pythonnative/native/yoga/yoga/YGMacros.h +99 -0
  215. pythonnative/native/yoga/yoga/YGNode.cpp +366 -0
  216. pythonnative/native/yoga/yoga/YGNode.h +304 -0
  217. pythonnative/native/yoga/yoga/YGNodeLayout.cpp +92 -0
  218. pythonnative/native/yoga/yoga/YGNodeLayout.h +35 -0
  219. pythonnative/native/yoga/yoga/YGNodeStyle.cpp +405 -0
  220. pythonnative/native/yoga/yoga/YGNodeStyle.h +130 -0
  221. pythonnative/native/yoga/yoga/YGPixelGrid.cpp +22 -0
  222. pythonnative/native/yoga/yoga/YGPixelGrid.h +29 -0
  223. pythonnative/native/yoga/yoga/YGValue.cpp +20 -0
  224. pythonnative/native/yoga/yoga/YGValue.h +84 -0
  225. pythonnative/native/yoga/yoga/Yoga.h +21 -0
  226. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.cpp +563 -0
  227. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.h +41 -0
  228. pythonnative/native/yoga/yoga/algorithm/Align.h +72 -0
  229. pythonnative/native/yoga/yoga/algorithm/Baseline.cpp +78 -0
  230. pythonnative/native/yoga/yoga/algorithm/Baseline.h +21 -0
  231. pythonnative/native/yoga/yoga/algorithm/BoundAxis.h +79 -0
  232. pythonnative/native/yoga/yoga/algorithm/Cache.cpp +121 -0
  233. pythonnative/native/yoga/yoga/algorithm/Cache.h +30 -0
  234. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.cpp +2428 -0
  235. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.h +38 -0
  236. pythonnative/native/yoga/yoga/algorithm/FlexDirection.h +120 -0
  237. pythonnative/native/yoga/yoga/algorithm/FlexLine.cpp +124 -0
  238. pythonnative/native/yoga/yoga/algorithm/FlexLine.h +75 -0
  239. pythonnative/native/yoga/yoga/algorithm/PixelGrid.cpp +132 -0
  240. pythonnative/native/yoga/yoga/algorithm/PixelGrid.h +29 -0
  241. pythonnative/native/yoga/yoga/algorithm/SizingMode.h +73 -0
  242. pythonnative/native/yoga/yoga/algorithm/TrailingPosition.h +44 -0
  243. pythonnative/native/yoga/yoga/config/Config.cpp +135 -0
  244. pythonnative/native/yoga/yoga/config/Config.h +92 -0
  245. pythonnative/native/yoga/yoga/debug/AssertFatal.cpp +53 -0
  246. pythonnative/native/yoga/yoga/debug/AssertFatal.h +29 -0
  247. pythonnative/native/yoga/yoga/debug/Log.cpp +107 -0
  248. pythonnative/native/yoga/yoga/debug/Log.h +34 -0
  249. pythonnative/native/yoga/yoga/enums/Align.h +47 -0
  250. pythonnative/native/yoga/yoga/enums/BoxSizing.h +40 -0
  251. pythonnative/native/yoga/yoga/enums/Dimension.h +40 -0
  252. pythonnative/native/yoga/yoga/enums/Direction.h +41 -0
  253. pythonnative/native/yoga/yoga/enums/Display.h +41 -0
  254. pythonnative/native/yoga/yoga/enums/Edge.h +47 -0
  255. pythonnative/native/yoga/yoga/enums/Errata.h +41 -0
  256. pythonnative/native/yoga/yoga/enums/ExperimentalFeature.h +39 -0
  257. pythonnative/native/yoga/yoga/enums/FlexDirection.h +42 -0
  258. pythonnative/native/yoga/yoga/enums/Gutter.h +41 -0
  259. pythonnative/native/yoga/yoga/enums/Justify.h +44 -0
  260. pythonnative/native/yoga/yoga/enums/LogLevel.h +44 -0
  261. pythonnative/native/yoga/yoga/enums/MeasureMode.h +41 -0
  262. pythonnative/native/yoga/yoga/enums/NodeType.h +40 -0
  263. pythonnative/native/yoga/yoga/enums/Overflow.h +41 -0
  264. pythonnative/native/yoga/yoga/enums/PhysicalEdge.h +21 -0
  265. pythonnative/native/yoga/yoga/enums/PositionType.h +41 -0
  266. pythonnative/native/yoga/yoga/enums/Unit.h +42 -0
  267. pythonnative/native/yoga/yoga/enums/Wrap.h +41 -0
  268. pythonnative/native/yoga/yoga/enums/YogaEnums.h +85 -0
  269. pythonnative/native/yoga/yoga/event/event.cpp +87 -0
  270. pythonnative/native/yoga/yoga/event/event.h +130 -0
  271. pythonnative/native/yoga/yoga/module.modulemap +21 -0
  272. pythonnative/native/yoga/yoga/node/CachedMeasurement.h +53 -0
  273. pythonnative/native/yoga/yoga/node/LayoutResults.cpp +48 -0
  274. pythonnative/native/yoga/yoga/node/LayoutResults.h +122 -0
  275. pythonnative/native/yoga/yoga/node/LayoutableChildren.h +148 -0
  276. pythonnative/native/yoga/yoga/node/Node.cpp +443 -0
  277. pythonnative/native/yoga/yoga/node/Node.h +337 -0
  278. pythonnative/native/yoga/yoga/numeric/Comparison.h +81 -0
  279. pythonnative/native/yoga/yoga/numeric/FloatOptional.h +93 -0
  280. pythonnative/native/yoga/yoga/style/SmallValueBuffer.h +133 -0
  281. pythonnative/native/yoga/yoga/style/Style.h +757 -0
  282. pythonnative/native/yoga/yoga/style/StyleLength.h +107 -0
  283. pythonnative/native/yoga/yoga/style/StyleValueHandle.h +98 -0
  284. pythonnative/native/yoga/yoga/style/StyleValuePool.h +127 -0
  285. pythonnative/native_modules/__init__.py +124 -0
  286. pythonnative/native_modules/app_state.py +99 -0
  287. pythonnative/native_modules/battery.py +75 -0
  288. pythonnative/native_modules/biometrics.py +42 -0
  289. pythonnative/native_modules/camera.py +65 -0
  290. pythonnative/native_modules/clipboard.py +46 -0
  291. pythonnative/native_modules/fallback.py +324 -0
  292. pythonnative/native_modules/file_system.py +145 -0
  293. pythonnative/native_modules/haptics.py +75 -0
  294. pythonnative/native_modules/linking.py +123 -0
  295. pythonnative/native_modules/location.py +75 -0
  296. pythonnative/native_modules/net_info.py +112 -0
  297. pythonnative/native_modules/notifications.py +129 -0
  298. pythonnative/native_modules/permissions.py +108 -0
  299. pythonnative/native_modules/registry.py +526 -0
  300. pythonnative/native_modules/secure_store.py +52 -0
  301. pythonnative/native_modules/share.py +51 -0
  302. pythonnative/native_views/__init__.py +375 -0
  303. pythonnative/native_views/base.py +316 -0
  304. pythonnative/native_views/bridge_backend.py +277 -0
  305. pythonnative/navigation/__init__.py +103 -0
  306. pythonnative/navigation/container.py +154 -0
  307. pythonnative/navigation/handle.py +540 -0
  308. pythonnative/navigation/hooks.py +133 -0
  309. pythonnative/navigation/host.py +58 -0
  310. pythonnative/navigation/linking.py +200 -0
  311. pythonnative/navigation/navigators.py +659 -0
  312. pythonnative/navigation/screen.py +149 -0
  313. pythonnative/navigation/state.py +269 -0
  314. pythonnative/net.py +248 -0
  315. pythonnative/platform.py +166 -0
  316. pythonnative/platform_metrics.py +252 -0
  317. pythonnative/preview.py +287 -0
  318. pythonnative/profiling.py +101 -0
  319. pythonnative/project/__init__.py +68 -0
  320. pythonnative/project/android.py +557 -0
  321. pythonnative/project/builder.py +817 -0
  322. pythonnative/project/config.py +773 -0
  323. pythonnative/project/deps.py +719 -0
  324. pythonnative/project/devices.py +304 -0
  325. pythonnative/project/doctor.py +283 -0
  326. pythonnative/project/fingerprint.py +171 -0
  327. pythonnative/project/icons.py +247 -0
  328. pythonnative/project/ios.py +325 -0
  329. pythonnative/project/lockfile.py +100 -0
  330. pythonnative/project/permissions.py +361 -0
  331. pythonnative/project/plugins.py +519 -0
  332. pythonnative/project/runtime_assets.py +183 -0
  333. pythonnative/py.typed +0 -0
  334. pythonnative/query.py +153 -0
  335. pythonnative/reconciler/__init__.py +29 -0
  336. pythonnative/reconciler/boundaries.py +375 -0
  337. pythonnative/reconciler/children.py +88 -0
  338. pythonnative/reconciler/core.py +1165 -0
  339. pythonnative/reconciler/layout_pass.py +393 -0
  340. pythonnative/reconciler/vnode.py +266 -0
  341. pythonnative/refresh.py +55 -0
  342. pythonnative/runtime.py +306 -0
  343. pythonnative/scheduler.py +159 -0
  344. pythonnative/sdk/__init__.py +153 -0
  345. pythonnative/sdk/_components.py +427 -0
  346. pythonnative/sdk/builtins.py +91 -0
  347. pythonnative/sdk/codegen.py +149 -0
  348. pythonnative/sdk/module_codegen.py +184 -0
  349. pythonnative/sdk/schema.py +224 -0
  350. pythonnative/sdk/templates/contracts.kt +46 -0
  351. pythonnative/sdk/templates/contracts.swift +46 -0
  352. pythonnative/storage.py +184 -0
  353. pythonnative/style.py +841 -0
  354. pythonnative/suspense.py +183 -0
  355. pythonnative/templates/android_template/app/build.gradle +75 -0
  356. pythonnative/templates/android_template/app/proguard-rules.pro +21 -0
  357. pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +24 -0
  358. pythonnative/templates/android_template/app/src/debug/AndroidManifest.xml +7 -0
  359. pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +32 -0
  360. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +130 -0
  361. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +13 -0
  362. pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  363. pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +30 -0
  364. pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +10 -0
  365. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
  366. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
  367. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  368. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  369. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  370. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  371. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  372. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  373. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  374. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  375. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  376. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  377. pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +22 -0
  378. pythonnative/templates/android_template/app/src/main/res/values/colors.xml +5 -0
  379. pythonnative/templates/android_template/app/src/main/res/values/strings.xml +5 -0
  380. pythonnative/templates/android_template/app/src/main/res/values/themes.xml +9 -0
  381. pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +7 -0
  382. pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +13 -0
  383. pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +19 -0
  384. pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +17 -0
  385. pythonnative/templates/android_template/build.gradle +10 -0
  386. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
  387. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +6 -0
  388. pythonnative/templates/android_template/gradle.properties +23 -0
  389. pythonnative/templates/android_template/gradlew +185 -0
  390. pythonnative/templates/android_template/gradlew.bat +89 -0
  391. pythonnative/templates/android_template/settings.gradle +17 -0
  392. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +51 -0
  393. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  394. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +13 -0
  395. pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +6 -0
  396. pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +25 -0
  397. pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
  398. pythonnative/templates/ios_template/ios_template/Info.plist +28 -0
  399. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +390 -0
  400. pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +61 -0
  401. pythonnative/templates/ios_template/ios_template/ViewController.swift +23 -0
  402. pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +745 -0
  403. pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  404. pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +36 -0
  405. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +41 -0
  406. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +32 -0
  407. pythonnative/testing/__init__.py +53 -0
  408. pythonnative/testing/backend.py +276 -0
  409. pythonnative/testing/harness.py +369 -0
  410. pythonnative/utils.py +145 -0
  411. pythonnative-0.40.0.dist-info/DELVEWHEEL +2 -0
  412. pythonnative-0.40.0.dist-info/METADATA +150 -0
  413. pythonnative-0.40.0.dist-info/RECORD +418 -0
  414. pythonnative-0.40.0.dist-info/WHEEL +5 -0
  415. pythonnative-0.40.0.dist-info/entry_points.txt +2 -0
  416. pythonnative-0.40.0.dist-info/licenses/LICENSE +21 -0
  417. pythonnative-0.40.0.dist-info/top_level.txt +1 -0
  418. pythonnative.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
@@ -0,0 +1,73 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import android.app.Activity
4
+ import android.content.Intent
5
+ import com.pythonnative.runtime.bridge.PNRegistry
6
+
7
+ /**
8
+ * Registers the built-in modules and forwards activity callbacks to
9
+ * the modules that need them. The app's `MainActivity` calls the
10
+ * `on*` hooks; nothing here touches Python directly.
11
+ */
12
+ object BuiltinModules {
13
+ val host = HostModule()
14
+ val device = DeviceModule()
15
+ val alert = AlertModule()
16
+ val storage = StorageModule()
17
+ val secureStore = SecureStoreModule()
18
+ val clipboard = ClipboardModule()
19
+ val share = ShareModule()
20
+ val linking = LinkingModule()
21
+ val haptics = HapticsModule()
22
+ val battery = BatteryModule()
23
+ val netInfo = NetInfoModule()
24
+ val appState = AppStateModule()
25
+ val permissions = PermissionsModule()
26
+ val notifications = NotificationsModule()
27
+ val camera = CameraModule()
28
+ val location = LocationModule()
29
+ val biometrics = BiometricsModule()
30
+
31
+ private val all: List<NativeModule> = listOf(
32
+ host, device, alert, storage, secureStore, clipboard, share, linking, haptics,
33
+ battery, netInfo, appState, permissions, notifications, camera, location, biometrics,
34
+ )
35
+
36
+ fun register(registry: PNRegistry) {
37
+ for (module in all) registry.registerModule { module }
38
+ }
39
+
40
+ /** Called from `PNBridge.setContext`; starts the observers that need a context. */
41
+ fun onContextAttached(activity: Activity) {
42
+ battery.attach(activity)
43
+ netInfo.attach(activity)
44
+ activity.intent?.dataString?.let { linking.onDeepLink(it) }
45
+ }
46
+
47
+ /** Forward `Activity.onActivityResult`. Returns `true` when a module consumed it. */
48
+ fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean =
49
+ camera.onActivityResult(requestCode, resultCode, data) || share.onActivityResult(requestCode)
50
+
51
+ /** Forward `Activity.onRequestPermissionsResult`. Returns `true` when a module consumed it. */
52
+ fun onRequestPermissionsResult(
53
+ requestCode: Int,
54
+ @Suppress("UNUSED_PARAMETER") permissionNames: Array<out String>,
55
+ grantResults: IntArray,
56
+ ): Boolean = permissions.onRequestPermissionsResult(requestCode, grantResults)
57
+
58
+ /** Forward `Activity.onNewIntent` (deep links). */
59
+ fun onNewIntent(intent: Intent?) {
60
+ intent?.dataString?.let { linking.onDeepLink(it) }
61
+ }
62
+
63
+ /** Forward activity lifecycle transitions to the `AppState` module. */
64
+ fun onActivityResumed() = appState.transition("active")
65
+ fun onActivityPaused() = appState.transition("inactive")
66
+ fun onActivityStopped() = appState.transition("background")
67
+
68
+ /** Release observers when the activity is destroyed. */
69
+ fun onActivityDestroyed(activity: Activity) {
70
+ battery.detach(activity)
71
+ netInfo.detach(activity)
72
+ }
73
+ }
@@ -0,0 +1,316 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import android.app.AlertDialog
4
+ import android.content.ClipData
5
+ import android.content.ClipboardManager
6
+ import android.content.Context
7
+ import android.content.Intent
8
+ import android.net.Uri
9
+ import android.os.Build
10
+ import android.os.VibrationEffect
11
+ import android.os.Vibrator
12
+ import android.os.VibratorManager
13
+ import android.provider.Settings
14
+ import com.pythonnative.runtime.PNBridge
15
+ import com.pythonnative.runtime.bridge.JsonUtil
16
+ import com.pythonnative.runtime.bridge.PNLog
17
+ import com.pythonnative.runtime.bridge.str
18
+ import com.pythonnative.runtime.bridge.value
19
+ import org.json.JSONArray
20
+ import org.json.JSONObject
21
+ import java.util.Locale
22
+
23
+ /** `Device.info()`: static facts about the OS, hardware, and app directories. */
24
+ class DeviceModule : NativeModule {
25
+ override val name = "Device"
26
+
27
+ override fun call(method: String, args: JSONObject, promise: Promise) {
28
+ when (method) {
29
+ "info" -> {
30
+ val ctx = PNBridge.context()
31
+ val locale = Locale.getDefault()
32
+ promise.resolve(
33
+ mapOf(
34
+ "os" to "android",
35
+ "os_version" to Build.VERSION.RELEASE,
36
+ "sdk_int" to Build.VERSION.SDK_INT,
37
+ "model" to Build.MODEL,
38
+ "manufacturer" to Build.MANUFACTURER,
39
+ "app_dir" to ctx.filesDir.absolutePath,
40
+ "cache_dir" to ctx.cacheDir.absolutePath,
41
+ "locale" to locale.toLanguageTag(),
42
+ "density" to PNBridge.density().toDouble(),
43
+ ),
44
+ )
45
+ }
46
+ else -> promise.rejectUnknownMethod(method)
47
+ }
48
+ }
49
+ }
50
+
51
+ /**
52
+ * `Alert.show({title, message, buttons:[{label, style}], style})`:
53
+ * an `AlertDialog` resolving to the selected button index, or `-1`
54
+ * on dismiss. `AlertDialog` has three slots; the first `default`
55
+ * button takes positive, the first `cancel` negative, the first
56
+ * `destructive` neutral, and leftovers spill into free slots.
57
+ */
58
+ class AlertModule : NativeModule {
59
+ override val name = "Alert"
60
+
61
+ override fun call(method: String, args: JSONObject, promise: Promise) {
62
+ when (method) {
63
+ "present" -> present(args, promise, fireAndForget = false)
64
+ "show" -> present(args, promise, fireAndForget = true)
65
+ else -> promise.rejectUnknownMethod(method)
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Build and show the dialog. `present` resolves with the tapped button
71
+ * index (or -1 on dismiss); `show` resolves immediately so the Python
72
+ * side's synchronous `call("show")` returns before the dialog closes.
73
+ */
74
+ private fun present(args: JSONObject, promise: Promise, fireAndForget: Boolean) {
75
+ val activity = PNBridge.activity()
76
+ if (activity == null) {
77
+ if (fireAndForget) promise.resolve(null) else promise.reject("no activity", "no_activity")
78
+ return
79
+ }
80
+ if (fireAndForget) promise.resolve(null)
81
+ val builder = AlertDialog.Builder(activity)
82
+ builder.setTitle(args.str("title") ?: "")
83
+ args.str("message")?.let { builder.setMessage(it) }
84
+ val buttons = args.value("buttons") as? JSONArray
85
+ val specs = ArrayList<JSONObject>()
86
+ if (buttons != null) for (i in 0 until buttons.length()) buttons.optJSONObject(i)?.let { specs.add(it) }
87
+ if (specs.isEmpty()) specs.add(JSONObject().put("label", "OK").put("style", "default"))
88
+
89
+ val slotFor = HashMap<Int, String>()
90
+ val free = arrayListOf("positive", "negative", "neutral")
91
+ specs.forEachIndexed { i, spec ->
92
+ val preferred = when (spec.str("style") ?: "default") {
93
+ "cancel" -> "negative"
94
+ "destructive" -> "neutral"
95
+ else -> "positive"
96
+ }
97
+ if (free.remove(preferred)) slotFor[i] = preferred
98
+ }
99
+ specs.forEachIndexed { i, _ ->
100
+ if (!slotFor.containsKey(i) && free.isNotEmpty()) slotFor[i] = free.removeAt(0)
101
+ }
102
+ var delivered = false
103
+ fun deliver(index: Int) {
104
+ if (delivered) return
105
+ delivered = true
106
+ if (!fireAndForget) promise.resolve(index)
107
+ }
108
+ specs.forEachIndexed { i, spec ->
109
+ val label = spec.str("label") ?: "OK"
110
+ when (slotFor[i]) {
111
+ "positive" -> builder.setPositiveButton(label) { _, _ -> deliver(i) }
112
+ "negative" -> builder.setNegativeButton(label) { _, _ -> deliver(i) }
113
+ "neutral" -> builder.setNeutralButton(label) { _, _ -> deliver(i) }
114
+ }
115
+ }
116
+ builder.setOnCancelListener { deliver(-1) }
117
+ builder.setOnDismissListener { deliver(-1) }
118
+ builder.show()
119
+ }
120
+ }
121
+
122
+ /** `Clipboard.set_string(value)` / `get_string()`. */
123
+ class ClipboardModule : NativeModule {
124
+ override val name = "Clipboard"
125
+
126
+ private fun manager(): ClipboardManager? =
127
+ PNBridge.context().getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
128
+
129
+ override fun call(method: String, args: JSONObject, promise: Promise) {
130
+ when (method) {
131
+ "set_string" -> {
132
+ manager()?.setPrimaryClip(ClipData.newPlainText("pythonnative", args.str("value") ?: ""))
133
+ promise.resolve(null)
134
+ }
135
+ "get_string" -> {
136
+ val clip = manager()?.primaryClip
137
+ val text = if (clip != null && clip.itemCount > 0) clip.getItemAt(0).text?.toString() else null
138
+ promise.resolve(text ?: "")
139
+ }
140
+ "has_string" -> {
141
+ val clip = manager()?.primaryClip
142
+ promise.resolve(clip != null && clip.itemCount > 0 && !clip.getItemAt(0).text.isNullOrEmpty())
143
+ }
144
+ else -> promise.rejectUnknownMethod(method)
145
+ }
146
+ }
147
+ }
148
+
149
+ /** `Share.share({message, url, title})`: an `ACTION_SEND` chooser resolving `true` when it returns. */
150
+ class ShareModule : NativeModule {
151
+ override val name = "Share"
152
+ private var pending: Promise? = null
153
+ private var pendingCode = 0
154
+
155
+ override fun call(method: String, args: JSONObject, promise: Promise) {
156
+ when (method) {
157
+ "share" -> share(args, promise)
158
+ else -> promise.rejectUnknownMethod(method)
159
+ }
160
+ }
161
+
162
+ private fun share(args: JSONObject, promise: Promise) {
163
+ val activity = PNBridge.activity() ?: return promise.reject("no activity", "no_activity")
164
+ val message = args.str("message")
165
+ val url = args.str("url")
166
+ val body = listOfNotNull(message, url).joinToString("\n")
167
+ if (body.isEmpty()) return promise.resolve(false)
168
+ val intent = Intent(Intent.ACTION_SEND)
169
+ intent.type = "text/plain"
170
+ intent.putExtra(Intent.EXTRA_TEXT, body)
171
+ args.str("title")?.let { intent.putExtra(Intent.EXTRA_SUBJECT, it) }
172
+ try {
173
+ pending?.resolve(true)
174
+ pending = promise
175
+ pendingCode = RequestCodes.next()
176
+ @Suppress("DEPRECATION")
177
+ activity.startActivityForResult(Intent.createChooser(intent, args.str("title")), pendingCode)
178
+ } catch (e: Exception) {
179
+ pending = null
180
+ promise.resolve(false)
181
+ }
182
+ }
183
+
184
+ /** Resolve the pending share when the chooser activity returns. */
185
+ fun onActivityResult(requestCode: Int): Boolean {
186
+ if (requestCode != pendingCode || pending == null) return false
187
+ val p = pending
188
+ pending = null
189
+ // The chooser gives no success signal; returning to the app counts as shared.
190
+ p?.resolve(true)
191
+ return true
192
+ }
193
+ }
194
+
195
+ /**
196
+ * `Linking`: `open_url`, `can_open_url`, `open_settings` (sync bools)
197
+ * plus `url` events for deep links, buffered until a `PythonHost` is
198
+ * installed.
199
+ */
200
+ class LinkingModule : NativeModule {
201
+ override val name = "Linking"
202
+ private val buffered = ArrayList<String>()
203
+ private var initialUrl: String? = null
204
+
205
+ override fun call(method: String, args: JSONObject, promise: Promise) {
206
+ when (method) {
207
+ "open_url" -> promise.resolve(openUrl(args.str("url") ?: ""))
208
+ "can_open_url" -> promise.resolve(canOpen(args.str("url") ?: ""))
209
+ "open_settings" -> promise.resolve(openSettings())
210
+ "get_initial_url" -> promise.resolve(initialUrl)
211
+ else -> promise.rejectUnknownMethod(method)
212
+ }
213
+ }
214
+
215
+ /** Record a deep link and emit it once Python can receive it. */
216
+ fun onDeepLink(url: String) {
217
+ if (initialUrl == null) initialUrl = url
218
+ buffered.add(url)
219
+ PNBridge.runWhenHostReady { flush() }
220
+ }
221
+
222
+ private fun flush() {
223
+ val urls = ArrayList(buffered)
224
+ buffered.clear()
225
+ for (url in urls) ModuleEvents.emit(name, "url", JSONObject().put("url", url))
226
+ }
227
+
228
+ private fun openUrl(url: String): Boolean {
229
+ if (url.isEmpty()) return false
230
+ return try {
231
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
232
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
233
+ PNBridge.context().startActivity(intent)
234
+ true
235
+ } catch (e: Exception) {
236
+ PNLog.swallowed("Linking.open_url", e)
237
+ false
238
+ }
239
+ }
240
+
241
+ private fun canOpen(url: String): Boolean {
242
+ if (url.isEmpty()) return false
243
+ return try {
244
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
245
+ intent.resolveActivity(PNBridge.context().packageManager) != null
246
+ } catch (e: Exception) {
247
+ false
248
+ }
249
+ }
250
+
251
+ private fun openSettings(): Boolean {
252
+ return try {
253
+ val ctx = PNBridge.context()
254
+ val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
255
+ intent.data = Uri.fromParts("package", ctx.packageName, null)
256
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
257
+ ctx.startActivity(intent)
258
+ true
259
+ } catch (e: Exception) {
260
+ false
261
+ }
262
+ }
263
+ }
264
+
265
+ /** `Haptics`: `impact(style)`, `notification(type)`, `selection()`, `vibrate(duration_ms)`, `cancel()`. */
266
+ class HapticsModule : NativeModule {
267
+ override val name = "Haptics"
268
+
269
+ override fun call(method: String, args: JSONObject, promise: Promise) {
270
+ when (method) {
271
+ "impact" -> buzz(IMPACT_MS[args.str("style") ?: "medium"] ?: 20L)
272
+ "notification" -> buzz(NOTIFICATION_MS[args.str("type") ?: args.str("type_") ?: "success"] ?: 30L)
273
+ "selection" -> buzz(10L)
274
+ "vibrate" -> buzz(JsonUtil.toLong(args.opt("duration_ms"), 400L))
275
+ "cancel" -> vibrator()?.cancel()
276
+ else -> return promise.rejectUnknownMethod(method)
277
+ }
278
+ promise.resolve(null)
279
+ }
280
+
281
+ private fun vibrator(): Vibrator? {
282
+ val ctx = PNBridge.context()
283
+ return if (Build.VERSION.SDK_INT >= 31) {
284
+ (ctx.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as? VibratorManager)?.defaultVibrator
285
+ } else {
286
+ @Suppress("DEPRECATION")
287
+ ctx.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator
288
+ }
289
+ }
290
+
291
+ private fun buzz(durationMs: Long) {
292
+ val v = vibrator() ?: return
293
+ try {
294
+ if (Build.VERSION.SDK_INT >= 26) {
295
+ v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE))
296
+ } else {
297
+ @Suppress("DEPRECATION")
298
+ v.vibrate(durationMs)
299
+ }
300
+ } catch (e: Exception) {
301
+ PNLog.swallowed("Haptics.buzz", e)
302
+ }
303
+ }
304
+
305
+ private companion object {
306
+ val IMPACT_MS = mapOf("light" to 10L, "medium" to 20L, "heavy" to 40L, "soft" to 15L, "rigid" to 30L)
307
+ val NOTIFICATION_MS = mapOf("success" to 30L, "warning" to 50L, "error" to 70L)
308
+ }
309
+ }
310
+
311
+ /** Monotonic request codes for `startActivityForResult` / `requestPermissions`. */
312
+ object RequestCodes {
313
+ private var next = 50001
314
+
315
+ fun next(): Int = next++
316
+ }
@@ -0,0 +1,61 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import androidx.fragment.app.FragmentActivity
4
+ import com.pythonnative.runtime.PNBridge
5
+ import com.pythonnative.runtime.bridge.JsonUtil
6
+ import com.pythonnative.runtime.bridge.str
7
+ import com.pythonnative.runtime.bridge.value
8
+ import com.pythonnative.runtime.screens.PNScreenFragment
9
+ import com.pythonnative.runtime.screens.ScreenRegistry
10
+ import org.json.JSONObject
11
+
12
+ /**
13
+ * `Host`: screen hosting and navigation. Screens are the integer ids
14
+ * assigned by [ScreenRegistry] when a [PNScreenFragment] is created.
15
+ */
16
+ class HostModule : NativeModule {
17
+ override val name = "Host"
18
+
19
+ private fun screen(args: JSONObject): PNScreenFragment? = ScreenRegistry.get(JsonUtil.toInt(args.opt("screen")))
20
+
21
+ private fun activity(): FragmentActivity? = PNBridge.activity() as? FragmentActivity
22
+
23
+ override fun call(method: String, args: JSONObject, promise: Promise) {
24
+ when (method) {
25
+ "cache_state" -> {
26
+ screen(args)?.cachedStateJSON = args.str("state")
27
+ promise.resolve(null)
28
+ }
29
+ "attach_root" -> {
30
+ val fragment = screen(args) ?: return promise.reject("unknown screen", "unknown_screen")
31
+ val record = PNBridge.registry.get(JsonUtil.toLong(args.opt("tag")))
32
+ ?: return promise.reject("unknown tag", "unknown_tag")
33
+ fragment.attachRoot(record.view)
34
+ promise.resolve(null)
35
+ }
36
+ "detach_root" -> {
37
+ val fragment = screen(args)
38
+ val record = PNBridge.registry.get(JsonUtil.toLong(args.opt("tag")))
39
+ if (record != null) {
40
+ if (fragment != null) fragment.detachRoot(record.view) else (record.view.parent as? android.view.ViewGroup)?.removeView(record.view)
41
+ }
42
+ promise.resolve(null)
43
+ }
44
+ "finish" -> { activity()?.finish(); promise.resolve(null) }
45
+ "set_options" -> {
46
+ val options = args.value("options") as? JSONObject ?: JSONObject()
47
+ options.str("title")?.let { title -> activity()?.title = title }
48
+ promise.resolve(null)
49
+ }
50
+ "viewport" -> {
51
+ val fragment = screen(args) ?: ScreenRegistry.get(ScreenRegistry.activeId())
52
+ val payload = fragment?.viewport() ?: activity()?.window?.decorView?.let {
53
+ com.pythonnative.runtime.screens.Viewport.describe(it)
54
+ } ?: JSONObject()
55
+ promise.resolve(payload)
56
+ }
57
+ "active_screen" -> promise.resolve(ScreenRegistry.activeId())
58
+ else -> promise.rejectUnknownMethod(method)
59
+ }
60
+ }
61
+ }
@@ -0,0 +1,200 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.app.Activity
5
+ import android.content.Context
6
+ import android.content.Intent
7
+ import android.graphics.Bitmap
8
+ import android.location.Location
9
+ import android.location.LocationListener
10
+ import android.location.LocationManager
11
+ import android.os.Bundle
12
+ import android.provider.MediaStore
13
+ import androidx.biometric.BiometricManager
14
+ import androidx.biometric.BiometricPrompt
15
+ import androidx.core.content.ContextCompat
16
+ import androidx.fragment.app.FragmentActivity
17
+ import com.pythonnative.runtime.PNBridge
18
+ import com.pythonnative.runtime.bridge.MainThread
19
+ import com.pythonnative.runtime.bridge.PNLog
20
+ import com.pythonnative.runtime.bridge.str
21
+ import org.json.JSONObject
22
+ import java.io.File
23
+ import java.io.FileOutputStream
24
+
25
+ /**
26
+ * `Camera.take_photo()` / `pick_from_gallery()`: launch the system
27
+ * capture or pick intent and resolve to the resulting path (a content
28
+ * URI string, or a JPEG written to the cache dir for thumbnails) or
29
+ * `null` when cancelled.
30
+ */
31
+ class CameraModule : NativeModule {
32
+ override val name = "Camera"
33
+ private val pending = HashMap<Int, Promise>()
34
+
35
+ override fun call(method: String, args: JSONObject, promise: Promise) {
36
+ when (method) {
37
+ "take_photo" -> launch(Intent(MediaStore.ACTION_IMAGE_CAPTURE), promise)
38
+ "pick_from_gallery" -> launch(Intent(Intent.ACTION_PICK).apply { type = "image/*" }, promise)
39
+ else -> promise.rejectUnknownMethod(method)
40
+ }
41
+ }
42
+
43
+ private fun launch(intent: Intent, promise: Promise) {
44
+ val activity = PNBridge.activity() ?: return promise.resolve(null)
45
+ val code = RequestCodes.next()
46
+ pending[code] = promise
47
+ try {
48
+ @Suppress("DEPRECATION")
49
+ activity.startActivityForResult(intent, code)
50
+ } catch (e: Exception) {
51
+ pending.remove(code)
52
+ PNLog.swallowed("Camera.launch", e)
53
+ promise.resolve(null)
54
+ }
55
+ }
56
+
57
+ /** Route `Activity.onActivityResult`; `true` when a pending picker matched. */
58
+ fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
59
+ val promise = pending.remove(requestCode) ?: return false
60
+ var path: String? = null
61
+ if (resultCode == Activity.RESULT_OK && data != null) {
62
+ val uri = data.data
63
+ if (uri != null) {
64
+ path = uri.toString()
65
+ } else {
66
+ @Suppress("DEPRECATION")
67
+ val thumb = data.extras?.get("data") as? Bitmap
68
+ if (thumb != null) path = writeBitmapToCache(thumb)
69
+ }
70
+ }
71
+ promise.resolve(path)
72
+ return true
73
+ }
74
+
75
+ private fun writeBitmapToCache(bitmap: Bitmap): String? {
76
+ return try {
77
+ val target = File(PNBridge.context().cacheDir, "pn-camera-${System.currentTimeMillis()}.jpg")
78
+ FileOutputStream(target).use { bitmap.compress(Bitmap.CompressFormat.JPEG, 85, it) }
79
+ target.absolutePath
80
+ } catch (e: Exception) {
81
+ PNLog.swallowed("Camera.writeBitmapToCache", e)
82
+ null
83
+ }
84
+ }
85
+ }
86
+
87
+ /**
88
+ * `Location.get_current()`: the last known fix if fresh enough,
89
+ * otherwise a single `network`/`gps` update with a 15 s timeout.
90
+ * Resolves to `{latitude, longitude}` or `null`.
91
+ */
92
+ class LocationModule : NativeModule {
93
+ override val name = "Location"
94
+
95
+ override fun call(method: String, args: JSONObject, promise: Promise) {
96
+ when (method) {
97
+ "get_current" -> getCurrent(promise)
98
+ else -> promise.rejectUnknownMethod(method)
99
+ }
100
+ }
101
+
102
+ @SuppressLint("MissingPermission")
103
+ private fun getCurrent(promise: Promise) {
104
+ val ctx = PNBridge.context()
105
+ val lm = ctx.getSystemService(Context.LOCATION_SERVICE) as? LocationManager ?: return promise.resolve(null)
106
+ try {
107
+ for (provider in listOf(LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER)) {
108
+ val last = lm.getLastKnownLocation(provider) ?: continue
109
+ if (System.currentTimeMillis() - last.time < 60_000) return promise.resolve(coords(last))
110
+ }
111
+ } catch (e: SecurityException) {
112
+ return promise.resolve(null)
113
+ } catch (e: Exception) {
114
+ PNLog.swallowed("Location.lastKnown", e)
115
+ }
116
+ var settled = false
117
+ val listener = object : LocationListener {
118
+ override fun onLocationChanged(location: Location) {
119
+ if (settled) return
120
+ settled = true
121
+ lm.removeUpdates(this)
122
+ promise.resolve(coords(location))
123
+ }
124
+
125
+ @Deprecated("Deprecated in Java")
126
+ override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {}
127
+ override fun onProviderEnabled(provider: String) {}
128
+ override fun onProviderDisabled(provider: String) {}
129
+ }
130
+ try {
131
+ val provider = when {
132
+ lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) -> LocationManager.NETWORK_PROVIDER
133
+ lm.isProviderEnabled(LocationManager.GPS_PROVIDER) -> LocationManager.GPS_PROVIDER
134
+ else -> return promise.resolve(null)
135
+ }
136
+ lm.requestLocationUpdates(provider, 1000L, 0f, listener)
137
+ MainThread.postDelayed({
138
+ if (settled) return@postDelayed
139
+ settled = true
140
+ lm.removeUpdates(listener)
141
+ promise.resolve(null)
142
+ }, 15_000L)
143
+ } catch (e: Exception) {
144
+ PNLog.swallowed("Location.requestUpdates", e)
145
+ promise.resolve(null)
146
+ }
147
+ }
148
+
149
+ private fun coords(location: Location): Map<String, Any?> = mapOf(
150
+ "latitude" to location.latitude,
151
+ "longitude" to location.longitude,
152
+ "accuracy" to location.accuracy.toDouble(),
153
+ "altitude" to if (location.hasAltitude()) location.altitude else null,
154
+ "timestamp" to location.time,
155
+ )
156
+ }
157
+
158
+ /** `Biometrics.is_available()` (sync bool) and `authenticate(reason)` (async bool via `BiometricPrompt`). */
159
+ class BiometricsModule : NativeModule {
160
+ override val name = "Biometrics"
161
+
162
+ override fun call(method: String, args: JSONObject, promise: Promise) {
163
+ when (method) {
164
+ "is_available" -> promise.resolve(isAvailable())
165
+ "authenticate" -> authenticate(args.str("reason") ?: "Authenticate", promise)
166
+ else -> promise.rejectUnknownMethod(method)
167
+ }
168
+ }
169
+
170
+ private fun isAvailable(): Boolean {
171
+ return try {
172
+ val manager = BiometricManager.from(PNBridge.context())
173
+ manager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
174
+ } catch (e: Exception) {
175
+ false
176
+ }
177
+ }
178
+
179
+ private fun authenticate(reason: String, promise: Promise) {
180
+ val activity = PNBridge.activity() as? FragmentActivity ?: return promise.resolve(false)
181
+ if (!isAvailable()) return promise.resolve(false)
182
+ try {
183
+ val executor = ContextCompat.getMainExecutor(activity)
184
+ val prompt = BiometricPrompt(activity, executor, object : BiometricPrompt.AuthenticationCallback() {
185
+ override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) = promise.resolve(true)
186
+ override fun onAuthenticationError(errorCode: Int, errString: CharSequence) = promise.resolve(false)
187
+ override fun onAuthenticationFailed() {}
188
+ })
189
+ val info = BiometricPrompt.PromptInfo.Builder()
190
+ .setTitle(reason)
191
+ .setNegativeButtonText("Cancel")
192
+ .setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK)
193
+ .build()
194
+ prompt.authenticate(info)
195
+ } catch (e: Exception) {
196
+ PNLog.swallowed("Biometrics.authenticate", e)
197
+ promise.resolve(false)
198
+ }
199
+ }
200
+ }