@symbiote-native/location 0.1.1 → 0.1.3
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 +60 -32
- package/build/angular/index.d.ts +1 -0
- package/build/angular/index.js +3 -3
- package/build/angular/services/location-permissions.service.d.ts +12 -0
- package/build/angular/services/location-permissions.service.js +104 -0
- package/build/core/geolocation-polyfill.d.ts +2 -0
- package/build/core/geolocation-polyfill.js +52 -0
- package/build/core/index.d.ts +1 -0
- package/build/core/index.js +1 -0
- package/build/core/location-permission-api.d.ts +13 -0
- package/build/core/location-permission-api.js +15 -0
- package/build/core/location.d.ts +0 -3
- package/build/core/location.js +1 -13
- package/build/core/native-module.d.ts +1 -0
- package/build/react/index.d.ts +2 -0
- package/build/react/index.js +2 -0
- package/build/react/use-location-permissions.d.ts +11 -0
- package/build/react/use-location-permissions.js +6 -0
- package/build/solid/index.d.ts +2 -0
- package/build/solid/index.js +2 -0
- package/build/solid/use-location-permissions.d.ts +12 -0
- package/build/solid/use-location-permissions.js +6 -0
- package/build/svelte/index.d.ts +2 -0
- package/build/svelte/index.js +2 -0
- package/build/svelte/use-location-permissions.svelte.d.ts +11 -0
- package/build/svelte/use-location-permissions.svelte.js +6 -0
- package/build/vue/index.d.ts +2 -0
- package/build/vue/index.js +2 -0
- package/build/vue/use-location-permissions.d.ts +12 -0
- package/build/vue/use-location-permissions.js +6 -0
- package/build-ngc/angular/index.d.ts +1 -0
- package/build-ngc/angular/index.js +3 -3
- package/build-ngc/angular/index.js.map +1 -1
- package/build-ngc/angular/services/location-permissions.service.d.ts +19 -0
- package/build-ngc/angular/services/location-permissions.service.js +39 -0
- package/build-ngc/angular/services/location-permissions.service.js.map +1 -0
- package/build-ngc/core/geolocation-polyfill.d.ts +2 -0
- package/build-ngc/core/geolocation-polyfill.js +53 -0
- package/build-ngc/core/geolocation-polyfill.js.map +1 -0
- package/build-ngc/core/index.d.ts +1 -0
- package/build-ngc/core/index.js +1 -0
- package/build-ngc/core/index.js.map +1 -1
- package/build-ngc/core/location-permission-api.d.ts +13 -0
- package/build-ngc/core/location-permission-api.js +16 -0
- package/build-ngc/core/location-permission-api.js.map +1 -0
- package/build-ngc/core/location.d.ts +0 -3
- package/build-ngc/core/location.js +1 -13
- package/build-ngc/core/location.js.map +1 -1
- package/build-ngc/core/native-module.d.ts +1 -0
- package/build-ngc/core/native-module.js.map +1 -1
- package/package.json +23 -23
- package/src/angular/index.ts +7 -3
- package/src/angular/services/location-permissions.service.ts +40 -0
- package/src/core/geolocation-polyfill.ts +82 -0
- package/src/core/index.ts +1 -0
- package/src/core/location-permission-api.ts +26 -0
- package/src/core/location.ts +1 -16
- package/src/core/native-module.ts +1 -0
- package/src/react/index.ts +6 -0
- package/src/react/use-location-permissions.ts +25 -0
- package/src/solid/index.ts +6 -0
- package/src/solid/use-location-permissions.ts +26 -0
- package/src/svelte/index.ts +6 -0
- package/src/svelte/svelte-ambient.d.ts +3 -0
- package/src/svelte/svelte-compile.test-helper.ts +7 -0
- package/src/svelte/use-location-permissions.svelte.ts +25 -0
- package/src/vue/index.ts +6 -0
- package/src/vue/use-location-permissions.ts +26 -0
package/README.md
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
# @symbiote-native/location
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function or a `usePermissions`-style hook built by `expo-modules-core`'s `createPermissionHook`,
|
|
7
|
-
so there is no adapter-specific state to wrap: the React, Vue, Svelte, Solid, and Angular entry
|
|
8
|
-
points are plain re-exports of the same `core`.
|
|
3
|
+
Find out where the user is, which way they face and whether they are walking, turn an address into
|
|
4
|
+
coordinates and back, and keep tracking in the background or watch for entering a region. One API
|
|
5
|
+
for every [SymbioteNative](../../README.md) adapter (React, Vue, Svelte, Solid and Angular).
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
and
|
|
7
|
+
It wraps [`expo-location`](https://github.com/expo/expo/tree/main/packages/expo-location).
|
|
8
|
+
Functions and streams live in a shared `core`; the three permission hooks
|
|
9
|
+
(`useForegroundPermissions`, `useBackgroundPermissions`, `useMotionActivityPermissions`) are
|
|
10
|
+
per-adapter over the shared `createPermissionHook` factory, and Angular gets one
|
|
11
|
+
`*PermissionsService` each. Background updates and geofencing register as tasks through
|
|
12
|
+
[`@symbiote-native/task-manager`](../task-manager).
|
|
12
13
|
|
|
13
14
|
## Install
|
|
14
15
|
|
|
@@ -24,36 +25,36 @@ npx @symbiote-native/cli new my-app --location
|
|
|
24
25
|
npx @symbiote-native/cli add --location
|
|
25
26
|
```
|
|
26
27
|
|
|
27
|
-
Either way: installs `@symbiote-native/location`, wires the native autolinking automatically, and
|
|
28
|
-
this package has an optional, policy-sensitive Android bundle
|
|
28
|
+
Either way: installs `@symbiote-native/location`, wires the native autolinking automatically, and - since
|
|
29
|
+
this package has an optional, policy-sensitive Android bundle - asks at the end whether to grant
|
|
29
30
|
background location too (see the note below the manual-install block). See
|
|
30
31
|
[`@symbiote-native/cli`](../cli).
|
|
31
32
|
|
|
32
33
|
<details>
|
|
33
|
-
<summary>Manual install (no CLI
|
|
34
|
+
<summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
|
|
34
35
|
|
|
35
36
|
```bash
|
|
36
37
|
npm install @symbiote-native/location
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
`expo-location` and `expo-modules-core` come along as regular dependencies, pinned to exact
|
|
40
|
-
versions
|
|
41
|
+
versions - never install them yourself, and never add the `expo` meta-package to your project.
|
|
41
42
|
|
|
42
43
|
## Required one-time step: native autolinking wiring
|
|
43
44
|
|
|
44
|
-
Same one-time step as every other `expo-modules-core` package this project ships
|
|
45
|
+
Same one-time step as every other `expo-modules-core` package this project ships - see
|
|
45
46
|
[`@symbiote-native/local-auth`'s README](../local-auth/README.md#required-one-time-step-native-autolinking-wiring)
|
|
46
47
|
and the `symbiote-expo-native-module` project skill.
|
|
47
48
|
|
|
48
49
|
`native-link.json` declares four iOS `Info.plist` usage-description keys
|
|
49
50
|
(`NSLocationAlwaysAndWhenInUseUsageDescription`, `NSLocationAlwaysUsageDescription`,
|
|
50
|
-
`NSLocationWhenInUseUsageDescription`, `NSMotionUsageDescription`) with generic default text
|
|
51
|
+
`NSLocationWhenInUseUsageDescription`, `NSMotionUsageDescription`) with generic default text -
|
|
51
52
|
override any of them by setting the same key yourself before or after install
|
|
52
53
|
(`@symbiote-native/expo-modules-link`'s patcher is additive-only). Android's two base permissions
|
|
53
54
|
(`ACCESS_COARSE_LOCATION`/`ACCESS_FINE_LOCATION`) already ship in `expo-location`'s own
|
|
54
55
|
`AndroidManifest.xml` and merge automatically.
|
|
55
56
|
|
|
56
|
-
`native-link.json` also declares `ios.infoPlistArrayKeys.UIBackgroundModes: ["location"]`
|
|
57
|
+
`native-link.json` also declares `ios.infoPlistArrayKeys.UIBackgroundModes: ["location"]` -
|
|
57
58
|
upstream's own `withLocation.ts` config plugin always adds it, since without it iOS silently
|
|
58
59
|
stops delivering `startLocationUpdatesAsync` updates once the app backgrounds. Wired
|
|
59
60
|
automatically by the same postinstall step (see `@symbiote-native/expo-modules-link`), merged
|
|
@@ -61,9 +62,9 @@ into the same array `@symbiote-native/audio`/`@symbiote-native/task-manager` may
|
|
|
61
62
|
|
|
62
63
|
</details>
|
|
63
64
|
|
|
64
|
-
**Background location
|
|
65
|
+
**Background location - opt-in, asked for you.** `ACCESS_BACKGROUND_LOCATION`,
|
|
65
66
|
`FOREGROUND_SERVICE`, `FOREGROUND_SERVICE_LOCATION`, and `ACTIVITY_RECOGNITION` (+ its Play
|
|
66
|
-
Services counterpart) are Android permissions opt-in by default, matching upstream
|
|
67
|
+
Services counterpart) are Android permissions opt-in by default, matching upstream - requesting
|
|
67
68
|
background location triggers Play Console policy review, so it's a deliberate choice, never a
|
|
68
69
|
package side effect. `new --location`/`add --location` above already ask, interactively, whether
|
|
69
70
|
to grant them; say yes and the trio (minus `ACTIVITY_RECOGNITION`, still a hand-edit) lands in
|
|
@@ -74,19 +75,20 @@ option reminder. Said no, or ran non-interactively (CI, piped stdin)? Run it any
|
|
|
74
75
|
npx @symbiote-native/cli grant location
|
|
75
76
|
```
|
|
76
77
|
|
|
77
|
-
Idempotent
|
|
78
|
+
Idempotent - safe to run again even if already granted.
|
|
78
79
|
|
|
79
80
|
## Shape
|
|
80
81
|
|
|
81
82
|
```
|
|
82
|
-
src/core/ location.ts (every function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
src/core/ location.ts (every function), subscribers.ts (the watchId-keyed event-subscriber
|
|
84
|
+
machinery shared by position/heading/motion-activity watches),
|
|
85
|
+
geolocation-polyfill.ts, location-permission-api.ts (get/request pairs the hooks
|
|
86
|
+
bind to), native-module.ts (requireNativeModule resolution), types.ts.
|
|
87
|
+
src/react|vue|solid|svelte/ use-location-permissions: the three permission hooks
|
|
88
|
+
src/angular/ location-permissions.service: Foreground/Background/MotionActivityPermissionsService
|
|
86
89
|
```
|
|
87
90
|
|
|
88
|
-
|
|
89
|
-
`src/core/`. `./angular` stays a physical file/subpath since Angular ships through a separate
|
|
91
|
+
Each adapter subpath re-exports `core` plus its own hooks. `./angular` ships through a separate
|
|
90
92
|
`ngc`/AOT build (`build-ngc/`).
|
|
91
93
|
|
|
92
94
|
## Use it
|
|
@@ -112,7 +114,7 @@ if (granted) {
|
|
|
112
114
|
```
|
|
113
115
|
|
|
114
116
|
Background updates and geofencing register a task defined with
|
|
115
|
-
[`@symbiote-native/task-manager`](../task-manager)'s `defineTask`
|
|
117
|
+
[`@symbiote-native/task-manager`](../task-manager)'s `defineTask` - the task itself must be
|
|
116
118
|
defined at module scope, since native can relaunch the JS bundle headlessly to run it:
|
|
117
119
|
|
|
118
120
|
```ts
|
|
@@ -140,8 +142,10 @@ if (granted) {
|
|
|
140
142
|
}
|
|
141
143
|
```
|
|
142
144
|
|
|
143
|
-
Identical
|
|
144
|
-
`/solid`, `/angular
|
|
145
|
+
Identical function surface on every adapter: `@symbiote-native/location/react`, `/vue`, `/svelte`,
|
|
146
|
+
`/solid`, `/angular`. The permission hooks return the adapter's own reactive box (React tuple,
|
|
147
|
+
Vue `Ref`, Solid `Accessor`, Svelte rune object); on Angular inject the matching service and call
|
|
148
|
+
`connect()` for a signal, `get()` / `request()` to refresh.
|
|
145
149
|
|
|
146
150
|
## API
|
|
147
151
|
|
|
@@ -156,12 +160,13 @@ watchHeadingAsync(callback, errorHandler?): Promise<ILocationSubscription>
|
|
|
156
160
|
geocodeAsync(address: string): Promise<ILocationGeocodedLocation[]>
|
|
157
161
|
reverseGeocodeAsync(location): Promise<ILocationGeocodedAddress[]>
|
|
158
162
|
getForegroundPermissionsAsync() / requestForegroundPermissionsAsync(): Promise<ILocationPermissionResponse>
|
|
159
|
-
useForegroundPermissions(options?)
|
|
163
|
+
useForegroundPermissions(options?) // Angular: ForegroundPermissionsService
|
|
160
164
|
getBackgroundPermissionsAsync() / requestBackgroundPermissionsAsync(): Promise<PermissionResponse>
|
|
161
165
|
useBackgroundPermissions(options?)
|
|
162
166
|
hasServicesEnabledAsync(): Promise<boolean>
|
|
163
167
|
getMotionActivityPermissionsAsync() / requestMotionActivityPermissionsAsync(): Promise<PermissionResponse>
|
|
164
168
|
useMotionActivityPermissions(options?)
|
|
169
|
+
installWebGeolocationPolyfill(): void // navigator.geolocation
|
|
165
170
|
getMotionActivityAsync(): Promise<IMotionActivityObject>
|
|
166
171
|
watchMotionActivityAsync(callback, errorHandler?): Promise<ILocationSubscription> // foreground only
|
|
167
172
|
isBackgroundLocationAvailableAsync(): Promise<boolean>
|
|
@@ -175,19 +180,42 @@ with this repo's `I`-prefix convention for exported types (`ts-js-best-practices
|
|
|
175
180
|
|
|
176
181
|
## Notes
|
|
177
182
|
|
|
178
|
-
- **Motion activity needs no location permission at all**
|
|
183
|
+
- **Motion activity needs no location permission at all** - it reads Play Services activity
|
|
179
184
|
recognition / the iOS motion coprocessor directly, gated only by its own
|
|
180
185
|
`getMotionActivityPermissionsAsync`/`requestMotionActivityPermissionsAsync`.
|
|
181
|
-
- **`watchMotionActivityAsync` is foreground-only**
|
|
186
|
+
- **`watchMotionActivityAsync` is foreground-only** - updates pause while the app is backgrounded
|
|
182
187
|
and resume when it returns, per upstream's own contract.
|
|
188
|
+
- **Ask foreground first, then background.** Background permission is a separate, stricter prompt.
|
|
189
|
+
- **Background tracking has hard limits.** It stops if the user terminates the app. On Android a
|
|
190
|
+
terminated app does not restart on a location or geofence event; on iOS the system relaunches it
|
|
191
|
+
for a new geofence event.
|
|
192
|
+
- **Emulators need a location set.** Android Emulator: Settings > Location > Use location (and turn
|
|
193
|
+
off Improve Location Accuracy). iOS Simulator: Features > Location, anything but None.
|
|
183
194
|
- **No Expo Go warning.** Upstream logs a one-time console warning about background-location
|
|
184
195
|
limits when running inside Expo Go; this project never runs under Expo Go
|
|
185
196
|
(`<examples_vs_dot_examples>` in root CLAUDE.md), so the check and the warning are dropped
|
|
186
197
|
rather than ported.
|
|
187
198
|
|
|
199
|
+
## Common questions
|
|
200
|
+
|
|
201
|
+
- **`getCurrentPositionAsync` hangs on some Android devices.** Race it against your own timer, fall
|
|
202
|
+
back to `getLastKnownPositionAsync()`, and prefer `watchPositionAsync` for updates.
|
|
203
|
+
- **Stops updating in the background after minutes on Android.** Pass `foregroundService` to
|
|
204
|
+
`startLocationUpdatesAsync`.
|
|
205
|
+
- **Background permission denied right away.** Ask foreground first; after Allow Once, a background
|
|
206
|
+
request in the same session silently fails.
|
|
207
|
+
- **Accuracy and battery.** `Accuracy.Balanced` for most uses.
|
|
208
|
+
- **Killed app.** Background tracking stops when the user terminates the app.
|
|
209
|
+
|
|
210
|
+
Sources: [Expo docs: Location](https://docs.expo.dev/versions/latest/sdk/location/),
|
|
211
|
+
[expo/expo#33981](https://github.com/expo/expo/issues/33981),
|
|
212
|
+
[expo/expo#39851](https://github.com/expo/expo/issues/39851),
|
|
213
|
+
[expo/expo#26825](https://github.com/expo/expo/issues/26825),
|
|
214
|
+
[expo/expo#14076](https://github.com/expo/expo/issues/14076).
|
|
215
|
+
|
|
188
216
|
## Test it
|
|
189
217
|
|
|
190
|
-
No Fabric/Descriptor angle at all
|
|
218
|
+
No Fabric/Descriptor angle at all - every function here is a pure async-function surface plus a
|
|
191
219
|
handful of `watchId`-keyed event subscriptions, never a view or per-instance state. Tests inject a
|
|
192
220
|
fake native-module object in place of the real `requireNativeModule` resolution and fire the wired
|
|
193
|
-
listeners directly (`src/core/location.test.ts`)
|
|
221
|
+
listeners directly (`src/core/location.test.ts`) - no `installFabric()`, no ViewConfig.
|
package/build/angular/index.d.ts
CHANGED
package/build/angular/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @symbiote-native/location/angular: the
|
|
2
|
-
//
|
|
3
|
-
// service, so this is a plain re-export.
|
|
1
|
+
// @symbiote-native/location/angular: the core plus the permission services, the location
|
|
2
|
+
// streams need no service wrapper
|
|
4
3
|
export * from '../core/index.js';
|
|
4
|
+
export { ForegroundPermissionsService, BackgroundPermissionsService, MotionActivityPermissionsService, } from './services/location-permissions.service.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PermissionsServiceBase } from '@symbiote-native/angular';
|
|
2
|
+
import type { ILocationPermissionResponse } from '../../core';
|
|
3
|
+
import type { PermissionResponse } from 'expo-modules-core';
|
|
4
|
+
export declare class ForegroundPermissionsService extends PermissionsServiceBase<ILocationPermissionResponse> {
|
|
5
|
+
constructor();
|
|
6
|
+
}
|
|
7
|
+
export declare class BackgroundPermissionsService extends PermissionsServiceBase<PermissionResponse> {
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
export declare class MotionActivityPermissionsService extends PermissionsServiceBase<PermissionResponse> {
|
|
11
|
+
constructor();
|
|
12
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
27
|
+
};
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
34
|
+
};
|
|
35
|
+
import { Injectable } from '@angular/core';
|
|
36
|
+
import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../../core/location-permission-api.js';
|
|
37
|
+
import { PermissionsServiceBase } from '@symbiote-native/angular';
|
|
38
|
+
// Angular twin of `../../react`'s location permission hooks
|
|
39
|
+
let ForegroundPermissionsService = (() => {
|
|
40
|
+
let _classDecorators = [Injectable({ providedIn: 'root' })];
|
|
41
|
+
let _classDescriptor;
|
|
42
|
+
let _classExtraInitializers = [];
|
|
43
|
+
let _classThis;
|
|
44
|
+
let _classSuper = PermissionsServiceBase;
|
|
45
|
+
var ForegroundPermissionsService = class extends _classSuper {
|
|
46
|
+
static { _classThis = this; }
|
|
47
|
+
static {
|
|
48
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
49
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
50
|
+
ForegroundPermissionsService = _classThis = _classDescriptor.value;
|
|
51
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
52
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
53
|
+
}
|
|
54
|
+
constructor() {
|
|
55
|
+
super(foregroundPermissionMethods.getMethod, foregroundPermissionMethods.requestMethod);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return ForegroundPermissionsService = _classThis;
|
|
59
|
+
})();
|
|
60
|
+
export { ForegroundPermissionsService };
|
|
61
|
+
let BackgroundPermissionsService = (() => {
|
|
62
|
+
let _classDecorators = [Injectable({ providedIn: 'root' })];
|
|
63
|
+
let _classDescriptor;
|
|
64
|
+
let _classExtraInitializers = [];
|
|
65
|
+
let _classThis;
|
|
66
|
+
let _classSuper = PermissionsServiceBase;
|
|
67
|
+
var BackgroundPermissionsService = class extends _classSuper {
|
|
68
|
+
static { _classThis = this; }
|
|
69
|
+
static {
|
|
70
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
71
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
72
|
+
BackgroundPermissionsService = _classThis = _classDescriptor.value;
|
|
73
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
74
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
75
|
+
}
|
|
76
|
+
constructor() {
|
|
77
|
+
super(backgroundPermissionMethods.getMethod, backgroundPermissionMethods.requestMethod);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return BackgroundPermissionsService = _classThis;
|
|
81
|
+
})();
|
|
82
|
+
export { BackgroundPermissionsService };
|
|
83
|
+
let MotionActivityPermissionsService = (() => {
|
|
84
|
+
let _classDecorators = [Injectable({ providedIn: 'root' })];
|
|
85
|
+
let _classDescriptor;
|
|
86
|
+
let _classExtraInitializers = [];
|
|
87
|
+
let _classThis;
|
|
88
|
+
let _classSuper = PermissionsServiceBase;
|
|
89
|
+
var MotionActivityPermissionsService = class extends _classSuper {
|
|
90
|
+
static { _classThis = this; }
|
|
91
|
+
static {
|
|
92
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
93
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
94
|
+
MotionActivityPermissionsService = _classThis = _classDescriptor.value;
|
|
95
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
96
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
97
|
+
}
|
|
98
|
+
constructor() {
|
|
99
|
+
super(motionActivityPermissionMethods.getMethod, motionActivityPermissionMethods.requestMethod);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
return MotionActivityPermissionsService = _classThis;
|
|
103
|
+
})();
|
|
104
|
+
export { MotionActivityPermissionsService };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Platform } from 'expo-modules-core';
|
|
2
|
+
import { expoLocation } from './native-module.js';
|
|
3
|
+
import { locationSubscriber } from './subscribers.js';
|
|
4
|
+
import { LocationAccuracy } from './types.js';
|
|
5
|
+
function convertGeolocationOptions(options) {
|
|
6
|
+
return {
|
|
7
|
+
accuracy: options.enableHighAccuracy
|
|
8
|
+
? LocationAccuracy.High
|
|
9
|
+
: LocationAccuracy.Balanced,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
async function requestCurrentPosition(success, error, options) {
|
|
13
|
+
try {
|
|
14
|
+
await expoLocation.requestPermissionsAsync();
|
|
15
|
+
success(await expoLocation.getCurrentPositionAsync(convertGeolocationOptions(options)));
|
|
16
|
+
}
|
|
17
|
+
catch (cause) {
|
|
18
|
+
error(cause);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Returns undefined like the web API, the async work runs detached and reports through `error`
|
|
22
|
+
function getCurrentPosition(success, error = () => { }, options = {}) {
|
|
23
|
+
void requestCurrentPosition(success, error, options);
|
|
24
|
+
}
|
|
25
|
+
function watchPosition(success, error = () => { }, options = {}) {
|
|
26
|
+
const watchId = locationSubscriber.registerCallback(success);
|
|
27
|
+
expoLocation
|
|
28
|
+
.watchPositionImplAsync(watchId, convertGeolocationOptions(options))
|
|
29
|
+
.catch((cause) => {
|
|
30
|
+
locationSubscriber.unregisterCallback(watchId);
|
|
31
|
+
error({ watchId, message: cause.message, code: cause.code });
|
|
32
|
+
});
|
|
33
|
+
return watchId;
|
|
34
|
+
}
|
|
35
|
+
function clearWatch(watchId) {
|
|
36
|
+
locationSubscriber.unregisterCallback(watchId);
|
|
37
|
+
}
|
|
38
|
+
/** Polyfills `navigator.geolocation` for interop with the React Native and Web geolocation API. */
|
|
39
|
+
export function installWebGeolocationPolyfill() {
|
|
40
|
+
if (Platform.OS === 'web')
|
|
41
|
+
return;
|
|
42
|
+
if (!Reflect.has(globalThis, 'window'))
|
|
43
|
+
Reflect.set(globalThis, 'window', globalThis);
|
|
44
|
+
const windowObject = Reflect.get(globalThis, 'window');
|
|
45
|
+
if (!Reflect.has(windowObject, 'navigator'))
|
|
46
|
+
Reflect.set(windowObject, 'navigator', {});
|
|
47
|
+
Reflect.set(Reflect.get(windowObject, 'navigator'), 'geolocation', {
|
|
48
|
+
getCurrentPosition,
|
|
49
|
+
watchPosition,
|
|
50
|
+
clearWatch,
|
|
51
|
+
});
|
|
52
|
+
}
|
package/build/core/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { PermissionStatus, type PermissionHookOptions, type PermissionExpiration, } from 'expo-modules-core';
|
|
2
2
|
export { getCurrentWatchId } from './subscribers';
|
|
3
|
+
export { installWebGeolocationPolyfill } from './geolocation-polyfill';
|
|
3
4
|
export * from './location';
|
|
4
5
|
export * from './types';
|
|
5
6
|
export { LocationAccuracy as Accuracy, LocationActivityType as ActivityType, LocationGeofencingEventType as GeofencingEventType, LocationGeofencingRegionState as GeofencingRegionState, } from './types';
|
package/build/core/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { PermissionStatus, } from 'expo-modules-core';
|
|
2
2
|
export { getCurrentWatchId } from './subscribers.js';
|
|
3
|
+
export { installWebGeolocationPolyfill } from './geolocation-polyfill.js';
|
|
3
4
|
export * from './location.js';
|
|
4
5
|
export * from './types.js';
|
|
5
6
|
export { LocationAccuracy as Accuracy, LocationActivityType as ActivityType, LocationGeofencingEventType as GeofencingEventType, LocationGeofencingRegionState as GeofencingRegionState, } from './types.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getBackgroundPermissionsAsync, getForegroundPermissionsAsync, getMotionActivityPermissionsAsync, requestBackgroundPermissionsAsync, requestForegroundPermissionsAsync, requestMotionActivityPermissionsAsync } from './location';
|
|
2
|
+
export declare const foregroundPermissionMethods: {
|
|
3
|
+
getMethod: typeof getForegroundPermissionsAsync;
|
|
4
|
+
requestMethod: typeof requestForegroundPermissionsAsync;
|
|
5
|
+
};
|
|
6
|
+
export declare const backgroundPermissionMethods: {
|
|
7
|
+
getMethod: typeof getBackgroundPermissionsAsync;
|
|
8
|
+
requestMethod: typeof requestBackgroundPermissionsAsync;
|
|
9
|
+
};
|
|
10
|
+
export declare const motionActivityPermissionMethods: {
|
|
11
|
+
getMethod: typeof getMotionActivityPermissionsAsync;
|
|
12
|
+
requestMethod: typeof requestMotionActivityPermissionsAsync;
|
|
13
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// `methods` every adapter's location permission hooks bind to the shared
|
|
2
|
+
// `@symbiote-native/{react,vue,solid,svelte}` `createPermissionHook` factory
|
|
3
|
+
import { getBackgroundPermissionsAsync, getForegroundPermissionsAsync, getMotionActivityPermissionsAsync, requestBackgroundPermissionsAsync, requestForegroundPermissionsAsync, requestMotionActivityPermissionsAsync, } from './location.js';
|
|
4
|
+
export const foregroundPermissionMethods = {
|
|
5
|
+
getMethod: getForegroundPermissionsAsync,
|
|
6
|
+
requestMethod: requestForegroundPermissionsAsync,
|
|
7
|
+
};
|
|
8
|
+
export const backgroundPermissionMethods = {
|
|
9
|
+
getMethod: getBackgroundPermissionsAsync,
|
|
10
|
+
requestMethod: requestBackgroundPermissionsAsync,
|
|
11
|
+
};
|
|
12
|
+
export const motionActivityPermissionMethods = {
|
|
13
|
+
getMethod: getMotionActivityPermissionsAsync,
|
|
14
|
+
requestMethod: requestMotionActivityPermissionsAsync,
|
|
15
|
+
};
|
package/build/core/location.d.ts
CHANGED
|
@@ -12,14 +12,11 @@ export declare function geocodeAsync(address: string): Promise<ILocationGeocoded
|
|
|
12
12
|
export declare function reverseGeocodeAsync(location: Pick<ILocationGeocodedLocation, 'latitude' | 'longitude'>): Promise<ILocationGeocodedAddress[]>;
|
|
13
13
|
export declare function getForegroundPermissionsAsync(): Promise<ILocationPermissionResponse>;
|
|
14
14
|
export declare function requestForegroundPermissionsAsync(): Promise<ILocationPermissionResponse>;
|
|
15
|
-
export declare const useForegroundPermissions: (options?: import("expo-modules-core").PermissionHookOptions<object> | undefined) => [ILocationPermissionResponse | null, () => Promise<ILocationPermissionResponse>, () => Promise<ILocationPermissionResponse>];
|
|
16
15
|
export declare function getBackgroundPermissionsAsync(): Promise<PermissionResponse>;
|
|
17
16
|
export declare function requestBackgroundPermissionsAsync(): Promise<PermissionResponse>;
|
|
18
|
-
export declare const useBackgroundPermissions: (options?: import("expo-modules-core").PermissionHookOptions<object> | undefined) => [PermissionResponse | null, () => Promise<PermissionResponse>, () => Promise<PermissionResponse>];
|
|
19
17
|
export declare function hasServicesEnabledAsync(): Promise<boolean>;
|
|
20
18
|
export declare function getMotionActivityPermissionsAsync(): Promise<PermissionResponse>;
|
|
21
19
|
export declare function requestMotionActivityPermissionsAsync(): Promise<PermissionResponse>;
|
|
22
|
-
export declare const useMotionActivityPermissions: (options?: import("expo-modules-core").PermissionHookOptions<object> | undefined) => [PermissionResponse | null, () => Promise<PermissionResponse>, () => Promise<PermissionResponse>];
|
|
23
20
|
/** No location permission required — uses Play Services activity recognition / the iOS motion
|
|
24
21
|
* coprocessor directly. */
|
|
25
22
|
export declare function getMotionActivityAsync(): Promise<IMotionActivityObject>;
|
package/build/core/location.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Platform } from 'expo-modules-core';
|
|
2
2
|
import { expoLocation } from './native-module.js';
|
|
3
3
|
import { headingSubscriber, locationErrorSubscriber, locationSubscriber, motionActivitySubscriber, } from './subscribers.js';
|
|
4
4
|
import { LocationAccuracy } from './types.js';
|
|
@@ -85,20 +85,12 @@ export async function getForegroundPermissionsAsync() {
|
|
|
85
85
|
export async function requestForegroundPermissionsAsync() {
|
|
86
86
|
return expoLocation.requestForegroundPermissionsAsync();
|
|
87
87
|
}
|
|
88
|
-
export const useForegroundPermissions = createPermissionHook({
|
|
89
|
-
getMethod: getForegroundPermissionsAsync,
|
|
90
|
-
requestMethod: requestForegroundPermissionsAsync,
|
|
91
|
-
});
|
|
92
88
|
export async function getBackgroundPermissionsAsync() {
|
|
93
89
|
return expoLocation.getBackgroundPermissionsAsync();
|
|
94
90
|
}
|
|
95
91
|
export async function requestBackgroundPermissionsAsync() {
|
|
96
92
|
return expoLocation.requestBackgroundPermissionsAsync();
|
|
97
93
|
}
|
|
98
|
-
export const useBackgroundPermissions = createPermissionHook({
|
|
99
|
-
getMethod: getBackgroundPermissionsAsync,
|
|
100
|
-
requestMethod: requestBackgroundPermissionsAsync,
|
|
101
|
-
});
|
|
102
94
|
export async function hasServicesEnabledAsync() {
|
|
103
95
|
return expoLocation.hasServicesEnabledAsync();
|
|
104
96
|
}
|
|
@@ -108,10 +100,6 @@ export async function getMotionActivityPermissionsAsync() {
|
|
|
108
100
|
export async function requestMotionActivityPermissionsAsync() {
|
|
109
101
|
return expoLocation.requestMotionActivityPermissionsAsync();
|
|
110
102
|
}
|
|
111
|
-
export const useMotionActivityPermissions = createPermissionHook({
|
|
112
|
-
getMethod: getMotionActivityPermissionsAsync,
|
|
113
|
-
requestMethod: requestMotionActivityPermissionsAsync,
|
|
114
|
-
});
|
|
115
103
|
/** No location permission required — uses Play Services activity recognition / the iOS motion
|
|
116
104
|
* coprocessor directly. */
|
|
117
105
|
export async function getMotionActivityAsync() {
|
|
@@ -4,6 +4,7 @@ export type INativeLocationModule = {
|
|
|
4
4
|
addListener(eventName: string, listener: (event: unknown) => void): EventSubscription;
|
|
5
5
|
getProviderStatusAsync(): Promise<ILocationProviderStatus>;
|
|
6
6
|
enableNetworkProviderAsync(): Promise<void>;
|
|
7
|
+
requestPermissionsAsync(): Promise<void>;
|
|
7
8
|
getCurrentPositionAsync(options: ILocationOptions): Promise<ILocationObject>;
|
|
8
9
|
getLastKnownPositionAsync(options: ILocationLastKnownOptions): Promise<ILocationObject | null>;
|
|
9
10
|
watchPositionImplAsync(watchId: number, options: ILocationOptions): Promise<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ILocationPermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
import type { PermissionResponse } from 'expo-modules-core';
|
|
4
|
+
export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => [
|
|
5
|
+
TPermission | null,
|
|
6
|
+
() => Promise<TPermission>,
|
|
7
|
+
() => Promise<TPermission>
|
|
8
|
+
];
|
|
9
|
+
export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
|
|
10
|
+
export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
11
|
+
export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/react';
|
|
2
|
+
import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
|
|
3
|
+
// React twin of `expo-location`'s permission hooks
|
|
4
|
+
export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
|
|
5
|
+
export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
|
|
6
|
+
export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ILocationPermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
import type { PermissionResponse } from 'expo-modules-core';
|
|
4
|
+
import type { Accessor } from 'solid-js';
|
|
5
|
+
export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => [
|
|
6
|
+
Accessor<TPermission | null>,
|
|
7
|
+
() => Promise<TPermission>,
|
|
8
|
+
() => Promise<TPermission>
|
|
9
|
+
];
|
|
10
|
+
export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
|
|
11
|
+
export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
12
|
+
export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/solid';
|
|
2
|
+
import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
|
|
3
|
+
// Solid twin of `../react`'s location permission hooks
|
|
4
|
+
export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
|
|
5
|
+
export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
|
|
6
|
+
export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ILocationPermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
import type { PermissionResponse } from 'expo-modules-core';
|
|
4
|
+
export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => {
|
|
5
|
+
readonly status: TPermission | null;
|
|
6
|
+
requestPermission: () => Promise<TPermission>;
|
|
7
|
+
getPermission: () => Promise<TPermission>;
|
|
8
|
+
};
|
|
9
|
+
export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
|
|
10
|
+
export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
11
|
+
export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/svelte/runes/create-permission-hook';
|
|
2
|
+
import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
|
|
3
|
+
// Svelte twin of `../react`'s location permission hooks
|
|
4
|
+
export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
|
|
5
|
+
export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
|
|
6
|
+
export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ILocationPermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
import type { PermissionResponse } from 'expo-modules-core';
|
|
4
|
+
import type { Ref } from '@vue/runtime-core';
|
|
5
|
+
export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => [
|
|
6
|
+
Ref<TPermission | null>,
|
|
7
|
+
() => Promise<TPermission>,
|
|
8
|
+
() => Promise<TPermission>
|
|
9
|
+
];
|
|
10
|
+
export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
|
|
11
|
+
export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
12
|
+
export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/vue';
|
|
2
|
+
import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
|
|
3
|
+
// Vue twin of `../react`'s location permission hooks
|
|
4
|
+
export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
|
|
5
|
+
export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
|
|
6
|
+
export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
|