Skip to content

Commit 91d08f2

Browse files
refactor: move geolocation helpers in their own utility
1 parent bd32159 commit 91d08f2

File tree

2 files changed

+200
-136
lines changed

2 files changed

+200
-136
lines changed

src/components/popups/sidebar/EditProfileProfile.vue

+44-136
Original file line numberDiff line numberDiff line change
@@ -44,45 +44,20 @@ import {
4444
// PROJECT: POPUPS
4545
import { FormProfile as ProfileFormProfile } from "@/popups/sidebar/EditProfile.vue";
4646

47-
// PROJECT: COMMONS
48-
import CONFIG from "@/commons/config";
47+
// PROJECT: UTILITIES
48+
import {
49+
default as UtilitiesGeolocation,
50+
GeolocationPermission
51+
} from "@/utilities/geolocation";
4952

5053
// 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 {
6555
// Allow action.
6656
Allow = "allow",
6757
// Refresh action.
6858
Refresh = "refresh"
6959
}
7060

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-
8661
export default {
8762
name: "EditProfileProfile",
8863

@@ -242,7 +217,7 @@ export default {
242217
type: FormFieldsetControlActionType.Button,
243218

244219
data: (this.locationPermissionDetails.action ===
245-
GeolocationAction.Refresh
220+
LocationPermissionAction.Refresh
246221
? {
247222
text: this.isRefreshingGeolocationPosition
248223
? "Refreshing"
@@ -263,7 +238,7 @@ export default {
263238

264239
notes: [
265240
"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."
267242
],
268243

269244
options: {
@@ -277,15 +252,15 @@ export default {
277252
label: string;
278253
color: string;
279254
emphasis?: boolean;
280-
action?: GeolocationAction;
255+
action?: LocationPermissionAction;
281256
} {
282257
switch (this.geolocationPermission) {
283258
case GeolocationPermission.NotYetAllowed: {
284259
return {
285260
label: "Not yet allowed",
286261
color: this.form.locationAutodetect.inner ? "orange" : "grey",
287262
emphasis: this.form.locationAutodetect.inner || false,
288-
action: GeolocationAction.Allow
263+
action: LocationPermissionAction.Allow
289264
};
290265
}
291266

@@ -303,7 +278,7 @@ export default {
303278
color: this.form.locationAutodetect.inner ? "green" : "grey",
304279

305280
action: this.form.locationAutodetect.inner
306-
? GeolocationAction.Refresh
281+
? LocationPermissionAction.Refresh
307282
: undefined
308283
};
309284
}
@@ -336,107 +311,26 @@ export default {
336311

337312
async acquireGeolocationPermission(): Promise<GeolocationPermission> {
338313
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();
358316
} catch (error) {
359317
this.$log.error("Failed acquiring geolocation permission", error);
360318

361319
return GeolocationPermission.Unknown;
362320
}
363321
},
364322

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-
427323
// --> EVENT LISTENERS <--
428324

429325
async onFieldsetLocationPermissionAllowClick(): Promise<void> {
430326
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();
434329

435330
// 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;
440334
} catch (error) {
441335
this.$log.error("Failed obtaining geolocation allow permission", error);
442336

@@ -454,29 +348,43 @@ export default {
454348

455349
try {
456350
// Obtain geolocation position
457-
const coordinates = await this.obtainGeolocationPositionCoordinates();
351+
const coordinates = await UtilitiesGeolocation.coordinates();
458352

459353
// No geolocation position obtained?
460354
if (coordinates === null) {
461355
throw new Error("Coordinates are empty");
462356
}
463357

464358
// 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+
}
468365

469366
// Update user city and country (in form)
470367
const form = this.form;
471368

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+
}
480388
} catch (error) {
481389
this.$log.error("Failed obtaining geolocation fresh position", error);
482390

0 commit comments

Comments
 (0)