Add a state file to persist data

This commit is contained in:
Quentin Boyer 2023-11-11 23:07:23 +01:00
parent e9058c6b27
commit 066bcb5555
3 changed files with 187 additions and 19 deletions

104
Cargo.lock generated
View file

@ -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"

View file

@ -5,9 +5,13 @@ authors = ["traxys <quentin@familleboyer.net>"]
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"

View file

@ -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<String, f64>,
}
struct AddRecurring<F> {
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<String, f64>,
save_file: File,
}
#[derive(Serialize, Deserialize, Default)]
struct SaveFile {
recurring: BTreeMap<String, f64>,
}
#[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<Message>) {
fn new(config: Self::Flags) -> (Self, Command<Message>) {
(
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<Self::Message> {
subscription::events().map(Message::Event)
}
fn update(&mut self, message: Self::Message) -> Command<Message> {
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(())
}