Originally created by: Waqasahmedwaseer
Inbox v1.1
A complete self-hosted WhatsApp inbox: a realtime two-pane UI on ShadCN, wired to the live REST + SSE layer (no mocks), hardened against real-world WhatsApp behaviour found in extensive live testing with real numbers.
Commits 1–3 (data model · ingestion + REST API · SSE) merged earlier in [#111]–#114. This PR = Commits 4–6 + all real-world fixes. 20 commits · 29 files · ~2.7k LOC across wa-server, dashboard-api, dashboard-ui.
✨ Features
Messaging
- Send: text · image · document (base64 ≤16 MB) · poll (single or multi-select) · reactions (6 quick + full emoji picker) · forward (to any active chat) · copy
- Receive + render: text · image (lightbox + download) · voice/audio (player) · video (player + full-view lightbox) · document (download) · sticker · poll votes ("🗳️ Voted: …") · reactions
- Editable quick replies (manage dialog, per-browser)
Inbox
- Conversation list (search by name/phone/preview, Open/Resolved tabs, unread badges, avatars), thread (bubbles, delivery ticks, auto-scroll), composer, contact panel
- Tags (add/remove) · Notes (per customer) · Mute (per chat) · Media & docs gallery
- Session filter: universal inbox ("All sessions") or per-session
- Realtime SSE (429→polling fallback, reconnect), sound toggle
- Fixed-height app shell (only the chat scrolls), WhatsApp-style empty state, mobile drawers + tappable actions
🛠 Real-world correctness (found in live testing)
- LID → real phone:
remoteJid is now @lid; the real number rides on key.senderPn. Resolved for display and as the reply target (replies were silently failing).
- Poll-vote decryption: correct LID/PN JID combos (creator=LID + cached-poll
fromMe) per Baileys [#2342] — votes decrypt + display; delivered to webhooks.
- Re-link recovery: logout→re-link no longer leaves chats stuck "read-only" (
session.connected un-archives).
- Avatars fetched + shown; undecryptable placeholders hidden; album/wrapper messages skipped; groups/status/broadcast/newsletter filtered (1:1 only); composer crash + search bug + reaction-clip + mobile-hover bugs fixed.
🔌 Shopify/Woo readiness (PRD §2.3)
Order-confirmation works end-to-end: send poll → customer votes → decrypted vote delivered via message.received (type poll_vote) and a dedicated poll.vote webhook ({ pollMessageId, selectedOptions, voter.phone }). Multi-session supported. Verified live in n8n.
🧪 Tests (Commit 6)
13 integration tests, green, against a real PostgreSQL (no WhatsApp mocks):
ingestion (LID, filtering, dedup, placeholder→decoded upgrade, media, unread, archive/restore) + service (member guard, search incl. regression, markRead, patch). Run: pnpm test:setup then pnpm test. All 3 packages pnpm build clean.
📋 Deferred to v1.2 (intentional)
- Streaming media endpoint for >16 MB files (avoids base64/DB bloat)
- Location-map + contact-card (vCard) previews
- Poll-resolve helper (grace-window + delete-to-lock) for order flows
- True cross-session "Customer view" (merge a number across sessions)
Notes
No GitHub issues map to this series (self-driven, like [#111]–#114), so no Closes #N. Do not merge until reviewed — final merge by Waqas.
Ticket changed by: Waqasahmedwaseer