85 lines
2.2 KiB
TypeScript
85 lines
2.2 KiB
TypeScript
import { App, Astal, Gdk } from "astal/gtk3";
|
|
import { bind, execAsync, 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();
|
|
}
|
|
|
|
export default function Agenda(gdkmonitor: Gdk.Monitor) {
|
|
const agenda = Variable([] as AgendaItem[]).watch(
|
|
["gcalcli", "agenda", "--tsv"],
|
|
(stdout, prev) => [...prev, transform(stdout)],
|
|
);
|
|
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={() => agenda.drop()}>
|
|
{bind(agenda).as(createAgenda)}
|
|
</box>
|
|
</button>
|
|
</window>
|
|
);
|
|
}
|