diff options
author | metamuffin <yvchraiqi@protonmail.com> | 2022-08-17 10:54:02 +0200 |
---|---|---|
committer | metamuffin <yvchraiqi@protonmail.com> | 2022-08-17 10:54:02 +0200 |
commit | cfc5fd51582d694b98ff69a680d0ad727354c8c3 (patch) | |
tree | ded58259b8eb3f8b25cc543a6c28883809a72127 | |
parent | 5e6509163df53788799bb7aa97d07a90bf416eb7 (diff) | |
download | karlender-cfc5fd51582d694b98ff69a680d0ad727354c8c3.tar karlender-cfc5fd51582d694b98ff69a680d0ad727354c8c3.tar.bz2 karlender-cfc5fd51582d694b98ff69a680d0ad727354c8c3.tar.zst |
idk
-rw-r--r-- | Cargo.lock | 31 | ||||
-rw-r--r-- | karlgui/Cargo.toml | 1 | ||||
-rw-r--r-- | karlgui/src/globals.rs | 96 | ||||
-rw-r--r-- | karlgui/src/helper.rs | 5 | ||||
-rw-r--r-- | karlgui/src/main.rs | 29 | ||||
-rw-r--r-- | karlgui/src/views/calendar.rs | 68 | ||||
-rw-r--r-- | karlgui/src/views/edit.rs | 2 |
7 files changed, 193 insertions, 39 deletions
@@ -45,6 +45,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" [[package]] +name = "android_system_properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" +dependencies = [ + "libc", +] + +[[package]] name = "anyhow" version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -179,15 +188,17 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", "time", + "wasm-bindgen", "winapi", ] @@ -739,6 +750,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] +name = "iana-time-zone" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5528d9c2817db4e10cc78f8d4c8228906e5854f389ff6b076cee3572a09d35" +dependencies = [ + "android_system_properties", + "core-foundation-sys 0.8.3", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -853,6 +877,7 @@ dependencies = [ name = "karlgui" version = "0.1.0" dependencies = [ + "chrono", "crossbeam-channel", "eframe", "egui", diff --git a/karlgui/Cargo.toml b/karlgui/Cargo.toml index fd1aec0..caf0777 100644 --- a/karlgui/Cargo.toml +++ b/karlgui/Cargo.toml @@ -8,6 +8,7 @@ karlcommon = { path = "../karlcommon" } crossbeam-channel = "0.5.6" serde_json = "1.0.83" +chrono = "0.4.22" env_logger = "0.9.0" log = "0.4.17" diff --git a/karlgui/src/globals.rs b/karlgui/src/globals.rs new file mode 100644 index 0000000..202cce6 --- /dev/null +++ b/karlgui/src/globals.rs @@ -0,0 +1,96 @@ +use crate::{client::Client, helper::from_timestamp}; +use chrono::NaiveDateTime; +use karlcommon::{ClientboundPacket, ServerboundPacket, Task}; +use log::warn; +use std::{ + collections::{HashMap, VecDeque}, + ops::Range, +}; + +pub struct Globals { + pub client: Client, + pub tasks: HashMap<u64, Task>, + pub awaiting_instance_requests: VecDeque<(u64, Range<NaiveDateTime>)>, + + pub instance_cache: + HashMap<(u64, Range<NaiveDateTime>), Option<Vec<Range<Option<NaiveDateTime>>>>>, +} + +impl Globals { + pub fn new(client: Client) -> Self { + Globals { + client, + tasks: Default::default(), + instance_cache: Default::default(), + awaiting_instance_requests: Default::default(), + } + } + pub fn update_network(&mut self) { + for p in self.client.receiver.try_iter() { + match p { + ClientboundPacket::TaskList(t) => { + self.tasks = HashMap::from_iter(t.into_iter().map(|e| (e.id, e))); + } + ClientboundPacket::Sync => { + self.client.busy = false; + } + ClientboundPacket::InstanceList(is) => { + if let Some(i) = self.awaiting_instance_requests.pop_front() { + self.instance_cache.insert( + i, + Some( + is.iter() + .map(|r| r.start.map(from_timestamp)..r.end.map(from_timestamp)) + .collect(), + ), + ); + } else { + warn!("got unknown instance list packet") + } + } + _ => {} + } + } + } + pub fn get_all_instances_range( + &mut self, + start: NaiveDateTime, + end: NaiveDateTime, + ) -> Option<Vec<(u64, Range<Option<NaiveDateTime>>)>> { + let mut l = vec![]; + for t in &self.tasks.values().map(|e| e.id).collect::<Vec<_>>() { + if let Some(r) = self.get_instances_range(*t, start, end) { + l.extend(r.into_iter().map(|e| (*t, e.clone()))); + } + } + if l.len() > 0 { + Some(l) + } else { + None + } + } + pub fn get_instances_range( + &mut self, + task: u64, + start: NaiveDateTime, + end: NaiveDateTime, + ) -> &Option<Vec<Range<Option<NaiveDateTime>>>> { + // looks silly but the borrow checker likes it more + let has = self.instance_cache.contains_key(&(task, start..end)); + if has { + if let Some(c) = self.instance_cache.get(&(task, start..end)) { + return c; + } + return &None; + } + self.awaiting_instance_requests + .push_back((task, start..end)); + self.instance_cache.insert((task, start..end), None); + self.client.send_sync(ServerboundPacket::ListInstances { + task, + range: Some(start.timestamp())..Some(end.timestamp()), + limit: 100, + }); + &None + } +} diff --git a/karlgui/src/helper.rs b/karlgui/src/helper.rs index eb4c981..4f8f4f4 100644 --- a/karlgui/src/helper.rs +++ b/karlgui/src/helper.rs @@ -1,6 +1,11 @@ +use chrono::NaiveDateTime; use egui::{DragValue, Ui}; use karlcommon::Property; +pub fn from_timestamp(t: i64) -> NaiveDateTime { + NaiveDateTime::from_timestamp(t, 0) +} + pub fn format_value(prop: Property, value: i64) -> String { match prop { Property::Year => format!("{value}"), diff --git a/karlgui/src/main.rs b/karlgui/src/main.rs index d683a78..b3a6f62 100644 --- a/karlgui/src/main.rs +++ b/karlgui/src/main.rs @@ -1,11 +1,12 @@ pub mod client; +pub mod globals; pub mod helper; pub mod views; -use crate::client::Client; +use crate::{client::Client, globals::Globals}; use eframe::CreationContext; use egui::CentralPanel; -use karlcommon::{socket_path, ClientboundPacket, ServerboundPacket, Task}; +use karlcommon::{socket_path, ServerboundPacket}; use log::{error, info}; use std::{os::unix::net::UnixStream, process::exit}; use views::{calendar::Calendar, edit::ShowAndEdit}; @@ -19,11 +20,6 @@ fn main() { ) } -pub struct Globals { - client: Client, - tasks: Vec<Task>, -} - struct App { g: Globals, @@ -57,31 +53,16 @@ impl App { client.send(ServerboundPacket::ListTasks); App { current_tab: Tab::ShowAndEdit, - g: Globals { - client, - tasks: vec![], - }, + g: Globals::new(client), show_and_edit: Default::default(), calendar: Default::default(), } } - - pub fn update_network(&mut self) { - for p in self.g.client.receiver.try_iter() { - match p { - ClientboundPacket::TaskList(t) => self.g.tasks = t, - ClientboundPacket::Sync => { - self.g.client.busy = false; - } - _ => {} - } - } - } } impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - self.update_network(); + self.g.update_network(); CentralPanel::default().show(ctx, |ui| { ui.add_enabled_ui(!self.g.client.busy, |ui| { ui.horizontal(|ui| { diff --git a/karlgui/src/views/calendar.rs b/karlgui/src/views/calendar.rs index b216504..c332b80 100644 --- a/karlgui/src/views/calendar.rs +++ b/karlgui/src/views/calendar.rs @@ -1,12 +1,32 @@ +use std::ops::Range; + use crate::{helper::weekday_to_str, Globals}; +use chrono::{Duration, NaiveDateTime}; use egui::Ui; use egui_extras::TableBuilder; #[derive(Default)] -pub struct Calendar; +pub struct Calendar { + // offset: NaiveDate, +} impl Calendar { - pub fn ui(&mut self, ui: &mut Ui, _g: &mut Globals) { + pub fn ui(&mut self, ui: &mut Ui, g: &mut Globals) { + let start_date = chrono::Utc::now().date_naive(); //self.offset; + let end_date = start_date + chrono::Duration::days(7); + let start_dt = start_date.and_hms(0, 0, 0); + let end_dt = end_date.and_hms(0, 0, 0); + + let instances = if let Some(instances) = g.get_all_instances_range(start_dt, end_dt) { + instances + } else { + ui.horizontal(|ui| { + ui.spinner(); + ui.label("Loading…"); + }); + return; + }; + TableBuilder::new(ui) .column(egui_extras::Size::exact(50.0)) .columns(egui_extras::Size::remainder(), 7) @@ -18,17 +38,43 @@ impl Calendar { }); } }) - .body(|ui| { - ui.rows(50.0, 24, |h, mut ui| { - ui.col(|ui| { - ui.heading(&format!("{h:02}:00")); - }); - for d in 0..7 { + .body(|mut ui| { + let mut cols: [Vec<u64>; 7] = + [vec![], vec![], vec![], vec![], vec![], vec![], vec![]]; + for h in 0..24 { + ui.row(50.0, |mut ui| { ui.col(|ui| { - ui.label(&format!("day {d} at {h}:00")); + ui.heading(&format!("{h:02}:00")); }); - } - }) + for d in 0..7 { + let _col = &mut cols[d]; + let time = start_dt + Duration::days(d as i64) + Duration::hours(h); + let instances_here = + instances.iter().filter(|(_, r)| r.includes(&time)); + + ui.col(|ui| { + for (id, _) in instances_here { + g.tasks.get(id).unwrap(); + ui.label(&format!("{id}")); + } + }); + } + }) + } }) } } + +trait Includes<T> { + fn includes(&self, p: &T) -> bool; +} +impl Includes<NaiveDateTime> for Range<Option<NaiveDateTime>> { + fn includes(&self, p: &NaiveDateTime) -> bool { + match (&self.start, &self.end) { + (None, None) => false, + (None, Some(e)) => p < e, + (Some(s), None) => s <= p, + (Some(s), Some(e)) => s <= p && p < e, + } + } +} diff --git a/karlgui/src/views/edit.rs b/karlgui/src/views/edit.rs index 04146dd..0a8058c 100644 --- a/karlgui/src/views/edit.rs +++ b/karlgui/src/views/edit.rs @@ -15,7 +15,7 @@ pub struct ShowAndEdit { impl ShowAndEdit { pub fn ui(&mut self, ui: &mut Ui, g: &mut Globals) { - for t in &mut g.tasks { + for t in g.tasks.values_mut() { let edit = self.edit == Some(t.id); let changed = if edit { if ui.button("💾 Save").clicked() { |