diff --git a/modules/rinbox/components/folk-inbox-client.ts b/modules/rinbox/components/folk-inbox-client.ts index 99ec640..aee99b8 100644 --- a/modules/rinbox/components/folk-inbox-client.ts +++ b/modules/rinbox/components/folk-inbox-client.ts @@ -78,6 +78,12 @@ class FolkInboxClient extends HTMLElement { }, ]; private demoThreads: Record = { + space: [ + { id: "s1", from_name: "Alice Chen", from_address: "alice@example.com", subject: "Welcome to the space mailbox", status: "open", is_read: true, is_starred: true, replied: false, forwarded: false, needsAttention: false, comment_count: 1, received_at: new Date(Date.now() - 1 * 3600000).toISOString(), body_text: "This is the shared space mailbox. All space members can read and triage messages here.", direction: 'inbound', comments: [{ username: "Bob Martinez", body: "Great, all set up!", created_at: new Date(Date.now() - 0.5 * 3600000).toISOString() }] }, + { id: "s2", from_name: "External Contact", from_address: "contact@example.org", subject: "Partnership inquiry", status: "open", is_read: false, is_starred: false, replied: false, forwarded: false, needsAttention: true, comment_count: 0, received_at: new Date(Date.now() - 3 * 3600000).toISOString(), body_text: "We'd love to discuss a potential collaboration with your community. Could we schedule a call?", direction: 'inbound', comments: [] }, + { id: "s3", from_name: "Community Bot", from_address: "bot@rspace.online", subject: "Weekly digest: 12 new members, 3 proposals", status: "open", is_read: true, is_starred: false, replied: false, forwarded: false, needsAttention: false, comment_count: 0, received_at: new Date(Date.now() - 12 * 3600000).toISOString(), body_text: "Here's your weekly summary:\n\n- 12 new members joined\n- 3 governance proposals submitted\n- 2 events scheduled\n\nVisit the dashboard for details.", direction: 'inbound', comments: [] }, + { id: "s4", from_name: "Dave Park", from_address: "dave@example.com", subject: "Governance proposal feedback", status: "closed", is_read: true, is_starred: false, replied: true, forwarded: false, needsAttention: false, comment_count: 2, received_at: new Date(Date.now() - 48 * 3600000).toISOString(), body_text: "I've reviewed the treasury allocation proposal. My feedback is inline below.", direction: 'inbound', comments: [{ username: "Alice Chen", body: "Good points, incorporated into v2.", created_at: new Date(Date.now() - 46 * 3600000).toISOString() }, { username: "Dave Park", body: "Looks great now, thanks!", created_at: new Date(Date.now() - 44 * 3600000).toISOString() }] }, + ], team: [ { id: "t1", from_name: "Alice Chen", from_address: "alice@example.com", subject: "Sprint planning notes", status: "open", is_read: true, is_starred: true, replied: true, forwarded: false, needsAttention: false, comment_count: 3, received_at: new Date(Date.now() - 2 * 3600000).toISOString(), body_text: "Here are the sprint planning notes from today's session. We agreed on the following priorities for the next two weeks:\n\n1. Ship local-first sync for notes module\n2. Polish the calendar demo mode\n3. Review provider registry API\n\nLet me know if I missed anything.", direction: 'inbound', comments: [{ username: "Bob Martinez", body: "Looks good! I'd add the inbox overhaul too.", created_at: new Date(Date.now() - 1.5 * 3600000).toISOString() }, { username: "Carol Wu", body: "Agreed, calendar polish is top priority.", created_at: new Date(Date.now() - 1 * 3600000).toISOString() }, { username: "Alice Chen", body: "Updated the list. Thanks!", created_at: new Date(Date.now() - 0.5 * 3600000).toISOString() }] }, { id: "t2", from_name: "Bob Martinez", from_address: "bob@example.com", subject: "Deploy checklist for v2.1", status: "open", is_read: false, is_starred: false, replied: false, forwarded: false, needsAttention: true, comment_count: 1, received_at: new Date(Date.now() - 5 * 3600000).toISOString(), body_text: "Here is the deploy checklist for v2.1. Please review before we cut the release.\n\n- [ ] Run full test suite\n- [ ] Update changelog\n- [ ] Tag release in Gitea\n- [ ] Deploy to staging\n- [ ] Smoke test all modules", direction: 'inbound', comments: [{ username: "Alice Chen", body: "I can handle the changelog update.", created_at: new Date(Date.now() - 4 * 3600000).toISOString() }] }, @@ -96,9 +102,7 @@ class FolkInboxClient extends HTMLElement { private static readonly TOUR_STEPS = [ { target: '[data-nav="mailboxes"]', title: "Mailboxes", message: "Shared team mailboxes — everyone sees the same inbox, threads, and comments.", advanceOnClick: true }, { target: '[data-nav="approvals"]', title: "Approvals", message: "Outbound emails require co-signer approval before sending. Review and sign here.", advanceOnClick: true }, - { target: '[data-nav="agents"]', title: "Agents", message: "AI agents monitor inboxes and draft replies automatically. Create and manage them here.", advanceOnClick: true }, - { target: '[data-nav="personal"]', title: "Personal Inbox", message: "Connect your own IMAP account for a personal inbox alongside shared ones.", advanceOnClick: true }, - { target: '[data-action="help"]', title: "Help Guide", message: "Open the full guide anytime to learn how collaborative email works in rInbox.", advanceOnClick: true }, + { target: '[data-action="help"]', title: "Info", message: "Open the guide anytime to learn how collaborative email works in rInbox.", advanceOnClick: true }, ]; constructor() { @@ -118,10 +122,6 @@ class FolkInboxClient extends HTMLElement { this._checkForwardStatus(); if (this.space === "demo") { this.loadDemoData(); } else { this.subscribeOffline(); this.loadMailboxes(); } - // Auto-start tour on first visit - if (!localStorage.getItem("rinbox_tour_done")) { - setTimeout(() => this._tour.start(), 1200); - } this._stopPresence = startPresenceHeartbeat(() => ({ module: 'rinbox', context: this.currentThread?.subject || 'Inbox' })); } @@ -173,8 +173,9 @@ class FolkInboxClient extends HTMLElement { private loadDemoData() { this.mailboxes = [ - { slug: "team", name: "Team Inbox", email: "team@rspace.online", description: "Shared workspace inbox for internal team communications", thread_count: 4, unread_count: 1 }, - { slug: "support", name: "Support", email: "support@rspace.online", description: "Community support requests with multi-sig approval workflows", thread_count: 3, unread_count: 1 }, + { slug: "space", name: `${this.space}@rspace.online`, email: `${this.space}@rspace.online`, description: "Shared space mailbox — all members can read and triage", thread_count: 4, unread_count: 1, primary: true }, + { slug: "team", name: "Team Inbox", email: "team@rspace.online", description: "Internal team communications", thread_count: 4, unread_count: 1 }, + { slug: "support", name: "Support", email: "support@rspace.online", description: "Community support requests with multi-sig approval", thread_count: 3, unread_count: 1 }, ]; this.render(); } @@ -188,7 +189,13 @@ class FolkInboxClient extends HTMLElement { }); if (resp.ok) { const data = await resp.json(); - this.mailboxes = data.mailboxes || []; + const list = data.mailboxes || []; + // Mark space mailbox as primary + const spaceEmail = `${this.space}@rspace.online`; + for (const m of list) { + if (m.email === spaceEmail) m.primary = true; + } + this.mailboxes = list; } } catch { /* ignore */ } @@ -559,6 +566,8 @@ class FolkInboxClient extends HTMLElement { .mailbox-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 0.75rem; } .mailbox-card { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 12px; padding: 1.25rem; cursor: pointer; transition: all 0.2s; } .mailbox-card:hover { border-color: var(--rs-primary); transform: translateY(-1px); box-shadow: 0 4px 16px rgba(99,102,241,0.15); } + .mailbox-primary { border-color: #6366f1; background: linear-gradient(135deg, var(--rs-bg-surface), rgba(99,102,241,0.08)); grid-column: 1 / -1; } + .mailbox-primary .mailbox-name { font-size: 1.1rem; color: #818cf8; } .mailbox-icon { font-size: 1.5rem; margin-bottom: 0.75rem; } .mailbox-name { font-weight: 600; font-size: 1rem; margin-bottom: 0.25rem; color: var(--rs-text-primary); } .mailbox-email { font-size: 0.8rem; color: #6366f1; margin-bottom: 0.5rem; font-family: monospace; } @@ -815,8 +824,6 @@ class FolkInboxClient extends HTMLElement { const items: { id: string; label: string }[] = [ { id: "mailboxes", label: "Mailboxes" }, { id: "approvals", label: "Approvals" }, - { id: "personal", label: "Personal" }, - { id: "agents", label: "Agents" }, ]; if (this.currentMailbox) { items.unshift({ id: "threads", label: this.currentMailbox.name }); @@ -826,9 +833,7 @@ class FolkInboxClient extends HTMLElement { ${this.view !== "mailboxes" && this._history.canGoBack ? `` : ""} ${items.map((i) => ``).join("")} - ${this._currentUsername ? `${this._currentUsername}` : ''} - - + `; } @@ -857,12 +862,15 @@ class FolkInboxClient extends HTMLElement { `; } - return `
${this.mailboxes.map((m) => { + // Sort: primary (space) mailbox first + const sorted = [...this.mailboxes].sort((a, b) => (b.primary ? 1 : 0) - (a.primary ? 1 : 0)); + return `
${sorted.map((m) => { const demoThreads = this.demoThreads[m.slug] || []; const threadCount = m.thread_count ?? demoThreads.length; const unreadCount = m.unread_count ?? demoThreads.filter((t: any) => !t.is_read).length; + const isPrimary = m.primary || m.email === `${this.space}@rspace.online`; return ` -
+
📨
${m.name}
${m.email}
@@ -1367,9 +1375,6 @@ class FolkInboxClient extends HTMLElement { } private bindEvents() { - // Tour button - this.shadow.getElementById("btn-tour")?.addEventListener("click", () => this.startTour()); - // Navigation this.shadow.querySelectorAll("[data-nav]").forEach((btn) => { btn.addEventListener("click", () => {