1 | import { EventEmitter } from '@unimodules/core';
|
2 |
|
3 | interface Coordinates {
|
4 | latitude: number;
|
5 | longitude: number;
|
6 | altitude?: number;
|
7 | accuracy?: number;
|
8 | altitudeAccuracy?: number;
|
9 | heading?: number;
|
10 | speed?: number;
|
11 | }
|
12 |
|
13 | interface Position {
|
14 | coords: Coordinates;
|
15 | timestamp: number;
|
16 | }
|
17 |
|
18 | interface PermissionResult {
|
19 | status: string;
|
20 | }
|
21 |
|
22 | class GeocoderError extends Error {
|
23 | code: string;
|
24 |
|
25 | constructor() {
|
26 | super('Geocoder service is not available for this device.');
|
27 | this.code = 'E_NO_GEOCODER';
|
28 | }
|
29 | }
|
30 |
|
31 | const emitter = new EventEmitter({} as any);
|
32 |
|
33 | function positionToJSON(position: any): Position | null {
|
34 | if (!position) return null;
|
35 |
|
36 | const { coords = {}, timestamp } = position;
|
37 | return {
|
38 | coords: {
|
39 | latitude: coords.latitude,
|
40 | longitude: coords.longitude,
|
41 | altitude: coords.altitude,
|
42 | accuracy: coords.accuracy,
|
43 | altitudeAccuracy: coords.altitudeAccuracy,
|
44 | heading: coords.heading,
|
45 | speed: coords.speed,
|
46 | },
|
47 | timestamp,
|
48 | };
|
49 | }
|
50 |
|
51 | export default {
|
52 | get name(): string {
|
53 | return 'ExpoLocation';
|
54 | },
|
55 | async getProviderStatusAsync(): Promise<{ locationServicesEnabled: boolean }> {
|
56 | return {
|
57 | locationServicesEnabled: 'geolocation' in navigator,
|
58 | };
|
59 | },
|
60 | async getCurrentPositionAsync(options: Object): Promise<Position | null> {
|
61 | return new Promise<Position | null>((resolve, reject) =>
|
62 | navigator.geolocation.getCurrentPosition(
|
63 | position => resolve(positionToJSON(position)),
|
64 | reject,
|
65 | options
|
66 | )
|
67 | );
|
68 | },
|
69 | async removeWatchAsync(watchId): Promise<void> {
|
70 | navigator.geolocation.clearWatch(watchId);
|
71 | },
|
72 | async watchDeviceHeading(headingId): Promise<void> {
|
73 | console.warn('Location.watchDeviceHeading: is not supported on web');
|
74 | },
|
75 | async hasServicesEnabledAsync(): Promise<boolean> {
|
76 | return 'geolocation' in navigator;
|
77 | },
|
78 | async geocodeAsync(): Promise<Array<any>> {
|
79 | throw new GeocoderError();
|
80 | },
|
81 | async reverseGeocodeAsync(): Promise<Array<any>> {
|
82 | throw new GeocoderError();
|
83 | },
|
84 | async watchPositionImplAsync(watchId: string, options: Object): Promise<string> {
|
85 | return new Promise<string>(resolve => {
|
86 |
|
87 | watchId = global.navigator.geolocation.watchPosition(
|
88 | location => {
|
89 | emitter.emit('Expo.locationChanged', { watchId, location: positionToJSON(location) });
|
90 | },
|
91 | null,
|
92 | options
|
93 | );
|
94 | resolve(watchId);
|
95 | });
|
96 | },
|
97 | async requestPermissionsAsync(): Promise<PermissionResult> {
|
98 | return new Promise<PermissionResult>(resolve => {
|
99 | navigator.geolocation.getCurrentPosition(
|
100 | () => resolve({ status: 'granted' }),
|
101 | ({ code }) => {
|
102 | if (code === 1 ) {
|
103 | resolve({ status: 'denied' });
|
104 | } else {
|
105 | resolve({ status: 'undetermined' });
|
106 | }
|
107 | }
|
108 | );
|
109 | });
|
110 | },
|
111 | };
|
112 |
|
\ | No newline at end of file |