mirror of
https://github.com/tiennm99/noitu.git
synced 2026-10-11 03:13:45 +00:00
8.5 KiB
8.5 KiB
Web review and refactor: dev vs main
Scope: git diff main...dev -- web (proto and lockfile excluded). Nothing committed.
Gates: npm run lint (0 errors, 0 warnings), npm run check (0/0), npm test (269 passed; the baseline was 266, plus 3 new tests).
Findings
| Sev | Where (before the change) | Finding |
|---|---|---|
| High | web/src/app.css .icon-button (--text-7), .rules-link (--text-4), .skip (--text-5) |
When the type ramp dropped from nine steps to seven, these three global rules kept their old token numbers. The meanings of those numbers changed: the dismiss "×" and the board's "?" went from 1.1rem to 2.25rem, rules links from 0.85rem to 1.125rem, and the skip link from 0.9rem to 1.5rem. The component files were remapped; app.css was missed. |
| Medium | WordInput.svelte style button:hover/active:not(:disabled) |
The bare button rule also matched the .fix buttons. Its hover and press states outranked .fix:hover, so on hover or press the report button turned solid accent with dark text on top (low contrast). |
| Medium | ChatPanel.svelte draft vs field |
The input unmounts while the panel is folded. After unfolding, the field was empty but draft still held the old text. "Gửi" stayed enabled and did nothing when pressed, and the typed text was lost. |
| Medium | GameBoard.svelte :global(.resign), :global(.claim-dead-end); Lobby.svelte :global(.kick) |
These selectors were global without any scope, so they applied to every element in the app with that class. |
| Low | online/+page.svelte ready/start/kick/leave/cancelQueue |
Five copies of send(x); if (!sent) session.holdAction(...), next to a dispatchAction switch that already mapped each action to its message. |
| Low | online/+page.svelte resume timeout and resume error effects |
The same three steps (noteResumeFailed, forgetSession, conditional flush) were written out in both places. |
| Low | online/+page.svelte queued-seconds effect |
resetQueued() was called on both branches. |
| Low | online/+page.svelte doc above ready() |
The comment described leaving the room, not readying. |
| Low | play/+page.svelte and online/+page.svelte |
Identical play, giveUp, claim and report wrappers in both routes. |
| Low | game-apply.js chatMessage / chatHistory |
The chat-line mapping was duplicated. The error case chained ` |
| Low | GameBoard.svelte canResign / canClaimDeadEnd |
Two identical deriveds. The .resign and .claim-dead-end CSS was about 80% the same, and .claim-error repeated .error. |
| Low | Banner CSS (.error/.notice) |
Copied into GameBoard, Lobby and the online page, each with its own markup for the dismiss button. |
| Low | ChatPanel.svelte header doc |
Said "Three facts" but listed two. Some spacing still used px literals where tokens exist. |
| Low | room-session.svelte.js startResume doc |
Said "optionally behind a held join", but the function takes no argument. |
| Low | ArmedButton.svelte |
clearTimeout(timer); armed = false appeared three times. |
| Low | Lobby.svelte ownerAway |
Had an inline JSDoc param type that inference already covers. |
| Low | Tests | Finding codes in comments (C6 in word-input, C1/"the review" in room-session and chat-panel). Each jsdom suite had its own copy of the gameStarted builder and the mount helper. room-code.test.js:77 produced an any lint warning. |
No unused i18n keys were found: every t.* key has a t.<key> reference.
Changes
- app.css: remapped
.icon-buttonto--text-4,.rules-linkto--text-2and.skipto--text-2, which are the same sizes they had on the old ramp. Updated the.rules-linkcomment, since the board header now uses a "?" icon-button. - New
AlertBanner.svelte: onerole="alert"banner withtone(error/notice),testid, and an optionalondismiss. It replaces 8 hand-written banners in GameBoard (error, claim error), Lobby (lobby-error,lobby-unsent) and the online page (name-needed,join-error,resume-failed,connect-stalled). All test ids and roles are unchanged. GameBoard's.offlinestrip keeps its own markup because it is deliberately not announced and it carries the retry button. turnActionsinws/connection.svelte.js:submit,resign,claimDeadEnd,reportWord. Both game routes pass these to GameBoard, and the four duplicated wrapper functions in each route are gone. GameBoard's props contract is unchanged, so the component tests still inject their own handlers.- online/+page.svelte:
act(action)=dispatchAction+ hold-on-failure.ready,start,kick,leaveandcancelQueueare now one-liners on top of it.abandonResume()is shared by the timeout path and the error path.- The queued-seconds effect is simplified.
- The misplaced doc comment is fixed.
- game-apply.js:
toChatLine()is used by both chat cases.- The error codes are grouped into named Sets:
LEAVES_ROOM,ANSWERED_BY_THE_BUTTON,ENDS_THE_QUEUE. - The rejection clearing moved into the single
if (played)block. - Behaviour is identical and the game-store tests pass unchanged.
- GameBoard.svelte: one
canPlayInsteadOfAWordderived. The shared secondary-button CSS is written once as.secondary :global(button), with the resign/claim colour differences layered on top and everything scoped under.secondary. - Lobby.svelte: kick CSS scoped under
.seats :global(...),ownerAwaysimplified, the local.errorCSS removed. - WordInput.svelte: submit-button styles scoped to
.input-row button. AcaretToEnd()helper replaces two copies of the samesetSelectionRangecall. - ChatPanel.svelte: an untracked, once-per-mount effect writes
draftback into the field when it remounts. It never writes during a composition. The doc is fixed and px spacing moved to tokens. - ArmedButton.svelte: added a
disarm()helper. - room-session.svelte.js: fixed the
startResumedoc. - Tests:
- New
tests/component-support.js(receive,startGame,render), used by the game-board, word-input and chat-panel suites. - Removed the finding codes from comments and fixed the
room-code.test.js:77warning with anunknown-to-stringcast. - New tests: a fold/unfold round trip keeps a sendable chat draft (confirmed to fail without the fix); dismissing a board error; a refused claim appears beside the claim/resign row and can be dismissed.
- New
- tests/error-codes.test.js: the scanner now also picks up the two code literals at
toRoom(limiter, notIn, dropped, …)call sites. Server work in progress (not mine) movednot_in_a_gamebehind that helper inserver/internal/wsapi/dispatch.go, and without this the "no stale message" guard failed.
Bugs fixed (user-visible)
- The dismiss "×", the board's "?" button, rules links and the skip link are back to their intended sizes (they had grown to as much as 2.25rem).
- The report-word button no longer turns solid accent with dark text on hover or press.
- A chat draft now survives folding and unfolding the panel, and "Gửi" no longer stays enabled over an empty field.
- The resign, claim and kick button styles no longer apply to unrelated elements elsewhere in the app that share those class names.
Checked
- The e2e selectors (
getByTestId,getByRole('alert'),.badge,.role) and the.resign/.claim-dead-end/.suggestionclasses used by the unit tests are all still present. Playwright was not run (no browser on this host). - The wire contract is untouched:
messages.jsdid not change, andturnActionscalls the same builders.
Deferred
- A global
.primaryaccent-button class. The same fill, hover, press and disabled styles are repeated in six places (online page, Lobby, WordInput, ChatPanel, GameOverPanel, landing page). Consolidating them runs into Lobby's.actions buttonspecificity and needs a visual check that this host cannot do. rules/+page.svelterepeats the section id in the table of contents and in each<section>. It could be generated from one array, but it is static and easy to read as it is.online/+page.svelteh1 { font-size: 1.3rem }is off the type ramp.startResume()+holdPendingJoin()could be merged into a singlestartResume(heldJoin?). Left alone to keep the store API and its tests stable.- The guard in
error-codes.test.jsdepends on the server's call-site shape. If the in-flight server refactor changestoRoomagain, the regex will need updating too.