Last active
December 14, 2020 13:36
-
-
Save HendrikRunte/8a17fcab2ff1c6ffbef0bd4d6011663f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Variables used by Scriptable. | |
// These must be at the very top of the file. Do not edit. | |
// icon-color: yellow; icon-glyph: sun; | |
/////////////////////////////////////////////////////////////////////// | |
// yesteryear.js | |
// Origin: | |
// https://gist.github.com/HendrikRunte/8a17fcab2ff1c6ffbef0bd4d6011663f | |
// Take it and have fun. | |
// Hendrik Runte, Dec 14, 2020, 14:36. | |
// | |
/////////////////////////////////////////////////////////////////////// | |
// Uses the excellent brightsky API. @see https://brightsky.dev | |
// Please note that this API will not work outside Germany. | |
// Therefore this widget might refuse to work properly. | |
/////////////////////////////////////////////////////////////////////// | |
// Helps adding icons from SF Symbols. | |
function addSymbol({ | |
symbolName = 'applelogo', | |
stack, | |
color = Color.white(), | |
size = 20, | |
}) { | |
const icon = stack.addImage(SFSymbol.named(symbolName).image); | |
icon.tintColor = color; | |
icon.imageSize = new Size(size, size); | |
} | |
// Locate yourself or use params. | |
async function getLocation() { | |
try { | |
if (args.widgetParameter) { | |
const fixedCoordinates = args.widgetParameter.split(',').map(parseFloat); | |
return { latitude: fixedCoordinates[0], longitude: fixedCoordinates[1] }; | |
} else { | |
Location.setAccuracyToThreeKilometers(); | |
return await Location.current(); | |
} | |
} catch (e) { | |
return null; | |
} | |
} | |
async function getLocality(geolocation) { | |
let locality = null; | |
try { | |
// Location.reverseGeocode returns an array with object properties. | |
// Uses Apple CLLocation. | |
const address = await Location.reverseGeocode( | |
geolocation.latitude, | |
geolocation.longitude | |
); | |
// The order is relevant for processing the | |
// address properties. | |
const cascade = [ | |
'ocean', | |
'inlandWater', | |
'administrativeArea', | |
'subAdministrativeArea', | |
'locality', | |
'subLocality', | |
]; | |
if (address.length) { | |
cascade.forEach((prop) => { | |
locality = address[0][prop] ? address[0][prop] : locality; | |
}); | |
} | |
return locality; | |
} catch (e) { | |
return null; | |
} | |
} | |
async function retrieveYesteryearsWeather(lat, lon) { | |
lat ||= 53; | |
lon ||= 9; | |
const yesteryearDate = new Date( | |
new Date().setFullYear(TODAY.getFullYear() - 1) | |
); | |
const API = `https://api.brightsky.dev/weather?date=${ | |
yesteryearDate.toISOString().split('T')[0] | |
}&lat=${lat}&lon=${lon}`; | |
console.log(API); | |
try { | |
return await new Request(API).loadJSON(); | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
async function retrieveTodaysWeather(lat, lon) { | |
lat ||= 53; | |
lon ||= 9; | |
const API = `https://api.brightsky.dev/current_weather?lat=${lat}&lon=${lon}`; | |
console.log(API); | |
try { | |
return await new Request(API).loadJSON(); | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
function displayLoadingIndicator() { | |
const listWidget = new ListWidget(); | |
const gradient = new LinearGradient(); | |
gradient.locations = [0, 1]; | |
gradient.colors = [new Color('#000618'), new Color('#121A34')]; | |
listWidget.backgroundGradient = gradient; | |
const iconStack = listWidget.addStack(); | |
addSymbol({ | |
symbolName: 'clock', | |
stack: iconStack, | |
color: Color.white(), | |
size: 32, | |
}); | |
listWidget.addSpacer(10); | |
const header = listWidget.addText('Das Widget'); | |
header.font = Font.regularRoundedSystemFont(FONTSETTINGS.medium); | |
header.textColor = Color.white(); | |
listWidget.addSpacer(2); | |
const footer = listWidget.addText('wird geladen …'); | |
footer.font = Font.regularRoundedSystemFont(FONTSETTINGS.medium); | |
footer.textColor = Color.white(); | |
return listWidget; | |
} | |
async function displayWidget(yesteryearsWeather, todaysWeather, locality) { | |
const listWidget = new ListWidget(); | |
const gradient = new LinearGradient(); | |
gradient.locations = [0, 1]; | |
gradient.colors = [new Color('#00095A'), new Color('#001899')]; | |
listWidget.backgroundGradient = gradient; | |
const regionLabel = listWidget.addText(`VOR EINEM JAHR …`); | |
regionLabel.font = Font.lightRoundedSystemFont(FONTSETTINGS.small); | |
regionLabel.textColor = Color.white(); | |
regionLabel.leftAlignText(); | |
listWidget.addSpacer(10); | |
if (yesteryearsWeather) { | |
const this_hour = TODAY.getHours(); | |
const selectedWeatherValues = yesteryearsWeather.weather.filter( | |
(hourly) => new Date(hourly.timestamp).getHours() === this_hour | |
)[0]; | |
const weatherLabel = listWidget.addText( | |
`${new Intl.NumberFormat('de-DE', {}).format( | |
selectedWeatherValues?.temperature | |
)}°C` | |
); | |
weatherLabel.font = Font.thinRoundedSystemFont(FONTSETTINGS.big); | |
weatherLabel.textColor = Color.orange(); | |
weatherLabel.rightAlignText(); | |
listWidget.addSpacer(10); | |
if (todaysWeather) { | |
const difference = | |
todaysWeather?.weather?.temperature - | |
selectedWeatherValues?.temperature; | |
const todaysStack = listWidget.addStack(); | |
const todaysLabel = todaysStack.addText(`HEUTE: `); | |
todaysLabel.font = Font.lightRoundedSystemFont(FONTSETTINGS.small); | |
todaysLabel.textColor = Color.orange(); | |
todaysLabel.leftAlignText(); | |
const todaysTemperatureLabel = todaysStack.addText( | |
`${new Intl.NumberFormat('de-DE', {}).format( | |
todaysWeather?.weather?.temperature | |
)}°C` | |
); | |
todaysTemperatureLabel.font = Font.lightRoundedSystemFont( | |
FONTSETTINGS.small | |
); | |
todaysTemperatureLabel.textColor = Color.orange(); | |
todaysTemperatureLabel.rightAlignText(); | |
let differenceLabelText = ''; | |
if (difference === 0) { | |
differenceLabelText = 'GLEICH'; | |
} else if (difference > 0) { | |
differenceLabelText = `${difference.toFixed(1)}°C WÄRMER`; | |
} else { | |
differenceLabelText = `${difference.toFixed(1)}°C KÄLTER`; | |
} | |
const differenceLabel = listWidget.addText(differenceLabelText); | |
differenceLabel.font = Font.lightRoundedSystemFont(FONTSETTINGS.small); | |
differenceLabel.textColor = Color.orange(); | |
differenceLabel.leftAlignText(); | |
listWidget.addSpacer(10); | |
} | |
} | |
// Footer: | |
const footerStack = listWidget.addStack(); | |
const footerLabel = locality | |
? footerStack.addText(`${locality.toUpperCase()} `) | |
: ''; | |
addSymbol({ | |
symbolName: locality ? 'location.fill' : 'arrowtriangle.right.circle', | |
stack: footerStack, | |
color: Color.white(), | |
size: FONTSETTINGS.small, | |
}); | |
footerLabel.font = Font.regularRoundedSystemFont(FONTSETTINGS.small); | |
footerLabel.textColor = Color.white(); | |
return listWidget; | |
} | |
const TODAY = new Date(); | |
let widget = {}; | |
const FONTSETTINGS = { | |
big: 42, | |
medium: 16, | |
small: 12, | |
}; | |
const location = await getLocation(); | |
const locality = await getLocality(location); | |
if (location) { | |
const yesteryearsWeather = await retrieveYesteryearsWeather( | |
location.latitude, | |
location.longitude | |
); | |
const todaysWeather = await retrieveTodaysWeather( | |
location.latitude, | |
location.longitude | |
); | |
widget = await displayWidget(yesteryearsWeather, todaysWeather, locality); | |
} else { | |
widget = await displayLoadingIndicator(); | |
} | |
if (!config.runsInWidget) { | |
await widget.presentSmall(); | |
} | |
Script.setWidget(widget); | |
Script.complete(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment