logicaffeine_web/storage.rs
1//! LocalStorage persistence layer for user progress.
2//!
3//! Provides low-level access to browser LocalStorage via WASM bindings.
4//! User progress is stored as a JSON string under a single key.
5//!
6//! # Storage Key
7//!
8//! All user progress is stored under `logos_user_progress`. This includes:
9//! - Exercise completion history
10//! - SRS scheduling data
11//! - Streak and XP totals
12//! - Achievement unlock state
13//!
14//! # Usage
15//!
16//! ```no_run
17//! use logicaffeine_web::storage;
18//!
19//! // Load existing progress
20//! if let Some(json) = storage::load_raw() {
21//! println!("Loaded: {}", json);
22//! }
23//!
24//! // Save progress
25//! storage::save_raw("{}");
26//!
27//! // Clear all progress (for reset functionality)
28//! storage::clear();
29//! ```
30
31use wasm_bindgen::prelude::*;
32
33/// LocalStorage key for user progress data.
34const PROGRESS_KEY: &str = "logos_user_progress";
35
36#[wasm_bindgen]
37extern "C" {
38 #[wasm_bindgen(js_namespace = localStorage, js_name = getItem)]
39 fn local_storage_get(key: &str) -> Option<String>;
40
41 #[wasm_bindgen(js_namespace = localStorage, js_name = setItem)]
42 fn local_storage_set(key: &str, value: &str);
43
44 #[wasm_bindgen(js_namespace = localStorage, js_name = removeItem)]
45 fn local_storage_remove(key: &str);
46}
47
48/// Loads the raw JSON progress string from LocalStorage.
49///
50/// Returns `None` if no progress has been saved or if LocalStorage is unavailable.
51pub fn load_raw() -> Option<String> {
52 local_storage_get(PROGRESS_KEY)
53}
54
55/// Saves a JSON progress string to LocalStorage.
56///
57/// # Arguments
58///
59/// * `json` - Serialized progress data. Should be valid JSON produced by
60/// `serde_json::to_string()` on a `UserProgress` struct.
61pub fn save_raw(json: &str) {
62 local_storage_set(PROGRESS_KEY, json);
63}
64
65/// Clears all stored progress data.
66///
67/// Used for "Reset Progress" functionality. This operation is irreversible.
68pub fn clear() {
69 local_storage_remove(PROGRESS_KEY);
70}