hyprpanel

This commit is contained in:
wt committed 2024-10-23 21:12:15 +07:00
1 parent 10080a83ee
commit 5151ac24da
322 files changed
+38276

No files matched your search

@@ -0,0 +1,24 @@
import { BoxWidget } from 'lib/types/widget';
const CalendarWidget = (): BoxWidget => {
return Widget.Box({
class_name: 'calendar-menu-item-container calendar',
hpack: 'fill',
vpack: 'fill',
expand: true,
child: Widget.Box({
class_name: 'calendar-container-box',
child: Widget.Calendar({
expand: true,
hpack: 'fill',
vpack: 'fill',
class_name: 'calendar-menu-widget',
showDayNames: true,
showDetails: false,
showHeading: true,
}),
}),
});
};
export { CalendarWidget };
@@ -0,0 +1,36 @@
import DropdownMenu from 'modules/menus/shared/dropdown/index';
import { TimeWidget } from './time/index';
import { CalendarWidget } from './calendar';
import { WeatherWidget } from './weather/index';
import options from 'options';
import Window from 'types/widgets/window';
import { Attribute, Child } from 'lib/types/widget';
const { enabled: weatherEnabled } = options.menus.clock.weather;
export default (): Window<Child, Attribute> => {
return DropdownMenu({
name: 'calendarmenu',
transition: options.menus.transition.bind('value'),
child: Widget.Box({
class_name: 'calendar-menu-content',
css: 'padding: 1px; margin: -1px;',
vexpand: false,
children: [
Widget.Box({
class_name: 'calendar-content-container',
vertical: true,
children: [
Widget.Box({
class_name: 'calendar-content-items',
vertical: true,
children: weatherEnabled.bind('value').as((isWeatherEnabled) => {
return [TimeWidget(), CalendarWidget(), ...(isWeatherEnabled ? [WeatherWidget()] : [])];
}),
}),
],
}),
],
}),
});
};
@@ -0,0 +1,75 @@
import { BoxWidget } from 'lib/types/widget';
import options from 'options';
const { military, hideSeconds } = options.menus.clock.time;
const time = Variable('', {
poll: [1000, 'date "+%I:%M:%S"'],
});
const period = Variable('', {
poll: [1000, 'date "+%p"'],
});
const militaryTime = Variable('', {
poll: [1000, 'date "+%H:%M:%S"'],
});
const TimeWidget = (): BoxWidget => {
return Widget.Box({
class_name: 'calendar-menu-item-container clock',
hexpand: true,
vpack: 'center',
hpack: 'fill',
child: Widget.Box({
hexpand: true,
vpack: 'center',
hpack: 'center',
class_name: 'clock-content-items',
children: Utils.merge(
[military.bind('value'), hideSeconds.bind('value')],
(is24hr: boolean, hideSeconds: boolean) => {
if (!is24hr) {
return [
Widget.Box({
hpack: 'center',
children: [
Widget.Label({
class_name: 'clock-content-time',
label: hideSeconds ? time.bind().as((str) => str.slice(0, -3)) : time.bind(),
}),
],
}),
Widget.Box({
hpack: 'center',
children: [
Widget.Label({
vpack: 'end',
class_name: 'clock-content-period',
label: period.bind(),
}),
],
}),
];
}
return [
Widget.Box({
hpack: 'center',
children: [
Widget.Label({
class_name: 'clock-content-time',
label: hideSeconds
? militaryTime.bind().as((str) => str.slice(0, -3))
: militaryTime.bind(),
}),
],
}),
];
},
),
}),
});
};
export { TimeWidget };
@@ -0,0 +1,43 @@
import { Weather, WeatherIconTitle } from 'lib/types/weather.js';
import { Variable } from 'types/variable.js';
import { weatherIcons } from 'modules/icons/weather.js';
import { isValidWeatherIconTitle } from 'globals/weather';
import { BoxWidget } from 'lib/types/widget';
import { getNextEpoch } from '../utils';
export const HourlyIcon = (theWeather: Variable<Weather>, hoursFromNow: number): BoxWidget => {
const getIconQuery = (wthr: Weather): WeatherIconTitle => {
const nextEpoch = getNextEpoch(wthr, hoursFromNow);
const weatherAtEpoch = wthr.forecast.forecastday[0].hour.find((h) => h.time_epoch === nextEpoch);
if (weatherAtEpoch === undefined) {
return 'warning';
}
let iconQuery = weatherAtEpoch.condition.text.trim().toLowerCase().replaceAll(' ', '_');
if (!weatherAtEpoch?.is_day && iconQuery === 'partly_cloudy') {
iconQuery = 'partly_cloudy_night';
}
if (isValidWeatherIconTitle(iconQuery)) {
return iconQuery;
} else {
return 'warning';
}
};
return Widget.Box({
hpack: 'center',
child: theWeather.bind('value').as((w) => {
const iconQuery = getIconQuery(w);
const weatherIcn = weatherIcons[iconQuery] || weatherIcons['warning'];
return Widget.Label({
hpack: 'center',
class_name: 'hourly-weather-icon txt-icon',
label: weatherIcn,
});
}),
});
};
@@ -0,0 +1,27 @@
import { Weather } from 'lib/types/weather';
import { Variable } from 'types/variable';
import { HourlyIcon } from './icon/index.js';
import { HourlyTemp } from './temperature/index.js';
import { HourlyTime } from './time/index.js';
import { BoxWidget } from 'lib/types/widget.js';
export const Hourly = (theWeather: Variable<Weather>): BoxWidget => {
return Widget.Box({
vertical: false,
hexpand: true,
hpack: 'fill',
class_name: 'hourly-weather-container',
children: [1, 2, 3, 4].map((hoursFromNow) => {
return Widget.Box({
class_name: 'hourly-weather-item',
hexpand: true,
vertical: true,
children: [
HourlyTime(theWeather, hoursFromNow),
HourlyIcon(theWeather, hoursFromNow),
HourlyTemp(theWeather, hoursFromNow),
],
});
}),
});
};
@@ -0,0 +1,27 @@
import { Weather } from 'lib/types/weather';
import { Variable } from 'types/variable';
import options from 'options';
import Label from 'types/widgets/label';
import { Child } from 'lib/types/widget';
import { getNextEpoch } from '../utils';
const { unit } = options.menus.clock.weather;
export const HourlyTemp = (theWeather: Variable<Weather>, hoursFromNow: number): Label<Child> => {
return Widget.Label({
class_name: 'hourly-weather-temp',
label: Utils.merge([theWeather.bind('value'), unit.bind('value')], (wthr, unt) => {
if (!Object.keys(wthr).length) {
return '-';
}
const nextEpoch = getNextEpoch(wthr, hoursFromNow);
const weatherAtEpoch = wthr.forecast.forecastday[0].hour.find((h) => h.time_epoch === nextEpoch);
if (unt === 'imperial') {
return `${weatherAtEpoch ? Math.ceil(weatherAtEpoch.temp_f) : '-'}° F`;
}
return `${weatherAtEpoch ? Math.ceil(weatherAtEpoch.temp_c) : '-'}° C`;
}),
});
};
@@ -0,0 +1,24 @@
import { Weather } from 'lib/types/weather';
import { Child } from 'lib/types/widget';
import { Variable } from 'types/variable';
import Label from 'types/widgets/label';
import { getNextEpoch } from '../utils';
export const HourlyTime = (theWeather: Variable<Weather>, hoursFromNow: number): Label<Child> => {
return Widget.Label({
class_name: 'hourly-weather-time',
label: theWeather.bind('value').as((w) => {
if (!Object.keys(w).length) {
return '-';
}
const nextEpoch = getNextEpoch(w, hoursFromNow);
const dateAtEpoch = new Date(nextEpoch * 1000);
let hours = dateAtEpoch.getHours();
const ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12 || 12;
return `${hours}${ampm}`;
}),
});
};
@@ -0,0 +1,20 @@
import { Weather } from 'lib/types/weather';
export const getNextEpoch = (wthr: Weather, hoursFromNow: number): number => {
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 > 19) {
const hoursToRewind = curHour - 19;
nextEpoch = 3600 * hoursFromNow + epochAtHourStart - hoursToRewind * 3600;
}
return nextEpoch;
};
@@ -0,0 +1,18 @@
import { Weather } from 'lib/types/weather';
import { Variable } from 'types/variable';
import { getWeatherStatusTextIcon } from 'globals/weather.js';
import { BoxWidget } from 'lib/types/widget';
export const TodayIcon = (theWeather: Variable<Weather>): BoxWidget => {
return Widget.Box({
vpack: 'center',
hpack: 'start',
class_name: 'calendar-menu-weather today icon container',
child: Widget.Label({
class_name: 'calendar-menu-weather today icon txt-icon',
label: theWeather.bind('value').as((w) => {
return getWeatherStatusTextIcon(w);
}),
}),
});
};
@@ -0,0 +1,38 @@
import { TodayIcon } from './icon/index.js';
import { TodayStats } from './stats/index.js';
import { TodayTemperature } from './temperature/index.js';
import { Hourly } from './hourly/index.js';
import { globalWeatherVar } from 'globals/weather.js';
import { BoxWidget } from 'lib/types/widget.js';
const WeatherWidget = (): BoxWidget => {
return Widget.Box({
class_name: 'calendar-menu-item-container weather',
child: Widget.Box({
class_name: 'weather-container-box',
setup: (self) => {
return (self.child = Widget.Box({
vertical: true,
hexpand: true,
children: [
Widget.Box({
class_name: 'calendar-menu-weather today',
hexpand: true,
children: [
TodayIcon(globalWeatherVar),
TodayTemperature(globalWeatherVar),
TodayStats(globalWeatherVar),
],
}),
Widget.Separator({
class_name: 'menu-separator weather',
}),
Hourly(globalWeatherVar),
],
}));
},
}),
});
};
export { WeatherWidget };
@@ -0,0 +1,50 @@
import { Weather } from 'lib/types/weather';
import { Variable } from 'types/variable';
import options from 'options';
import { Unit } from 'lib/types/options';
import { getRainChance, getWindConditions } from 'globals/weather';
import { BoxWidget } from 'lib/types/widget';
const { unit } = options.menus.clock.weather;
export const TodayStats = (theWeather: Variable<Weather>): BoxWidget => {
return Widget.Box({
class_name: 'calendar-menu-weather today stats container',
hpack: 'end',
vpack: 'center',
vertical: true,
children: [
Widget.Box({
class_name: 'weather wind',
children: [
Widget.Label({
class_name: 'weather wind icon txt-icon',
label: '',
}),
Widget.Label({
class_name: 'weather wind label',
label: Utils.merge(
[theWeather.bind('value'), unit.bind('value')],
(wthr: Weather, unt: Unit) => {
return getWindConditions(wthr, unt);
},
),
}),
],
}),
Widget.Box({
class_name: 'weather precip',
children: [
Widget.Label({
class_name: 'weather precip icon txt-icon',
label: '',
}),
Widget.Label({
class_name: 'weather precip label',
label: theWeather.bind('value').as((v) => getRainChance(v)),
}),
],
}),
],
});
};
@@ -0,0 +1,62 @@
import { Weather } from 'lib/types/weather';
import { Variable } from 'types/variable';
import options from 'options';
import { getTemperature, getWeatherIcon } from 'globals/weather';
import { BoxWidget } from 'lib/types/widget';
const { unit } = options.menus.clock.weather;
export const TodayTemperature = (theWeather: Variable<Weather>): BoxWidget => {
return Widget.Box({
hpack: 'center',
vpack: 'center',
vertical: true,
children: [
Widget.Box({
hexpand: true,
vpack: 'center',
class_name: 'calendar-menu-weather today temp container',
vertical: false,
children: [
Widget.Box({
hexpand: true,
hpack: 'center',
children: [
Widget.Label({
class_name: 'calendar-menu-weather today temp label',
label: Utils.merge([theWeather.bind('value'), unit.bind('value')], (wthr, unt) => {
return getTemperature(wthr, unt);
}),
}),
Widget.Label({
class_name: theWeather
.bind('value')
.as(
(v) =>
`calendar-menu-weather today temp label icon txt-icon ${getWeatherIcon(Math.ceil(v.current.temp_f)).color}`,
),
label: theWeather
.bind('value')
.as((v) => getWeatherIcon(Math.ceil(v.current.temp_f)).icon),
}),
],
}),
],
}),
Widget.Box({
hpack: 'center',
child: Widget.Label({
max_width_chars: 17,
truncate: 'end',
lines: 2,
class_name: theWeather
.bind('value')
.as(
(v) =>
`calendar-menu-weather today condition label ${getWeatherIcon(Math.ceil(v.current.temp_f)).color}`,
),
label: theWeather.bind('value').as((v) => v.current.condition.text),
}),
}),
],
});
};