import { Gtk } from "ags/gtk4"; import { createState } from "ags"; import GLib from "gi://GLib"; import Gio from "gi://Gio"; import { watchFile } from "../../lib/fileMonitor"; type Email = { subject: string; sender: string; date: string }; const CACHE_FILE = GLib.build_filenamev([ GLib.get_user_cache_dir(), "ags", "unread-emails.json", ]); export default function EmailList() { const [emails, setEmails] = createState([]); let listContainer: Gtk.Box | null = null; // holds the email items function readEmailsFromCache(): Email[] { try { const file = Gio.File.new_for_path(CACHE_FILE); const [ok, contents] = file.load_contents(null); if (!ok) return []; const data = JSON.parse(new TextDecoder("utf-8").decode(contents)); if (!Array.isArray(data)) return []; return data.map((m: any) => ({ subject: m.subject || "(no subject)", sender: m.from?.name || m.from?.addr || "Unknown", date: m.date ? new Date(m.date).toLocaleString() : "Unknown date", })); } catch (err) { console.error("Failed to read email cache", err); return []; } } function rebuildList() { if (!listContainer) return; // Clear existing children let child = listContainer.get_first_child(); while (child) { const next = child.get_next_sibling(); listContainer.remove(child); child = next; } const currentEmails = emails(); if (currentEmails.length === 0) { // Empty state const emptyBox = new Gtk.Box({ halign: Gtk.Align.CENTER, valign: Gtk.Align.START, orientation: Gtk.Orientation.VERTICAL, cssClasses: ["status-box"], }); emptyBox.append(new Gtk.Label({ label: "📭", cssClasses: ["empty-icon"] })); emptyBox.append(new Gtk.Label({ label: "No unread emails", cssClasses: ["status-text"] })); listContainer.append(emptyBox); } else { // Populate emails for (const email of currentEmails) { const item = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, cssClasses: ["email-item"], }); item.append(new Gtk.Label({ label: email.subject, halign: Gtk.Align.START, hexpand: false, cssClasses: ["email-subject"], })); const meta = new Gtk.Box({ spacing: 8 }); meta.append(new Gtk.Label({ label: email.sender, cssClasses: ["email-sender"] })); meta.append(new Gtk.Label({ label: "•", cssClasses: ["email-separator"] })); meta.append(new Gtk.Label({ label: email.date, cssClasses: ["email-date"] })); item.append(meta); listContainer.append(item); } } } function updateDisplay() { const parsed = readEmailsFromCache(); setEmails(parsed); rebuildList(); } const root = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, cssClasses: ["email-list-container"], }); const scrolled = new Gtk.ScrolledWindow({ vexpand: true, cssClasses: ["email-scroll", "grid-card"], }); listContainer = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 12, hexpand: true, cssClasses: ["email-list"], }); scrolled.set_child(listContainer); root.append(scrolled); // Initial load + monitor updateDisplay(); watchFile(CACHE_FILE, updateDisplay, root); return root; }