@capgo/background-geolocation 7.0.9 → 7.0.11

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/esm/web.js CHANGED
@@ -1,5 +1,11 @@
1
1
  import { WebPlugin } from "@capacitor/core";
2
2
  export class BackgroundGeolocationWeb extends WebPlugin {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.plannedRoute = [];
6
+ this.isOffRoute = true;
7
+ this.distanceThreshold = 50;
8
+ }
3
9
  async start(options, callback) {
4
10
  if (!navigator.geolocation) {
5
11
  callback(undefined, {
@@ -29,6 +35,17 @@ export class BackgroundGeolocationWeb extends WebPlugin {
29
35
  speed: position.coords.speed,
30
36
  time: position.timestamp,
31
37
  };
38
+ if (this.audio && this.plannedRoute.length > 0) {
39
+ const currentPoint = [
40
+ position.coords.longitude,
41
+ position.coords.latitude,
42
+ ];
43
+ const offRoute = this.distancePointToRoute(currentPoint) > this.distanceThreshold;
44
+ if (offRoute == true && this.isOffRoute === false) {
45
+ this.audio.play();
46
+ }
47
+ this.isOffRoute = offRoute;
48
+ }
32
49
  callback(location);
33
50
  }, (error) => {
34
51
  const callbackError = {
@@ -53,5 +70,89 @@ export class BackgroundGeolocationWeb extends WebPlugin {
53
70
  console.log("openSettings: Web implementation cannot open native settings");
54
71
  window.alert("Please enable location permissions in your browser settings");
55
72
  }
73
+ async setPlannedRoute(options) {
74
+ if (!options.soundFile) {
75
+ throw new Error("Sound file is required");
76
+ }
77
+ if (this.audio) {
78
+ this.audio.pause();
79
+ this.audio.src = "";
80
+ this.audio = undefined;
81
+ }
82
+ this.audio = new Audio(options.soundFile);
83
+ this.plannedRoute = options.route || [];
84
+ this.distanceThreshold = options.distance || 50;
85
+ }
86
+ toRadians(degrees) {
87
+ return (degrees * Math.PI) / 180;
88
+ }
89
+ haversine(point1, point2) {
90
+ const [lon1, lat1] = point1;
91
+ const [lon2, lat2] = point2;
92
+ const dLat = this.toRadians(lat2 - lat1);
93
+ const dLon = this.toRadians(lon2 - lon1);
94
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
95
+ Math.cos(this.toRadians(lat1)) *
96
+ Math.cos(this.toRadians(lat2)) *
97
+ Math.sin(dLon / 2) *
98
+ Math.sin(dLon / 2);
99
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
100
+ return BackgroundGeolocationWeb.EARTH_RADIUS_M * c;
101
+ }
102
+ distancePointToLineSegment(point, lineStart, lineEnd) {
103
+ // Calculate the distances between the three points using Haversine
104
+ const dist_A_B = this.haversine(point, lineStart);
105
+ const dist_A_C = this.haversine(point, lineEnd);
106
+ const dist_B_C = this.haversine(lineStart, lineEnd);
107
+ // Handle the edge case where the line segment is a single point
108
+ if (dist_B_C === 0) {
109
+ return dist_A_B;
110
+ }
111
+ // Check if the angles at the line segment's endpoints are obtuse.
112
+ // We use the Law of Cosines (c^2 = a^2 + b^2 - 2ab*cos(C))
113
+ // If cos(C) < 0, the angle is obtuse.
114
+ // Angle at B (lineStart)
115
+ // Use a small epsilon to handle floating point inaccuracies in division by zero
116
+ const cos_B = (dist_A_B ** 2 + dist_B_C ** 2 - dist_A_C ** 2) /
117
+ (2 * dist_A_B * dist_B_C + Number.EPSILON);
118
+ if (cos_B < 0) {
119
+ return dist_A_B;
120
+ }
121
+ // Angle at C (lineEnd)
122
+ const cos_C = (dist_A_C ** 2 + dist_B_C ** 2 - dist_A_B ** 2) /
123
+ (2 * dist_A_C * dist_B_C + Number.EPSILON);
124
+ if (cos_C < 0) {
125
+ return dist_A_C;
126
+ }
127
+ // If both angles are acute, the closest point is on the line segment itself.
128
+ // We can calculate the distance (height of the triangle) using its area.
129
+ // 1. Calculate the semi-perimeter of the triangle ABC
130
+ const s = (dist_A_B + dist_A_C + dist_B_C) / 2;
131
+ // 2. Calculate the area using Heron's formula
132
+ const area = Math.sqrt(Math.max(0, s * (s - dist_A_B) * (s - dist_A_C) * (s - dist_B_C)));
133
+ // 3. The distance is the height of the triangle from point A to the base BC
134
+ // Area = 0.5 * base * height => height = 2 * Area / base
135
+ return (2 * area) / (dist_B_C + Number.EPSILON);
136
+ }
137
+ distancePointToRoute(point) {
138
+ // If the route has less than 2 points, we can't form a segment.
139
+ if (this.plannedRoute.length < 2) {
140
+ if (this.plannedRoute.length === 1) {
141
+ return this.haversine(point, this.plannedRoute[0]);
142
+ }
143
+ return Infinity; // No line segments to measure against
144
+ }
145
+ let minDistance = Infinity;
146
+ for (let i = 0; i < this.plannedRoute.length - 1; i++) {
147
+ const lineStart = this.plannedRoute[i];
148
+ const lineEnd = this.plannedRoute[i + 1];
149
+ const distance = this.distancePointToLineSegment(point, lineStart, lineEnd);
150
+ if (distance < minDistance) {
151
+ minDistance = distance;
152
+ }
153
+ }
154
+ return minDistance;
155
+ }
56
156
  }
157
+ BackgroundGeolocationWeb.EARTH_RADIUS_M = 6371000;
57
158
  //# sourceMappingURL=web.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAS5C,MAAM,OAAO,wBACX,SAAQ,SAAS;IAKjB,KAAK,CAAC,KAAK,CACT,OAAqB,EACrB,QAA8D;QAE9D,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;YAC3B,QAAQ,CAAC,SAAS,EAAE;gBAClB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,8CAA8C;gBACvD,IAAI,EAAE,eAAe;aACtB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,QAAQ,CAAC,SAAS,EAAE;gBAClB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,6BAA6B;gBACtC,IAAI,EAAE,iBAAiB;aACxB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,aAAa,CAChD,CAAC,QAAQ,EAAE,EAAE;YACX,MAAM,QAAQ,GAAa;gBACzB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;gBACpC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB;gBAClD,SAAS,EAAE,KAAK;gBAChB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;gBAChC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;gBAC5B,IAAI,EAAE,QAAQ,CAAC,SAAS;aACzB,CAAC;YACF,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACR,MAAM,aAAa,GAAkB;gBACnC,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;aAC5B,CAAC;YACF,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACrC,CAAC,EACD;YACE,kBAAkB,EAAE,IAAI;YACxB,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SACvC,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC9E,CAAC;CACF","sourcesContent":["import { WebPlugin } from \"@capacitor/core\";\n\nimport type {\n BackgroundGeolocationPlugin,\n StartOptions,\n Location,\n CallbackError,\n} from \"./definitions\";\n\nexport class BackgroundGeolocationWeb\n extends WebPlugin\n implements BackgroundGeolocationPlugin\n{\n private watchId: number | undefined;\n\n async start(\n options: StartOptions,\n callback: (position?: Location, error?: CallbackError) => void,\n ): Promise<void> {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n\n this.watchId = navigator.geolocation.watchPosition(\n (position) => {\n const location: Location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n callback(location);\n },\n (error) => {\n const callbackError: CallbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n },\n {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n },\n );\n }\n\n async stop(): Promise<void> {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n\n async openSettings(): Promise<void> {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAU5C,MAAM,OAAO,wBACX,SAAQ,SAAS;IADnB;;QAOU,iBAAY,GAAuB,EAAE,CAAC;QAEtC,eAAU,GAAG,IAAI,CAAC;QAClB,sBAAiB,GAAG,EAAE,CAAC;IAoMjC,CAAC;IAlMC,KAAK,CAAC,KAAK,CACT,OAAqB,EACrB,QAA8D;QAE9D,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;YAC3B,QAAQ,CAAC,SAAS,EAAE;gBAClB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,8CAA8C;gBACvD,IAAI,EAAE,eAAe;aACtB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,QAAQ,CAAC,SAAS,EAAE;gBAClB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,6BAA6B;gBACtC,IAAI,EAAE,iBAAiB;aACxB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,aAAa,CAChD,CAAC,QAAQ,EAAE,EAAE;YACX,MAAM,QAAQ,GAAa;gBACzB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;gBACpC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;gBAClC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB;gBAClD,SAAS,EAAE,KAAK;gBAChB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;gBAChC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;gBAC5B,IAAI,EAAE,QAAQ,CAAC,SAAS;aACzB,CAAC;YACF,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/C,MAAM,YAAY,GAAqB;oBACrC,QAAQ,CAAC,MAAM,CAAC,SAAS;oBACzB,QAAQ,CAAC,MAAM,CAAC,QAAQ;iBACzB,CAAC;gBACF,MAAM,QAAQ,GACZ,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC;gBACnE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;oBAClD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBACpB,CAAC;gBACD,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;YAC7B,CAAC;YACD,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACR,MAAM,aAAa,GAAkB;gBACnC,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;aAC5B,CAAC;YACF,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACrC,CAAC,EACD;YACE,kBAAkB,EAAE,IAAI;YACxB,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SACvC,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,OAA+B;QACnD,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QACxC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IAClD,CAAC;IAEO,SAAS,CAAC,OAAe;QAC/B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;IACnC,CAAC;IAEO,SAAS,CACf,MAAwB,EACxB,MAAwB;QAExB,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC;QAC5B,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAEzC,MAAM,CAAC,GACL,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC5B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;gBAClB,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QAEvB,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAEzD,OAAO,wBAAwB,CAAC,cAAc,GAAG,CAAC,CAAC;IACrD,CAAC;IAEO,0BAA0B,CAChC,KAAuB,EACvB,SAA2B,EAC3B,OAAyB;QAEzB,mEAAmE;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAEpD,gEAAgE;QAChE,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACnB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,kEAAkE;QAClE,2DAA2D;QAC3D,sCAAsC;QAEtC,yBAAyB;QACzB,gFAAgF;QAChF,MAAM,KAAK,GACT,CAAC,QAAQ,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC;YAC/C,CAAC,CAAC,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,uBAAuB;QACvB,MAAM,KAAK,GACT,CAAC,QAAQ,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC;YAC/C,CAAC,CAAC,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,6EAA6E;QAC7E,yEAAyE;QAEzE,sDAAsD;QACtD,MAAM,CAAC,GAAG,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAE/C,8CAA8C;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CACpB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAClE,CAAC;QAEF,4EAA4E;QAC5E,2DAA2D;QAC3D,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAEO,oBAAoB,CAAC,KAAuB;QAClD,gEAAgE;QAChE,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACrD,CAAC;YACD,OAAO,QAAQ,CAAC,CAAC,sCAAsC;QACzD,CAAC;QAED,IAAI,WAAW,GAAG,QAAQ,CAAC;QAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACtD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,0BAA0B,CAC9C,KAAK,EACL,SAAS,EACT,OAAO,CACR,CAAC;YACF,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;gBAC3B,WAAW,GAAG,QAAQ,CAAC;YACzB,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;;AAzMuB,uCAAc,GAAG,OAAO,AAAV,CAAW","sourcesContent":["import { WebPlugin } from \"@capacitor/core\";\n\nimport type {\n BackgroundGeolocationPlugin,\n StartOptions,\n Location,\n CallbackError,\n SetPlannedRouteOptions,\n} from \"./definitions\";\n\nexport class BackgroundGeolocationWeb\n extends WebPlugin\n implements BackgroundGeolocationPlugin\n{\n private static readonly EARTH_RADIUS_M = 6371000;\n\n private watchId: number | undefined;\n private plannedRoute: [number, number][] = [];\n private audio: HTMLAudioElement | undefined;\n private isOffRoute = true;\n private distanceThreshold = 50;\n\n async start(\n options: StartOptions,\n callback: (position?: Location, error?: CallbackError) => void,\n ): Promise<void> {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n\n this.watchId = navigator.geolocation.watchPosition(\n (position) => {\n const location: Location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n if (this.audio && this.plannedRoute.length > 0) {\n const currentPoint: [number, number] = [\n position.coords.longitude,\n position.coords.latitude,\n ];\n const offRoute =\n this.distancePointToRoute(currentPoint) > this.distanceThreshold;\n if (offRoute == true && this.isOffRoute === false) {\n this.audio.play();\n }\n this.isOffRoute = offRoute;\n }\n callback(location);\n },\n (error) => {\n const callbackError: CallbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n },\n {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n },\n );\n }\n\n async stop(): Promise<void> {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n\n async openSettings(): Promise<void> {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n\n async setPlannedRoute(options: SetPlannedRouteOptions): Promise<void> {\n if (!options.soundFile) {\n throw new Error(\"Sound file is required\");\n }\n if (this.audio) {\n this.audio.pause();\n this.audio.src = \"\";\n this.audio = undefined;\n }\n this.audio = new Audio(options.soundFile);\n this.plannedRoute = options.route || [];\n this.distanceThreshold = options.distance || 50;\n }\n\n private toRadians(degrees: number): number {\n return (degrees * Math.PI) / 180;\n }\n\n private haversine(\n point1: [number, number],\n point2: [number, number],\n ): number {\n const [lon1, lat1] = point1;\n const [lon2, lat2] = point2;\n const dLat = this.toRadians(lat2 - lat1);\n const dLon = this.toRadians(lon2 - lon1);\n\n const a =\n Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(this.toRadians(lat1)) *\n Math.cos(this.toRadians(lat2)) *\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2);\n\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n return BackgroundGeolocationWeb.EARTH_RADIUS_M * c;\n }\n\n private distancePointToLineSegment(\n point: [number, number],\n lineStart: [number, number],\n lineEnd: [number, number],\n ): number {\n // Calculate the distances between the three points using Haversine\n const dist_A_B = this.haversine(point, lineStart);\n const dist_A_C = this.haversine(point, lineEnd);\n const dist_B_C = this.haversine(lineStart, lineEnd);\n\n // Handle the edge case where the line segment is a single point\n if (dist_B_C === 0) {\n return dist_A_B;\n }\n\n // Check if the angles at the line segment's endpoints are obtuse.\n // We use the Law of Cosines (c^2 = a^2 + b^2 - 2ab*cos(C))\n // If cos(C) < 0, the angle is obtuse.\n\n // Angle at B (lineStart)\n // Use a small epsilon to handle floating point inaccuracies in division by zero\n const cos_B =\n (dist_A_B ** 2 + dist_B_C ** 2 - dist_A_C ** 2) /\n (2 * dist_A_B * dist_B_C + Number.EPSILON);\n if (cos_B < 0) {\n return dist_A_B;\n }\n\n // Angle at C (lineEnd)\n const cos_C =\n (dist_A_C ** 2 + dist_B_C ** 2 - dist_A_B ** 2) /\n (2 * dist_A_C * dist_B_C + Number.EPSILON);\n if (cos_C < 0) {\n return dist_A_C;\n }\n\n // If both angles are acute, the closest point is on the line segment itself.\n // We can calculate the distance (height of the triangle) using its area.\n\n // 1. Calculate the semi-perimeter of the triangle ABC\n const s = (dist_A_B + dist_A_C + dist_B_C) / 2;\n\n // 2. Calculate the area using Heron's formula\n const area = Math.sqrt(\n Math.max(0, s * (s - dist_A_B) * (s - dist_A_C) * (s - dist_B_C)),\n );\n\n // 3. The distance is the height of the triangle from point A to the base BC\n // Area = 0.5 * base * height => height = 2 * Area / base\n return (2 * area) / (dist_B_C + Number.EPSILON);\n }\n\n private distancePointToRoute(point: [number, number]): number {\n // If the route has less than 2 points, we can't form a segment.\n if (this.plannedRoute.length < 2) {\n if (this.plannedRoute.length === 1) {\n return this.haversine(point, this.plannedRoute[0]);\n }\n return Infinity; // No line segments to measure against\n }\n\n let minDistance = Infinity;\n\n for (let i = 0; i < this.plannedRoute.length - 1; i++) {\n const lineStart = this.plannedRoute[i];\n const lineEnd = this.plannedRoute[i + 1];\n const distance = this.distancePointToLineSegment(\n point,\n lineStart,\n lineEnd,\n );\n if (distance < minDistance) {\n minDistance = distance;\n }\n }\n\n return minDistance;\n }\n}\n"]}
@@ -7,6 +7,12 @@ const BackgroundGeolocation = core.registerPlugin("BackgroundGeolocation", {
7
7
  });
8
8
 
9
9
  class BackgroundGeolocationWeb extends core.WebPlugin {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.plannedRoute = [];
13
+ this.isOffRoute = true;
14
+ this.distanceThreshold = 50;
15
+ }
10
16
  async start(options, callback) {
11
17
  if (!navigator.geolocation) {
12
18
  callback(undefined, {
@@ -36,6 +42,17 @@ class BackgroundGeolocationWeb extends core.WebPlugin {
36
42
  speed: position.coords.speed,
37
43
  time: position.timestamp,
38
44
  };
45
+ if (this.audio && this.plannedRoute.length > 0) {
46
+ const currentPoint = [
47
+ position.coords.longitude,
48
+ position.coords.latitude,
49
+ ];
50
+ const offRoute = this.distancePointToRoute(currentPoint) > this.distanceThreshold;
51
+ if (offRoute == true && this.isOffRoute === false) {
52
+ this.audio.play();
53
+ }
54
+ this.isOffRoute = offRoute;
55
+ }
39
56
  callback(location);
40
57
  }, (error) => {
41
58
  const callbackError = {
@@ -60,7 +77,91 @@ class BackgroundGeolocationWeb extends core.WebPlugin {
60
77
  console.log("openSettings: Web implementation cannot open native settings");
61
78
  window.alert("Please enable location permissions in your browser settings");
62
79
  }
80
+ async setPlannedRoute(options) {
81
+ if (!options.soundFile) {
82
+ throw new Error("Sound file is required");
83
+ }
84
+ if (this.audio) {
85
+ this.audio.pause();
86
+ this.audio.src = "";
87
+ this.audio = undefined;
88
+ }
89
+ this.audio = new Audio(options.soundFile);
90
+ this.plannedRoute = options.route || [];
91
+ this.distanceThreshold = options.distance || 50;
92
+ }
93
+ toRadians(degrees) {
94
+ return (degrees * Math.PI) / 180;
95
+ }
96
+ haversine(point1, point2) {
97
+ const [lon1, lat1] = point1;
98
+ const [lon2, lat2] = point2;
99
+ const dLat = this.toRadians(lat2 - lat1);
100
+ const dLon = this.toRadians(lon2 - lon1);
101
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
102
+ Math.cos(this.toRadians(lat1)) *
103
+ Math.cos(this.toRadians(lat2)) *
104
+ Math.sin(dLon / 2) *
105
+ Math.sin(dLon / 2);
106
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
107
+ return BackgroundGeolocationWeb.EARTH_RADIUS_M * c;
108
+ }
109
+ distancePointToLineSegment(point, lineStart, lineEnd) {
110
+ // Calculate the distances between the three points using Haversine
111
+ const dist_A_B = this.haversine(point, lineStart);
112
+ const dist_A_C = this.haversine(point, lineEnd);
113
+ const dist_B_C = this.haversine(lineStart, lineEnd);
114
+ // Handle the edge case where the line segment is a single point
115
+ if (dist_B_C === 0) {
116
+ return dist_A_B;
117
+ }
118
+ // Check if the angles at the line segment's endpoints are obtuse.
119
+ // We use the Law of Cosines (c^2 = a^2 + b^2 - 2ab*cos(C))
120
+ // If cos(C) < 0, the angle is obtuse.
121
+ // Angle at B (lineStart)
122
+ // Use a small epsilon to handle floating point inaccuracies in division by zero
123
+ const cos_B = (dist_A_B ** 2 + dist_B_C ** 2 - dist_A_C ** 2) /
124
+ (2 * dist_A_B * dist_B_C + Number.EPSILON);
125
+ if (cos_B < 0) {
126
+ return dist_A_B;
127
+ }
128
+ // Angle at C (lineEnd)
129
+ const cos_C = (dist_A_C ** 2 + dist_B_C ** 2 - dist_A_B ** 2) /
130
+ (2 * dist_A_C * dist_B_C + Number.EPSILON);
131
+ if (cos_C < 0) {
132
+ return dist_A_C;
133
+ }
134
+ // If both angles are acute, the closest point is on the line segment itself.
135
+ // We can calculate the distance (height of the triangle) using its area.
136
+ // 1. Calculate the semi-perimeter of the triangle ABC
137
+ const s = (dist_A_B + dist_A_C + dist_B_C) / 2;
138
+ // 2. Calculate the area using Heron's formula
139
+ const area = Math.sqrt(Math.max(0, s * (s - dist_A_B) * (s - dist_A_C) * (s - dist_B_C)));
140
+ // 3. The distance is the height of the triangle from point A to the base BC
141
+ // Area = 0.5 * base * height => height = 2 * Area / base
142
+ return (2 * area) / (dist_B_C + Number.EPSILON);
143
+ }
144
+ distancePointToRoute(point) {
145
+ // If the route has less than 2 points, we can't form a segment.
146
+ if (this.plannedRoute.length < 2) {
147
+ if (this.plannedRoute.length === 1) {
148
+ return this.haversine(point, this.plannedRoute[0]);
149
+ }
150
+ return Infinity; // No line segments to measure against
151
+ }
152
+ let minDistance = Infinity;
153
+ for (let i = 0; i < this.plannedRoute.length - 1; i++) {
154
+ const lineStart = this.plannedRoute[i];
155
+ const lineEnd = this.plannedRoute[i + 1];
156
+ const distance = this.distancePointToLineSegment(point, lineStart, lineEnd);
157
+ if (distance < minDistance) {
158
+ minDistance = distance;
159
+ }
160
+ }
161
+ return minDistance;
162
+ }
63
163
  }
164
+ BackgroundGeolocationWeb.EARTH_RADIUS_M = 6371000;
64
165
 
65
166
  var web = /*#__PURE__*/Object.freeze({
66
167
  __proto__: null,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n async start(options, callback) {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n this.watchId = navigator.geolocation.watchPosition((position) => {\n const location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n callback(location);\n }, (error) => {\n const callbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n }, {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n });\n }\n async stop() {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n async openSettings() {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,qBAAqB,GAAGA,mBAAc,CAAC,uBAAuB,EAAE;AACtE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,wBAAwB,EAAE,CAAC;AAC5E,CAAC;;ACFM,MAAM,wBAAwB,SAASC,cAAS,CAAC;AACxD,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE;AACnC,QAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;AACpC,YAAY,QAAQ,CAAC,SAAS,EAAE;AAChC,gBAAgB,IAAI,EAAE,kBAAkB;AACxC,gBAAgB,OAAO,EAAE,8CAA8C;AACvE,gBAAgB,IAAI,EAAE,eAAe;AACrC,aAAa,CAAC;AACd,YAAY;AACZ,QAAQ;AACR,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;AAC1B,YAAY,QAAQ,CAAC,SAAS,EAAE;AAChC,gBAAgB,IAAI,EAAE,kBAAkB;AACxC,gBAAgB,OAAO,EAAE,6BAA6B;AACtD,gBAAgB,IAAI,EAAE,iBAAiB;AACvC,aAAa,CAAC;AACd,YAAY;AACZ,QAAQ;AACR,QAAQ,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,QAAQ,KAAK;AACzE,YAAY,MAAM,QAAQ,GAAG;AAC7B,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;AAClD,gBAAgB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;AACpD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;AAClD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;AAClD,gBAAgB,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB;AAClE,gBAAgB,SAAS,EAAE,KAAK;AAChC,gBAAgB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;AAChD,gBAAgB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;AAC5C,gBAAgB,IAAI,EAAE,QAAQ,CAAC,SAAS;AACxC,aAAa;AACb,YAAY,QAAQ,CAAC,QAAQ,CAAC;AAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK;AACtB,YAAY,MAAM,aAAa,GAAG;AAClC,gBAAgB,IAAI,EAAE,kBAAkB;AACxC,gBAAgB,OAAO,EAAE,KAAK,CAAC,OAAO;AACtC,gBAAgB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;AAC3C,aAAa;AACb,YAAY,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;AAC9C,QAAQ,CAAC,EAAE;AACX,YAAY,kBAAkB,EAAE,IAAI;AACpC,YAAY,OAAO,EAAE,KAAK;AAC1B,YAAY,UAAU,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC;AAClD,SAAS,CAAC;AACV,IAAI;AACJ,IAAI,MAAM,IAAI,GAAG;AACjB,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;AAC1B,YAAY,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;AAC1D,YAAY,OAAO,IAAI,CAAC,OAAO;AAC/B,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC;AACnF,QAAQ,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC;AACnF,IAAI;AACJ;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.plannedRoute = [];\n this.isOffRoute = true;\n this.distanceThreshold = 50;\n }\n async start(options, callback) {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n this.watchId = navigator.geolocation.watchPosition((position) => {\n const location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n if (this.audio && this.plannedRoute.length > 0) {\n const currentPoint = [\n position.coords.longitude,\n position.coords.latitude,\n ];\n const offRoute = this.distancePointToRoute(currentPoint) > this.distanceThreshold;\n if (offRoute == true && this.isOffRoute === false) {\n this.audio.play();\n }\n this.isOffRoute = offRoute;\n }\n callback(location);\n }, (error) => {\n const callbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n }, {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n });\n }\n async stop() {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n async openSettings() {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n async setPlannedRoute(options) {\n if (!options.soundFile) {\n throw new Error(\"Sound file is required\");\n }\n if (this.audio) {\n this.audio.pause();\n this.audio.src = \"\";\n this.audio = undefined;\n }\n this.audio = new Audio(options.soundFile);\n this.plannedRoute = options.route || [];\n this.distanceThreshold = options.distance || 50;\n }\n toRadians(degrees) {\n return (degrees * Math.PI) / 180;\n }\n haversine(point1, point2) {\n const [lon1, lat1] = point1;\n const [lon2, lat2] = point2;\n const dLat = this.toRadians(lat2 - lat1);\n const dLon = this.toRadians(lon2 - lon1);\n const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(this.toRadians(lat1)) *\n Math.cos(this.toRadians(lat2)) *\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2);\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n return BackgroundGeolocationWeb.EARTH_RADIUS_M * c;\n }\n distancePointToLineSegment(point, lineStart, lineEnd) {\n // Calculate the distances between the three points using Haversine\n const dist_A_B = this.haversine(point, lineStart);\n const dist_A_C = this.haversine(point, lineEnd);\n const dist_B_C = this.haversine(lineStart, lineEnd);\n // Handle the edge case where the line segment is a single point\n if (dist_B_C === 0) {\n return dist_A_B;\n }\n // Check if the angles at the line segment's endpoints are obtuse.\n // We use the Law of Cosines (c^2 = a^2 + b^2 - 2ab*cos(C))\n // If cos(C) < 0, the angle is obtuse.\n // Angle at B (lineStart)\n // Use a small epsilon to handle floating point inaccuracies in division by zero\n const cos_B = (dist_A_B ** 2 + dist_B_C ** 2 - dist_A_C ** 2) /\n (2 * dist_A_B * dist_B_C + Number.EPSILON);\n if (cos_B < 0) {\n return dist_A_B;\n }\n // Angle at C (lineEnd)\n const cos_C = (dist_A_C ** 2 + dist_B_C ** 2 - dist_A_B ** 2) /\n (2 * dist_A_C * dist_B_C + Number.EPSILON);\n if (cos_C < 0) {\n return dist_A_C;\n }\n // If both angles are acute, the closest point is on the line segment itself.\n // We can calculate the distance (height of the triangle) using its area.\n // 1. Calculate the semi-perimeter of the triangle ABC\n const s = (dist_A_B + dist_A_C + dist_B_C) / 2;\n // 2. Calculate the area using Heron's formula\n const area = Math.sqrt(Math.max(0, s * (s - dist_A_B) * (s - dist_A_C) * (s - dist_B_C)));\n // 3. The distance is the height of the triangle from point A to the base BC\n // Area = 0.5 * base * height => height = 2 * Area / base\n return (2 * area) / (dist_B_C + Number.EPSILON);\n }\n distancePointToRoute(point) {\n // If the route has less than 2 points, we can't form a segment.\n if (this.plannedRoute.length < 2) {\n if (this.plannedRoute.length === 1) {\n return this.haversine(point, this.plannedRoute[0]);\n }\n return Infinity; // No line segments to measure against\n }\n let minDistance = Infinity;\n for (let i = 0; i < this.plannedRoute.length - 1; i++) {\n const lineStart = this.plannedRoute[i];\n const lineEnd = this.plannedRoute[i + 1];\n const distance = this.distancePointToLineSegment(point, lineStart, lineEnd);\n if (distance < minDistance) {\n minDistance = distance;\n }\n }\n return minDistance;\n }\n}\nBackgroundGeolocationWeb.EARTH_RADIUS_M = 6371000;\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
package/dist/plugin.js CHANGED
@@ -6,6 +6,12 @@ var capacitorBackgroundGeolocation = (function (exports, core) {
6
6
  });
7
7
 
8
8
  class BackgroundGeolocationWeb extends core.WebPlugin {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.plannedRoute = [];
12
+ this.isOffRoute = true;
13
+ this.distanceThreshold = 50;
14
+ }
9
15
  async start(options, callback) {
10
16
  if (!navigator.geolocation) {
11
17
  callback(undefined, {
@@ -35,6 +41,17 @@ var capacitorBackgroundGeolocation = (function (exports, core) {
35
41
  speed: position.coords.speed,
36
42
  time: position.timestamp,
37
43
  };
44
+ if (this.audio && this.plannedRoute.length > 0) {
45
+ const currentPoint = [
46
+ position.coords.longitude,
47
+ position.coords.latitude,
48
+ ];
49
+ const offRoute = this.distancePointToRoute(currentPoint) > this.distanceThreshold;
50
+ if (offRoute == true && this.isOffRoute === false) {
51
+ this.audio.play();
52
+ }
53
+ this.isOffRoute = offRoute;
54
+ }
38
55
  callback(location);
39
56
  }, (error) => {
40
57
  const callbackError = {
@@ -59,7 +76,91 @@ var capacitorBackgroundGeolocation = (function (exports, core) {
59
76
  console.log("openSettings: Web implementation cannot open native settings");
60
77
  window.alert("Please enable location permissions in your browser settings");
61
78
  }
79
+ async setPlannedRoute(options) {
80
+ if (!options.soundFile) {
81
+ throw new Error("Sound file is required");
82
+ }
83
+ if (this.audio) {
84
+ this.audio.pause();
85
+ this.audio.src = "";
86
+ this.audio = undefined;
87
+ }
88
+ this.audio = new Audio(options.soundFile);
89
+ this.plannedRoute = options.route || [];
90
+ this.distanceThreshold = options.distance || 50;
91
+ }
92
+ toRadians(degrees) {
93
+ return (degrees * Math.PI) / 180;
94
+ }
95
+ haversine(point1, point2) {
96
+ const [lon1, lat1] = point1;
97
+ const [lon2, lat2] = point2;
98
+ const dLat = this.toRadians(lat2 - lat1);
99
+ const dLon = this.toRadians(lon2 - lon1);
100
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
101
+ Math.cos(this.toRadians(lat1)) *
102
+ Math.cos(this.toRadians(lat2)) *
103
+ Math.sin(dLon / 2) *
104
+ Math.sin(dLon / 2);
105
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
106
+ return BackgroundGeolocationWeb.EARTH_RADIUS_M * c;
107
+ }
108
+ distancePointToLineSegment(point, lineStart, lineEnd) {
109
+ // Calculate the distances between the three points using Haversine
110
+ const dist_A_B = this.haversine(point, lineStart);
111
+ const dist_A_C = this.haversine(point, lineEnd);
112
+ const dist_B_C = this.haversine(lineStart, lineEnd);
113
+ // Handle the edge case where the line segment is a single point
114
+ if (dist_B_C === 0) {
115
+ return dist_A_B;
116
+ }
117
+ // Check if the angles at the line segment's endpoints are obtuse.
118
+ // We use the Law of Cosines (c^2 = a^2 + b^2 - 2ab*cos(C))
119
+ // If cos(C) < 0, the angle is obtuse.
120
+ // Angle at B (lineStart)
121
+ // Use a small epsilon to handle floating point inaccuracies in division by zero
122
+ const cos_B = (dist_A_B ** 2 + dist_B_C ** 2 - dist_A_C ** 2) /
123
+ (2 * dist_A_B * dist_B_C + Number.EPSILON);
124
+ if (cos_B < 0) {
125
+ return dist_A_B;
126
+ }
127
+ // Angle at C (lineEnd)
128
+ const cos_C = (dist_A_C ** 2 + dist_B_C ** 2 - dist_A_B ** 2) /
129
+ (2 * dist_A_C * dist_B_C + Number.EPSILON);
130
+ if (cos_C < 0) {
131
+ return dist_A_C;
132
+ }
133
+ // If both angles are acute, the closest point is on the line segment itself.
134
+ // We can calculate the distance (height of the triangle) using its area.
135
+ // 1. Calculate the semi-perimeter of the triangle ABC
136
+ const s = (dist_A_B + dist_A_C + dist_B_C) / 2;
137
+ // 2. Calculate the area using Heron's formula
138
+ const area = Math.sqrt(Math.max(0, s * (s - dist_A_B) * (s - dist_A_C) * (s - dist_B_C)));
139
+ // 3. The distance is the height of the triangle from point A to the base BC
140
+ // Area = 0.5 * base * height => height = 2 * Area / base
141
+ return (2 * area) / (dist_B_C + Number.EPSILON);
142
+ }
143
+ distancePointToRoute(point) {
144
+ // If the route has less than 2 points, we can't form a segment.
145
+ if (this.plannedRoute.length < 2) {
146
+ if (this.plannedRoute.length === 1) {
147
+ return this.haversine(point, this.plannedRoute[0]);
148
+ }
149
+ return Infinity; // No line segments to measure against
150
+ }
151
+ let minDistance = Infinity;
152
+ for (let i = 0; i < this.plannedRoute.length - 1; i++) {
153
+ const lineStart = this.plannedRoute[i];
154
+ const lineEnd = this.plannedRoute[i + 1];
155
+ const distance = this.distancePointToLineSegment(point, lineStart, lineEnd);
156
+ if (distance < minDistance) {
157
+ minDistance = distance;
158
+ }
159
+ }
160
+ return minDistance;
161
+ }
62
162
  }
163
+ BackgroundGeolocationWeb.EARTH_RADIUS_M = 6371000;
63
164
 
64
165
  var web = /*#__PURE__*/Object.freeze({
65
166
  __proto__: null,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n async start(options, callback) {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n this.watchId = navigator.geolocation.watchPosition((position) => {\n const location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n callback(location);\n }, (error) => {\n const callbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n }, {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n });\n }\n async stop() {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n async openSettings() {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,qBAAqB,GAAGA,mBAAc,CAAC,uBAAuB,EAAE;IACtE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,wBAAwB,EAAE,CAAC;IAC5E,CAAC;;ICFM,MAAM,wBAAwB,SAASC,cAAS,CAAC;IACxD,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE;IACnC,QAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;IACpC,YAAY,QAAQ,CAAC,SAAS,EAAE;IAChC,gBAAgB,IAAI,EAAE,kBAAkB;IACxC,gBAAgB,OAAO,EAAE,8CAA8C;IACvE,gBAAgB,IAAI,EAAE,eAAe;IACrC,aAAa,CAAC;IACd,YAAY;IACZ,QAAQ;IACR,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;IAC1B,YAAY,QAAQ,CAAC,SAAS,EAAE;IAChC,gBAAgB,IAAI,EAAE,kBAAkB;IACxC,gBAAgB,OAAO,EAAE,6BAA6B;IACtD,gBAAgB,IAAI,EAAE,iBAAiB;IACvC,aAAa,CAAC;IACd,YAAY;IACZ,QAAQ;IACR,QAAQ,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,QAAQ,KAAK;IACzE,YAAY,MAAM,QAAQ,GAAG;IAC7B,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;IAClD,gBAAgB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;IACpD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;IAClD,gBAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ;IAClD,gBAAgB,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB;IAClE,gBAAgB,SAAS,EAAE,KAAK;IAChC,gBAAgB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO;IAChD,gBAAgB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;IAC5C,gBAAgB,IAAI,EAAE,QAAQ,CAAC,SAAS;IACxC,aAAa;IACb,YAAY,QAAQ,CAAC,QAAQ,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK;IACtB,YAAY,MAAM,aAAa,GAAG;IAClC,gBAAgB,IAAI,EAAE,kBAAkB;IACxC,gBAAgB,OAAO,EAAE,KAAK,CAAC,OAAO;IACtC,gBAAgB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;IAC3C,aAAa;IACb,YAAY,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAC9C,QAAQ,CAAC,EAAE;IACX,YAAY,kBAAkB,EAAE,IAAI;IACpC,YAAY,OAAO,EAAE,KAAK;IAC1B,YAAY,UAAU,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC;IAClD,SAAS,CAAC;IACV,IAAI;IACJ,IAAI,MAAM,IAAI,GAAG;IACjB,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE;IAC1B,YAAY,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;IAC1D,YAAY,OAAO,IAAI,CAAC,OAAO;IAC/B,QAAQ;IACR,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC;IACnF,QAAQ,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC;IACnF,IAAI;IACJ;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst BackgroundGeolocation = registerPlugin(\"BackgroundGeolocation\", {\n web: () => import(\"./web\").then((m) => new m.BackgroundGeolocationWeb()),\n});\nexport * from \"./definitions\";\nexport { BackgroundGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class BackgroundGeolocationWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.plannedRoute = [];\n this.isOffRoute = true;\n this.distanceThreshold = 50;\n }\n async start(options, callback) {\n if (!navigator.geolocation) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation is not supported by this browser\",\n code: \"NOT_SUPPORTED\",\n });\n return;\n }\n if (this.watchId) {\n callback(undefined, {\n name: \"GeolocationError\",\n message: \"Geolocation already started\",\n code: \"ALREADY_STARTED\",\n });\n return;\n }\n this.watchId = navigator.geolocation.watchPosition((position) => {\n const location = {\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n simulated: false,\n bearing: position.coords.heading,\n speed: position.coords.speed,\n time: position.timestamp,\n };\n if (this.audio && this.plannedRoute.length > 0) {\n const currentPoint = [\n position.coords.longitude,\n position.coords.latitude,\n ];\n const offRoute = this.distancePointToRoute(currentPoint) > this.distanceThreshold;\n if (offRoute == true && this.isOffRoute === false) {\n this.audio.play();\n }\n this.isOffRoute = offRoute;\n }\n callback(location);\n }, (error) => {\n const callbackError = {\n name: \"GeolocationError\",\n message: error.message,\n code: error.code.toString(),\n };\n callback(undefined, callbackError);\n }, {\n enableHighAccuracy: true,\n timeout: 10000,\n maximumAge: options.stale ? 300000 : 0,\n });\n }\n async stop() {\n if (this.watchId) {\n navigator.geolocation.clearWatch(this.watchId);\n delete this.watchId;\n }\n }\n async openSettings() {\n console.log(\"openSettings: Web implementation cannot open native settings\");\n window.alert(\"Please enable location permissions in your browser settings\");\n }\n async setPlannedRoute(options) {\n if (!options.soundFile) {\n throw new Error(\"Sound file is required\");\n }\n if (this.audio) {\n this.audio.pause();\n this.audio.src = \"\";\n this.audio = undefined;\n }\n this.audio = new Audio(options.soundFile);\n this.plannedRoute = options.route || [];\n this.distanceThreshold = options.distance || 50;\n }\n toRadians(degrees) {\n return (degrees * Math.PI) / 180;\n }\n haversine(point1, point2) {\n const [lon1, lat1] = point1;\n const [lon2, lat2] = point2;\n const dLat = this.toRadians(lat2 - lat1);\n const dLon = this.toRadians(lon2 - lon1);\n const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(this.toRadians(lat1)) *\n Math.cos(this.toRadians(lat2)) *\n Math.sin(dLon / 2) *\n Math.sin(dLon / 2);\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n return BackgroundGeolocationWeb.EARTH_RADIUS_M * c;\n }\n distancePointToLineSegment(point, lineStart, lineEnd) {\n // Calculate the distances between the three points using Haversine\n const dist_A_B = this.haversine(point, lineStart);\n const dist_A_C = this.haversine(point, lineEnd);\n const dist_B_C = this.haversine(lineStart, lineEnd);\n // Handle the edge case where the line segment is a single point\n if (dist_B_C === 0) {\n return dist_A_B;\n }\n // Check if the angles at the line segment's endpoints are obtuse.\n // We use the Law of Cosines (c^2 = a^2 + b^2 - 2ab*cos(C))\n // If cos(C) < 0, the angle is obtuse.\n // Angle at B (lineStart)\n // Use a small epsilon to handle floating point inaccuracies in division by zero\n const cos_B = (dist_A_B ** 2 + dist_B_C ** 2 - dist_A_C ** 2) /\n (2 * dist_A_B * dist_B_C + Number.EPSILON);\n if (cos_B < 0) {\n return dist_A_B;\n }\n // Angle at C (lineEnd)\n const cos_C = (dist_A_C ** 2 + dist_B_C ** 2 - dist_A_B ** 2) /\n (2 * dist_A_C * dist_B_C + Number.EPSILON);\n if (cos_C < 0) {\n return dist_A_C;\n }\n // If both angles are acute, the closest point is on the line segment itself.\n // We can calculate the distance (height of the triangle) using its area.\n // 1. Calculate the semi-perimeter of the triangle ABC\n const s = (dist_A_B + dist_A_C + dist_B_C) / 2;\n // 2. Calculate the area using Heron's formula\n const area = Math.sqrt(Math.max(0, s * (s - dist_A_B) * (s - dist_A_C) * (s - dist_B_C)));\n // 3. The distance is the height of the triangle from point A to the base BC\n // Area = 0.5 * base * height => height = 2 * Area / base\n return (2 * area) / (dist_B_C + Number.EPSILON);\n }\n distancePointToRoute(point) {\n // If the route has less than 2 points, we can't form a segment.\n if (this.plannedRoute.length < 2) {\n if (this.plannedRoute.length === 1) {\n return this.haversine(point, this.plannedRoute[0]);\n }\n return Infinity; // No line segments to measure against\n }\n let minDistance = Infinity;\n for (let i = 0; i < this.plannedRoute.length - 1; i++) {\n const lineStart = this.plannedRoute[i];\n const lineEnd = this.plannedRoute[i + 1];\n const distance = this.distancePointToLineSegment(point, lineStart, lineEnd);\n if (distance < minDistance) {\n minDistance = distance;\n }\n }\n return minDistance;\n }\n}\nBackgroundGeolocationWeb.EARTH_RADIUS_M = 6371000;\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
@@ -5,4 +5,5 @@ CAP_PLUGIN(BackgroundGeolocation, "BackgroundGeolocation",
5
5
  CAP_PLUGIN_METHOD(start, CAPPluginReturnCallback);
6
6
  CAP_PLUGIN_METHOD(stop, CAPPluginReturnPromise);
7
7
  CAP_PLUGIN_METHOD(openSettings, CAPPluginReturnPromise);
8
+ CAP_PLUGIN_METHOD(setPlannedRoute, CAPPluginReturnPromise);
8
9
  )