feat(nudge): name the sender; blink lobby cards; re-animate toasts
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 16s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m21s

The "waiting for your move" popup was the nudge (chat.nudge), shown without a
sender name. Resolve the nudger's per-game seat name server-side and carry it on
a new NudgeEvent.sender_name field, so:

- the in-app toast reads "<opponent>: Waiting for your move 🤭" (chat.nudgeBy);
- the out-of-app Telegram push names the sender too (render nudgeBy);

falling back to the plain phrase when the name is absent (RU mirrored). The
your_turn toast already named the opponent and is unchanged.

Lobby: when a card transitions into "your turn" or "finished" while the lobby is
open, its status emoji blinks twice (two 1s fades); the opponent's-turn change
stays in place. Blink state is keyed by game id (SvelteSet + per-id nonce/timer)
so overlapping events animate in isolation; suppressed under reduce-motion.

Toast: a per-message seq re-keys Toast.svelte, so the freshest toast cancels the
previous one and replays its entrance, uniformly on every screen.

Tests: notify.Nudge round-trip + render named/fallback (Go), game.Service.SeatName
(integration), codec/i18n/gamePhase/shouldBlink (UI). Docs (FUNCTIONAL +_ru,
UI_DESIGN) + PLAN TODO-7 (deferred FLIP card-relocation animation) updated.
This commit is contained in:
Ilia Denisov
2026-06-16 19:09:24 +02:00
parent e9dfa4ccb8
commit 12d128f1cc
26 changed files with 331 additions and 36 deletions
+5 -2
View File
@@ -75,7 +75,9 @@ The lobby lists **my games** and offers a bottom tab bar — new game, statistic
sections — *your turn*, *opponent's turn* and *finished* (empty sections are hidden) — and
orders them so the games awaiting your move come first, the longest-waiting on top, while
opponent-turn and finished games are most-recent first; it renders as a compact,
line-separated list. You can **remove a finished game from your own list**:
line-separated list. While the lobby is open and a listed game **becomes your turn or
finishes**, its status icon **blinks twice** to draw the eye (an opponent's-turn change is
silent, applied in place). You can **remove a finished game from your own list**:
swipe a finished row left (or, on desktop, tap its **⋮**) to reveal a **❌**, then tap it.
The removal is per-account and permanent — the game disappears only from your list and stays
in the other players' lists, and there is no undo. The game types offered on **New Game** are
@@ -177,7 +179,8 @@ existing friendship). Per-game chat is for quick reactions: messages are short
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
is awaited at most once per hour (the
nudge is part of the game chat); the out-of-app push is delivered via the platform.
nudge is part of the game chat); both the in-app toast and the out-of-app push (delivered
via the platform) **name the nudger** ("<opponent>: waiting for your move").
Chat and the word-check tool share one **comms screen** with **💬 chat** / **🔎 dictionary**
tabs, reached from the 💬 in the move-history header (with a back to the game); a new chat
message raises an **unread badge** on the game's score bar and the 💬 until the chat is opened.
+6 -3
View File
@@ -76,7 +76,9 @@ nudge) приходят от бота **этой партии** — по язы
*твой ход*, *ход соперника* и *завершённые* (пустые секции скрыты) — и упорядочен так,
что игры, ждущие твоего хода, идут первыми, дольше всего ждущие сверху, а игры на ходу
соперника и завершённые — самые свежие сверху; отображается компактным списком с
линиями-разделителями. Завершённую партию можно **убрать из своего списка**:
линиями-разделителями. Пока лобби открыто и партия из списка **переходит на твой ход или
завершается**, её значок статуса **дважды моргает**, привлекая внимание (переход на ход
соперника — без моргания, применяется на месте). Завершённую партию можно **убрать из своего списка**:
проведи по строке завершённой партии влево (или, на десктопе, нажми её **⋮**), чтобы открыть
**❌**, и нажми её. Удаление действует только для твоего аккаунта и необратимо — партия
исчезает лишь из твоего списка и остаётся в списках других игроков, отмены нет. Типы партий
@@ -180,8 +182,9 @@ nudge) приходят от бота **этой партии** — по язы
содержать ссылок, email и телефонов, даже завуалированных. В свой ход можно отправить
**одно сообщение за ход**; после отправки поле сменяется короткой подписью до следующего
хода. Nudge ожидаемого
соперника — не чаще раза в час (nudge — часть игрового чата); внеприложенческий
push доставляется через платформу.
соперника — не чаще раза в час (nudge — часть игрового чата); и всплывашка в приложении,
и внеприложенческий push (доставляется через платформу) **называют отправителя**
(«<соперник>: жду вашего хода»).
Чат и инструмент проверки слова — один **экран связи** со вкладками **💬 чат** / **🔎 словарь**,
открываемый по 💬 в шапке истории ходов (с кнопкой «назад» в партию); новое сообщение рисует
**бейдж непрочитанного** на строке счёта партии и на 💬 до открытия чата.
+6 -1
View File
@@ -233,7 +233,12 @@ and a long message does not scroll.
Lobby rows show two lines (opponents, then result + score) with a large place-based emoji
on the right: Victory 🏆 / Defeat 🥈 / Draw 🏅, and for 34-player games II 🥈 / III 🥉 /
IV 🏅; active games show Your move 🟢 / Opponent's move ⏳; invitations use 💌.
IV 🏅; active games show Your move 🟢 / Opponent's move ⏳; invitations use 💌. When a listed
game **becomes your turn or finishes** while the lobby is open, that status emoji **blinks
twice** (a two-cycle opacity fade, ~2 s; suppressed under reduce-motion) to draw the eye — the
opponent's-turn change is silent. Each card's blink is keyed by game id, so overlapping
events animate in isolation, and the newest bottom toast cancels the previous one and replays
its entrance (`components/Toast.svelte`, re-keyed on a per-message sequence).
## Social, account & history surfaces