Stage 8: UI social/account/history surfaces
Wire the deferred Stage 7 surfaces end-to-end (UI -> gateway transcode -> backend REST -> existing domain services): friends (incl. one-time friend codes), per-user blocks, friend-game invitations, profile editing + email binding, the statistics screen, and the in-game history + GCG export. Friends gain two add paths (interview decision, a deliberate plan change): one-time 6-digit codes (friend_codes table, 12h TTL, single-use, rate-limited redeem); and play-gated requests (shared game required) where an explicit decline is permanent, an ignored request lapses after 30 days, and a code bypasses a decline. Migration 00006 widens friendships_status_chk and adds friend_codes. Lobby notification badge is poll + push: a new generic `notify` event drives it live; the client polls on open/focus. Language stays a single Settings control that writes through to the durable account's preferred_language. GCG export is finished-only (game.ErrGameActive) and shares/downloads the .gcg file. Tests: backend unit + inttest (friend gate/decline/code, ListInvitations, GetStats, GCG gate), gateway transcode round-trips + notify constructor, UI vitest (codecs, win-rate, share choice) + Playwright social specs. Docs: PLAN (Stage 8 done + refinements + TODO-5), ARCHITECTURE, FUNCTIONAL(+ru), UI_DESIGN, TESTING, module READMEs.
This commit is contained in:
@@ -5,18 +5,25 @@
|
||||
// message.
|
||||
|
||||
import type {
|
||||
AccountRef,
|
||||
ChatMessage,
|
||||
EvalResult,
|
||||
FriendCode,
|
||||
GameList,
|
||||
GameView,
|
||||
GcgExport,
|
||||
History,
|
||||
HintResult,
|
||||
Invitation,
|
||||
InvitationSettings,
|
||||
MatchResult,
|
||||
MoveResult,
|
||||
Profile,
|
||||
ProfileUpdate,
|
||||
PushEvent,
|
||||
Session,
|
||||
StateView,
|
||||
Stats,
|
||||
Tile,
|
||||
Variant,
|
||||
WordCheckResult,
|
||||
@@ -74,6 +81,35 @@ export interface GatewayClient {
|
||||
chatList(gameId: string): Promise<ChatMessage[]>;
|
||||
nudge(gameId: string): Promise<ChatMessage>;
|
||||
|
||||
// --- friends (Stage 8) ---
|
||||
friendsList(): Promise<AccountRef[]>;
|
||||
friendsIncoming(): Promise<AccountRef[]>;
|
||||
friendRequest(accountId: string): Promise<void>;
|
||||
friendRespond(requesterId: string, accept: boolean): Promise<void>;
|
||||
friendCancel(accountId: string): Promise<void>;
|
||||
unfriend(accountId: string): Promise<void>;
|
||||
friendCodeIssue(): Promise<FriendCode>;
|
||||
friendCodeRedeem(code: string): Promise<AccountRef>;
|
||||
|
||||
// --- blocks (Stage 8) ---
|
||||
blocksList(): Promise<AccountRef[]>;
|
||||
block(accountId: string): Promise<void>;
|
||||
unblock(accountId: string): Promise<void>;
|
||||
|
||||
// --- invitations (Stage 8) ---
|
||||
invitationsList(): Promise<Invitation[]>;
|
||||
invitationCreate(inviteeIds: string[], settings: InvitationSettings): Promise<Invitation>;
|
||||
invitationAccept(invitationId: string): Promise<Invitation>;
|
||||
invitationDecline(invitationId: string): Promise<Invitation>;
|
||||
invitationCancel(invitationId: string): Promise<void>;
|
||||
|
||||
// --- profile / stats / history (Stage 8) ---
|
||||
profileUpdate(p: ProfileUpdate): Promise<Profile>;
|
||||
emailBindRequest(email: string): Promise<void>;
|
||||
emailBindConfirm(email: string, code: string): Promise<Profile>;
|
||||
statsGet(): Promise<Stats>;
|
||||
exportGcg(gameId: string): Promise<GcgExport>;
|
||||
|
||||
// --- live stream ---
|
||||
subscribe(onEvent: (e: PushEvent) => void, onError?: (err: unknown) => void): Unsubscribe;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user