Notice when the same table is open twice #79
Closed
jheaps
wants to merge 1 commits from
fix/casino-holdem-two-tabs into fix/casino-holdem-unreadable-save
pull from: fix/casino-holdem-two-tabs
merge into: :fix/casino-holdem-unreadable-save
:master
:feature/socialism
:polish/holdem-seats-one-size
:fix/holdem-dealer-chip-eats-its-seat
:polish/holdem-game-night-ready
:polish/holdem-round-next
:polish/holdem-seat-collisions
:polish/holdem-offline-and-render
:fix/naming-a-blind-deals-the-hand
:release/casino-holdem-polish
:fix/casino-holdem-phone-look
:fix/casino-holdem-sidebar-crowding
:fix/casino-holdem-contribution-rule
:fix/casino-holdem-one-stack-rule
:fix/casino-holdem-default-stack-buyin
:feat/casino-holdem-waiting-list
:feat/casino-holdem-misdeal
:feat/casino-holdem-cash-out
:feat/casino-holdem-clock
:feat/casino-holdem-rake
:fix/casino-holdem-stadium-ring
:fix/casino-holdem-phone-felt-shape
:fix/casino-holdem-audit-runs-everything
:feat/casino-holdem-straddle
:fix/casino-holdem-landscape-ring
:feat/casino-holdem-table-file
:fix/casino-holdem-touch-targets
:fix/casino-holdem-audit-modal-blindspot
:fix/casino-holdem-quicksplit-chop
:fix/casino-holdem-buildable-bet-sizes
:fix/casino-holdem-pot-sized-raise
:fix/casino-holdem-chips-to-count-out
:fix/casino-holdem-first-buy-in
:fix/casino-holdem-seating-a-table
:fix/casino-holdem-showdown-order
:fix/casino-holdem-hand-log-filter
:fix/casino-holdem-posting-in
:fix/casino-holdem-dead-button
:fix/casino-holdem-discarded-pot
:fix/casino-holdem-honest-tank-clock
:fix/casino-holdem-export-the-notes
:fix/casino-holdem-stacks-in-chips
:fix/casino-holdem-close-audit-blind-spots
:fix/casino-holdem-readable-dim-states
:fix/casino-holdem-drop-broken-watermark
:fix/casino-holdem-two-tabs
:fix/casino-holdem-unreadable-save
:fix/casino-holdem-say-when-not-saving
:fix/casino-holdem-shortcut-discovery
:fix/casino-holdem-rulings-index-compact
:fix/casino-holdem-rulings-index
:fix/casino-holdem-payout-in-chips
:fix/casino-holdem-move-seat-on-touch
:fix/casino-holdem-amount-fields-select
:fix/casino-holdem-touch-targets-by-pointer
:fix/casino-holdem-button-box-model
:fix/casino-holdem-blind-badge-placement
:fix/casino-holdem-buyin-deals-in
:fix/casino-holdem-bet-vs-raise
:fix/casino-holdem-deal-around-broke
:fix/casino-holdem-settle-up
:fix/casino-holdem-allin-and-bar
:fix/casino-holdem-one-dealer-button
:fix/casino-holdem-manual-deal
:fix/casino-holdem-less-guessing
:feature/casino-holdem-seat-editor
:fix/casino-holdem-landscape-table
:feature/casino-holdem-acting-seat
:feature/casino-holdem-raise-guard
:feature/casino-holdem-first-run
:feature/casino-holdem-contrast-audit
:feature/casino-holdem-layout-audit
:feature/casino-holdem-blind-fairness
:feature/casino-holdem-rulings-depth
:feature/casino-holdem-bank-audit
:feature/casino-holdem-fewer-taps
:feature/casino-holdem-render-perf
:feature/casino-holdem-keyboard-focus
:feature/casino-holdem-resilience
:feature/casino-holdem-messy-tables
:feature/casino-holdem-touch-mobile
:chore/casino-holdem-tech-debt
:feature/casino-holdem-dealer-batch
:feature/casino-holdem-seat-count-safety
:feature/casino-holdem-odd-chip
:feature/casino-holdem-button-moves
:feature/casino-holdem-allin-runout
:feature/casino-holdem-heads-up
:feature/casino-holdem-contrast
:feature/casino-holdem-touch-audit
:feature/casino-holdem-wizard-polish
:feature/casino-quicksplit-side-pots
:feature/casino-holdem-rebuys
:feature/casino-holdem-rulings
:feature/casino-holdem-sidebar-polish
:feature/casino-holdem-keyboard
:feature/casino-holdem-action-undo
:feature/casino-holdem-pace
:feature/casino-holdem-side-pot-breakdown
:feature/casino-holdem-gestures
:feature/casino-holdem-card-picker
:feature/casino-holdem-live-betting
:feature/casino-holdem-bet-chips
:feature/casino-holdem-seat-legibility
:feature/casino-holdem-undo-toasts
:feature/casino-holdem-quick-split
:feature/casino-holdem-mobile-table
:feature/casino-holdem-hand-history
:feature/casino-texas-holdem
:feature/casino-holdem-dealer-mode-polish
:feature/fractional-learned-weights
:fix/stockfish-dispose-hang
:fix/blog-cache-staleness
:fix/workflows
:gitea/workflows
:echo-acoustic-ranging
:chess-ui-overhaul
:feature/customChessEngine
:feature/blog
:AddProject
:feature/generalUpdate
:tech-debt/chess-cleanup
:tests/CreatePlaywrightTests
:UpdateParticleSimulatorButton
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Opening the tool in a second tab — tapping the bookmark again rather than hunting for the tab you already had — silently throws away whatever the first one is doing. Stacked on #78.
Each tab holds its own copy in memory and each save writes the whole table, so the second one to act wins. Driven with two tabs on one profile:
The deal, the blinds and the call are gone, and neither tab said anything. That's the same silent shape as the save and load failures either side of this change.
The browser already tells us
A
storageevent fires in every other tab when the key changes, and never in the one that wrote — so our own saves can't trip it. A tab that sees its table move underneath it now says so, once, with the way out attached:Watched rather than merged, deliberately. Replacing the table under a dealer's hands in the middle of a hand would be its own hazard, and reloading is the only resolution that doesn't throw somebody's work away — so it's offered rather than taken.
Validation
6 tests (269 total): a write from elsewhere is noticed, another app's key and our own recovery key aren't our business, ten writes produce one warning, watching twice listens once, no listener isn't an error, and no
windowat all isn't an error.Driven with two live tabs: both quiet at first, A deals and B warns with the reload offer, A stays quiet about its own writes, two more actions in A add no further toasts in B, and reloading B picks up A's table —
bettingOpen: true,committed: [2,1,2,2]— with the warning cleared. Audit and contrast clean, no console errors.Opening the tool in a second tab -- tapping the bookmark again rather than hunting for the tab you already had -- silently throws away whatever the first one is doing. Each tab holds its own copy in memory and each save writes the whole table, so the second one to act wins. Driven with two tabs on one profile: tab A: deal, and Ann calls stored -> bettingOpen true, committed [0,1,2,2] tab B: type a name in seat 5 stored -> bettingOpen false, committed [0,0,0,0] The deal, the blinds and the call are gone, and neither tab said anything. That is the same silent shape as the save and load failures either side of this change. The browser already tells us: a storage event fires in every other tab when the key changes, and never in the one that wrote. So a tab that sees its table move underneath it now says so, once, with the way out attached: toast: "This table is open in another tab. Whichever acts last wins." [Reload] panel: "This table is open in another tab, and both are writing to it — whichever acts last wins, so work done in the other one can vanish. Close one, then reload this tab to pick up the table as it stands." Watched rather than merged, deliberately. Replacing the table under a dealer's hands in the middle of a hand would be its own hazard, and reloading is the only resolution that does not throw somebody's work away -- so it is offered rather than taken. 6 tests (269 total): a write from elsewhere is noticed, another app's key and our own recovery key are not our business, ten writes produce one warning, watching twice listens once, no listener is not an error, and no window at all is not an error. Driven with two live tabs: both quiet at first, A deals and B warns with the reload offer, A stays quiet about its own writes, two more actions in A add no further toasts in B, and reloading B picks up A's table -- bettingOpen true, committed [2,1,2,2] -- with the warning cleared. Audit and contrast clean, no console errors. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgbPull request closed