Review fixes #2: bigger flag star, TG header below nav, board-tile relocation
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 31s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m7s
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 31s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m7s
Addressing the review on #23: - Flag star scaled up ~25% (the hammer&sickle emblem unchanged, kept clear of it). - TG fullscreen header: drop the WHOLE header below the content-safe-area top inset (the hamburger stays to the right of the title), instead of pinning the hamburger to the physical top edge. - DnD: a placed (pending) tile can now be relocated by dragging it to another board cell (board->board); it lifts off its source cell while dragged; and it can be grabbed even on the zoomed board (touch-action:none on the pending cell, so the drag wins over the board pan). The manual-selection blue frame now clears on recall.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 16" role="img" aria-label="СССР">
|
||||
<rect width="24" height="16" fill="#cc0000"/>
|
||||
<!-- small five-pointed star -->
|
||||
<path fill="#ffd700" d="M6 1.9 L6.32 2.86 7.33 2.87 6.51 3.47 6.82 4.43 6 3.84 5.18 4.43 5.49 3.47 4.67 2.87 5.68 2.86 Z"/>
|
||||
<!-- five-pointed star (scaled up ~25% around its centre per review) -->
|
||||
<path fill="#ffd700" transform="translate(6 3.17) scale(1.25) translate(-6 -3.17)" d="M6 1.9 L6.32 2.86 7.33 2.87 6.51 3.47 6.82 4.43 6 3.84 5.18 4.43 5.49 3.47 4.67 2.87 5.68 2.86 Z"/>
|
||||
<g fill="none" stroke="#ffd700" stroke-linecap="round" stroke-linejoin="round" transform="translate(6.8 6) scale(0.667) translate(-6.8 -6)">
|
||||
<!-- sickle: a crescent blade + short handle, mirrored across a diagonal through its centre
|
||||
so it reads as the canonical sickle (blade sweeping down-right); the hammer is untouched -->
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -96,13 +96,4 @@
|
||||
:global(html.tg-fullscreen) .bar {
|
||||
padding-top: var(--tg-content-top);
|
||||
}
|
||||
:global(html.tg-fullscreen) .end {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
height: var(--tg-content-top);
|
||||
justify-content: center;
|
||||
z-index: 30;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -277,6 +277,9 @@
|
||||
}
|
||||
.cell.pending {
|
||||
background: var(--tile-pending);
|
||||
/* The placed tile owns the pointer so it can be dragged to relocate it (even on the zoomed
|
||||
board) instead of the touch starting a board pan (Stage 17). */
|
||||
touch-action: none;
|
||||
}
|
||||
/* Lines-off variant: a gapless checkerboard. The 1px grid gaps (and the cell-line they
|
||||
reveal) collapse, saving ~14px of board width; plain cells alternate shades, and tiles
|
||||
|
||||
+36
-6
@@ -70,7 +70,11 @@
|
||||
const premium = $derived(premiumGrid(variant));
|
||||
const ctr = $derived(centre(variant));
|
||||
const pendingMap = $derived(
|
||||
new Map(placement.pending.map((p) => [`${p.row},${p.col}`, { letter: p.letter, blank: p.blank }])),
|
||||
new Map(
|
||||
placement.pending
|
||||
.filter((p) => !(draggingPend && p.row === draggingPend.row && p.col === draggingPend.col))
|
||||
.map((p) => [`${p.row},${p.col}`, { letter: p.letter, blank: p.blank }]),
|
||||
),
|
||||
);
|
||||
const lastPlay = $derived([...moves].reverse().find((m) => m.action === 'play') ?? null);
|
||||
// Highlight the last word with a dark tile bg; while placing, only the pending tiles
|
||||
@@ -228,6 +232,9 @@
|
||||
// (a gap opens there). Only when no tiles are pending, so the order is a clean permutation.
|
||||
let reorderDragId = $state<number | null>(null);
|
||||
let reorderTo = $state<number | null>(null);
|
||||
// While a placed (pending) board tile is dragged to relocate it, draggingPend is its cell —
|
||||
// hidden from the board (the ghost stands in) like a lifted rack tile (Stage 17).
|
||||
let draggingPend = $state<{ row: number; col: number } | null>(null);
|
||||
|
||||
let dragPointerId = -1;
|
||||
function beginDrag(src: DragSrc, e: PointerEvent) {
|
||||
@@ -261,10 +268,10 @@
|
||||
if (busy || gameOver) return;
|
||||
beginDrag({ from: 'rack', index }, e);
|
||||
}
|
||||
// A pending tile can be dragged back to the rack, but only on the unzoomed board: when
|
||||
// zoomed the one-finger gesture scrolls the board, so recall there is via double-tap.
|
||||
// A placed (pending) tile can be dragged to relocate it on the board or back to the rack —
|
||||
// works zoomed too (the tile has touch-action:none, so its drag wins over the board pan).
|
||||
function onBoardDown(e: PointerEvent, row: number, col: number) {
|
||||
if (busy || zoomed || gameOver) return;
|
||||
if (busy || gameOver) return;
|
||||
beginDrag({ from: 'board', row, col }, e);
|
||||
}
|
||||
function cellUnder(x: number, y: number): { row: number; col: number } | null {
|
||||
@@ -283,6 +290,7 @@
|
||||
function clearReorder() {
|
||||
reorderDragId = null;
|
||||
reorderTo = null;
|
||||
draggingPend = null;
|
||||
}
|
||||
// overRack reports whether y is within the rack's row (a small margin makes the target
|
||||
// forgiving); rackTilesUnderX is the insertion slot for the pointer among the shown tiles.
|
||||
@@ -316,8 +324,10 @@
|
||||
const letter =
|
||||
src.from === 'rack' ? placement.rack[src.index] : pendingMap.get(`${src.row},${src.col}`)?.letter ?? '';
|
||||
drag = { letter, blank: letter === BLANK, x: e.clientX, y: e.clientY, touch: e.pointerType === 'touch' };
|
||||
// A rack tile is lifted out of the rack while dragged (the ghost stands in for it).
|
||||
// A rack tile is lifted out of the rack while dragged (the ghost stands in for it); a
|
||||
// placed board tile is likewise lifted off its cell while relocated.
|
||||
reorderDragId = src.from === 'rack' ? rackIds[src.index] ?? null : null;
|
||||
draggingPend = src.from === 'board' ? { row: src.row, col: src.col } : null;
|
||||
// No zoom on drag start: the player may still change their mind. Holding the tile
|
||||
// over a cell for ~1s auto-zooms there (hover-hold below); a drop also zooms+centres.
|
||||
}
|
||||
@@ -371,9 +381,13 @@
|
||||
} else if (di.src.from === 'rack' && onRack && to != null) {
|
||||
// Dropped a rack tile back onto the rack → reorder it to the drop slot.
|
||||
reorderRack(di.src.index, to);
|
||||
} else if (di.src.from === 'board' && cell) {
|
||||
// Dropped a placed tile on another board cell → relocate it there.
|
||||
relocatePending(di.src.row, di.src.col, cell.row, cell.col);
|
||||
} else if (di.src.from === 'board' && onRack) {
|
||||
// Dropped a pending tile back onto the rack → recall it to its original slot.
|
||||
// Dropped a placed tile back onto the rack → recall it to its original slot.
|
||||
placement = recallAt(placement, di.src.row, di.src.col);
|
||||
selected = null;
|
||||
recompute();
|
||||
scheduleDraftSave();
|
||||
}
|
||||
@@ -416,6 +430,22 @@
|
||||
}
|
||||
function onRecall(row: number, col: number) {
|
||||
placement = recallAt(placement, row, col);
|
||||
selected = null;
|
||||
recompute();
|
||||
scheduleDraftSave();
|
||||
}
|
||||
// relocatePending moves a placed-but-unsubmitted tile from one board cell to another free one
|
||||
// (a board→board drag), keeping its rack slot and any blank letter (Stage 17).
|
||||
function relocatePending(fromRow: number, fromCol: number, toRow: number, toCol: number) {
|
||||
const pt = placement.pending.find((p) => p.row === fromRow && p.col === fromCol);
|
||||
if (!pt) return;
|
||||
if ((fromRow === toRow && fromCol === toCol) || board[toRow]?.[toCol] || pendingMap.has(`${toRow},${toCol}`)) {
|
||||
return;
|
||||
}
|
||||
let p = recallAt(placement, fromRow, fromCol);
|
||||
p = place(p, pt.rackIndex, toRow, toCol, pt.blank ? pt.letter : undefined);
|
||||
placement = p;
|
||||
focus = { row: toRow, col: toCol };
|
||||
recompute();
|
||||
scheduleDraftSave();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user