242 lines
7.3 KiB
JavaScript
242 lines
7.3 KiB
JavaScript
//
|
|
// License: Do whatever you want with it. I'm not liable.
|
|
//
|
|
import ApiKeys from './lib/rs-module-api-keys.mjs';
|
|
import Geocoder from './lib/geocode.mjs';
|
|
import initializeSettings from './lib/settings.mjs';
|
|
import initializeProfileUpdates from './lib/profile.mjs';
|
|
import { showElement, hideElement, renderImage } from './lib/dom-helpers.mjs';
|
|
|
|
const remoteStorage = new RemoteStorage({ modules: [ApiKeys] });
|
|
remoteStorage.access.claim('profile', 'rw');
|
|
remoteStorage.access.claim('api-keys', 'rw');
|
|
remoteStorage.caching.enable('/profile/');
|
|
remoteStorage.caching.enable('/public/profile/');
|
|
|
|
const widget = new Widget(remoteStorage, {
|
|
modalBackdrop: true,
|
|
skipInitial: true
|
|
});
|
|
widget.attach('rs-widget-container');
|
|
|
|
document.querySelector('.rs-account .disconnect').addEventListener('click', e => {
|
|
remoteStorage.disconnect();
|
|
});
|
|
|
|
let data = {
|
|
currentUserLocation: {
|
|
coords: null,
|
|
openCageResult: null
|
|
},
|
|
currentCity: {
|
|
coords: null,
|
|
openCageResult: null,
|
|
geoJSON: null,
|
|
imageBlob: null,
|
|
imageObjectURL: null
|
|
}
|
|
};
|
|
|
|
data.currentUserLocation = new Proxy(data.currentUserLocation, {
|
|
set (obj, prop, value) {
|
|
obj[prop] = value;
|
|
|
|
switch(prop) {
|
|
case 'coords':
|
|
renderCoordinates();
|
|
break;
|
|
case 'openCageResult':
|
|
renderFormattedResult();
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
|
|
data.currentCity = new Proxy(data.currentCity, {
|
|
set (obj, prop, value) {
|
|
obj[prop] = value;
|
|
|
|
switch(prop) {
|
|
case 'coords':
|
|
fetchMapImage();
|
|
break;
|
|
case 'openCageResult':
|
|
renderFormattedCityResult();
|
|
createGeoJSON();
|
|
break;
|
|
case 'geoJSON':
|
|
break;
|
|
case 'imageBlob':
|
|
break;
|
|
case 'imageObjectURL':
|
|
renderMapImage();
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
|
|
remoteStorage.on('not-connected', () => {
|
|
showElement('.view.disconnected');
|
|
});
|
|
|
|
remoteStorage.on('connected', () => {
|
|
hideElement('.view.disconnected');
|
|
showElement('.view.connected');
|
|
|
|
document.querySelector('.rs-account .user-address').innerHTML = remoteStorage.remote.userAddress;
|
|
|
|
initializeSettings(remoteStorage);
|
|
initializeProfileUpdates(remoteStorage, data);
|
|
});
|
|
|
|
remoteStorage.on('disconnected', () => {
|
|
hideElement('.view.connected');
|
|
showElement('.view.disconnected');
|
|
});
|
|
|
|
const geocoder = new Geocoder(remoteStorage);
|
|
|
|
const mapBoxStyle = 'v1/mapbox/streets-v10'
|
|
const imageSize = '260x100@2x'
|
|
|
|
document.querySelector('button.get-coordinates').addEventListener('click', () => {
|
|
console.debug('Getting current/GPS location...');
|
|
navigator.geolocation.getCurrentPosition(async position => {
|
|
console.debug('Location data:', position);
|
|
data.currentUserLocation.coords = {
|
|
lat: position.coords.latitude.toFixed(4),
|
|
lng: position.coords.longitude.toFixed(4)
|
|
};
|
|
await geocodeUserLocation();
|
|
geocodeNearestCity();
|
|
});
|
|
})
|
|
|
|
document.querySelector('form.get-location').addEventListener('submit', e => {
|
|
e.preventDefault();
|
|
console.debug('Geocoding supplied location...');
|
|
geocodeLocationInput().catch(err => window.alert(err));
|
|
})
|
|
|
|
async function geocodeUserLocation () {
|
|
console.debug('Geocoding coordinates...');
|
|
const { lat, lng } = data.currentUserLocation.coords;
|
|
|
|
return geocoder.reverse(lat, lng).then(res => {
|
|
const result = res.results[0];
|
|
console.debug('Result:', result);
|
|
data.currentUserLocation.openCageResult = result;
|
|
})
|
|
}
|
|
|
|
function geocodeNearestCity () {
|
|
console.debug('Geocoding nearest city...');
|
|
const result = data.currentUserLocation.openCageResult;
|
|
let { city, town, village, hamlet, county } = result.components;
|
|
if (!city) { city = town || village || hamlet || county; }
|
|
const query = `${city}, ${result.components.state}, ${result.components['ISO_3166-1_alpha-2']}&no_record=1&min_confidence=3`;
|
|
|
|
return geocoder.geocode(query).then(res => {
|
|
const result = res.results[0];
|
|
console.debug('Result:', result);
|
|
data.currentCity.coords = {
|
|
lat: result.geometry.lat.toFixed(4),
|
|
lng: result.geometry.lng.toFixed(4)
|
|
};
|
|
data.currentCity.openCageResult = result;
|
|
})
|
|
}
|
|
|
|
function geocodeLocationInput () {
|
|
console.debug('Geocoding supplied location...');
|
|
const input = document.querySelector('input.location').value;
|
|
const query = `${input},&no_record=1&min_confidence=3`;
|
|
|
|
return geocoder.geocode(query).then(res => {
|
|
return new Promise((resolve, reject) => {
|
|
const result = res.results[0];
|
|
console.debug('Result:', result);
|
|
if (result) {
|
|
data.currentCity.coords = {
|
|
lat: result.geometry.lat.toFixed(4),
|
|
lng: result.geometry.lng.toFixed(4)
|
|
};
|
|
data.currentCity.openCageResult = result;
|
|
resolve();
|
|
} else {
|
|
reject('Nothing found');
|
|
}
|
|
});
|
|
})
|
|
}
|
|
|
|
function createGeoJSON () {
|
|
const res = data.currentCity.openCageResult;
|
|
const { city, town, village, hamlet, county } = res.components;
|
|
data.currentCity.geoJSON = {
|
|
"type": "Feature",
|
|
"geometry": {
|
|
"type": "Point",
|
|
"coordinates": [res.geometry.lng, res.geometry.lat]
|
|
},
|
|
"city": city || town || village || hamlet,
|
|
"state": res.components.state,
|
|
"country": res.components.country,
|
|
"timezone": res.annotations.timezone
|
|
}
|
|
console.debug('Created GeoJSON object:', data.currentCity.geoJSON);
|
|
}
|
|
|
|
async function fetchMapImage () {
|
|
const mapBoxToken = await remoteStorage.apiKeys.get('mapbox').then(c => c.token);
|
|
const zoomFactor = localStorage.getItem('rs-location:map-zoom-factor');
|
|
const { lat, lng } = data.currentCity.coords;
|
|
const url = encodeURI(`https://api.mapbox.com/styles/${mapBoxStyle}/static/pin-s-harbor+fff(${lng},${lat})/${lng},${lat},${zoomFactor}/${imageSize}?access_token=${mapBoxToken}`)
|
|
console.debug('Fetching map image...');
|
|
|
|
return fetch(url)
|
|
.then(response => response.blob())
|
|
.then(imageData => {
|
|
const url = URL.createObjectURL(imageData);
|
|
data.currentCity.imageBlob = imageData;
|
|
data.currentCity.imageObjectURL = url
|
|
|
|
return fetch(url)
|
|
.then(res => res.arrayBuffer())
|
|
.then(arrayBuffer => {
|
|
data.currentCity.imageArrayBuffer = arrayBuffer;
|
|
})
|
|
});
|
|
}
|
|
|
|
function renderMapImage () {
|
|
const url = data.currentCity.imageObjectURL;
|
|
renderImage('section.current-city .map', url, '260x100');
|
|
}
|
|
|
|
function renderCoordinates () {
|
|
showElement('section.current-location');
|
|
const coordsEl = document.querySelector('section.current-location .coords');
|
|
const coords = data.currentUserLocation.coords;
|
|
coordsEl.innerHTML = `Latitude: ${coords.lat}<br>Longitude: ${coords.lng}`;
|
|
}
|
|
|
|
function renderFormattedResult () {
|
|
const el = document.querySelector('section.current-location .formatted-result');
|
|
el.innerHTML = data.currentUserLocation.openCageResult.formatted;
|
|
}
|
|
|
|
function renderFormattedCityResult () {
|
|
showElement('section.current-city');
|
|
const coordsEl = document.querySelector('section.current-city .coords');
|
|
const coords = data.currentCity.coords;
|
|
coordsEl.innerHTML = `Latitude: ${coords.lat}<br>Longitude: ${coords.lng}`;
|
|
|
|
const result = data.currentCity.openCageResult;
|
|
const el = document.querySelector('section.current-city .formatted-result');
|
|
const { city, town, village, hamlet, county } = result.components;
|
|
el.innerHTML = `${city || town || village || hamlet || county}, ${result.components.country}`;
|
|
}
|