mirror of
https://github.com/tiennm99/loto.git
synced 2026-09-10 04:19:58 +00:00
refactor(active-tab): rename tab-lock to active-tab for clarity
The "lock" framing was misleading — there's no OS-level mutex; this is a soft coordinator that decides which tab is the active one. Rename makes the role obvious at the import site. - file: tab-lock.svelte.js → active-tab.svelte.js (+ test) - export: tabLock → activeTab - field: .frozen → .inactive (positive form: this tab is inactive) - fn: startTabLock → watchActiveTab - fn: reclaimTab → claimActiveTab - BroadcastChannel name: loto_tab_lock → loto_active_tab No behavior change. Banner copy already updated separately.
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
|------|---------|
|
||||
| `src/lib/game-logic.js` | Stateless utilities: generateGrid (constraint-aware picker — exact 5 per row & per col, ascending-sorted columns, soft "no 3 consecutive filled cols per row" via rejection sampling), saveGrid, loadGrid, saveCrossedState, loadCrossedState, isRowComplete, getWaitingNumber. |
|
||||
| `src/lib/master-store.svelte.js` | Shared reactive `{called, remaining}` $state for the master deck, persisted to `loto_master`. Exports `masterState`, `loadMaster`, `saveMaster`, `startNewGame`, `drawNext`, `resetMaster`. Hydrated once via `+layout.svelte`'s `onMount` so player-side reads see the full history regardless of mount order. Replaced the single-slot `call-bus` to fix history-loss bugs (regen, reload, multi-tab) — see `plans/reports/code-reviewer-260430-2024-both-mode-consistency.md`. |
|
||||
| `src/lib/tab-lock.svelte.js` | Single-tab guard via `BroadcastChannel`. New tab broadcasts `claim`; old tab sets `tabLock.frozen = true`. `+layout.svelte` mounts it on boot and renders a fullscreen overlay banner ("Loto đã mở ở tab khác. Tap để chuyển về tab này.") when frozen — tap calls `reclaimTab` which broadcasts back, freezing the other tab in turn. No-op in browsers without `BroadcastChannel` (legacy iOS Safari ≤15.4). Prevents double auto-call intervals, double localStorage writers, and overlapping audio across tabs. |
|
||||
| `src/lib/active-tab.svelte.js` | Single-active-tab coordinator via `BroadcastChannel`. New tab broadcasts `claim`; old tab sets `activeTab.inactive = true`. `+layout.svelte` mounts `watchActiveTab()` on boot and renders a fullscreen overlay banner ("Phiên Lô tô đang chạy ở tab khác. Nhấn để tiếp tục tại đây.") when inactive — nhấn calls `claimActiveTab()` which broadcasts back, inactivating the other tab in turn. Soft coordination only (cooperating tabs); no-op in browsers without `BroadcastChannel` (legacy iOS Safari ≤15.4). Prevents double auto-call intervals, double localStorage writers, and overlapping audio across tabs. |
|
||||
| `src/lib/player-auto-cross.js` | Pure `applyMasterCalls({grid, crossed, called, lastHandledIndex, manualUnticks, mode})`. Cursor-by-index dedup (vs the retired `at`-timestamp model), so any caller can pass `lastHandledIndex: 0` to replay master's full history (used by player regen + "Xoá đánh dấu" in both mode). Manual unticks suppress re-cross on replay. |
|
||||
| `src/lib/vietnamese-number.js` | `numberToVietnamese(n)` — pure utility mapping 0..90 to spoken Vietnamese, with tonal exceptions (15 → "mười lăm", 21 → "hai mươi mốt", 25 → "hai mươi lăm"). Out-of-range falls back to `String(n)`. |
|
||||
| `src/lib/voice.js` | Bundled-MP3 playback. Exports `playNumber(n)`, `playWaiting(n)` (sequences cho + N), `playBingo()`, `cancelPlayback()`. Lazy `<audio>` cache, cancel-then-play, token-based cancel ensures stale promises can't resume after a new event. Reads active voice from `settings.voice`; URLs go through `import { base } from "$app/paths"` for basePath safety. |
|
||||
|
||||
Reference in New Issue
Block a user