fix: manual my-sea draws persist on refresh + reloaded slots stay clickable — root cause was SeaDeal stamping slot.dataset.posKey w. selector form (".sea-pos-cover") while my-sea's inline _collectHandFromDom + template's _my_sea_slot.html use raw names ("cover"). Key mismatch silently dropped manual draws from the lock POST → server rejected empty hand → no row → refresh showed empty state. AUTO DRAW worked only because it assembled fullHand w. raw posNames directly, bypassing the broken collector. TDD — 2 new FTs pin the contract:
- test_manual_draw_persists_on_refresh - test_reloaded_slot_can_reopen_stage_modal_on_click Changes: - sea.js: stamp `dataset.posKey` w. raw name (strip `.sea-pos-` prefix); `_seaHand` keyed by raw; `_viewingPos` is raw too (`_hideStage` prefixes when querySelector'ing); new `SeaDeal.seedHand(handByPosName)` public method for init-time DOM-walk seeding. - my_sea.html inline init: walk server-rendered filled slots, look up each card by `data-card-id` from the embedded deck JSON, reconstruct per-instance `reversed` + polarity from the slot's classes, hand the map to `SeaDeal.seedHand`. Without this, reloaded slots short-circuit the overlay click handler on `if (!_seaHand[pos]) return;`. The gameroom-side SeaDeal callers in `_sea_overlay.html` continue to pass selector form (SeaDeal accepts either — `_posName` helper strips prefix tolerantly). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -796,6 +796,50 @@
|
||||
_lockSpread();
|
||||
}
|
||||
|
||||
// Seed SeaDeal's `_seaHand` from the server-rendered
|
||||
// saved slots so they remain clickable for re-opening
|
||||
// the stage modal after a refresh. Walks the filled
|
||||
// slots + maps each `data-card-id` against the embedded
|
||||
// deck JSON. Without this, the overlay click handler
|
||||
// short-circuits on `if (!_seaHand[pos]) return;` —
|
||||
// sea.js's in-memory `_seaHand` only gets populated by
|
||||
// openStage/register during the live session.
|
||||
// (User-reported 2026-05-21.)
|
||||
if (window.SeaDeal && window.SeaDeal.seedHand) {
|
||||
var _allCards = (_deckData.levity || [])
|
||||
.concat(_deckData.gravity || []);
|
||||
var _byId = {};
|
||||
_allCards.forEach(function (c) { _byId[c.id] = c; });
|
||||
var _seed = {};
|
||||
cross.querySelectorAll(
|
||||
'.sea-card-slot.sea-card-slot--filled'
|
||||
).forEach(function (slot) {
|
||||
var posName = slot.dataset.posKey;
|
||||
var cardId = parseInt(slot.dataset.cardId, 10);
|
||||
var card = _byId[cardId];
|
||||
if (!posName || !card) return;
|
||||
// Reconstruct the per-instance `reversed` flag
|
||||
// from the slot's DOM class (the deck JSON's
|
||||
// `reversed` field is the original-shuffle axis
|
||||
// — server's saved hand may have flipped it
|
||||
// independently). Polarity also DOM-sourced.
|
||||
var slotCard = {};
|
||||
for (var k in card) {
|
||||
if (Object.prototype.hasOwnProperty.call(card, k)) {
|
||||
slotCard[k] = card[k];
|
||||
}
|
||||
}
|
||||
slotCard.reversed = slot.classList.contains(
|
||||
'sea-card-slot--reversed'
|
||||
);
|
||||
var isLevity = slot.classList.contains(
|
||||
'sea-card-slot--levity'
|
||||
);
|
||||
_seed[posName] = { card: slotCard, isLevity: isLevity };
|
||||
});
|
||||
SeaDeal.seedHand(_seed);
|
||||
}
|
||||
|
||||
// Belt-and-braces autofill defense (paired w. autocomplete=
|
||||
// off on the hidden input above). Firefox occasionally
|
||||
// restores form-history values on soft reload even on
|
||||
|
||||
Reference in New Issue
Block a user