Add localStorage persistence for UI state#56
Merged
Conversation
Adds a pure src/persist.js module (serialize / deserialize / defaultState / versioned STORAGE_KEY) covered by golden-value tests, and wires src/ui.js to read the last snapshot on start and rewrite it after every refresh. Deserialize validates every field against the canonical enums and ranges, so a stale or hand-edited blob is dropped to defaults rather than poisoning the engine. localStorage I/O is wrapped in try/catch so private-mode and quota errors degrade silently. https://claude.ai/code/session_019NDndqSRkT7BonKsEGXxfL
Adds "(Jan 14, 2001 patch)" as a faint subtitle next to the toggle so players know exactly which era flipping it switches between. https://claude.ai/code/session_019NDndqSRkT7BonKsEGXxfL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds localStorage persistence so users' party composition and encounter settings are automatically saved and restored across sessions. Introduces a pure
persist.jsmodule that handles serialization/deserialization with strict validation to prevent stale or hand-edited snapshots from corrupting the engine state.Type of change
Implementation details
New module:
src/persist.jsdefaultState()— factory for the canonical initial stateserialize(state)— converts UI state to JSON-safe snapshotdeserialize(raw)— rehydrates from storage with validation:isRace/isClasschecks)defaultState()on null/undefined/garbage inputSTORAGE_KEY— versioned string ("eq-xp-calculator/v1") for localStorageChanges to
src/ui.jsdefaultState()loadFromStorage()— pulls snapshot on page load (before DOM build) with graceful fallback if localStorage is disabled or corruptedsaveToStorage()— writes serialized state after everyrefresh()with best-effort error handlingDocumentation:
architecture.mdpersist.jsto the module breakdown with description of its roleValidation approach
The
deserialize()function is defensive: it validates every field independently and falls back to defaults for any invalid data. This ensures a stale snapshot (e.g., from a previous version) or hand-edited JSON blob can never inject a non-canonical race/class or out-of-range number into the engine.Checklist
test/persist.test.js)npm testpasses (185 lines of golden-value tests covering all validation paths)npm run lintpassesnpm run format:checkpassessrc/xp.jsremains pure (no DOM access)https://claude.ai/code/session_019NDndqSRkT7BonKsEGXxfL