From 63dbf078fefea444073813e834c2d35fa25eb3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Mon, 18 Nov 2019 00:13:18 +0100 Subject: [PATCH] Improve persistence in `todos` --- examples/todos.rs | 100 ++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/examples/todos.rs b/examples/todos.rs index 05142fb2..a1dfc5aa 100644 --- a/examples/todos.rs +++ b/examples/todos.rs @@ -41,7 +41,10 @@ impl Application for Todos { type Message = Message; fn new() -> (Todos, Command) { - (Todos::Loading, Command::perform(load(), Message::Loaded)) + ( + Todos::Loading, + Command::perform(SavedState::load(), Message::Loaded), + ) } fn title(&self) -> String { @@ -115,11 +118,12 @@ impl Application for Todos { state.saving = true; Command::perform( - save(SavedState { + SavedState { input_value: state.input_value.clone(), filter: state.filter, tasks: state.tasks.clone(), - }), + } + .save(), Message::Saved, ) } else { @@ -483,41 +487,12 @@ struct SavedState { tasks: Vec, } -fn save_path() -> std::path::PathBuf { - let mut path = if let Some(project_dirs) = - directories::ProjectDirs::from("rs", "Iced", "Todos") - { - project_dirs.data_dir().into() - } else { - std::env::current_dir() - .expect("The current directory is not accessible") - }; - - path.push("todos.json"); - - path -} - #[derive(Debug, Clone)] enum LoadError { FileError, FormatError, } -async fn load() -> Result { - use std::io::Read; - - let mut contents = String::new(); - - let mut file = - std::fs::File::open(save_path()).map_err(|_| LoadError::FileError)?; - - file.read_to_string(&mut contents) - .map_err(|_| LoadError::FileError)?; - - serde_json::from_str(&contents).map_err(|_| LoadError::FormatError) -} - #[derive(Debug, Clone)] enum SaveError { DirectoryError, @@ -526,26 +501,57 @@ enum SaveError { FormatError, } -async fn save(state: SavedState) -> Result<(), SaveError> { - use std::io::Write; +impl SavedState { + fn path() -> std::path::PathBuf { + let mut path = if let Some(project_dirs) = + directories::ProjectDirs::from("rs", "Iced", "Todos") + { + project_dirs.data_dir().into() + } else { + std::env::current_dir() + .expect("The current directory is not accessible") + }; - let json = serde_json::to_string_pretty(&state) - .map_err(|_| SaveError::FormatError)?; + path.push("todos.json"); - let save_path = save_path(); - let save_dir = save_path.parent().ok_or(SaveError::DirectoryError)?; + path + } - std::fs::create_dir_all(save_dir).map_err(|_| SaveError::DirectoryError)?; + async fn load() -> Result { + use std::io::Read; - let mut file = - std::fs::File::create(save_path).map_err(|_| SaveError::FileError)?; + let mut contents = String::new(); - file.write_all(json.as_bytes()) - .map_err(|_| SaveError::WriteError)?; + let mut file = std::fs::File::open(Self::path()) + .map_err(|_| LoadError::FileError)?; - // This is a simple way to save at most once every couple seconds - // We will be able to get rid of it once we implement event subscriptions - std::thread::sleep(std::time::Duration::from_secs(2)); + file.read_to_string(&mut contents) + .map_err(|_| LoadError::FileError)?; - Ok(()) + serde_json::from_str(&contents).map_err(|_| LoadError::FormatError) + } + + async fn save(self) -> Result<(), SaveError> { + use std::io::Write; + + let json = serde_json::to_string_pretty(&self) + .map_err(|_| SaveError::FormatError)?; + + let path = Self::path(); + let dir = path.parent().ok_or(SaveError::DirectoryError)?; + + std::fs::create_dir_all(dir).map_err(|_| SaveError::DirectoryError)?; + + let mut file = + std::fs::File::create(path).map_err(|_| SaveError::FileError)?; + + file.write_all(json.as_bytes()) + .map_err(|_| SaveError::WriteError)?; + + // This is a simple way to save at most once every couple seconds + // We will be able to get rid of it once we implement event subscriptions + std::thread::sleep(std::time::Duration::from_secs(2)); + + Ok(()) + } }