Skip to content

Instantly share code, notes, and snippets.

@HendrikRunte
Last active December 14, 2020 13:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HendrikRunte/8a17fcab2ff1c6ffbef0bd4d6011663f to your computer and use it in GitHub Desktop.
Save HendrikRunte/8a17fcab2ff1c6ffbef0bd4d6011663f to your computer and use it in GitHub Desktop.
// 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