preferences serialization and saving

This commit is contained in:
Brandon Thomas committed 2025-05-04 13:33:43 -04:00
1 parent a0abe8b9e5
commit 51f4e74954
2 files changed
+159 -2

No files matched your search

@@ -0,0 +1,65 @@
use crate::state::app_preferences::app_preferences_manager::AppPreferencesManager;
use crate::state::app_preferences::preferred_download_directory::PreferredDownloadDirectory;
use errors::AnyhowResult;
use log::{error, info};
use serde_derive::{Deserialize, Serialize};
use tauri::{AppHandle, State};
/// For now we'll only update a single preference at a time.
#[derive(Deserialize)]
pub struct UpdateAppPreferencesRequest {
pub preference: PreferenceName,
/// We'll decode this with respect to the preference value.
pub value: String,
}
#[derive(Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PreferenceName {
PreferredDownloadDirectory,
PlaySounds,
}
#[derive(Serialize)]
pub struct UpdateAppPreferencesResponse {
pub success: bool,
}
#[tauri::command]
pub async fn update_app_preferences_command(
request: UpdateAppPreferencesRequest,
app_prefs: State<'_, AppPreferencesManager>,
) -> Result<UpdateAppPreferencesResponse, String> {
info!("update_app_preferences_command called");
update_prefs(request, &app_prefs)
.await
.map_err(|err| {
error!("Error getting app preferences: {:?}", err);
format!("Error getting app preferences: {:?}", err)
})?;
Ok(UpdateAppPreferencesResponse {
success: true,
})
}
async fn update_prefs(request: UpdateAppPreferencesRequest, app_prefs: &AppPreferencesManager) -> AnyhowResult<()> {
let mut prefs = app_prefs.get_clone()?;
match request.preference {
PreferenceName::PreferredDownloadDirectory => {
prefs.preferred_download_directory = request.value.parse::<PreferredDownloadDirectory>()?;
}
PreferenceName::PlaySounds => {
prefs.play_sounds = request.value.parse::<bool>()?;
}
}
app_prefs.set_clone(&prefs)?;
// TODO: Write to filesystem.
Ok(())
}
@@ -1,8 +1,100 @@
use std::path::PathBuf;
use errors::AnyhowError;
use serde_derive::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::path::PathBuf;
use std::str::FromStr;
#[derive(Debug, Clone, Serialize, Deserialize)]
const SYSTEM_DEFAULT_SENTINEL_VALUE: &str = "system_default";
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum PreferredDownloadDirectory {
/// The system-default downloads directory, which varies by OS.
/// NB: Serializes as `"system_default"` in JSON.
SystemDefault,
/// A user-defined path
/// NB: Serializes as `{"custom": "/path/to/dir"}` in JSON.
Custom(PathBuf),
}
impl FromStr for PreferredDownloadDirectory {
type Err = AnyhowError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == SYSTEM_DEFAULT_SENTINEL_VALUE || s == "\"system_default\"" {
Ok(PreferredDownloadDirectory::SystemDefault)
} else {
// TODO: If it gets serialized as JSON, we may need to remove the `{"custom": ...` wrapping layer.
let path = PathBuf::from(s);
Ok(PreferredDownloadDirectory::Custom(path))
}
}
}
impl Display for PreferredDownloadDirectory {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
PreferredDownloadDirectory::SystemDefault => write!(f, "{}", SYSTEM_DEFAULT_SENTINEL_VALUE),
PreferredDownloadDirectory::Custom(path) => write!(f, "{}", path.to_string_lossy()),
}
}
}
#[cfg(test)]
mod tests {
use crate::state::app_preferences::preferred_download_directory::PreferredDownloadDirectory;
use std::path::PathBuf;
use std::str::FromStr;
mod json {
use super::*;
#[test]
fn to_json_system_default() {
let val = PreferredDownloadDirectory::SystemDefault;
let val = serde_json::to_string(&val).unwrap();
assert_eq!(&val, "\"system_default\"");
}
#[test]
fn to_json_custom() {
let val = PreferredDownloadDirectory::Custom("/tmp".into());
let val = serde_json::to_string(&val).unwrap();
assert_eq!(&val, "{\"custom\":\"/tmp\"}");
}
}
mod string {
use super::*;
#[test]
fn to_string_system_default() {
let val = PreferredDownloadDirectory::SystemDefault;
let val = val.to_string();
assert_eq!(&val, "system_default");
}
#[test]
fn to_string_custom() {
let val = PreferredDownloadDirectory::Custom("/tmp/foo".into());
let val = val.to_string();
assert_eq!(&val, "/tmp/foo");
}
}
#[test]
fn from_string_system_default() {
let val = "system_default";
let val = PreferredDownloadDirectory::from_str(val).unwrap();
assert_eq!(val, PreferredDownloadDirectory::SystemDefault);
}
#[test]
fn from_string_custom() {
let val = "/tmp/foo";
let val = PreferredDownloadDirectory::from_str(val).unwrap();
assert_eq!(val, PreferredDownloadDirectory::Custom(PathBuf::from("/tmp/foo")));
}
}