fix(offline): keep the local game's composition across a state reload
A local (offline) game persisted no draft: draftGet returned an empty string and draftSave was a no-op, on the assumption that the arrangement is only ever rebuilt from the rack when the game is reopened. The game screen, however, refetches the state on several triggers, and every one of them applied that empty draft over the live composition — dropping the player's pending tiles back into the rack and resetting the rack order. Offline the most visible trigger fires on its own: with no network the live-stream watchdog declares the stream dead after 25 s, the reconnect 4 s later flips app.streamAlive back to true, and the game screen's reconnect effect refetches. Composing a move offline was therefore reset roughly every half minute. Store the draft in the game's own record instead, so a reload restores it and it survives leaving and reopening the app, and clear it wherever the turn advances (a committed move, a resignation, a host skip) so a hotseat seat never inherits the previous player's arrangement. Gate the two stream-driven refetches on the game being a network one: a local game takes its events from the source, so reacting to the stream only cost it a pointless reload.
This commit is contained in:
@@ -24,9 +24,9 @@ function load(): Promise<LocalSource> {
|
||||
* local-only create() and the robot-reply event subscription events().
|
||||
*/
|
||||
export const localSource = {
|
||||
// Offline scoring is self-contained, so the local source ignores includeAlphabet, the evaluate
|
||||
// abort signal, and the draft (drafts are not persisted offline); the proxy accepts the full
|
||||
// gateway signatures but forwards only what the local source uses.
|
||||
// Offline scoring is self-contained, so the local source ignores includeAlphabet and the evaluate
|
||||
// abort signal; the proxy accepts the full gateway signatures but forwards only what the local
|
||||
// source uses.
|
||||
gameState: (id, _includeAlphabet) => load().then((s) => s.gameState(id)),
|
||||
gameHistory: (id) => load().then((s) => s.gameHistory(id)),
|
||||
submitPlay: (id, tiles, variant) => load().then((s) => s.submitPlay(id, tiles, variant)),
|
||||
@@ -36,8 +36,8 @@ export const localSource = {
|
||||
hint: (id) => load().then((s) => s.hint(id)),
|
||||
evaluate: (id, tiles, variant, _signal) => load().then((s) => s.evaluate(id, tiles, variant)),
|
||||
checkWord: (id, word, variant) => load().then((s) => s.checkWord(id, word, variant)),
|
||||
draftGet: (_id) => load().then((s) => s.draftGet()),
|
||||
draftSave: (_id, _json) => load().then((s) => s.draftSave()),
|
||||
draftGet: (id) => load().then((s) => s.draftGet(id)),
|
||||
draftSave: (id, json) => load().then((s) => s.draftSave(id, json)),
|
||||
create: (opts) => load().then((s) => s.create(opts)),
|
||||
list: () => load().then((s) => s.list()),
|
||||
delete: (id) => load().then((s) => s.delete(id)),
|
||||
|
||||
Reference in New Issue
Block a user