@tokamakdev/plugin-location 0.1.0-beta.82 → 0.1.0-beta.84
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/README.md +12 -0
- package/android/LocationPlugin.kt +14 -3
- package/apple/LocationPlugin.swift +12 -6
- package/package.json +3 -3
- package/src/index.ts +2 -2
package/README.md
CHANGED
|
@@ -25,6 +25,18 @@ milliseconds, 0 by default, or takes a new one, and rejects with
|
|
|
25
25
|
`TimeoutError` when none arrives within `timeout` milliseconds, unlimited by
|
|
26
26
|
default. The timeout starts once the user allows location.
|
|
27
27
|
|
|
28
|
+
## Off screen
|
|
29
|
+
|
|
30
|
+
The plugin asks for location while the app is in use only. While the app is
|
|
31
|
+
off screen on iOS or Android, as when Worker code runs in the background, a
|
|
32
|
+
call that would ask the user for permission rejects with `NeedsUIError`. With
|
|
33
|
+
permission granted, the platforms stop locating an app that is off screen
|
|
34
|
+
without background location permission, which the plugin does not request, so
|
|
35
|
+
`getCurrentPosition` rejects with `NotAllowedError` there. iOS still locates
|
|
36
|
+
the app for a few seconds after it leaves the screen.
|
|
37
|
+
|
|
38
|
+
## Platforms
|
|
39
|
+
|
|
28
40
|
The web implementation uses `navigator.geolocation`. Native Tokamak builds use
|
|
29
41
|
Core Location on Apple platforms, `LocationManager` on Android, and WebView2's
|
|
30
42
|
location implementation on Windows. Calling the API on a platform without
|
|
@@ -59,7 +59,10 @@ class TokamakLocationPlugin(
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Passes [action] whether the app may read fine or coarse location, asking when it may not.
|
|
64
|
+
* Throws `NeedsUIError` when asking would show UI while the app is in the background.
|
|
65
|
+
*/
|
|
63
66
|
private fun withPermission(action: (Boolean) -> Unit) {
|
|
64
67
|
if (PERMISSIONS.any { context.checkSelfPermission(it) == PackageManager.PERMISSION_GRANTED }) {
|
|
65
68
|
action(true)
|
|
@@ -93,8 +96,7 @@ class TokamakLocationPlugin(
|
|
|
93
96
|
context.mainExecutor,
|
|
94
97
|
) { location ->
|
|
95
98
|
handler.removeCallbacks(timeout)
|
|
96
|
-
if (location == null)
|
|
97
|
-
else reply(Result.success(position(location)))
|
|
99
|
+
reply(if (location == null) missingFix() else Result.success(position(location)))
|
|
98
100
|
}
|
|
99
101
|
}.onFailure {
|
|
100
102
|
handler.removeCallbacks(timeout)
|
|
@@ -165,6 +167,14 @@ class TokamakLocationPlugin(
|
|
|
165
167
|
private fun permissionDenied(): Result<Any?> =
|
|
166
168
|
Result.failure(TokamakPluginError("NotAllowedError", "Location permission was denied"))
|
|
167
169
|
|
|
170
|
+
/** Why no fix came: Android gives none in the background without background location permission. */
|
|
171
|
+
private fun missingFix(): Result<Any?> =
|
|
172
|
+
if (host.isInForeground || context.checkSelfPermission(BACKGROUND) == PackageManager.PERMISSION_GRANTED) {
|
|
173
|
+
unavailable("Location is unavailable")
|
|
174
|
+
} else {
|
|
175
|
+
Result.failure(TokamakPluginError("NotAllowedError", "Location permission does not cover the background"))
|
|
176
|
+
}
|
|
177
|
+
|
|
168
178
|
private fun unavailable(message: String): Result<Any?> =
|
|
169
179
|
Result.failure(TokamakPluginError("NotReadableError", message))
|
|
170
180
|
|
|
@@ -176,5 +186,6 @@ class TokamakLocationPlugin(
|
|
|
176
186
|
/** The `timeout` that never expires, as the page sends it. */
|
|
177
187
|
const val UNLIMITED = 0xffffffffL
|
|
178
188
|
val PERMISSIONS = setOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
|
|
189
|
+
const val BACKGROUND = Manifest.permission.ACCESS_BACKGROUND_LOCATION
|
|
179
190
|
}
|
|
180
191
|
}
|
|
@@ -23,6 +23,7 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
23
23
|
var timer: DispatchWorkItem?
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
private let host: TokamakHost
|
|
26
27
|
/// Updates watchers.
|
|
27
28
|
private let updates = CLLocationManager()
|
|
28
29
|
/// Takes single fixes for current position requests, apart from watching.
|
|
@@ -31,6 +32,7 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
31
32
|
private var watchers: [UUID: TokamakPluginReply] = [:]
|
|
32
33
|
|
|
33
34
|
init(host: TokamakHost) {
|
|
35
|
+
self.host = host
|
|
34
36
|
super.init()
|
|
35
37
|
for manager in [updates, fixes] {
|
|
36
38
|
manager.delegate = self
|
|
@@ -60,10 +62,9 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
60
62
|
method: String,
|
|
61
63
|
arguments: Any,
|
|
62
64
|
reply: @escaping TokamakPluginReply
|
|
63
|
-
) -> (() -> Void) {
|
|
65
|
+
) throws(TokamakPluginError) -> (() -> Void) {
|
|
64
66
|
guard method == "watchPosition" else {
|
|
65
|
-
|
|
66
|
-
return {}
|
|
67
|
+
throw .notSupported("\(id).\(method) is not supported")
|
|
67
68
|
}
|
|
68
69
|
let subscription = UUID()
|
|
69
70
|
watchers[subscription] = reply
|
|
@@ -121,10 +122,15 @@ final class TokamakLocationPlugin: NSObject, TokamakPlugin,
|
|
|
121
122
|
return
|
|
122
123
|
}
|
|
123
124
|
let status = updates.authorizationStatus
|
|
124
|
-
|
|
125
|
-
updates.requestWhenInUseAuthorization()
|
|
126
|
-
} else {
|
|
125
|
+
guard status == .notDetermined else {
|
|
127
126
|
serve(status)
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
do throws(TokamakPluginError) {
|
|
130
|
+
try host.requireUI()
|
|
131
|
+
updates.requestWhenInUseAuthorization()
|
|
132
|
+
} catch {
|
|
133
|
+
fail(error)
|
|
128
134
|
}
|
|
129
135
|
}
|
|
130
136
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokamakdev/plugin-location",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.84",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/mantty/tokamak.git",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
".": "./src/index.ts"
|
|
12
12
|
},
|
|
13
|
-
"
|
|
14
|
-
"@tokamakdev/plugin": "0.1.0-beta.
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"@tokamakdev/plugin": "0.1.0-beta.84"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"android",
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Plugin } from "@tokamakdev/plugin";
|
|
2
2
|
import * as web from "../web/index.js";
|
|
3
3
|
|
|
4
4
|
export interface Coordinates {
|
|
@@ -27,7 +27,7 @@ export interface PositionOptions {
|
|
|
27
27
|
export type PositionCallback = (position: Position) => void;
|
|
28
28
|
export type PositionErrorCallback = (error: DOMException) => void;
|
|
29
29
|
|
|
30
|
-
class Location extends
|
|
30
|
+
class Location extends Plugin {
|
|
31
31
|
constructor() {
|
|
32
32
|
super("location");
|
|
33
33
|
}
|