craft-native 0.0.90 → 0.0.92
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.
- package/dist/android/src/index.d.ts +36 -1
- package/dist/android/src/index.js +332 -44
- package/dist/android/src/promise-runtime.d.ts +3 -0
- package/dist/android/templates/CraftBridge.kt.template +2167 -1177
- package/dist/android/templates/CraftHealthConnect.kt.template +45 -6
- package/dist/android/templates/CraftHealthConnectStub.kt.template +7 -1
- package/dist/android/templates/CraftNative.kt.template +2250 -0
- package/dist/android/templates/LocationRecordingService.kt.template +34 -9
- package/dist/android/templates/MainActivity.kt.template +42 -8
- package/dist/android/templates/proguard-rules.pro.template +4 -1
- package/dist/android/templates/test-bridges.html +10 -33
- package/dist/api/index.d.ts +1 -1
- package/dist/api/ios-advanced.d.ts +8 -5
- package/dist/api/live-activity-handle.d.ts +6 -0
- package/dist/api/mobile.d.ts +25 -7
- package/dist/api/window.d.ts +2 -0
- package/dist/cli.js +452 -129
- package/dist/index.cjs +77 -22
- package/dist/index.js +77 -22
- package/dist/ios/src/index.d.ts +1 -1
- package/dist/ios/src/index.js +23 -5
- package/dist/ios/templates/CraftApp.swift +706 -92
- package/dist/ios/templates/CraftWatchApp.swift.template +8 -0
- package/dist/ios/templates/WatchApp.Info.plist.template +2 -0
- package/dist/ios/templates/WatchExtension.Info.plist.template +34 -0
- package/dist/ios/templates/project.yml.template +10 -4
- package/dist/mobile.js +52 -21
- package/dist/scaffold-version.d.ts +5 -0
- package/package.json +1 -1
- package/dist/android/templates/CraftBridgeExtensions.kt.template +0 -383
- package/dist/android/templates/CraftWidgetProvider.kt.template +0 -246
|
@@ -35,7 +35,10 @@ class CraftHealthConnect(
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
|
38
|
+
private val closed = java.util.concurrent.atomic.AtomicBoolean(false)
|
|
38
39
|
private val permissionContract = PermissionController.createRequestPermissionResultContract()
|
|
40
|
+
private val authorizationPending = java.util.concurrent.atomic.AtomicBoolean(false)
|
|
41
|
+
@Volatile
|
|
39
42
|
private var pendingPermissions: Set<String> = emptySet()
|
|
40
43
|
|
|
41
44
|
private val client: HealthConnectClient?
|
|
@@ -46,7 +49,13 @@ class CraftHealthConnect(
|
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
fun requestAuthorization(typesJson: String) {
|
|
49
|
-
val requested =
|
|
52
|
+
val requested = try {
|
|
53
|
+
permissionsFor(JSONArray(typesJson)).also {
|
|
54
|
+
require(it.isNotEmpty()) { "At least one Health Connect permission type is required" }
|
|
55
|
+
}
|
|
56
|
+
} catch (error: Exception) {
|
|
57
|
+
return reject("_craftFitnessAuthReject", error.message ?: "Health permissions are invalid")
|
|
58
|
+
}
|
|
50
59
|
val healthClient = client ?: return reject("_craftFitnessAuthReject", "Health Connect is unavailable or requires an update")
|
|
51
60
|
scope.launch {
|
|
52
61
|
try {
|
|
@@ -55,9 +64,25 @@ class CraftHealthConnect(
|
|
|
55
64
|
resolve("_craftFitnessAuthResolve", "true")
|
|
56
65
|
} else {
|
|
57
66
|
pendingPermissions = requested
|
|
67
|
+
authorizationPending.set(true)
|
|
68
|
+
if (closed.get()) {
|
|
69
|
+
authorizationPending.set(false)
|
|
70
|
+
pendingPermissions = emptySet()
|
|
71
|
+
return@launch
|
|
72
|
+
}
|
|
58
73
|
activity.runOnUiThread {
|
|
59
|
-
|
|
60
|
-
|
|
74
|
+
if (closed.get()) return@runOnUiThread
|
|
75
|
+
try {
|
|
76
|
+
val intent = permissionContract.createIntent(activity, requested)
|
|
77
|
+
activity.startActivityForResult(intent, PERMISSION_REQUEST_CODE)
|
|
78
|
+
} catch (error: Exception) {
|
|
79
|
+
authorizationPending.set(false)
|
|
80
|
+
pendingPermissions = emptySet()
|
|
81
|
+
reject(
|
|
82
|
+
"_craftFitnessAuthReject",
|
|
83
|
+
error.message ?: "Health permissions could not be requested"
|
|
84
|
+
)
|
|
85
|
+
}
|
|
61
86
|
}
|
|
62
87
|
}
|
|
63
88
|
} catch (error: Exception) {
|
|
@@ -68,9 +93,17 @@ class CraftHealthConnect(
|
|
|
68
93
|
|
|
69
94
|
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
|
|
70
95
|
if (requestCode != PERMISSION_REQUEST_CODE) return false
|
|
71
|
-
|
|
72
|
-
|
|
96
|
+
if (closed.get()) return true
|
|
97
|
+
if (!authorizationPending.compareAndSet(true, false)) return true
|
|
98
|
+
val requested = pendingPermissions
|
|
73
99
|
pendingPermissions = emptySet()
|
|
100
|
+
val granted = try {
|
|
101
|
+
permissionContract.parseResult(resultCode, data)
|
|
102
|
+
} catch (error: Exception) {
|
|
103
|
+
reject("_craftFitnessAuthReject", error.message ?: "Health permission result could not be read")
|
|
104
|
+
return true
|
|
105
|
+
}
|
|
106
|
+
resolve("_craftFitnessAuthResolve", if (granted.containsAll(requested)) "true" else "false")
|
|
74
107
|
return true
|
|
75
108
|
}
|
|
76
109
|
|
|
@@ -135,7 +168,7 @@ class CraftHealthConnect(
|
|
|
135
168
|
endTime = end,
|
|
136
169
|
endZoneOffset = zone,
|
|
137
170
|
exerciseType = exerciseType,
|
|
138
|
-
title =
|
|
171
|
+
title = activity.applicationInfo.loadLabel(activity.packageManager).toString(),
|
|
139
172
|
metadata = Metadata.manualEntry(clientRecordId = activityId)
|
|
140
173
|
))
|
|
141
174
|
val distance = data.optDouble("distanceMeters", 0.0)
|
|
@@ -166,6 +199,9 @@ class CraftHealthConnect(
|
|
|
166
199
|
}
|
|
167
200
|
|
|
168
201
|
fun close() {
|
|
202
|
+
closed.set(true)
|
|
203
|
+
authorizationPending.set(false)
|
|
204
|
+
pendingPermissions = emptySet()
|
|
169
205
|
scope.cancel()
|
|
170
206
|
}
|
|
171
207
|
|
|
@@ -183,13 +219,16 @@ class CraftHealthConnect(
|
|
|
183
219
|
permissions.add(HealthPermission.getWritePermission(ActiveCaloriesBurnedRecord::class))
|
|
184
220
|
permissions.add(HealthPermission.getWritePermission(DistanceRecord::class))
|
|
185
221
|
}
|
|
222
|
+
else -> throw IllegalArgumentException("Unsupported Health Connect permission type: ${types.optString(index)}")
|
|
186
223
|
}
|
|
187
224
|
}
|
|
188
225
|
return permissions
|
|
189
226
|
}
|
|
190
227
|
|
|
191
228
|
private fun resolve(callback: String, json: String) {
|
|
229
|
+
if (closed.get()) return
|
|
192
230
|
activity.runOnUiThread {
|
|
231
|
+
if (closed.get()) return@runOnUiThread
|
|
193
232
|
webView.evaluateJavascript("window.$callback && window.$callback($json)", null)
|
|
194
233
|
}
|
|
195
234
|
}
|
|
@@ -9,6 +9,8 @@ class CraftHealthConnect(
|
|
|
9
9
|
private val activity: Activity,
|
|
10
10
|
private val webView: WebView
|
|
11
11
|
) {
|
|
12
|
+
private val closed = java.util.concurrent.atomic.AtomicBoolean(false)
|
|
13
|
+
|
|
12
14
|
fun requestAuthorization(typesJson: String) = reject("_craftFitnessAuthReject")
|
|
13
15
|
|
|
14
16
|
fun getData(type: String, startDate: Long, endDate: Long) = reject("_craftFitnessDataReject")
|
|
@@ -17,10 +19,14 @@ class CraftHealthConnect(
|
|
|
17
19
|
|
|
18
20
|
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean = false
|
|
19
21
|
|
|
20
|
-
fun close()
|
|
22
|
+
fun close() {
|
|
23
|
+
closed.set(true)
|
|
24
|
+
}
|
|
21
25
|
|
|
22
26
|
private fun reject(callback: String) {
|
|
27
|
+
if (closed.get()) return
|
|
23
28
|
activity.runOnUiThread {
|
|
29
|
+
if (closed.get()) return@runOnUiThread
|
|
24
30
|
val reason = JSONObject.quote("Health Connect is disabled")
|
|
25
31
|
webView.evaluateJavascript("window.$callback && window.$callback($reason)", null)
|
|
26
32
|
}
|