2024-11-22 22:31:33 +07:00
|
|
|
import { App, Astal, Gdk } from "astal/gtk3";
|
2024-11-23 18:41:28 +07:00
|
|
|
import { bind, execAsync, interval, timeout, Variable } from "astal";
|
2024-11-21 22:45:00 +07:00
|
|
|
|
2024-11-22 22:31:33 +07:00
|
|
|
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();
|
|
|
|
}
|
2024-11-21 22:45:00 +07:00
|
|
|
|
2024-11-24 09:44:47 +07:00
|
|
|
async function fetchAgenda() {
|
|
|
|
const output = await execAsync(["gcalcli", "agenda", "--tsv"]);
|
|
|
|
const items = output.trim().split("\n").map(transform);
|
|
|
|
return createAgenda(items);
|
|
|
|
}
|
|
|
|
|
2024-11-21 22:45:00 +07:00
|
|
|
export default function Agenda(gdkmonitor: Gdk.Monitor) {
|
2024-11-24 09:44:47 +07:00
|
|
|
const text = Variable("");
|
|
|
|
|
|
|
|
const fetchAgendaData = () => {
|
|
|
|
fetchAgenda()
|
|
|
|
.then((agenda) => text.set(agenda))
|
|
|
|
.catch((err) => {
|
|
|
|
text.set(`failed to fetch agenda: ${err.message}`);
|
|
|
|
timeout(5000, fetchAgendaData);
|
|
|
|
});
|
2024-11-23 18:36:32 +07:00
|
|
|
};
|
2024-11-24 09:44:47 +07:00
|
|
|
const intervalHandler = interval(
|
|
|
|
1000 * 60 * 10 /* 10 minutes */,
|
|
|
|
fetchAgendaData,
|
|
|
|
);
|
2024-11-21 22:45:00 +07:00
|
|
|
return (
|
|
|
|
<window
|
2024-11-22 22:31:33 +07:00
|
|
|
className="Agenda"
|
2024-11-21 22:45:00 +07:00
|
|
|
gdkmonitor={gdkmonitor}
|
|
|
|
exclusivity={Astal.Exclusivity.EXCLUSIVE}
|
2024-11-22 22:31:33 +07:00
|
|
|
anchor={Astal.WindowAnchor.RIGHT | Astal.WindowAnchor.TOP}
|
|
|
|
layer={Astal.Layer.BOTTOM}
|
2024-11-21 22:45:00 +07:00
|
|
|
application={App}
|
|
|
|
>
|
2024-11-22 22:31:33 +07:00
|
|
|
<button
|
|
|
|
borderWidth={0}
|
|
|
|
onClick={() => {
|
|
|
|
execAsync(["xdg-open", "https://www.google.com/calendar"]);
|
|
|
|
}}
|
|
|
|
>
|
2024-11-23 18:36:32 +07:00
|
|
|
<box
|
|
|
|
onDestroy={() => {
|
|
|
|
intervalHandler.cancel();
|
2024-11-24 09:44:47 +07:00
|
|
|
text.drop();
|
2024-11-23 18:36:32 +07:00
|
|
|
}}
|
|
|
|
>
|
2024-11-24 09:44:47 +07:00
|
|
|
{bind(text)}
|
2024-11-22 22:31:33 +07:00
|
|
|
</box>
|
|
|
|
</button>
|
2024-11-21 22:45:00 +07:00
|
|
|
</window>
|
|
|
|
);
|
|
|
|
}
|