Finish calendar menu
This commit is contained in:
@@ -22,6 +22,15 @@ const defaultWeather = {
|
|||||||
day: {
|
day: {
|
||||||
daily_chance_of_rain: 0,
|
daily_chance_of_rain: 0,
|
||||||
},
|
},
|
||||||
|
hour: [
|
||||||
|
{
|
||||||
|
time_epoch: 1719471600,
|
||||||
|
temp_f: 0,
|
||||||
|
condition: {
|
||||||
|
text: "Clear",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -120,15 +129,24 @@ const WeatherWidget = () => {
|
|||||||
child: Widget.Box({
|
child: Widget.Box({
|
||||||
class_name: "weather-container-box",
|
class_name: "weather-container-box",
|
||||||
setup: (self) => {
|
setup: (self) => {
|
||||||
Utils.interval(6000, () => {
|
Utils.interval(60 * 1000, () => {
|
||||||
Utils.execAsync(
|
Utils.execAsync(
|
||||||
`curl "https://api.weatherapi.com/v1/forecast.json?key=${keyRing.weatherapi}&q=93722&days=1&aqi=no&alerts=no"`,
|
`curl "https://api.weatherapi.com/v1/forecast.json?key=${keyRing.weatherapi}&q=93722&days=1&aqi=no&alerts=no"`,
|
||||||
).then((res) => {
|
)
|
||||||
|
.then((res) => {
|
||||||
theWeather.value = JSON.parse(res);
|
theWeather.value = JSON.parse(res);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(`Failed to fetch weather: ${err}`);
|
||||||
|
theWeather.value = defaultWeather;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return (self.child = Widget.Box({
|
return (self.child = Widget.Box({
|
||||||
|
vertical: true,
|
||||||
|
hexpand: true,
|
||||||
|
children: [
|
||||||
|
Widget.Box({
|
||||||
class_name: "calendar-menu-weather today",
|
class_name: "calendar-menu-weather today",
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
children: [
|
children: [
|
||||||
@@ -142,6 +160,7 @@ const WeatherWidget = () => {
|
|||||||
icon: theWeather.bind("value").as((v) => {
|
icon: theWeather.bind("value").as((v) => {
|
||||||
return icons.weather[
|
return icons.weather[
|
||||||
v.current.condition.text
|
v.current.condition.text
|
||||||
|
.trim()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replaceAll(" ", "_")
|
.replaceAll(" ", "_")
|
||||||
];
|
];
|
||||||
@@ -150,16 +169,23 @@ const WeatherWidget = () => {
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
Widget.Box({
|
Widget.Box({
|
||||||
hexpand: true,
|
|
||||||
vpack: "center",
|
|
||||||
hpack: "center",
|
hpack: "center",
|
||||||
class_name: "calendar-menu-weather today temp container",
|
vpack: "center",
|
||||||
vertical: true,
|
vertical: true,
|
||||||
children: [
|
children: [
|
||||||
Widget.Box({
|
Widget.Box({
|
||||||
|
hexpand: true,
|
||||||
|
vpack: "center",
|
||||||
|
class_name: "calendar-menu-weather today temp container",
|
||||||
|
vertical: false,
|
||||||
|
children: [
|
||||||
|
Widget.Box({
|
||||||
|
hexpand: true,
|
||||||
|
hpack: "center",
|
||||||
children: [
|
children: [
|
||||||
Widget.Label({
|
Widget.Label({
|
||||||
class_name: "calendar-menu-weather today temp label",
|
class_name:
|
||||||
|
"calendar-menu-weather today temp label",
|
||||||
label: theWeather
|
label: theWeather
|
||||||
.bind("value")
|
.bind("value")
|
||||||
.as((v) => `${Math.ceil(v.current.temp_f)}° F`),
|
.as((v) => `${Math.ceil(v.current.temp_f)}° F`),
|
||||||
@@ -173,11 +199,21 @@ const WeatherWidget = () => {
|
|||||||
),
|
),
|
||||||
label: theWeather
|
label: theWeather
|
||||||
.bind("value")
|
.bind("value")
|
||||||
.as((v) => getIcon(Math.ceil(v.current.temp_f)).icon),
|
.as(
|
||||||
|
(v) =>
|
||||||
|
getIcon(Math.ceil(v.current.temp_f)).icon,
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
Widget.Label({
|
],
|
||||||
|
}),
|
||||||
|
Widget.Box({
|
||||||
|
hpack: "center",
|
||||||
|
child: Widget.Label({
|
||||||
|
max_width_chars: 17,
|
||||||
|
truncate: "end",
|
||||||
|
lines: 2,
|
||||||
class_name: theWeather
|
class_name: theWeather
|
||||||
.bind("value")
|
.bind("value")
|
||||||
.as(
|
.as(
|
||||||
@@ -188,12 +224,13 @@ const WeatherWidget = () => {
|
|||||||
.bind("value")
|
.bind("value")
|
||||||
.as((v) => v.current.condition.text),
|
.as((v) => v.current.condition.text),
|
||||||
}),
|
}),
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
Widget.Box({
|
Widget.Box({
|
||||||
class_name: "calendar-menu-weather today stats container",
|
class_name: "calendar-menu-weather today stats container",
|
||||||
hpack: "end",
|
hpack: "end",
|
||||||
vpack: "start",
|
vpack: "center",
|
||||||
vertical: true,
|
vertical: true,
|
||||||
children: [
|
children: [
|
||||||
Widget.Box({
|
Widget.Box({
|
||||||
@@ -232,6 +269,101 @@ const WeatherWidget = () => {
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
}),
|
||||||
|
Widget.Separator({
|
||||||
|
class_name: "menu-separator weather",
|
||||||
|
}),
|
||||||
|
Widget.Box({
|
||||||
|
vertical: false,
|
||||||
|
hexpand: true,
|
||||||
|
hpack: "fill",
|
||||||
|
class_name: "hourly-weather-container",
|
||||||
|
children: [1, 2, 3, 4].map((hoursFromNow) => {
|
||||||
|
const getNextEpoch = (wthr) => {
|
||||||
|
const currentEpoch = wthr.location.localtime_epoch;
|
||||||
|
const epochAtHourStart = currentEpoch - (currentEpoch % 3600);
|
||||||
|
let nextEpoch = 3600 * hoursFromNow + epochAtHourStart;
|
||||||
|
|
||||||
|
const curHour = new Date(currentEpoch * 1000).getHours();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Since the API is only capable of showing the current day; if
|
||||||
|
* the hours left in the day are less than 4 (aka spilling into the next day),
|
||||||
|
* then rewind to contain the prediction within the current day.
|
||||||
|
*/
|
||||||
|
if (curHour > 20) {
|
||||||
|
const hoursToRewind = curHour - 19;
|
||||||
|
nextEpoch =
|
||||||
|
3600 * hoursFromNow +
|
||||||
|
epochAtHourStart -
|
||||||
|
hoursToRewind * 3600;
|
||||||
|
}
|
||||||
|
return nextEpoch;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Widget.Box({
|
||||||
|
class_name: "hourly-weather-item",
|
||||||
|
hexpand: true,
|
||||||
|
vertical: true,
|
||||||
|
children: [
|
||||||
|
Widget.Label({
|
||||||
|
class_name: "hourly-weather-time",
|
||||||
|
label: theWeather.bind("value").as((w) => {
|
||||||
|
if (!Object.keys(w).length) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextEpoch = getNextEpoch(w);
|
||||||
|
const dateAtEpoch = new Date(nextEpoch * 1000);
|
||||||
|
let hours = dateAtEpoch.getHours();
|
||||||
|
const ampm = hours >= 12 ? "PM" : "AM";
|
||||||
|
hours = hours % 12 || 12;
|
||||||
|
|
||||||
|
return `${hours}${ampm}`;
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
Widget.Icon({
|
||||||
|
class_name: "hourly-weather-icon",
|
||||||
|
icon: theWeather.bind("value").as((w) => {
|
||||||
|
if (!Object.keys(w).length) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextEpoch = getNextEpoch(w);
|
||||||
|
const weatherAtEpoch =
|
||||||
|
w.forecast.forecastday[0].hour.find(
|
||||||
|
(h) => h.time_epoch === nextEpoch,
|
||||||
|
);
|
||||||
|
|
||||||
|
return icons.weather[
|
||||||
|
weatherAtEpoch.condition.text
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.replaceAll(" ", "_")
|
||||||
|
];
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
Widget.Label({
|
||||||
|
class_name: "hourly-weather-temp",
|
||||||
|
label: theWeather.bind("value").as((w) => {
|
||||||
|
if (!Object.keys(w).length) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextEpoch = getNextEpoch(w);
|
||||||
|
const weatherAtEpoch =
|
||||||
|
w.forecast.forecastday[0].hour.find(
|
||||||
|
(h) => h.time_epoch === nextEpoch,
|
||||||
|
);
|
||||||
|
|
||||||
|
return `${Math.ceil(weatherAtEpoch.temp_f)}° F`;
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -87,13 +87,14 @@
|
|||||||
.weather-container-box {
|
.weather-container-box {
|
||||||
color: $red;
|
color: $red;
|
||||||
margin: 1.5em;
|
margin: 1.5em;
|
||||||
|
margin-top: 2.5em;
|
||||||
min-width: 3em;
|
min-width: 3em;
|
||||||
// min-height: 10em;
|
// min-height: 10em;
|
||||||
|
|
||||||
.calendar-menu-weather.today.icon {
|
.calendar-menu-weather.today.icon {
|
||||||
image {
|
image {
|
||||||
color: $pink;
|
color: $pink;
|
||||||
font-size: 5em;
|
font-size: 6em;
|
||||||
// margin-right: 0.3em;
|
// margin-right: 0.3em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,12 +103,16 @@
|
|||||||
color: $text;
|
color: $text;
|
||||||
margin-left: 0.2em;
|
margin-left: 0.2em;
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
|
|
||||||
|
&.icon {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-menu-weather.today.condition.label {
|
.calendar-menu-weather.today.condition.label {
|
||||||
color: $teal;
|
color: $teal;
|
||||||
font-size: 1.75em;
|
font-size: 1.5em;
|
||||||
margin-left: -1.4em;
|
margin-bottom: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
// .calendar-menu-weather.today.condition.label.weather-color.red {
|
// .calendar-menu-weather.today.condition.label.weather-color.red {
|
||||||
@@ -144,7 +149,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.calendar-menu-weather.today.stats.container {
|
.calendar-menu-weather.today.stats.container {
|
||||||
// margin-left: 2.2em;
|
margin-bottom: 0.75em;
|
||||||
color: $pink;
|
color: $pink;
|
||||||
|
|
||||||
.weather.label {
|
.weather.label {
|
||||||
@@ -152,14 +157,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-separator.weather {
|
||||||
|
margin: 1.5em 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hourly-weather-time {
|
||||||
|
color: $pink;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hourly-weather-icon {
|
||||||
|
color: $pink;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hourly-weather-temp {
|
||||||
|
color: $pink;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
29
style.css
29
style.css
@@ -1190,21 +1190,25 @@ image {
|
|||||||
.weather-container-box {
|
.weather-container-box {
|
||||||
color: #f38ba8;
|
color: #f38ba8;
|
||||||
margin: 1.5em;
|
margin: 1.5em;
|
||||||
|
margin-top: 2.5em;
|
||||||
min-width: 3em;
|
min-width: 3em;
|
||||||
}
|
}
|
||||||
.weather-container-box .calendar-menu-weather.today.icon image {
|
.weather-container-box .calendar-menu-weather.today.icon image {
|
||||||
color: #f5c2e7;
|
color: #f5c2e7;
|
||||||
font-size: 5em;
|
font-size: 6em;
|
||||||
}
|
}
|
||||||
.weather-container-box .calendar-menu-weather.today.temp.label {
|
.weather-container-box .calendar-menu-weather.today.temp.label {
|
||||||
color: #cdd6f4;
|
color: #cdd6f4;
|
||||||
margin-left: 0.2em;
|
margin-left: 0.2em;
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
}
|
}
|
||||||
|
.weather-container-box .calendar-menu-weather.today.temp.label.icon {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
.weather-container-box .calendar-menu-weather.today.condition.label {
|
.weather-container-box .calendar-menu-weather.today.condition.label {
|
||||||
color: #94e2d5;
|
color: #94e2d5;
|
||||||
font-size: 1.75em;
|
font-size: 1.5em;
|
||||||
margin-left: -1.4em;
|
margin-bottom: 0.4em;
|
||||||
}
|
}
|
||||||
.weather-container-box .calendar-menu-weather.today.temp.label.icon.weather-color.red {
|
.weather-container-box .calendar-menu-weather.today.temp.label.icon.weather-color.red {
|
||||||
color: #f38ba8;
|
color: #f38ba8;
|
||||||
@@ -1223,12 +1227,31 @@ image {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.calendar-menu-weather.today.stats.container {
|
.calendar-menu-weather.today.stats.container {
|
||||||
|
margin-bottom: 0.75em;
|
||||||
color: #f5c2e7;
|
color: #f5c2e7;
|
||||||
}
|
}
|
||||||
.calendar-menu-weather.today.stats.container .weather.label {
|
.calendar-menu-weather.today.stats.container .weather.label {
|
||||||
margin-left: 0.35em;
|
margin-left: 0.35em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-separator.weather {
|
||||||
|
margin: 1.5em 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hourly-weather-time {
|
||||||
|
color: #f5c2e7;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hourly-weather-icon {
|
||||||
|
color: #f5c2e7;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hourly-weather-temp {
|
||||||
|
color: #f5c2e7;
|
||||||
|
}
|
||||||
|
|
||||||
.notification-card-container {
|
.notification-card-container {
|
||||||
margin-top: 3.5rem;
|
margin-top: 3.5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user