feat(settings): keep the settings inside a portable suite

portable.txt puts ArtCraftLauncherData next to the exe, but the settings still went
to eframe's storage folder in the user's profile, so a suite carried on a stick lost
its settings on another computer.

path() now returns the suite's own data folder when a portable suite is detected, and
main.rs passes it as persistence_path so eframe writes the window state to the same
file. Nothing changes for a normal install.
This commit is contained in:
EternalShade3D authored and EternalShade3D committed 2026-10-19 20:46:05 +01:00
1 parent 7c7271e5f6
commit 2bb173f2e3
2 files changed
+26 -3

No files matched your search

+9 -1
View File
@@ -154,7 +154,15 @@ fn native_options(hidden: bool) -> eframe::NativeOptions {
} else if let Some(icon) = icon {
viewport = viewport.with_icon(icon);
}
eframe::NativeOptions { viewport, persist_window: true, wgpu_options: wgpu_options(), ..Default::default() }
// Persistence goes to the same file `settings_file` uses, so a portable suite keeps its
// settings and window state inside itself instead of in the user's profile.
eframe::NativeOptions {
viewport,
persist_window: true,
persistence_path: settings_file::path(APP_ID),
wgpu_options: wgpu_options(),
..Default::default()
}
}
/// wgpu's backend list. On Windows that is Direct3D 12 with GL as the fallback, not Vulkan:
+17 -2
View File
@@ -8,9 +8,18 @@
use std::collections::HashMap;
use std::path::{Path, PathBuf};
/// Where eframe keeps its state for `app_id`, as it picks it for a window with that app id.
/// Where the settings file is. In portable mode it is inside `ArtCraftLauncherData`, so a suite
/// carried on a stick keeps its settings when it is plugged into another computer. Without
/// `portable.txt` it is eframe's own folder, which is in the user's profile and cannot travel.
pub fn path(app_id: &str) -> Option<PathBuf> {
eframe::storage_dir(app_id).map(|dir| dir.join("app.ron"))
artcraft_launcher_native::paths::portable_root()
.map(|root| portable_settings(&root))
.or_else(|| eframe::storage_dir(app_id).map(|dir| dir.join("app.ron")))
}
/// The settings file inside a portable suite: the same `data` folder `Paths` already uses.
fn portable_settings(root: &Path) -> PathBuf {
root.join("data").join("app.ron")
}
/// The value stored under `key`, if the file has one that still reads.
@@ -91,6 +100,12 @@ mod tests {
}
}
#[test]
fn a_portable_suite_keeps_its_settings_inside_itself() {
let root = PathBuf::from("E:\\Suite\\ArtCraftLauncherData");
assert_eq!(portable_settings(&root), PathBuf::from("E:\\Suite\\ArtCraftLauncherData\\data\\app.ron"));
}
#[test]
fn settings_saved_with_no_file_read_back() {
let dir = Scratch::new("settings-round-trip");