message: Improve persistence in `todos`
diff: @@ -41,7 +41,10 @@ impl Application for Todos {
  type Message = Message;
  fn new() -> (Todos, Command<Message>) {
  - (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,7 +487,22 @@ struct SavedState {
  tasks: Vec<Task>,
  }
  -fn save_path() -> std::path::PathBuf {
  +#[derive(Debug, Clone)]
  +enum LoadError {
  + FileError,
  + FormatError,
  +}
  +
  +#[derive(Debug, Clone)]
  +enum SaveError {
  + DirectoryError,
  + FileError,
  + WriteError,
  + FormatError,
  +}
  +
  +impl SavedState {
  + fn path() -> std::path::PathBuf {
  let mut path = if let Some(project_dirs) =
  directories::ProjectDirs::from("rs", "Iced", "Todos")
  {
  @@ -498,19 +517,13 @@ fn save_path() -> std::path::PathBuf {
  path
  }
  -#[derive(Debug, Clone)]
  -enum LoadError {
  - FileError,
  - FormatError,
  -}
  -
  async fn load() -> Result<SavedState, LoadError> {
  use std::io::Read;
  let mut contents = String::new();
  - let mut file =
  - std::fs::File::open(save_path()).map_err(|_| LoadError::FileError)?;
  + let mut file = std::fs::File::open(Self::path())
  + .map_err(|_| LoadError::FileError)?;
  file.read_to_string(&mut contents)
  .map_err(|_| LoadError::FileError)?;
  @@ -518,27 +531,19 @@ async fn load() -> Result<SavedState, LoadError> {
  serde_json::from_str(&contents).map_err(|_| LoadError::FormatError)
  }
  -#[derive(Debug, Clone)]
  -enum SaveError {
  - DirectoryError,
  - FileError,
  - WriteError,
  - FormatError,
  -}
  -
  -async fn save(state: SavedState) -> Result<(), SaveError> {
  + async fn save(self) -> Result<(), SaveError> {
  use std::io::Write;
  - let json = serde_json::to_string_pretty(&state)
  + let json = serde_json::to_string_pretty(&self)
  .map_err(|_| SaveError::FormatError)?;
  - let save_path = save_path();
  - let save_dir = save_path.parent().ok_or(SaveError::DirectoryError)?;
  + let path = Self::path();
  + let dir = path.parent().ok_or(SaveError::DirectoryError)?;
  - std::fs::create_dir_all(save_dir).map_err(|_| SaveError::DirectoryError)?;
  + std::fs::create_dir_all(dir).map_err(|_| SaveError::DirectoryError)?;
  let mut file =
  - std::fs::File::create(save_path).map_err(|_| SaveError::FileError)?;
  + std::fs::File::create(path).map_err(|_| SaveError::FileError)?;
  file.write_all(json.as_bytes())
  .map_err(|_| SaveError::WriteError)?;
  @@ -549,3 +554,4 @@ async fn save(state: SavedState) -> Result<(), SaveError> {
  Ok(())
  }
  +}
  