fix(data): route data_dir() through a per-platform shim so Android persists
dirs::data_dir() returns None on Android, which silently disabled every persistence path (settings, stats, achievements, replays, game-state, time-attack sessions, user themes). New solitaire_data::platform::data_dir() shim falls through to dirs::data_dir() on desktop and returns the per-app sandbox at /data/data/com.solitairequest.app/files on Android — no JNI needed, since the package id is pinned in [package.metadata.android]. CLAUDE.md §10 already flagged this as a known pitfall; the shim pays it down at the one chokepoint instead of per feature. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -19,9 +19,9 @@ const GAME_STATE_FILE_NAME: &str = "game_state.json";
|
||||
const TIME_ATTACK_SESSION_FILE_NAME: &str = "time_attack_session.json";
|
||||
|
||||
/// Returns the platform-specific path to `stats.json`, or `None` if
|
||||
/// `dirs::data_dir()` is unavailable (e.g. minimal Linux containers).
|
||||
/// `crate::data_dir()` is unavailable (e.g. minimal Linux containers).
|
||||
pub fn stats_file_path() -> Option<PathBuf> {
|
||||
dirs::data_dir().map(|d| d.join(APP_DIR_NAME).join(STATS_FILE_NAME))
|
||||
crate::data_dir().map(|d| d.join(APP_DIR_NAME).join(STATS_FILE_NAME))
|
||||
}
|
||||
|
||||
/// Load stats from an explicit path. Returns `StatsSnapshot::default()` if
|
||||
@@ -69,9 +69,9 @@ pub fn save_stats(stats: &StatsSnapshot) -> io::Result<()> {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the platform-specific path to `game_state.json`, or `None` if
|
||||
/// `dirs::data_dir()` is unavailable.
|
||||
/// `crate::data_dir()` is unavailable.
|
||||
pub fn game_state_file_path() -> Option<PathBuf> {
|
||||
dirs::data_dir().map(|d| d.join(APP_DIR_NAME).join(GAME_STATE_FILE_NAME))
|
||||
crate::data_dir().map(|d| d.join(APP_DIR_NAME).join(GAME_STATE_FILE_NAME))
|
||||
}
|
||||
|
||||
/// Load an in-progress `GameState` from `path`. Returns `None` if the file is
|
||||
@@ -129,7 +129,7 @@ pub fn delete_game_state_at(path: &Path) -> io::Result<()> {
|
||||
/// in an atomic save. Safe to call on startup; missing or unreadable entries
|
||||
/// are silently skipped.
|
||||
pub fn cleanup_orphaned_tmp_files() -> io::Result<()> {
|
||||
let dir = match dirs::data_dir() {
|
||||
let dir = match crate::data_dir() {
|
||||
Some(d) => d.join(APP_DIR_NAME),
|
||||
None => return Ok(()),
|
||||
};
|
||||
@@ -179,9 +179,9 @@ pub struct TimeAttackSession {
|
||||
}
|
||||
|
||||
/// Returns the platform-specific path to `time_attack_session.json`, or
|
||||
/// `None` if `dirs::data_dir()` is unavailable.
|
||||
/// `None` if `crate::data_dir()` is unavailable.
|
||||
pub fn time_attack_session_path() -> Option<PathBuf> {
|
||||
dirs::data_dir().map(|d| d.join(APP_DIR_NAME).join(TIME_ATTACK_SESSION_FILE_NAME))
|
||||
crate::data_dir().map(|d| d.join(APP_DIR_NAME).join(TIME_ATTACK_SESSION_FILE_NAME))
|
||||
}
|
||||
|
||||
/// Save a Time Attack session atomically. Mirrors `save_game_state_to`'s
|
||||
|
||||
Reference in New Issue
Block a user