Improve persistence in todos
This commit is contained in:
parent
a803ab240b
commit
63dbf078fe
@ -41,7 +41,10 @@ impl Application for Todos {
|
|||||||
type Message = Message;
|
type Message = Message;
|
||||||
|
|
||||||
fn new() -> (Todos, Command<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 {
|
fn title(&self) -> String {
|
||||||
@ -115,11 +118,12 @@ impl Application for Todos {
|
|||||||
state.saving = true;
|
state.saving = true;
|
||||||
|
|
||||||
Command::perform(
|
Command::perform(
|
||||||
save(SavedState {
|
SavedState {
|
||||||
input_value: state.input_value.clone(),
|
input_value: state.input_value.clone(),
|
||||||
filter: state.filter,
|
filter: state.filter,
|
||||||
tasks: state.tasks.clone(),
|
tasks: state.tasks.clone(),
|
||||||
}),
|
}
|
||||||
|
.save(),
|
||||||
Message::Saved,
|
Message::Saved,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -483,41 +487,12 @@ struct SavedState {
|
|||||||
tasks: Vec<Task>,
|
tasks: Vec<Task>,
|
||||||
}
|
}
|
||||||
|
|
||||||
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)]
|
#[derive(Debug, Clone)]
|
||||||
enum LoadError {
|
enum LoadError {
|
||||||
FileError,
|
FileError,
|
||||||
FormatError,
|
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)?;
|
|
||||||
|
|
||||||
file.read_to_string(&mut contents)
|
|
||||||
.map_err(|_| LoadError::FileError)?;
|
|
||||||
|
|
||||||
serde_json::from_str(&contents).map_err(|_| LoadError::FormatError)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum SaveError {
|
enum SaveError {
|
||||||
DirectoryError,
|
DirectoryError,
|
||||||
@ -526,26 +501,57 @@ enum SaveError {
|
|||||||
FormatError,
|
FormatError,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save(state: SavedState) -> Result<(), SaveError> {
|
impl SavedState {
|
||||||
use std::io::Write;
|
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)
|
path.push("todos.json");
|
||||||
.map_err(|_| SaveError::FormatError)?;
|
|
||||||
|
|
||||||
let save_path = save_path();
|
path
|
||||||
let save_dir = save_path.parent().ok_or(SaveError::DirectoryError)?;
|
}
|
||||||
|
|
||||||
std::fs::create_dir_all(save_dir).map_err(|_| SaveError::DirectoryError)?;
|
async fn load() -> Result<SavedState, LoadError> {
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
let mut file =
|
let mut contents = String::new();
|
||||||
std::fs::File::create(save_path).map_err(|_| SaveError::FileError)?;
|
|
||||||
|
|
||||||
file.write_all(json.as_bytes())
|
let mut file = std::fs::File::open(Self::path())
|
||||||
.map_err(|_| SaveError::WriteError)?;
|
.map_err(|_| LoadError::FileError)?;
|
||||||
|
|
||||||
// This is a simple way to save at most once every couple seconds
|
file.read_to_string(&mut contents)
|
||||||
// We will be able to get rid of it once we implement event subscriptions
|
.map_err(|_| LoadError::FileError)?;
|
||||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
|
||||||
|
|
||||||
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user