From 578cc7723cbb5cbc05d5b92a617140b1162c4456 Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Thu, 4 Jan 2024 23:28:47 +0100 Subject: [PATCH] feat: minimum viable product --- Cargo.lock | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 + src/main.rs | 106 ++++++++++++++++++----- 3 files changed, 326 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2ed816..8d95fbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,21 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "arboard" version = "3.3.0" @@ -229,6 +244,19 @@ dependencies = [ "libc", ] +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.48.5", +] + [[package]] name = "clipboard-win" version = "4.5.0" @@ -564,6 +592,95 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "gethostname" version = "0.3.0" @@ -687,6 +804,43 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "homedir" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22074da8bba2ef26fc1737ae6c777b5baab5524c2dc403b5c6a76166766ccda5" +dependencies = [ + "cfg-if", + "nix 0.26.4", + "serde", + "widestring", + "windows-sys 0.48.0", + "wmi", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.5.0" @@ -977,6 +1131,7 @@ dependencies = [ "cfg-if", "libc", "memoffset 0.7.1", + "pin-utils", ] [[package]] @@ -1165,6 +1320,18 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.28" @@ -1306,6 +1473,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "slotmap" version = "1.0.7" @@ -1424,6 +1600,7 @@ name = "todoodoo" version = "0.1.0" dependencies = [ "eframe", + "homedir", ] [[package]] @@ -1697,6 +1874,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "winapi" version = "0.3.9" @@ -1737,6 +1920,48 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-implement" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "windows-interface" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -1978,6 +2203,20 @@ dependencies = [ "memchr", ] +[[package]] +name = "wmi" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced703d10188571ce53582c2932ce640ed3c413cff7ee6e2d961f9abdb6a63d1" +dependencies = [ + "chrono", + "futures", + "log", + "serde", + "thiserror", + "windows", +] + [[package]] name = "x11-dl" version = "2.21.0" diff --git a/Cargo.toml b/Cargo.toml index 95191ea..142f40b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,6 @@ codegen-units = 1 version = "0.24" default-features = false features = [ "wayland", "default_fonts", "glow", "persistence" ] + +[dependencies.homedir] +version = "0.2" diff --git a/src/main.rs b/src/main.rs index ee4b6b7..d3b877a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,34 +1,96 @@ -use eframe::egui; +use std::{ + error::Error, + fmt::{self, Debug, Display}, + fs::{File, OpenOptions}, + io::{Read, Seek, SeekFrom, Write}, + path::Path, +}; -fn main() { +use eframe::egui::{self, Key, TextEdit}; + +enum RunError { + HomeDir(homedir::GetHomeError), + NoHome, + OpenFile(std::io::Error), + EFrame(eframe::Error), +} + +impl Debug for RunError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} +impl Display for RunError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::HomeDir(e) => f.write_fmt(format_args!("homedir error: {e}")), + Self::NoHome => f.write_fmt(format_args!("failed to find home directory")), + Self::OpenFile(e) => f.write_fmt(format_args!("error while opening todo.txt: {e}")), + Self::EFrame(e) => f.write_fmt(format_args!("eframe error: {e}")), + } + } +} +impl Error for RunError {} + +fn main() -> Result<(), RunError> { std::env::set_var("WINIT_UNIX_BACKEND", "wayland"); + let home_dir = homedir::get_my_home() + .map_err(RunError::HomeDir)? + .ok_or(RunError::NoHome)?; + let todo_file = OpenOptions::new() + .create(true) + .read(true) + .write(true) + .append(false) + .open(Path::join(&home_dir, "todo.txt")) + .map_err(RunError::OpenFile)?; + let native_options = eframe::NativeOptions::default(); - if let Err(err) = eframe::run_native( - "My egui App", + eframe::run_native( + "To-DooDoo", native_options, - Box::new(|cc| Box::new(MyEguiApp::new(cc))), - ) { - eprintln!("{err}"); + Box::new(|_cc| Box::new(ToDooDooApp::new(todo_file))), + ) + .map_err(RunError::EFrame)?; + Ok(()) +} + +struct ToDooDooApp { + notes: String, + file: File, +} + +impl ToDooDooApp { + fn new(mut file: File) -> Self { + let mut notes = String::with_capacity( + file.metadata() + .expect("file metadata") + .len() + .try_into() + .expect("file too big"), + ); + file.read_to_string(&mut notes) + .expect("failed to read file"); + Self { file, notes } + } + + fn save(&mut self) { + self.file.set_len(0).expect("failed to truncate file"); + self.file.seek(SeekFrom::Start(0)).expect("failed to seek"); + self.file + .write_all(self.notes.as_bytes()) + .expect("failed to write file"); + self.file.flush().expect("failed to flush"); } } -#[derive(Default)] -struct MyEguiApp {} - -impl MyEguiApp { - fn new(_cc: &eframe::CreationContext<'_>) -> Self { - // Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_visuals. - // Restore app state using cc.storage (requires the "persistence" feature). - // Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use - // for e.g. egui::PaintCallback. - Self::default() - } -} - -impl eframe::App for MyEguiApp { +impl eframe::App for ToDooDooApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("Hello World!"); + if ctx.input(|i| i.key_pressed(Key::S) && i.modifiers.command) { + self.save(); + } + ui.add_sized(ui.available_size(), TextEdit::multiline(&mut self.notes)); }); } }