# @vojo/widget-whatsapp Vojo WhatsApp bridge management widget — mounts inside `/bots/whatsapp` in the Vojo client. Drives the mautrix-whatsapp bridge bot (`@whatsappbot:vojo.chat`) by sending bridgev2 commands in the control DM and rendering the bot's text replies into a typed login flow. This is **not** a WhatsApp client — Vojo continues using the Matrix room the bridge writes to. The widget is a panel that handles authentication (QR scan or pairing code) and surfaces session status. ## Layout ``` src/ ├── bootstrap.ts Parse URL params the host appends (mirrors BotWidgetEmbed.ts) ├── widget-api.ts Inline matrix-widget-api postMessage transport (no SDK) ├── App.tsx UI: login forms, QR / pairing-code panels, transcript pane ├── main.tsx Entry: init bootstrap, render App or diagnostic ├── styles.css Theme-aware CSS (Vojo Dawn palette) ├── state.ts Login state machine + hydrate-from-timeline ├── i18n/ Russian primary + English fallback └── bridge-protocol/ ├── types.ts LoginEvent discriminated union ├── parser.ts Dispatch shim └── dialects/ └── bridgev2_v0264.ts Regex table pinned to mautrix-whatsapp v0.26.4 ``` ## Login flows WhatsApp's mautrix bridge ships TWO login flows (see `pkg/connector/login.go::GetLoginFlows`): 1. **QR** (`!wa login qr`) — bridge emits a rotating `m.image` whose body is the raw whatsmeow handshake payload (`,,,`, four base64 fields). The widget renders it as a QR matrix client-side. Whatsmeow `qrIntervals = [60s, 20s, 20s, 20s, 20s, 20s]` — first QR lasts 60 seconds, then five rotations of 20 seconds each. Total active window: 2 minutes 40 seconds. Each rotation arrives as an `m.replace` edit of the original event; the state machine matches on the original id and repaints the matrix. 2. **Pairing code** (`!wa login phone`) — alternative for users whose camera doesn't work or who prefer typing. The user enters a phone number; the bridge replies with two notices: - `Input the pairing code in the WhatsApp mobile app to log in` - The 8-character code itself (`XXXX-XXXX`, custom base32 alphabet). The widget renders the code prominently and the user enters it in WhatsApp → Settings → Linked devices → Link with phone number. There is **no 2FA cloud-password step** — multidevice handshake is single-factor. The state machine has no `awaiting_password` arm. ## Capability contract The widget requests EXACTLY this set (matches the host's `BotWidgetDriver.getBotWidgetCapabilities`): ``` org.matrix.msc2762.timeline: org.matrix.msc2762.send.event:m.room.message#m.text org.matrix.msc2762.receive.event:m.room.message#m.text org.matrix.msc2762.receive.event:m.room.message#m.notice org.matrix.msc2762.receive.event:m.room.message#m.image org.matrix.msc2762.receive.event:m.room.redaction org.matrix.msc2762.receive.state_event:m.room.member ``` Anything else is silently dropped by the host. The capability set is identical to the Telegram widget's M13 expansion — the host driver already supports `m.image` + `m.room.redaction`. ## Local development ```bash cd apps/widget-whatsapp && npm install cd /home/ubuntu/projects/vojo/cinny && cat > config.local.json <<'JSON' { "bots": [ { "id": "whatsapp", "experience": { "type": "matrix-widget", "url": "http://localhost:8083/" } } ] } JSON ``` Run both servers: ```bash # terminal 1 — widget on :8083 with HMR cd apps/widget-whatsapp && npm run dev # terminal 2 — host SPA on :8080 cd /home/ubuntu/projects/vojo/cinny && npm start ``` Open `http://localhost:8080/bots/whatsapp`. The host's URL validator accepts `http://localhost:*` only in dev builds. ## Build ```bash npm run build ``` Outputs to `apps/widget-whatsapp/dist/`. Deploy by rsyncing `dist/*` into `~/vojo/widgets/whatsapp/` on the production host. The VSCode task `Deploy widgets` already includes the third subshell — running it from the host root pushes all three widgets in sequence. ## Capacitor (Android) `capacitor.config.ts` already allows `widgets.vojo.chat` for the existing TG / Discord widgets — no extra entry needed for WhatsApp. ## Hosting (server-side) Same Caddy `widgets.vojo.chat` block as the other widgets — add a third `handle_path /whatsapp/* { … }` block alongside `/telegram/*` and `/discord/*`. Then `mkdir -p ~/vojo/widgets/whatsapp` on the server, run the deploy task, and verify with `curl -I https://widgets.vojo.chat/whatsapp/index.html`. ## Source-of-truth pointers - mautrix-whatsapp connector: - mautrix-whatsapp connector (post-login session events): - whatsmeow QR format: (`makeQRData`) - whatsmeow pairing-code: (`PairPhone`) - bridgev2 commands layer (shared with mautrix-telegram): The dialect file `src/bridge-protocol/dialects/bridgev2_v0264.ts` has inline upstream pointers per regex; when the bridge image is upgraded, spot-check those pointers and either confirm the wording is still valid or drop a sibling dialect file with new regexes.