From 066bcb555508fb800e3b85cb576c7f6b081f1c66 Mon Sep 17 00:00:00 2001 From: Quentin Boyer Date: Sat, 11 Nov 2023 23:07:23 +0100 Subject: [PATCH] Add a state file to persist data --- Cargo.lock | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 4 ++ src/main.rs | 98 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 187 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd3c194..2eeb8a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,6 +90,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "approx" version = "0.5.1" @@ -428,6 +434,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -679,9 +706,13 @@ checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" name = "glaurung" version = "0.1.0" dependencies = [ + "anyhow", + "directories", "iced", "iced_aw", "itertools", + "serde", + "serde_json", ] [[package]] @@ -1055,6 +1086,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + [[package]] name = "jni-sys" version = "0.3.0" @@ -1137,6 +1174,17 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall 0.4.1", +] + [[package]] name = "libredox" version = "0.0.2" @@ -1517,13 +1565,19 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "orbclient" version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "libredox", + "libredox 0.0.2", ] [[package]] @@ -1857,6 +1911,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox 0.0.1", + "thiserror", +] + [[package]] name = "renderdoc-sys" version = "1.0.0" @@ -1892,6 +1957,12 @@ dependencies = [ "unicode-script", ] +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + [[package]] name = "scoped-tls" version = "1.0.1" @@ -1917,6 +1988,37 @@ dependencies = [ "tiny-skia 0.8.4", ] +[[package]] +name = "serde" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "simd-adler32" version = "0.3.7" diff --git a/Cargo.toml b/Cargo.toml index 8b705c6..efa75d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,9 +5,13 @@ authors = ["traxys "] edition = "2021" [dependencies] +anyhow = "1.0.75" +directories = "5.0.1" iced = { version = "0.10.0", features = ["lazy"] } iced_aw = { version = "0.7.0", default-features = false, features = [ "modal", "card", ] } itertools = "0.11.0" +serde = { version = "1.0.192", features = ["derive"] } +serde_json = "1.0.108" diff --git a/src/main.rs b/src/main.rs index 83545e6..618b6c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,23 @@ -use std::collections::BTreeMap; +use std::{ + collections::BTreeMap, + fs::{File, OpenOptions}, + io::BufReader, + path::PathBuf, +}; +use anyhow::anyhow; +use directories::ProjectDirs; use iced::{ - font, + font, subscription, widget::{button, column, component, horizontal_rule, row, text, text_input}, - Application, Command, Renderer, Settings, Theme, + window, Application, Command, Event, Renderer, Settings, Theme, }; use iced_aw::{card, modal}; use itertools::Itertools; +use serde::{Deserialize, Serialize}; type Element<'a> = iced::Element<'a, Message>; -#[derive(Clone, Debug)] -enum Message { - AddRecurring(String, f64), - FontLoaded(Result<(), font::Error>), -} - -struct Glaurung { - recurring: BTreeMap, -} - struct AddRecurring { on_submit: F, } @@ -226,16 +224,45 @@ where } } +#[derive(Clone, Debug)] +enum Message { + Event(Event), + AddRecurring(String, f64), + FontLoaded(Result<(), font::Error>), +} + +struct Glaurung { + recurring: BTreeMap, + save_file: File, +} + +#[derive(Serialize, Deserialize, Default)] +struct SaveFile { + recurring: BTreeMap, +} + +#[derive(Default)] +struct AppConfig { + save: SaveFile, + save_file: PathBuf, +} + impl Application for Glaurung { type Message = Message; type Theme = Theme; type Executor = iced::executor::Default; - type Flags = (); + type Flags = AppConfig; - fn new(_flags: Self::Flags) -> (Self, Command) { + fn new(config: Self::Flags) -> (Self, Command) { ( Self { - recurring: BTreeMap::new(), + recurring: config.save.recurring, + save_file: OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(config.save_file) + .expect("Can't open data file"), }, Command::batch(vec![ font::load(iced_aw::graphics::icons::ICON_FONT_BYTES).map(Message::FontLoaded) @@ -247,12 +274,29 @@ impl Application for Glaurung { "Glaurung - Account Manager".into() } + fn subscription(&self) -> iced::Subscription { + subscription::events().map(Message::Event) + } + fn update(&mut self, message: Self::Message) -> Command { match message { Message::AddRecurring(name, value) => { self.recurring.insert(name, value); } Message::FontLoaded(r) => r.expect("could not load font"), + Message::Event(ev) => { + if let Event::Window(window::Event::CloseRequested) = ev { + serde_json::to_writer( + &mut self.save_file, + &SaveFile { + recurring: std::mem::take(&mut self.recurring), + }, + ) + .expect("could not write save file"); + + return window::close(); + } + } } Command::none() @@ -275,6 +319,24 @@ impl Application for Glaurung { } } -fn main() -> iced::Result { - Glaurung::run(Settings::default()) +fn main() -> anyhow::Result<()> { + let project_dir = ProjectDirs::from("net", "traxys", "glaurung").ok_or(anyhow!(""))?; + let state_dir = project_dir + .state_dir() + .ok_or(anyhow!("No state directory"))?; + std::fs::create_dir_all(state_dir)?; + + let save_file = state_dir.join("data.json"); + + let save = match save_file.exists() { + false => Default::default(), + true => serde_json::from_reader(BufReader::new(File::open(&save_file)?))?, + }; + + let mut settings = Settings::with_flags(AppConfig { save, save_file }); + settings.exit_on_close_request = false; + + Glaurung::run(settings)?; + + Ok(()) }