Phase 28 (Step 10): docs — diplomail UI topic + FUNCTIONAL mirror
- `ui/docs/diplomail-ui.md`: new topic doc covering the wire surface, recipient-by-race-name decision, threading model, translation toggle, push events, badge, layout, and accessibility. - `docs/FUNCTIONAL.md` §11.4 grows a paragraph that records the UI's per-race threading rule, the absent read-receipt UX, and the recipient-by-race-name compose path. Mirrored verbatim into `docs/FUNCTIONAL_ru.md`. - `ui/PLAN.md` Phase 28 marked done with a "Decisions during stage" block matching the implementation plan, and the artifact list updated to the actual file set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+66
-2
@@ -3070,9 +3070,73 @@ bottom):
|
||||
- animated transitions when survivors re-distribute after an
|
||||
elimination (currently hard-jumps).
|
||||
|
||||
## Phase 28. Diplomatic Mail View
|
||||
## ~~Phase 28. Diplomatic Mail View~~
|
||||
|
||||
Status: pending.
|
||||
Status: done (pending CI gate).
|
||||
|
||||
Decisions baked in during implementation:
|
||||
|
||||
1. **Transport: ConnectRPC `user.games.mail.*`.** Eight new
|
||||
authenticated commands (inbox / sent / message.get / send /
|
||||
broadcast / admin / read / delete) plumbed end-to-end through
|
||||
the existing gateway → backend REST surface. Schemas in
|
||||
`pkg/schema/fbs/diplomail.fbs`; constants in
|
||||
`pkg/model/diplomail/diplomail.go`; gateway translation in
|
||||
`gateway/internal/backendclient/mail_commands.go`.
|
||||
2. **Recipient by race name.** The send / admin endpoints accept
|
||||
an alternative `recipient_race_name` field; backend resolves it
|
||||
via `Memberships.ListMembers(gameID, "active")`. The UI feeds
|
||||
the picker straight off `report.races[].name` — no client-side
|
||||
memberships RPC.
|
||||
3. **`sender_race_name` snapshot.** New nullable column on
|
||||
`diplomail_messages`, populated for `sender_kind='player'`
|
||||
senders that have an active membership at send time. Drives the
|
||||
per-race threading on the client.
|
||||
4. **/sent returns full message detail.** Backend's bulk sent
|
||||
listing now returns the same `UserMailMessageDetail` shape as
|
||||
`/inbox`, one row per (message, recipient). The UI collapses
|
||||
broadcasts by `message_id` into a single stand-alone item.
|
||||
5. **Threading + stand-alones.** `MailStore.entries` groups
|
||||
personal messages by the other party's race name. System,
|
||||
admin, and outgoing broadcasts render as stand-alone items in
|
||||
the same list pane.
|
||||
6. **No read receipts.** `read_at` and `deleted_at` drive the
|
||||
badge counter and soft-delete affordance but are never shown
|
||||
to the user.
|
||||
7. **Header badge.** Inline pill on the view-menu "diplomatic
|
||||
mail" row, fed by `mailStore.unreadCount`. No always-visible
|
||||
chrome added.
|
||||
8. **Push event reuse.** A new
|
||||
`eventStream.on("diplomail.message.received", …)` handler in
|
||||
`routes/games/[id]/+layout.svelte` parses the verified payload,
|
||||
refreshes the inbox, and raises a `toast.show` with a "view"
|
||||
deep-link.
|
||||
9. **Translation toggle.** Per-message Show original / Show
|
||||
translation toggle inside both `thread-pane.svelte` and
|
||||
`system-item-pane.svelte`; the body defaults to the cached
|
||||
translation when present.
|
||||
|
||||
Artifacts (delivered):
|
||||
|
||||
- backend: `internal/postgres/migrations/00001_init.sql`,
|
||||
`internal/diplomail/{types.go,store.go,service.go,admin_send.go,diplomail_e2e_test.go,README.md}`,
|
||||
`internal/server/{handlers_user_mail.go,handlers_admin_diplomail.go}`,
|
||||
`openapi.yaml`;
|
||||
- wire: `pkg/schema/fbs/diplomail.fbs` + generated Go and TS
|
||||
bindings; `pkg/model/diplomail/diplomail.go`;
|
||||
- gateway: `gateway/internal/backendclient/{mail_commands.go,routes.go,mail_commands_test.go}`,
|
||||
`gateway/cmd/gateway/main.go`;
|
||||
- ui: `ui/frontend/src/api/diplomail.ts`,
|
||||
`ui/frontend/src/lib/mail-store.svelte.ts`,
|
||||
`ui/frontend/src/lib/active-view/mail.svelte` (+ subdir
|
||||
`mail/{thread-list,thread-pane,system-item-pane,compose,system-titles}.svelte|.ts`),
|
||||
`ui/frontend/src/lib/header/view-menu.svelte`,
|
||||
`ui/frontend/src/routes/games/[id]/+layout.svelte`,
|
||||
`ui/frontend/src/lib/i18n/locales/{en,ru}.ts`;
|
||||
- docs: `ui/docs/diplomail-ui.md`, `docs/FUNCTIONAL.md` §11.4 +
|
||||
mirror in `docs/FUNCTIONAL_ru.md`.
|
||||
|
||||
Original phase brief follows.
|
||||
|
||||
Goal: implement a mail inbox and compose flow as a dedicated view that
|
||||
replaces the map.
|
||||
|
||||
Reference in New Issue
Block a user