feat(social): asymmetric per-user block, in-game block control, admin lists
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 51s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m19s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 51s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m19s
Make a per-user block one-directional and non-destructive: the blocker stops
receiving everything from the blocked user (chat, nudge, friend requests,
invitations) and the matchmaker never pairs them, while the blocked user
notices nothing — their sends still persist by the normal rules but are never
delivered or surfaced (born-read). A block no longer deletes the friendship
(an unblock cleanly restores it) and instant-reads any unread the blocked user
had left for the blocker.
- backend: a directional blockExists guard across chat/nudge/friends/invitations
(store-but-hide for the blocked->blocker direction, refuse blocker->blocked);
the matchmaker excludes a block-related pair (both directions) from auto-match;
user_blocked/user_unblocked notifications to the blocker only (in-app only).
- ui: the opponent score card gains a block ✖️ control mirroring add-friend
(red "Block?" confirm, mutual-hide while confirming, struck name, hidden chat
composer when blocked); optimistic apply + event confirm + rollback for both.
- admin: the user card gains cross-linked blocks / blocked-by / friends lists.
- docs: FUNCTIONAL(+ru), ARCHITECTURE §10 + decision record, UI_DESIGN, PRERELEASE.
This commit is contained in:
+20
-8
@@ -179,14 +179,26 @@ digits, valid for twelve hours), or send a **request to someone you have played
|
||||
with** — they accept, ignore it (a request lapses after thirty days and can then be
|
||||
re-sent), or decline (a decline blocks further requests from you until they hand you
|
||||
a code). Cancelling your own pending request withdraws it; unfriending removes the
|
||||
friendship. In a game, each opponent's score card carries an **add-to-friends 🤝** control (while the
|
||||
move history is open) that mirrors the live relationship: it confirms with a tap on a fading
|
||||
✅ (the card reads *Add friend?* while confirming), goes **disabled** while a request is
|
||||
pending or was declined, and **disappears** once you are friends — updating in place the
|
||||
moment the opponent answers, and staying correct across reloads. Block globally — switch off incoming chat
|
||||
and/or friend requests — and block individual players (a per-user block hides that
|
||||
person's chat and stops requests and game invitations both ways; it also ends any
|
||||
existing friendship). Per-game chat is for quick reactions: messages are short
|
||||
friendship. In a game, each opponent's score card (while the move history is open) carries two controls:
|
||||
an **add-to-friends 🤝** on the right and a **block ✖️** on the left. Each confirms with a tap
|
||||
on a fading ✅ — the card reads *Add friend?* (or *Block?*, in red) in place of the score while
|
||||
confirming — and while one is confirming the other is hidden so they never overlap. The 🤝
|
||||
goes **disabled** while a request is pending or was declined and **disappears** once you are
|
||||
friends; both controls **disappear and the opponent's name is struck through** once you have
|
||||
blocked them. They update in place the moment the relationship changes and stay correct across
|
||||
reloads. Applying a block (or friend request) takes effect immediately and is confirmed by a
|
||||
live event; a transport failure rolls the control back to its prior state.
|
||||
|
||||
Block globally — switch off incoming chat and/or friend requests — or block an **individual
|
||||
player**. A per-user block is **one-directional and silent**: you stop receiving everything
|
||||
**from** that person — chat, nudges, friend requests and game invitations — and the matchmaker
|
||||
never pairs you with them, while they **notice nothing**. Their messages and nudges still send
|
||||
by the normal rules but never reach you (anything that would show as unread for you is marked
|
||||
read at once), and a friend request or invitation they send you is kept but never surfaces. A
|
||||
block **overrides but does not delete** an existing friendship (so you may block a friend, and
|
||||
they keep seeing you as one); active games are never interrupted — you can finish them, with
|
||||
the blocked opponent's chat composer hidden (only the log remains). Blocking from a game card
|
||||
mirrors the block in **Settings → Friends**; **unblock** and **unfriend** live there only. Per-game chat is for quick reactions: messages are short
|
||||
(up to 60 characters) and may not contain links, email addresses or phone numbers,
|
||||
even disguised. You may send **one message per turn, on your own turn**; once it is sent
|
||||
the field gives way to a short caption until your next turn. Nudge the player whose turn
|
||||
|
||||
Reference in New Issue
Block a user