Add `eframe::storage_dir` (#3286)

* Add `eframe::storage_dir`

Now you can easily tell where eframe stores its state

* egui_plot: work even without the `serde` featur flag
This commit is contained in:
Emil Ernerfeldt 2023-08-29 15:22:07 +02:00 committed by GitHub
parent a59eda7a27
commit 70bfc7e09f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 16 deletions

View File

@ -139,13 +139,8 @@ pub trait App {
/// Only called when the "persistence" feature is enabled.
///
/// On web the state is stored to "Local Storage".
/// On native the path is picked using [`directories_next::ProjectDirs::data_dir`](https://docs.rs/directories-next/2.0.0/directories_next/struct.ProjectDirs.html#method.data_dir) which is:
/// * Linux: `/home/UserName/.local/share/APP_ID`
/// * macOS: `/Users/UserName/Library/Application Support/APP_ID`
/// * Windows: `C:\Users\UserName\AppData\Roaming\APP_ID`
///
/// where `APP_ID` is determined by either [`NativeOptions::app_id`] or
/// the title argument to [`crate::run_native`].
/// On native the path is picked using [`crate::storage_dir`].
fn save(&mut self, _storage: &mut dyn Storage) {}
/// Called when the user attempts to close the desktop window and/or quit the application.
@ -422,13 +417,10 @@ pub struct NativeOptions {
/// The application id, used for determining the folder to persist the app to.
///
/// On native the path is picked using [`directories_next::ProjectDirs::data_dir`](https://docs.rs/directories-next/2.0.0/directories_next/struct.ProjectDirs.html#method.data_dir) which is:
/// * Linux: `/home/UserName/.local/share/APP_ID`
/// * macOS: `/Users/UserName/Library/Application Support/APP_ID`
/// * Windows: `C:\Users\UserName\AppData\Roaming\APP_ID`
/// On native the path is picked using [`crate::storage_dir`].
///
/// If you don't set [`Self::app_id`], the title argument to [`crate::run_native`]
/// will be used instead.
/// will be used as app id instead.
///
/// ### On Wayland
/// On Wayland this sets the Application ID for the window.

View File

@ -159,6 +159,11 @@ pub use web::{WebLogger, WebRunner};
#[cfg(any(feature = "glow", feature = "wgpu"))]
mod native;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(any(feature = "glow", feature = "wgpu"))]
#[cfg(feature = "persistence")]
pub use native::file_storage::storage_dir;
/// This is how you start a native (desktop) app.
///
/// The first argument is name of your app, used for the title bar of the native window

View File

@ -331,7 +331,7 @@ pub fn handle_app_output(
/// For loading/saving app state and/or egui memory to disk.
pub fn create_storage(_app_name: &str) -> Option<Box<dyn epi::Storage>> {
#[cfg(feature = "persistence")]
if let Some(storage) = super::file_storage::FileStorage::from_app_name(_app_name) {
if let Some(storage) = super::file_storage::FileStorage::from_app_id(_app_name) {
return Some(Box::new(storage));
}
None

View File

@ -3,6 +3,20 @@ use std::{
path::{Path, PathBuf},
};
/// The folder where `eframe` will store its state.
///
/// The given `app_id` is either [`crate::NativeOptions::app_id`] or
/// the title argument to [`crate::run_native`].
///
/// On native the path is picked using [`directories_next::ProjectDirs::data_dir`](https://docs.rs/directories-next/2.0.0/directories_next/struct.ProjectDirs.html#method.data_dir) which is:
/// * Linux: `/home/UserName/.local/share/APP_ID`
/// * macOS: `/Users/UserName/Library/Application Support/APP_ID`
/// * Windows: `C:\Users\UserName\AppData\Roaming\APP_ID`
pub fn storage_dir(app_id: &str) -> Option<PathBuf> {
directories_next::ProjectDirs::from("", "", app_id)
.map(|proj_dirs| proj_dirs.data_dir().to_path_buf())
}
// ----------------------------------------------------------------------------
/// A key-value store backed by a [RON](https://github.com/ron-rs/ron) file on disk.
@ -24,7 +38,7 @@ impl Drop for FileStorage {
impl FileStorage {
/// Store the state in this .ron file.
pub fn from_ron_filepath(ron_filepath: impl Into<PathBuf>) -> Self {
fn from_ron_filepath(ron_filepath: impl Into<PathBuf>) -> Self {
let ron_filepath: PathBuf = ron_filepath.into();
log::debug!("Loading app state from {:?}…", ron_filepath);
Self {
@ -36,9 +50,8 @@ impl FileStorage {
}
/// Find a good place to put the files that the OS likes.
pub fn from_app_name(app_name: &str) -> Option<Self> {
if let Some(proj_dirs) = directories_next::ProjectDirs::from("", "", app_name) {
let data_dir = proj_dirs.data_dir().to_path_buf();
pub fn from_app_id(app_id: &str) -> Option<Self> {
if let Some(data_dir) = storage_dir(app_id) {
if let Err(err) = std::fs::create_dir_all(&data_dir) {
log::warn!(
"Saving disabled: Failed to create app path at {:?}: {}",

View File

@ -126,6 +126,7 @@ struct PlotMemory {
last_click_pos_for_zoom: Option<Pos2>,
}
#[cfg(feature = "serde")]
impl PlotMemory {
pub fn load(ctx: &Context, id: Id) -> Option<Self> {
ctx.data_mut(|d| d.get_persisted(id))
@ -136,6 +137,17 @@ impl PlotMemory {
}
}
#[cfg(not(feature = "serde"))]
impl PlotMemory {
pub fn load(ctx: &Context, id: Id) -> Option<Self> {
ctx.data_mut(|d| d.get_temp(id))
}
pub fn store(self, ctx: &Context, id: Id) {
ctx.data_mut(|d| d.insert_temp(id, self));
}
}
// ----------------------------------------------------------------------------
/// Indicates a vertical or horizontal cursor line in plot coordinates.