f7300f25a3
Step 6 — mail active view + subcomponents. - `lib/active-view/mail.svelte` replaces the Phase 10 stub with the list / detail layout: two-pane on desktop, one-pane stack on mobile (CSS media query, no separate route). - `lib/active-view/mail/thread-list.svelte` renders per-race threads collapsed to their last message plus stand-alone system / admin / outgoing-broadcast items, with unread badges. - `lib/active-view/mail/thread-pane.svelte` is the chat-style transcript for one race; bodies render through `textContent`, per-message Show original / translation toggles flip the rendering when a translated body is present, and a persistent reply box at the bottom calls `mailStore.composePersonal`. - `lib/active-view/mail/system-item-pane.svelte` renders one stand-alone item read-only with the same translation toggle. - `lib/active-view/mail/compose.svelte` is the compose dialog: recipient race picker fed from `report.races[]`, kind toggle (personal / broadcast / admin), admin sub-toggle for target user / all and recipient-scope picker. Server-side enforces paid-tier and owner gating; the UI surfaces 403 inline. - `lib/active-view/mail/system-titles.ts` keeps the keyword → i18n-title mapping for lifecycle-hook system mail so both the list and the detail pane pick the same canonical title. Step 9 — i18n strings (en + ru). `game.mail.*`, `game.view.mail.badge`, `game.events.mail_new.*`, `game.mail.system.*` keys added in lockstep across both locales covering compose labels / validation copy / per-system titles / translation toggle / reply / delete affordances. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
31 lines
1.3 KiB
TypeScript
31 lines
1.3 KiB
TypeScript
// Maps a system-mail message (lifecycle hook) to its i18n title key.
|
|
// Kept as a typed helper so the thread-list and detail panes pick the
|
|
// same title even when the body templates evolve.
|
|
|
|
import type { TranslationKey } from "$lib/i18n/index.svelte";
|
|
import type { MailMessage } from "../../../api/diplomail";
|
|
|
|
const KEYWORDS: Array<{ test: RegExp; key: TranslationKey }> = [
|
|
{ test: /game[._ ]paused/i, key: "game.mail.system.game_paused.title" },
|
|
{ test: /game[._ ]cancelled|cancelled/i, key: "game.mail.system.game_cancelled.title" },
|
|
{ test: /membership[._ ]removed|kicked/i, key: "game.mail.system.membership_removed.title" },
|
|
{ test: /membership[._ ]blocked|blocked/i, key: "game.mail.system.membership_blocked.title" },
|
|
];
|
|
|
|
/**
|
|
* systemTitleKey returns the localised title key for a system mail
|
|
* row. The lobby renders these messages through templated subjects;
|
|
* the UI matches on the subject to pick a canonical title regardless
|
|
* of language. Falls back to a generic system-mail title when no
|
|
* pattern matches.
|
|
*/
|
|
export function systemTitleKey(message: MailMessage): TranslationKey {
|
|
const subject = message.subject ?? "";
|
|
for (const { test, key } of KEYWORDS) {
|
|
if (test.test(subject)) {
|
|
return key;
|
|
}
|
|
}
|
|
return "game.mail.system.generic.title";
|
|
}
|