// // 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}
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}
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}`; }