// ── Email Plugin Frontend ── // // Self-registering plugin: // - Injects header button "mail" // - Registers a "mail" tab in core settings (accounts management lives there) // - Mail overlay shows welcome view when no accounts exist // - Otherwise shows split-pane reader // - Extracts messages as cards via /api/cards const hyprcrd = window.hyprcrd; if (!hyprcrd) throw new Error('[email plugin] window.hyprcrd missing'); const $ = (id) => document.getElementById(id); // ── State ───────────────────────────────────────────────────────── let accounts = []; let currentAccountId = null; let currentMessages = []; let currentMessage = null; let editingAccountId = null; let selectedUids = new Set(); // Pagination state let currentOffset = 0; let currentTotal = 0; const PAGE_SIZE_KEY = 'email_messages_per_page'; const PAGE_SIZE_DEFAULT = 30; const getPageSize = () => { const v = parseInt(localStorage.getItem(PAGE_SIZE_KEY) || ''); return Number.isFinite(v) && v >= 5 && v <= 200 ? v : PAGE_SIZE_DEFAULT; }; const setPageSize = (n) => { const clamped = Math.max(5, Math.min(200, parseInt(n) || PAGE_SIZE_DEFAULT)); localStorage.setItem(PAGE_SIZE_KEY, String(clamped)); return clamped; }; // Drag-select state for the message list let dragActive = false; let dragStartUid = null; let dragMoved = false; // true once mouse entered another row let dragMode = 'add'; // 'add' or 'remove' — based on start row's initial state // ── Overlay open / close ────────────────────────────────────────── async function openEmail() { $('email-overlay').classList.add('open'); selectedUids.clear(); currentOffset = 0; await loadAccounts(); if (accounts.length === 0) { showWelcomeView(); } else { // If currentAccountId still valid, keep it; otherwise reset if (!accounts.find(a => a.id === currentAccountId)) { currentAccountId = accounts[0].id; } $('email-account-select').value = currentAccountId; showMailView(); await loadMessages(); } } function closeEmail() { $('email-overlay').classList.remove('open'); } function showWelcomeView() { // Welcome is a plain block; the inner wrapper does flex centering with h-full $('email-view-welcome').classList.remove('hidden'); $('email-view-mail').classList.add('hidden'); $('email-view-mail').classList.remove('flex'); $('email-status').textContent = ''; } function showMailView() { $('email-view-welcome').classList.add('hidden'); $('email-view-welcome').classList.remove('flex'); $('email-view-mail').classList.remove('hidden'); $('email-view-mail').classList.add('flex'); } function gotoAccountsSettings() { closeEmail(); hyprcrd.settings.openTab('email'); } // ── Accounts: data ──────────────────────────────────────────────── async function loadAccounts() { const res = await fetch('api/email/accounts'); accounts = await res.json(); if (!Array.isArray(accounts)) accounts = []; renderAccountSelect(); } function renderAccountSelect() { const sel = $('email-account-select'); if (!sel) return; sel.innerHTML = accounts.length ? accounts.map(a => ``).join('') : ''; } // ── Settings tab: rendering ─────────────────────────────────────── function buildSettingsPanel(panelEl) { panelEl.innerHTML = `
Number of mails fetched per page (5–200). Affects all accounts.
Configure IMAP accounts to read mail inside hyprcrd. Passwords are encrypted with the vault key. For Gmail/Outlook, use an app password instead of your regular password.
No accounts configured yet. Use the form below to add one.
'; return; } list.innerHTML = accounts.map(a => `