AGS/widget/Agenda.tsx

106 lines
2.7 KiB
TypeScript

import { App, Astal, Gdk } from "astal/gtk3";
import { bind, execAsync, interval, timeout, Variable } from "astal";
type AgendaItem = {
startDate: string;
startHour: string;
endDate: string;
endHour: string;
activity: string;
};
function transform(stdout: string): AgendaItem {
const [startDate, startHour, endDate, endHour, activity] = stdout.split("\t");
return { startDate, startHour, endDate, endHour, activity };
}
// Helper function to get the day name from a date string
function getDayName(dateString: string): string {
const date = new Date(dateString);
const dayNames = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
return dayNames[date.getDay()];
}
// Helper function to format the agenda
function createAgenda(agendaItems: AgendaItem[]): string {
// Group items by date
const groupedByDate: { [date: string]: AgendaItem[] } = {};
agendaItems.forEach((item) => {
if (!groupedByDate[item.startDate]) {
groupedByDate[item.startDate] = [];
}
groupedByDate[item.startDate].push(item);
});
// Format each group with extra space between them
let result = "";
for (const date in groupedByDate) {
const dayName = getDayName(date);
result += `\n${date} - ${dayName}\n`; // Include the day name
groupedByDate[date].forEach((item) => {
result += `\t${item.startHour} - ${item.endHour} | ${item.activity}\n`;
});
result += "\n"; // Add extra space between date groups
}
return result.trim();
}
async function fetchAgenda() {
const output = await execAsync(["gcalcli", "agenda", "--tsv"]);
const items = output.trim().split("\n").map(transform);
return createAgenda(items);
}
export default function Agenda(gdkmonitor: Gdk.Monitor) {
const text = Variable("");
const fetchAgendaData = () => {
fetchAgenda()
.then((agenda) => text.set(agenda))
.catch((err) => {
text.set(`failed to fetch agenda: ${err.message}`);
timeout(5000, fetchAgendaData);
});
};
const intervalHandler = interval(
1000 * 60 * 10 /* 10 minutes */,
fetchAgendaData,
);
return (
<window
className="Agenda"
gdkmonitor={gdkmonitor}
exclusivity={Astal.Exclusivity.EXCLUSIVE}
anchor={Astal.WindowAnchor.RIGHT | Astal.WindowAnchor.TOP}
layer={Astal.Layer.BOTTOM}
application={App}
>
<button
borderWidth={0}
onClick={() => {
execAsync(["xdg-open", "https://www.google.com/calendar"]);
}}
>
<box
onDestroy={() => {
intervalHandler.cancel();
text.drop();
}}
>
{bind(text)}
</box>
</button>
</window>
);
}