@@ -44,45 +44,20 @@ import {
44
44
// PROJECT: POPUPS
45
45
import { FormProfile as ProfileFormProfile } from "@/popups/sidebar/EditProfile.vue";
46
46
47
- // PROJECT: COMMONS
48
- import CONFIG from "@/commons/config";
47
+ // PROJECT: UTILITIES
48
+ import {
49
+ default as UtilitiesGeolocation,
50
+ GeolocationPermission
51
+ } from "@/utilities/geolocation";
49
52
50
53
// ENUMERATIONS
51
- enum GeolocationPermission {
52
- // Not yet allowed permission.
53
- NotYetAllowed = "not-yet-allowed",
54
- // Disallowed permission.
55
- Disallowed = "disallowed",
56
- // Allowed permission.
57
- Allowed = "allowed",
58
- // FailedToObtain permission.
59
- FailedToObtain = "failed-to-obtain",
60
- // Unknown permission.
61
- Unknown = "unknown"
62
- }
63
-
64
- enum GeolocationAction {
54
+ enum LocationPermissionAction {
65
55
// Allow action.
66
56
Allow = "allow",
67
57
// Refresh action.
68
58
Refresh = "refresh"
69
59
}
70
60
71
- // INTERFACES
72
- interface GeolocationPositionCoordinates {
73
- latitude: number;
74
- longitude: number;
75
- }
76
-
77
- interface GeolocationPositionAddress {
78
- cityName: string;
79
- countryCode: string;
80
- }
81
-
82
- // CONSTANTS
83
- const GEOLOCATION_ACQUIRE_STALE_AGE = 3600000; // 1 hour
84
- const GEOLOCATION_ACQUIRE_TIMEOUT = 10000; // 10 seconds
85
-
86
61
export default {
87
62
name: "EditProfileProfile",
88
63
@@ -242,7 +217,7 @@ export default {
242
217
type: FormFieldsetControlActionType.Button,
243
218
244
219
data: (this.locationPermissionDetails.action ===
245
- GeolocationAction .Refresh
220
+ LocationPermissionAction .Refresh
246
221
? {
247
222
text: this.isRefreshingGeolocationPosition
248
223
? "Refreshing"
@@ -263,7 +238,7 @@ export default {
263
238
264
239
notes: [
265
240
"You can opt-in to automatic location detection. It is handy if you travel a lot, and would like to easily update your location in a single click. Your current city and country will be shared, not your exact GPS location.",
266
- "Note that geolocation permissions are required for automatic mode."
241
+ "Note that geolocation permissions are required for the auto-detect mode."
267
242
],
268
243
269
244
options: {
@@ -277,15 +252,15 @@ export default {
277
252
label: string;
278
253
color: string;
279
254
emphasis?: boolean;
280
- action?: GeolocationAction ;
255
+ action?: LocationPermissionAction ;
281
256
} {
282
257
switch (this.geolocationPermission) {
283
258
case GeolocationPermission.NotYetAllowed: {
284
259
return {
285
260
label: "Not yet allowed",
286
261
color: this.form.locationAutodetect.inner ? "orange" : "grey",
287
262
emphasis: this.form.locationAutodetect.inner || false,
288
- action: GeolocationAction .Allow
263
+ action: LocationPermissionAction .Allow
289
264
};
290
265
}
291
266
@@ -303,7 +278,7 @@ export default {
303
278
color: this.form.locationAutodetect.inner ? "green" : "grey",
304
279
305
280
action: this.form.locationAutodetect.inner
306
- ? GeolocationAction .Refresh
281
+ ? LocationPermissionAction .Refresh
307
282
: undefined
308
283
};
309
284
}
@@ -336,107 +311,26 @@ export default {
336
311
337
312
async acquireGeolocationPermission(): Promise<GeolocationPermission> {
338
313
try {
339
- // Request geolocation permission
340
- const permission = await navigator.permissions.query({
341
- name: "geolocation"
342
- });
343
-
344
- // Handle acquired permission
345
- switch (permission.state) {
346
- case "granted": {
347
- return GeolocationPermission.Allowed;
348
- }
349
-
350
- case "denied": {
351
- return GeolocationPermission.Disallowed;
352
- }
353
-
354
- case "prompt": {
355
- return GeolocationPermission.NotYetAllowed;
356
- }
357
- }
314
+ // Acquire geolocation permission
315
+ return await UtilitiesGeolocation.permission();
358
316
} catch (error) {
359
317
this.$log.error("Failed acquiring geolocation permission", error);
360
318
361
319
return GeolocationPermission.Unknown;
362
320
}
363
321
},
364
322
365
- async obtainGeolocationPositionCoordinates(): Promise<GeolocationPositionCoordinates | null> {
366
- return new Promise((resolve, reject) => {
367
- try {
368
- navigator.geolocation.getCurrentPosition(
369
- position => {
370
- // Resolve with success
371
- resolve({
372
- latitude: position.coords.latitude,
373
- longitude: position.coords.longitude
374
- });
375
- },
376
-
377
- () => {
378
- // Reject with error
379
- resolve(null);
380
- },
381
-
382
- {
383
- timeout: GEOLOCATION_ACQUIRE_TIMEOUT,
384
- maximumAge: GEOLOCATION_ACQUIRE_STALE_AGE
385
- }
386
- );
387
- } catch (error) {
388
- // Reject with error
389
- reject(error);
390
- }
391
- });
392
- },
393
-
394
- async obtainGeolocationPositionAddress(
395
- coordinates: GeolocationPositionCoordinates
396
- ): Promise<GeolocationPositionAddress> {
397
- // Geocode obtained coordinates (to a city and a country)
398
- const geocoderQuery = new URLSearchParams();
399
-
400
- geocoderQuery.append("format", "jsonv2");
401
- geocoderQuery.append("lat", `${coordinates.latitude}`);
402
- geocoderQuery.append("lon", `${coordinates.longitude}`);
403
-
404
- const geocoderResponse = await fetch(
405
- `${CONFIG.url.nominatim_geocoder}/reverse?${geocoderQuery}`,
406
- {
407
- mode: "cors"
408
- }
409
- );
410
-
411
- if (geocoderResponse.ok !== true) {
412
- throw new Error("Geocoding request failed");
413
- }
414
-
415
- const geocoding = (await geocoderResponse.json()) || {};
416
-
417
- if (geocoding.address?.city && geocoding.address?.country_code) {
418
- return {
419
- cityName: geocoding.address.city,
420
- countryCode: geocoding.address.country_code.toUpperCase()
421
- };
422
- }
423
-
424
- throw new Error("Geocoding got no result");
425
- },
426
-
427
323
// --> EVENT LISTENERS <--
428
324
429
325
async onFieldsetLocationPermissionAllowClick(): Promise<void> {
430
326
try {
431
- // Obtain geolocation position (this will request for permission if \
432
- // needed)
433
- const coordinates = await this.obtainGeolocationPositionCoordinates();
327
+ // Obtain consent from user for the geolocation permission
328
+ const isPermitted = await UtilitiesGeolocation.grant();
434
329
435
330
// Mark as allowed or disallowed?
436
- this.geolocationPermission =
437
- coordinates === null
438
- ? GeolocationPermission.Disallowed
439
- : GeolocationPermission.Allowed;
331
+ this.geolocationPermission = isPermitted
332
+ ? GeolocationPermission.Allowed
333
+ : GeolocationPermission.Disallowed;
440
334
} catch (error) {
441
335
this.$log.error("Failed obtaining geolocation allow permission", error);
442
336
@@ -454,29 +348,43 @@ export default {
454
348
455
349
try {
456
350
// Obtain geolocation position
457
- const coordinates = await this.obtainGeolocationPositionCoordinates ();
351
+ const coordinates = await UtilitiesGeolocation.coordinates ();
458
352
459
353
// No geolocation position obtained?
460
354
if (coordinates === null) {
461
355
throw new Error("Coordinates are empty");
462
356
}
463
357
464
358
// Geocode obtained coordinates (to a city and a country)
465
- const address = await this.obtainGeolocationPositionAddress(
466
- coordinates
467
- );
359
+ const address = await UtilitiesGeolocation.address(coordinates);
360
+
361
+ // No address obtained?
362
+ if (address === null) {
363
+ throw new Error("Address not found");
364
+ }
468
365
469
366
// Update user city and country (in form)
470
367
const form = this.form;
471
368
472
- form.locationCity.inner = address.cityName;
473
- form.locationCountry.inner = address.countryCode;
474
-
475
- // Show success alert
476
- BaseAlert.success(
477
- "Location refreshed",
478
- "Please save your profile to confirm"
479
- );
369
+ if (
370
+ form.locationCity.inner !== address.cityName ||
371
+ form.locationCountry.inner !== address.countryCode
372
+ ) {
373
+ form.locationCity.inner = address.cityName;
374
+ form.locationCountry.inner = address.countryCode;
375
+
376
+ // Show success alert
377
+ BaseAlert.success(
378
+ "Location refreshed",
379
+ "Please save your profile to confirm"
380
+ );
381
+ } else {
382
+ // Show information alert
383
+ BaseAlert.info(
384
+ "Location unchanged",
385
+ "Your location did not change"
386
+ );
387
+ }
480
388
} catch (error) {
481
389
this.$log.error("Failed obtaining geolocation fresh position", error);
482
390
0 commit comments