Skip to content

Commit

Permalink
desktop: Make settings persisted (written back to disk when changed).
Browse files Browse the repository at this point in the history
  • Loading branch information
kpreid committed Jan 11, 2025
1 parent b5eda10 commit 9f7b669
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

### Added

- Functionality:
- In the desktop version, changes to graphics options are now persisted across launches.

- `all-is-cubes-ui` library:
- `apps::Settings` manages user-editable settings that eventually will be more than just the graphics options.
- `apps::SessionBuilder::settings()` links a possibly-shared `Settings` to the created session.
Expand Down
8 changes: 4 additions & 4 deletions all-is-cubes-desktop/src/bin/all-is-cubes/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use clap::{CommandFactory as _, Parser as _};
use all_is_cubes::euclid::Size2D;
use all_is_cubes::listen;
use all_is_cubes_render::camera::{GraphicsOptions, Viewport};
use all_is_cubes_ui::apps::Settings;

#[cfg(feature = "record")]
use all_is_cubes_desktop::record;
Expand Down Expand Up @@ -81,8 +82,8 @@ fn main() -> Result<(), anyhow::Error> {
}
})?;

let graphics_options = if no_config_files {
GraphicsOptions::default()
let settings = if no_config_files {
Settings::new(Arc::new(GraphicsOptions::default()))
} else {
load_config().context("Error loading configuration files")?
};
Expand All @@ -104,14 +105,13 @@ fn main() -> Result<(), anyhow::Error> {
let mut session = runtime.block_on(
Session::builder()
.ui(viewport_cell.as_source())
.settings_from(settings)
.quit(Arc::new(|| {
// TODO: command the event loop to exit instead
std::process::exit(0)
}))
.build(),
);
// TODO: this code should live in the lib
session.settings().set_graphics_options(graphics_options);
universe_task.attach_to_session(&mut session);
let session_done_time = Instant::now();
log::debug!(
Expand Down
46 changes: 40 additions & 6 deletions all-is-cubes-desktop/src/config_files.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use std::fs::create_dir_all;
use std::fs;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use std::sync::Arc;

use all_is_cubes_ui::apps::Settings;
use directories_next::ProjectDirs;
use serde::{de::DeserializeOwned, Serialize};

use all_is_cubes_render::camera::GraphicsOptions;

/// Load preferences/settings/config files from a platform-appropriate read/write location.
pub fn load_config() -> Result<GraphicsOptions, anyhow::Error> {
pub fn load_config() -> Result<Settings, anyhow::Error> {
// TODO: make testable
// TODO: allow users of this library function to pick their own config dir

Expand All @@ -23,15 +25,23 @@ pub fn load_config() -> Result<GraphicsOptions, anyhow::Error> {

let project_dirs = ProjectDirs::from("org.switchb", "", "all-is-cubes")
.ok_or_else(|| anyhow::anyhow!("could not find configuration directory"))?;
create_dir_all(project_dirs.config_dir())?;
fs::create_dir_all(project_dirs.config_dir())?;

let settings_path = project_dirs.config_dir().join("graphics.json");

let graphics_options = read_or_create_default_json_file(
"graphics options",
&project_dirs.config_dir().join("graphics.json"),
&settings_path,
GraphicsOptions::default,
);

Ok(graphics_options)
Ok(Settings::with_persistence(
Arc::new(graphics_options),
// TODO: ideally, writes would be performed asynchronously and with rate-limiting
Arc::new(move |data| {
write_json_file("graphics options", &settings_path, &data);
}),
))
}

fn read_or_create_default_json_file<V: DeserializeOwned + Serialize>(
Expand Down Expand Up @@ -63,7 +73,7 @@ fn read_or_create_default_json_file<V: DeserializeOwned + Serialize>(
);
let value = default();
let json_text = serde_json::to_string_pretty(&value).unwrap();
std::fs::write(path, json_text.as_bytes()).expect("Error writing default file");
fs::write(path, json_text.as_bytes()).expect("Error writing default file");
value
}
Err(e) => {
Expand All @@ -77,3 +87,27 @@ fn read_or_create_default_json_file<V: DeserializeOwned + Serialize>(
}
}
}

fn write_json_file<V: Serialize>(description: &str, path: &Path, value: &V) {
match fs::OpenOptions::new().write(true).truncate(true).open(path) {
Ok(file) => match serde_json::to_writer_pretty(file, &value) {
Ok(()) => log::trace!("Wrote {} to {}", description, path.to_string_lossy()),
Err(e) => {
log::error!(
"Error while writing {} file {}: {}",
description,
path.to_string_lossy(),
e
);
}
},
Err(e) => {
log::error!(
"Error while opening {} file {}: {}",
description,
path.to_string_lossy(),
e
);
}
}
}
15 changes: 8 additions & 7 deletions all-is-cubes-desktop/src/record/rmain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ where
// Modify graphics options to suit recording
// TODO: Find a better place to put this policy, and in particular allow the user to
// override it if they do want to record the UI.
dsession
.session
.settings()
.mutate_graphics_options(|graphics_options| {
graphics_options.show_ui = false;
graphics_options.debug_info_text = false;
});
let settings = dsession.session.settings();
// TODO: instead of blanket disinheriting, there should be a way to set explicitly ephemeral
// settings.
settings.disinherit();
settings.mutate_graphics_options(|graphics_options| {
graphics_options.show_ui = false;
graphics_options.debug_info_text = false;
});

Ok(())
}
Expand Down

0 comments on commit 9f7b669

Please sign in to comment.