📄
src/lib/gps.svelte.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import type { Coords } from "./types";
const CONSENT_KEY = "birdgo-gps-consent";
class GpsService {
consent = $state<"granted" | "denied" | null>(null);
position = $state<GeolocationCoordinates | null>(null);
#watchId: number | null = null;
constructor() {
const stored = localStorage.getItem(CONSENT_KEY);
if (stored === "granted") {
this.consent = "granted";
this.#startWatching();
} else if (stored === "denied") {
this.consent = "denied";
}
// null/missing → first visit, dialog will show
}
grant(): void {
if (!navigator.geolocation) {
this.deny();
return;
}
navigator.geolocation.getCurrentPosition(
() => {
this.consent = "granted";
localStorage.setItem(CONSENT_KEY, "granted");
this.#startWatching();
},
() => this.deny(),
);
}
deny(): void {
this.consent = "denied";
this.#stopWatching();
localStorage.setItem(CONSENT_KEY, "denied");
}
get coords(): Coords | undefined {
if (!this.position) return undefined;
return { lat: this.position.latitude, lng: this.position.longitude };
}
#startWatching(): void {
if (!navigator.geolocation || this.#watchId !== null) return;
this.#watchId = navigator.geolocation.watchPosition(
(pos) => {
this.position = pos.coords;
},
() => {},
{ enableHighAccuracy: true },
);
}
#stopWatching(): void {
if (this.#watchId !== null) {
navigator.geolocation.clearWatch(this.#watchId);
this.#watchId = null;
}
this.position = null;
}
}
export const gps = new GpsService();