pythonnative 0.35.0__py3-none-any.whl → 0.37.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pythonnative/__init__.py +6 -4
- pythonnative/_ios_log.py +1 -1
- pythonnative/alerts.py +34 -88
- pythonnative/bootstrap.py +90 -0
- pythonnative/bridge/__init__.py +306 -0
- pythonnative/bridge/android.py +78 -0
- pythonnative/bridge/codec.py +164 -0
- pythonnative/bridge/fake.py +236 -0
- pythonnative/bridge/ios.py +138 -0
- pythonnative/cli/pn.py +24 -6
- pythonnative/components/layout.py +65 -3
- pythonnative/gestures.py +13 -10
- pythonnative/hooks.py +41 -26
- pythonnative/hosts/__init__.py +13 -36
- pythonnative/hosts/native.py +348 -0
- pythonnative/images.py +6 -5
- pythonnative/mutations.py +21 -0
- pythonnative/native_modules/__init__.py +30 -29
- pythonnative/native_modules/app_state.py +10 -6
- pythonnative/native_modules/battery.py +20 -84
- pythonnative/native_modules/biometrics.py +11 -124
- pythonnative/native_modules/camera.py +15 -291
- pythonnative/native_modules/clipboard.py +14 -109
- pythonnative/native_modules/desktop.py +322 -0
- pythonnative/native_modules/file_system.py +15 -21
- pythonnative/native_modules/haptics.py +19 -129
- pythonnative/native_modules/linking.py +24 -137
- pythonnative/native_modules/location.py +28 -180
- pythonnative/native_modules/net_info.py +25 -135
- pythonnative/native_modules/notifications.py +36 -257
- pythonnative/native_modules/permissions.py +20 -184
- pythonnative/native_modules/registry.py +513 -0
- pythonnative/native_modules/secure_store.py +18 -155
- pythonnative/native_modules/share.py +8 -113
- pythonnative/native_views/__init__.py +67 -86
- pythonnative/native_views/bridge_backend.py +264 -0
- pythonnative/platform.py +19 -15
- pythonnative/platform_metrics.py +3 -3
- pythonnative/project/android.py +0 -3
- pythonnative/project/builder.py +38 -16
- pythonnative/project/config.py +12 -2
- pythonnative/project/plugins.py +366 -0
- pythonnative/py.typed +0 -0
- pythonnative/runtime.py +35 -203
- pythonnative/sdk/__init__.py +48 -33
- pythonnative/sdk/_components.py +57 -76
- pythonnative/storage.py +18 -243
- pythonnative/templates/android_template/app/build.gradle +6 -9
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +34 -166
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +13 -151
- pythonnative/templates/android_template/pythonnative/build.gradle +48 -0
- pythonnative/templates/android_template/pythonnative/src/main/AndroidManifest.xml +11 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/PNBridge.kt +214 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/PythonHost.kt +20 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/animation/AnimationSpecs.kt +141 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/animation/PNAnimator.kt +249 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/bridge/JsonUtil.kt +175 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/bridge/MainThread.kt +32 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/bridge/PNLog.kt +33 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/bridge/PNRegistry.kt +82 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/bridge/PNTransaction.kt +80 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt +115 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/bridge/ViewRegistry.kt +74 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt +35 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt +33 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt +213 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ContainerManagers.kt +69 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ControlManagers.kt +186 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/DatePickerManager.kt +123 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ImageLoader.kt +141 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ImageManager.kt +156 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ModalManager.kt +134 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/PNColor.kt +201 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/PickerManager.kt +87 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/PortalManager.kt +55 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/PressableManager.kt +122 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ScrollViewManager.kt +214 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/SegmentedControlManager.kt +113 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/StatusBarManager.kt +52 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/TabBarManager.kt +131 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/TextInputManager.kt +245 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/TextManager.kt +233 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/ViewStyler.kt +355 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/VirtualListManager.kt +179 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/components/WebViewManager.kt +149 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/gestures/GestureArbiter.kt +233 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/gestures/GestureCoordinator.kt +127 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/gestures/GestureRecognizers.kt +527 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/BuiltinModules.kt +73 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/DeviceModules.kt +316 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/HostModule.kt +97 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/MediaModules.kt +200 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/NativeModule.kt +135 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/NotificationsModule.kt +100 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +88 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/StorageModules.kt +89 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/SystemModules.kt +178 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/plugins/GeneratedPlugins.kt +16 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/screens/Navigator.kt +116 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/screens/PNScreenFragment.kt +223 -0
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/screens/ScreenRegistry.kt +80 -0
- pythonnative/templates/android_template/{app/src/main/java/com/pythonnative/android_template → pythonnative/src/main/java/com/pythonnative/runtime/views}/PNAccessibilityDelegate.kt +5 -4
- pythonnative/templates/android_template/{app/src/main/java/com/pythonnative/android_template → pythonnative/src/main/java/com/pythonnative/runtime/views}/PNBorderDrawable.kt +12 -3
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/views/PNEditText.kt +18 -0
- pythonnative/templates/android_template/{app/src/main/java/com/pythonnative/android_template → pythonnative/src/main/java/com/pythonnative/runtime/views}/PNFrameLayout.kt +9 -10
- pythonnative/templates/android_template/{app/src/main/java/com/pythonnative/android_template → pythonnative/src/main/java/com/pythonnative/runtime/views}/PNVirtualListView.java +9 -12
- pythonnative/templates/android_template/pythonnative/src/test/java/com/pythonnative/runtime/AnimationSpecsTest.kt +75 -0
- pythonnative/templates/android_template/pythonnative/src/test/java/com/pythonnative/runtime/GestureArbiterTest.kt +197 -0
- pythonnative/templates/android_template/pythonnative/src/test/java/com/pythonnative/runtime/PNColorTest.kt +47 -0
- pythonnative/templates/android_template/pythonnative/src/test/java/com/pythonnative/runtime/PNTransactionTest.kt +78 -0
- pythonnative/templates/android_template/pythonnative/src/test/java/com/pythonnative/runtime/PromiseTest.kt +75 -0
- pythonnative/templates/android_template/settings.gradle +1 -0
- pythonnative/templates/ios_template/PythonNativeKit/Package.swift +21 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Animation/PNAnimator.swift +301 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Bridge/PNBridge.swift +191 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Bridge/PNRegistry.swift +140 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Bridge/PNTransaction.swift +165 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Bridge/PNViewRegistry.swift +53 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNButtonManagers.swift +206 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNColor.swift +173 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNComponentManager.swift +183 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNContainerView.swift +56 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNControlManagers.swift +281 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNImageManager.swift +221 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNOverlayManagers.swift +243 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNPressableManager.swift +114 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNScrollViewManager.swift +197 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNTabBarManager.swift +106 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNTextInputManager.swift +289 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNTextManager.swift +230 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNTransform.swift +82 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNViewManager.swift +86 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNViewState.swift +87 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNViewStyler.swift +340 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNVirtualListManager.swift +257 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Components/PNWebViewManager.swift +124 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Gestures/PNGestureCoordinator.swift +260 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/AlertModule.swift +92 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/HostModule.swift +158 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/LifecycleModules.swift +174 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/MediaModules.swift +177 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/PNNativeModule.swift +125 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/PermissionModules.swift +251 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/SystemModules.swift +251 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Plugins/PNPluginRegistration.swift +8 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Screens/PNScreenRegistry.swift +46 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Screens/PNViewController.swift +251 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Support/PNCompat.swift +46 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Support/PNJSON.swift +173 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Support/PNLog.swift +47 -0
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Support/PNWindow.swift +51 -0
- pythonnative/templates/ios_template/PythonNativeKit/Tests/PythonNativeKitTests/PNColorTests.swift +50 -0
- pythonnative/templates/ios_template/PythonNativeKit/Tests/PythonNativeKitTests/PNGestureTests.swift +101 -0
- pythonnative/templates/ios_template/PythonNativeKit/Tests/PythonNativeKitTests/PNManagerTests.swift +124 -0
- pythonnative/templates/ios_template/PythonNativeKit/Tests/PythonNativeKitTests/PNModuleTests.swift +98 -0
- pythonnative/templates/ios_template/PythonNativeKit/Tests/PythonNativeKitTests/PNTransactionTests.swift +91 -0
- pythonnative/templates/ios_template/ios_template/AppDelegate.swift +8 -50
- pythonnative/templates/ios_template/ios_template/Info.plist +4 -4
- pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +38 -46
- pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +11 -16
- pythonnative/templates/ios_template/ios_template/ViewController.swift +12 -142
- pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +47 -1
- pythonnative/utils.py +4 -82
- pythonnative/virtual_rows.py +3 -3
- {pythonnative-0.35.0.dist-info → pythonnative-0.37.0.dist-info}/METADATA +3 -5
- pythonnative-0.37.0.dist-info/RECORD +263 -0
- pythonnative/hosts/android.py +0 -269
- pythonnative/hosts/ios.py +0 -404
- pythonnative/native_views/android.py +0 -3702
- pythonnative/native_views/ios.py +0 -5253
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/Navigator.kt +0 -43
- pythonnative-0.35.0.dist-info/RECORD +0 -155
- {pythonnative-0.35.0.dist-info → pythonnative-0.37.0.dist-info}/WHEEL +0 -0
- {pythonnative-0.35.0.dist-info → pythonnative-0.37.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.35.0.dist-info → pythonnative-0.37.0.dist-info}/licenses/LICENSE +0 -0
- {pythonnative-0.35.0.dist-info → pythonnative-0.37.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
package com.pythonnative.runtime.gestures
|
|
2
|
+
|
|
3
|
+
import kotlin.math.abs
|
|
4
|
+
import kotlin.math.atan2
|
|
5
|
+
import kotlin.math.hypot
|
|
6
|
+
import kotlin.math.max
|
|
7
|
+
|
|
8
|
+
/** Gesture states reported on event payloads. */
|
|
9
|
+
object GestureState {
|
|
10
|
+
const val BEGAN = "began"
|
|
11
|
+
const val CHANGED = "changed"
|
|
12
|
+
const val ENDED = "ended"
|
|
13
|
+
const val CANCELLED = "cancelled"
|
|
14
|
+
|
|
15
|
+
/** Internal verdict used by recognizers to tell the arbiter they cannot succeed. */
|
|
16
|
+
const val FAILED = "__failed"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** A pointer position in the view's coordinate space, in dp. */
|
|
20
|
+
data class Point(val x: Double, val y: Double)
|
|
21
|
+
|
|
22
|
+
/** Output channel of recognizers and the arbiter: `(gesture_index, payload)`. */
|
|
23
|
+
typealias EmitFn = (Int, Map<String, Any?>) -> Unit
|
|
24
|
+
|
|
25
|
+
/** Configuration for one leaf gesture, decoded from the serialized `gestures` prop. */
|
|
26
|
+
data class GestureConfig(
|
|
27
|
+
val kind: String,
|
|
28
|
+
val nTaps: Int = 1,
|
|
29
|
+
val maxDistance: Double = 12.0,
|
|
30
|
+
val minDurationMs: Double = 500.0,
|
|
31
|
+
val minDistance: Double = 10.0,
|
|
32
|
+
val minPointers: Int = 1,
|
|
33
|
+
val direction: String = "any",
|
|
34
|
+
val minVelocity: Double = 300.0,
|
|
35
|
+
val nPointers: Int = 1,
|
|
36
|
+
/** Indices this gesture may be active alongside; `null` means everything. */
|
|
37
|
+
val simultaneous: Set<Int>? = null,
|
|
38
|
+
/** Indices that must fail before this gesture may activate. */
|
|
39
|
+
val waitFor: Set<Int> = emptySet(),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
/** Estimate pointer velocity from recent samples (dp per second). */
|
|
43
|
+
class VelocityEstimator {
|
|
44
|
+
private data class Sample(val x: Double, val y: Double, val t: Double)
|
|
45
|
+
|
|
46
|
+
private val samples = ArrayList<Sample>()
|
|
47
|
+
|
|
48
|
+
fun add(x: Double, y: Double, t: Double) {
|
|
49
|
+
samples.add(Sample(x, y, t))
|
|
50
|
+
val cutoff = t - WINDOW_S
|
|
51
|
+
while (samples.size > 2 && samples[0].t < cutoff) samples.removeAt(0)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fun velocity(): Point {
|
|
55
|
+
if (samples.size < 2) return Point(0.0, 0.0)
|
|
56
|
+
val first = samples.first()
|
|
57
|
+
val last = samples.last()
|
|
58
|
+
val dt = last.t - first.t
|
|
59
|
+
if (dt <= 1e-6) return Point(0.0, 0.0)
|
|
60
|
+
return Point((last.x - first.x) / dt, (last.y - first.y) / dt)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fun reset() = samples.clear()
|
|
64
|
+
|
|
65
|
+
private companion object {
|
|
66
|
+
const val WINDOW_S = 0.1
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
internal fun centroid(pointers: Map<Int, Point>): Point {
|
|
71
|
+
if (pointers.isEmpty()) return Point(0.0, 0.0)
|
|
72
|
+
var xs = 0.0
|
|
73
|
+
var ys = 0.0
|
|
74
|
+
for (p in pointers.values) {
|
|
75
|
+
xs += p.x
|
|
76
|
+
ys += p.y
|
|
77
|
+
}
|
|
78
|
+
return Point(xs / pointers.size, ys / pointers.size)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Base class for one gesture's state machine. `pointers` maps pointer id to position. */
|
|
82
|
+
abstract class Recognizer(val index: Int, val config: GestureConfig, private val emitFn: EmitFn) {
|
|
83
|
+
protected fun emit(state: String, vararg fields: Pair<String, Any?>) {
|
|
84
|
+
val payload = LinkedHashMap<String, Any?>()
|
|
85
|
+
payload["kind"] = config.kind
|
|
86
|
+
payload["state"] = state
|
|
87
|
+
for ((k, v) in fields) payload[k] = v
|
|
88
|
+
emitFn(index, payload)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Report that this gesture can no longer succeed this interaction. */
|
|
92
|
+
protected fun fail() {
|
|
93
|
+
emitFn(index, mapOf("kind" to config.kind, "state" to GestureState.FAILED))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Abandon recognition without emitting anything (lost a race). */
|
|
97
|
+
open fun forceFail(t: Double) = cancel(t)
|
|
98
|
+
|
|
99
|
+
open fun down(pointers: Map<Int, Point>, t: Double) {}
|
|
100
|
+
open fun move(pointers: Map<Int, Point>, t: Double) {}
|
|
101
|
+
open fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {}
|
|
102
|
+
open fun cancel(t: Double) {}
|
|
103
|
+
|
|
104
|
+
/** Next time `poll` should run, or `null`. */
|
|
105
|
+
open fun deadline(): Double? = null
|
|
106
|
+
open fun poll(t: Double) {}
|
|
107
|
+
|
|
108
|
+
companion object {
|
|
109
|
+
/** Build the recognizer for `config.kind`, or `null` for unknown kinds. */
|
|
110
|
+
fun create(index: Int, config: GestureConfig, emit: EmitFn): Recognizer? = when (config.kind) {
|
|
111
|
+
"tap" -> TapRecognizer(index, config, emit)
|
|
112
|
+
"long_press" -> LongPressRecognizer(index, config, emit)
|
|
113
|
+
"pan" -> PanRecognizer(index, config, emit)
|
|
114
|
+
"swipe", "fling" -> SwipeRecognizer(index, config, emit)
|
|
115
|
+
"pinch" -> PinchRecognizer(index, config, emit)
|
|
116
|
+
"rotation" -> RotationRecognizer(index, config, emit)
|
|
117
|
+
else -> null
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
class TapRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
|
|
123
|
+
private val nTaps = max(1, config.nTaps)
|
|
124
|
+
private val slop = config.maxDistance
|
|
125
|
+
private var downPos: Point? = null
|
|
126
|
+
private var downTime = 0.0
|
|
127
|
+
private var tapCount = 0
|
|
128
|
+
private var lastTapTime = 0.0
|
|
129
|
+
private var failed = false
|
|
130
|
+
private var gapDeadline: Double? = null
|
|
131
|
+
|
|
132
|
+
override fun down(pointers: Map<Int, Point>, t: Double) {
|
|
133
|
+
if (pointers.size != 1) {
|
|
134
|
+
if (!failed) {
|
|
135
|
+
failed = true
|
|
136
|
+
fail()
|
|
137
|
+
}
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
if (tapCount > 0 && t - lastTapTime > MULTI_TAP_GAP_S) tapCount = 0
|
|
141
|
+
failed = false
|
|
142
|
+
gapDeadline = null
|
|
143
|
+
downPos = centroid(pointers)
|
|
144
|
+
downTime = t
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
override fun move(pointers: Map<Int, Point>, t: Double) {
|
|
148
|
+
val origin = downPos ?: return
|
|
149
|
+
if (failed) return
|
|
150
|
+
val c = centroid(pointers)
|
|
151
|
+
if (hypot(c.x - origin.x, c.y - origin.y) > slop) {
|
|
152
|
+
failed = true
|
|
153
|
+
fail()
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
|
|
158
|
+
if (failed || downPos == null) {
|
|
159
|
+
reset()
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
if (t - downTime > MAX_TAP_DURATION_S) {
|
|
163
|
+
reset()
|
|
164
|
+
fail()
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
tapCount += 1
|
|
168
|
+
lastTapTime = t
|
|
169
|
+
if (tapCount >= nTaps) {
|
|
170
|
+
emit(GestureState.ENDED, "x" to x, "y" to y)
|
|
171
|
+
reset()
|
|
172
|
+
} else {
|
|
173
|
+
gapDeadline = t + MULTI_TAP_GAP_S
|
|
174
|
+
}
|
|
175
|
+
downPos = null
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
override fun cancel(t: Double) = reset()
|
|
179
|
+
|
|
180
|
+
override fun deadline(): Double? = gapDeadline
|
|
181
|
+
|
|
182
|
+
override fun poll(t: Double) {
|
|
183
|
+
val d = gapDeadline ?: return
|
|
184
|
+
if (t >= d) {
|
|
185
|
+
gapDeadline = null
|
|
186
|
+
tapCount = 0
|
|
187
|
+
fail()
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private fun reset() {
|
|
192
|
+
downPos = null
|
|
193
|
+
if (tapCount >= nTaps) tapCount = 0
|
|
194
|
+
failed = false
|
|
195
|
+
gapDeadline = null
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private companion object {
|
|
199
|
+
const val MAX_TAP_DURATION_S = 0.4
|
|
200
|
+
const val MULTI_TAP_GAP_S = 0.3
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
class LongPressRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
|
|
205
|
+
private val durationS = config.minDurationMs / 1000.0
|
|
206
|
+
private val slop = config.maxDistance
|
|
207
|
+
private var downPos: Point? = null
|
|
208
|
+
private var pressDeadline: Double? = null
|
|
209
|
+
private var active = false
|
|
210
|
+
|
|
211
|
+
override fun down(pointers: Map<Int, Point>, t: Double) {
|
|
212
|
+
downPos = centroid(pointers)
|
|
213
|
+
pressDeadline = t + durationS
|
|
214
|
+
active = false
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
override fun move(pointers: Map<Int, Point>, t: Double) {
|
|
218
|
+
val origin = downPos ?: return
|
|
219
|
+
val c = centroid(pointers)
|
|
220
|
+
if (hypot(c.x - origin.x, c.y - origin.y) > slop) {
|
|
221
|
+
if (active) emit(GestureState.CANCELLED, "x" to c.x, "y" to c.y)
|
|
222
|
+
reset()
|
|
223
|
+
fail()
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
|
|
228
|
+
if (active) {
|
|
229
|
+
emit(GestureState.ENDED, "x" to x, "y" to y)
|
|
230
|
+
} else if (downPos != null) {
|
|
231
|
+
fail()
|
|
232
|
+
}
|
|
233
|
+
reset()
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
override fun cancel(t: Double) {
|
|
237
|
+
if (active) emit(GestureState.CANCELLED)
|
|
238
|
+
reset()
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
override fun deadline(): Double? = pressDeadline
|
|
242
|
+
|
|
243
|
+
override fun poll(t: Double) {
|
|
244
|
+
val d = pressDeadline ?: return
|
|
245
|
+
val origin = downPos ?: return
|
|
246
|
+
if (active) return
|
|
247
|
+
if (t >= d) {
|
|
248
|
+
active = true
|
|
249
|
+
pressDeadline = null
|
|
250
|
+
emit(GestureState.BEGAN, "x" to origin.x, "y" to origin.y)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private fun reset() {
|
|
255
|
+
downPos = null
|
|
256
|
+
pressDeadline = null
|
|
257
|
+
active = false
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
class PanRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
|
|
262
|
+
private val minDistance = config.minDistance
|
|
263
|
+
private val minPointers = max(1, config.minPointers)
|
|
264
|
+
private var origin: Point? = null
|
|
265
|
+
private var anchor: Point? = null
|
|
266
|
+
private val velocity = VelocityEstimator()
|
|
267
|
+
private var lastTranslation = Point(0.0, 0.0)
|
|
268
|
+
|
|
269
|
+
/** Whether the pan has activated (hosts use this to block parent interception). */
|
|
270
|
+
var active = false
|
|
271
|
+
private set
|
|
272
|
+
|
|
273
|
+
override fun down(pointers: Map<Int, Point>, t: Double) {
|
|
274
|
+
if (pointers.size < minPointers) return
|
|
275
|
+
if (origin == null) {
|
|
276
|
+
val c = centroid(pointers)
|
|
277
|
+
origin = c
|
|
278
|
+
velocity.reset()
|
|
279
|
+
velocity.add(c.x, c.y, t)
|
|
280
|
+
} else {
|
|
281
|
+
rebase(pointers)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
override fun move(pointers: Map<Int, Point>, t: Double) {
|
|
286
|
+
val o = origin ?: return
|
|
287
|
+
if (pointers.size < minPointers) return
|
|
288
|
+
val c = centroid(pointers)
|
|
289
|
+
velocity.add(c.x, c.y, t)
|
|
290
|
+
if (!active) {
|
|
291
|
+
if (hypot(c.x - o.x, c.y - o.y) < minDistance) return
|
|
292
|
+
active = true
|
|
293
|
+
anchor = c
|
|
294
|
+
emit(GestureState.BEGAN, "x" to c.x, "y" to c.y, "pointer_count" to pointers.size)
|
|
295
|
+
return
|
|
296
|
+
}
|
|
297
|
+
val a = anchor ?: return
|
|
298
|
+
val v = velocity.velocity()
|
|
299
|
+
lastTranslation = Point(c.x - a.x, c.y - a.y)
|
|
300
|
+
emit(
|
|
301
|
+
GestureState.CHANGED,
|
|
302
|
+
"x" to c.x,
|
|
303
|
+
"y" to c.y,
|
|
304
|
+
"translation_x" to lastTranslation.x,
|
|
305
|
+
"translation_y" to lastTranslation.y,
|
|
306
|
+
"velocity_x" to v.x,
|
|
307
|
+
"velocity_y" to v.y,
|
|
308
|
+
"pointer_count" to pointers.size,
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
|
|
313
|
+
if (active && pointers.size < minPointers) {
|
|
314
|
+
val v = velocity.velocity()
|
|
315
|
+
val a = anchor ?: Point(x, y)
|
|
316
|
+
emit(
|
|
317
|
+
GestureState.ENDED,
|
|
318
|
+
"x" to x,
|
|
319
|
+
"y" to y,
|
|
320
|
+
"translation_x" to x - a.x,
|
|
321
|
+
"translation_y" to y - a.y,
|
|
322
|
+
"velocity_x" to v.x,
|
|
323
|
+
"velocity_y" to v.y,
|
|
324
|
+
"pointer_count" to pointers.size,
|
|
325
|
+
)
|
|
326
|
+
reset()
|
|
327
|
+
} else if (pointers.isEmpty()) {
|
|
328
|
+
if (!active && origin != null) fail()
|
|
329
|
+
reset()
|
|
330
|
+
} else if (active) {
|
|
331
|
+
rebase(pointers)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
override fun cancel(t: Double) {
|
|
336
|
+
if (active) emit(GestureState.CANCELLED)
|
|
337
|
+
reset()
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private fun rebase(pointers: Map<Int, Point>) {
|
|
341
|
+
val a = anchor
|
|
342
|
+
if (!active || a == null) {
|
|
343
|
+
origin = centroid(pointers)
|
|
344
|
+
return
|
|
345
|
+
}
|
|
346
|
+
val c = centroid(pointers)
|
|
347
|
+
anchor = Point(c.x - lastTranslation.x, c.y - lastTranslation.y)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private fun reset() {
|
|
351
|
+
origin = null
|
|
352
|
+
anchor = null
|
|
353
|
+
active = false
|
|
354
|
+
velocity.reset()
|
|
355
|
+
lastTranslation = Point(0.0, 0.0)
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/** Directional flick recognizer; also serves `fling` (adds a pointer-count requirement). */
|
|
360
|
+
class SwipeRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
|
|
361
|
+
private val direction = config.direction
|
|
362
|
+
private val minVelocity = config.minVelocity
|
|
363
|
+
private val nPointers = max(1, config.nPointers)
|
|
364
|
+
private val velocity = VelocityEstimator()
|
|
365
|
+
private var tracking = false
|
|
366
|
+
private var maxPointers = 0
|
|
367
|
+
|
|
368
|
+
override fun down(pointers: Map<Int, Point>, t: Double) {
|
|
369
|
+
if (!tracking) {
|
|
370
|
+
velocity.reset()
|
|
371
|
+
tracking = true
|
|
372
|
+
maxPointers = 0
|
|
373
|
+
}
|
|
374
|
+
maxPointers = max(maxPointers, pointers.size)
|
|
375
|
+
val c = centroid(pointers)
|
|
376
|
+
velocity.add(c.x, c.y, t)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
override fun move(pointers: Map<Int, Point>, t: Double) {
|
|
380
|
+
if (!tracking) return
|
|
381
|
+
maxPointers = max(maxPointers, pointers.size)
|
|
382
|
+
val c = centroid(pointers)
|
|
383
|
+
velocity.add(c.x, c.y, t)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
|
|
387
|
+
if (!tracking || pointers.isNotEmpty()) return
|
|
388
|
+
tracking = false
|
|
389
|
+
velocity.add(x, y, t)
|
|
390
|
+
val v = velocity.velocity()
|
|
391
|
+
val speed = hypot(v.x, v.y)
|
|
392
|
+
if (speed < minVelocity || maxPointers < nPointers) {
|
|
393
|
+
fail()
|
|
394
|
+
return
|
|
395
|
+
}
|
|
396
|
+
val resolved = if (abs(v.x) >= abs(v.y)) {
|
|
397
|
+
if (v.x > 0) "right" else "left"
|
|
398
|
+
} else {
|
|
399
|
+
if (v.y > 0) "down" else "up"
|
|
400
|
+
}
|
|
401
|
+
if (direction != "any" && direction != resolved) {
|
|
402
|
+
fail()
|
|
403
|
+
return
|
|
404
|
+
}
|
|
405
|
+
emit(
|
|
406
|
+
GestureState.ENDED,
|
|
407
|
+
"x" to x,
|
|
408
|
+
"y" to y,
|
|
409
|
+
"velocity_x" to v.x,
|
|
410
|
+
"velocity_y" to v.y,
|
|
411
|
+
"direction" to resolved,
|
|
412
|
+
"pointer_count" to maxPointers,
|
|
413
|
+
)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
override fun cancel(t: Double) {
|
|
417
|
+
tracking = false
|
|
418
|
+
maxPointers = 0
|
|
419
|
+
velocity.reset()
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
class PinchRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
|
|
424
|
+
private var initial: Double? = null
|
|
425
|
+
private var active = false
|
|
426
|
+
private var scale = 1.0
|
|
427
|
+
|
|
428
|
+
private fun span(pointers: Map<Int, Point>): Double? {
|
|
429
|
+
if (pointers.size < 2) return null
|
|
430
|
+
val pts = pointers.values.take(2)
|
|
431
|
+
return hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
override fun down(pointers: Map<Int, Point>, t: Double) {
|
|
435
|
+
val s = span(pointers)
|
|
436
|
+
if (s != null && s > 0 && initial == null) {
|
|
437
|
+
initial = s
|
|
438
|
+
active = true
|
|
439
|
+
val c = centroid(pointers)
|
|
440
|
+
emit(GestureState.BEGAN, "x" to c.x, "y" to c.y, "scale" to 1.0, "pointer_count" to pointers.size)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
override fun move(pointers: Map<Int, Point>, t: Double) {
|
|
445
|
+
val i = initial ?: return
|
|
446
|
+
if (!active) return
|
|
447
|
+
val s = span(pointers) ?: return
|
|
448
|
+
if (s <= 0) return
|
|
449
|
+
scale = s / i
|
|
450
|
+
val c = centroid(pointers)
|
|
451
|
+
emit(GestureState.CHANGED, "x" to c.x, "y" to c.y, "scale" to scale, "pointer_count" to pointers.size)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
|
|
455
|
+
if (active && pointers.size < 2) {
|
|
456
|
+
emit(GestureState.ENDED, "x" to x, "y" to y, "scale" to scale, "pointer_count" to pointers.size)
|
|
457
|
+
reset()
|
|
458
|
+
} else if (!active && pointers.isEmpty()) {
|
|
459
|
+
fail()
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
override fun cancel(t: Double) {
|
|
464
|
+
if (active) emit(GestureState.CANCELLED, "scale" to scale)
|
|
465
|
+
reset()
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
private fun reset() {
|
|
469
|
+
initial = null
|
|
470
|
+
active = false
|
|
471
|
+
scale = 1.0
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
class RotationRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
|
|
476
|
+
private var initial: Double? = null
|
|
477
|
+
private var active = false
|
|
478
|
+
private var rotation = 0.0
|
|
479
|
+
|
|
480
|
+
private fun angle(pointers: Map<Int, Point>): Double? {
|
|
481
|
+
if (pointers.size < 2) return null
|
|
482
|
+
val pts = pointers.values.take(2)
|
|
483
|
+
return atan2(pts[1].y - pts[0].y, pts[1].x - pts[0].x)
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
override fun down(pointers: Map<Int, Point>, t: Double) {
|
|
487
|
+
val a = angle(pointers)
|
|
488
|
+
if (a != null && initial == null) {
|
|
489
|
+
initial = a
|
|
490
|
+
active = true
|
|
491
|
+
val c = centroid(pointers)
|
|
492
|
+
emit(GestureState.BEGAN, "x" to c.x, "y" to c.y, "rotation" to 0.0, "pointer_count" to pointers.size)
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
override fun move(pointers: Map<Int, Point>, t: Double) {
|
|
497
|
+
val i = initial ?: return
|
|
498
|
+
if (!active) return
|
|
499
|
+
val a = angle(pointers) ?: return
|
|
500
|
+
var delta = a - i
|
|
501
|
+
while (delta > Math.PI) delta -= 2 * Math.PI
|
|
502
|
+
while (delta < -Math.PI) delta += 2 * Math.PI
|
|
503
|
+
rotation = delta
|
|
504
|
+
val c = centroid(pointers)
|
|
505
|
+
emit(GestureState.CHANGED, "x" to c.x, "y" to c.y, "rotation" to rotation, "pointer_count" to pointers.size)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
|
|
509
|
+
if (active && pointers.size < 2) {
|
|
510
|
+
emit(GestureState.ENDED, "x" to x, "y" to y, "rotation" to rotation, "pointer_count" to pointers.size)
|
|
511
|
+
reset()
|
|
512
|
+
} else if (!active && pointers.isEmpty()) {
|
|
513
|
+
fail()
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
override fun cancel(t: Double) {
|
|
518
|
+
if (active) emit(GestureState.CANCELLED, "rotation" to rotation)
|
|
519
|
+
reset()
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
private fun reset() {
|
|
523
|
+
initial = null
|
|
524
|
+
active = false
|
|
525
|
+
rotation = 0.0
|
|
526
|
+
}
|
|
527
|
+
}
|
|
@@ -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
|
+
}
|