Remove IFC from the dashboard app

This commit is contained in:
Savanni D'Gerinel 2024-09-23 22:44:25 -04:00
parent 6cae7dbb0e
commit b175401965
7 changed files with 76 additions and 194 deletions

186
Cargo.lock generated
View File

@ -166,11 +166,11 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c"
dependencies = [ dependencies = [
"async-lock 3.3.0", "async-lock",
"async-task", "async-task",
"concurrent-queue", "concurrent-queue",
"fastrand 2.0.1", "fastrand",
"futures-lite 2.2.0", "futures-lite",
"slab", "slab",
] ]
@ -182,61 +182,32 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c"
dependencies = [ dependencies = [
"async-channel 2.1.1", "async-channel 2.1.1",
"async-executor", "async-executor",
"async-io 2.3.1", "async-io",
"async-lock 3.3.0", "async-lock",
"blocking", "blocking",
"futures-lite 2.2.0", "futures-lite",
"once_cell", "once_cell",
] ]
[[package]]
name = "async-io"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
dependencies = [
"async-lock 2.8.0",
"autocfg 1.1.0",
"cfg-if",
"concurrent-queue",
"futures-lite 1.13.0",
"log 0.4.20",
"parking",
"polling 2.8.0",
"rustix 0.37.27",
"slab",
"socket2 0.4.10",
"waker-fn",
]
[[package]] [[package]]
name = "async-io" name = "async-io"
version = "2.3.1" version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65"
dependencies = [ dependencies = [
"async-lock 3.3.0", "async-lock",
"cfg-if", "cfg-if",
"concurrent-queue", "concurrent-queue",
"futures-io", "futures-io",
"futures-lite 2.2.0", "futures-lite",
"parking", "parking",
"polling 3.4.0", "polling",
"rustix 0.38.28", "rustix",
"slab", "slab",
"tracing", "tracing",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "async-lock"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
dependencies = [
"event-listener 2.5.3",
]
[[package]] [[package]]
name = "async-lock" name = "async-lock"
version = "3.3.0" version = "3.3.0"
@ -250,19 +221,19 @@ dependencies = [
[[package]] [[package]]
name = "async-std" name = "async-std"
version = "1.12.0" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615"
dependencies = [ dependencies = [
"async-channel 1.9.0", "async-channel 1.9.0",
"async-global-executor", "async-global-executor",
"async-io 1.13.0", "async-io",
"async-lock 2.8.0", "async-lock",
"crossbeam-utils", "crossbeam-utils",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-io", "futures-io",
"futures-lite 1.13.0", "futures-lite",
"gloo-timers", "gloo-timers",
"kv-log-macro", "kv-log-macro",
"log 0.4.20", "log 0.4.20",
@ -493,11 +464,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118"
dependencies = [ dependencies = [
"async-channel 2.1.1", "async-channel 2.1.1",
"async-lock 3.3.0", "async-lock",
"async-task", "async-task",
"fastrand 2.0.1", "fastrand",
"futures-io", "futures-io",
"futures-lite 2.2.0", "futures-lite",
"piper", "piper",
"tracing", "tracing",
] ]
@ -956,6 +927,7 @@ dependencies = [
name = "dashboard" name = "dashboard"
version = "0.1.2" version = "0.1.2"
dependencies = [ dependencies = [
"async-std",
"cairo-rs", "cairo-rs",
"chrono", "chrono",
"fluent", "fluent",
@ -967,13 +939,11 @@ dependencies = [
"glib", "glib",
"glib-build-tools 0.18.0", "glib-build-tools 0.18.0",
"gtk4", "gtk4",
"ifc",
"lazy_static", "lazy_static",
"libadwaita", "libadwaita",
"memorycache", "memorycache",
"reqwest", "reqwest",
"serde 1.0.209", "serde 1.0.209",
"serde_derive",
"serde_json", "serde_json",
"tokio", "tokio",
"unic-langid", "unic-langid",
@ -1219,15 +1189,6 @@ dependencies = [
"zune-inflate", "zune-inflate",
] ]
[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.0.1" version = "2.0.1"
@ -1554,28 +1515,13 @@ version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-lite"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
dependencies = [
"fastrand 1.9.0",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]] [[package]]
name = "futures-lite" name = "futures-lite"
version = "2.2.0" version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba"
dependencies = [ dependencies = [
"fastrand 2.0.1", "fastrand",
"futures-core", "futures-core",
"futures-io", "futures-io",
"parking", "parking",
@ -1852,9 +1798,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]] [[package]]
name = "gloo-timers" name = "gloo-timers"
version = "0.2.6" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -2244,7 +2190,7 @@ dependencies = [
"httpdate", "httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"socket2 0.5.5", "socket2",
"tokio", "tokio",
"tower-service", "tower-service",
"tracing", "tracing",
@ -2381,15 +2327,6 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "intl-memoizer" name = "intl-memoizer"
version = "0.5.1" version = "0.5.1"
@ -2409,17 +2346,6 @@ dependencies = [
"unic-langid", "unic-langid",
] ]
[[package]]
name = "io-lifetimes"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.9.0" version = "2.9.0"
@ -2449,7 +2375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"rustix 0.38.28", "rustix",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -2647,12 +2573,6 @@ version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
[[package]]
name = "linux-raw-sys"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.12" version = "0.4.12"
@ -3346,7 +3266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4"
dependencies = [ dependencies = [
"atomic-waker", "atomic-waker",
"fastrand 2.0.1", "fastrand",
"futures-io", "futures-io",
] ]
@ -3439,22 +3359,6 @@ dependencies = [
"miniz_oxide 0.7.1", "miniz_oxide 0.7.1",
] ]
[[package]]
name = "polling"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
dependencies = [
"autocfg 1.1.0",
"bitflags 1.3.2",
"cfg-if",
"concurrent-queue",
"libc",
"log 0.4.20",
"pin-project-lite",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "polling" name = "polling"
version = "3.4.0" version = "3.4.0"
@ -3464,7 +3368,7 @@ dependencies = [
"cfg-if", "cfg-if",
"concurrent-queue", "concurrent-queue",
"pin-project-lite", "pin-project-lite",
"rustix 0.38.28", "rustix",
"tracing", "tracing",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -3997,20 +3901,6 @@ dependencies = [
"semver 1.0.20", "semver 1.0.20",
] ]
[[package]]
name = "rustix"
version = "0.37.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2"
dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys 0.3.8",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.28" version = "0.38.28"
@ -4020,7 +3910,7 @@ dependencies = [
"bitflags 2.4.1", "bitflags 2.4.1",
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.12", "linux-raw-sys",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -4315,16 +4205,6 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27207bb65232eda1f588cf46db2fee75c0808d557f6b3cf19a75f5d6d7c94df1" checksum = "27207bb65232eda1f588cf46db2fee75c0808d557f6b3cf19a75f5d6d7c94df1"
[[package]]
name = "socket2"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.5.5" version = "0.5.5"
@ -4675,9 +4555,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"fastrand 2.0.1", "fastrand",
"redox_syscall", "redox_syscall",
"rustix 0.38.28", "rustix",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -4817,7 +4697,7 @@ dependencies = [
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2 0.5.5", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -5287,12 +5167,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "waker-fn"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690"
[[package]] [[package]]
name = "want" name = "want"
version = "0.3.1" version = "0.3.1"

View File

@ -7,6 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
adw = { version = "0.5", package = "libadwaita", features = [ "v1_2" ] } adw = { version = "0.5", package = "libadwaita", features = [ "v1_2" ] }
async-std = { version = "1.13" }
cairo-rs = { version = "0.18" } cairo-rs = { version = "0.18" }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
fluent-ergonomics = { path = "../fluent-ergonomics/" } fluent-ergonomics = { path = "../fluent-ergonomics/" }
@ -17,13 +18,11 @@ gio = { version = "0.18" }
glib = { version = "0.18" } glib = { version = "0.18" }
gdk = { version = "0.7", package = "gdk4" } gdk = { version = "0.7", package = "gdk4" }
gtk = { version = "0.7", package = "gtk4" } gtk = { version = "0.7", package = "gtk4" }
ifc = { path = "../ifc/" }
lazy_static = { version = "1.4" } lazy_static = { version = "1.4" }
memorycache = { path = "../memorycache/" } memorycache = { path = "../memorycache/" }
reqwest = { version = "0.11", features = ["json"] } reqwest = { version = "0.11", features = ["json"] }
serde_derive = { version = "1" }
serde_json = { version = "1" } serde_json = { version = "1" }
serde = { version = "1" } serde = { version = "1", features = [ "derive" ] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
unic-langid = { version = "0.9" } unic-langid = { version = "0.9" }

View File

@ -1,21 +1,19 @@
use chrono::Datelike;
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use ifc::IFC;
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use chrono::NaiveDate;
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
pub struct DatePrivate { pub struct DatePrivate {
date: Rc<RefCell<IFC>>, date: Rc<RefCell<NaiveDate>>,
label: Rc<RefCell<gtk::Label>>, label: Rc<RefCell<gtk::Label>>,
} }
impl Default for DatePrivate { impl Default for DatePrivate {
fn default() -> Self { fn default() -> Self {
let date = chrono::Local::now().date_naive(); let date = chrono::Local::now().date_naive();
let year = date.year();
let date = date.with_year(year + 10000).unwrap();
Self { Self {
date: Rc::new(RefCell::new(IFC::from(date))), date: Rc::new(RefCell::new(date)),
label: Rc::new(RefCell::new(gtk::Label::new(None))), label: Rc::new(RefCell::new(gtk::Label::new(None))),
} }
} }
@ -52,19 +50,16 @@ impl Default for Date {
} }
impl Date { impl Date {
pub fn update_date(&self, date: IFC) { pub fn update_date(&self, date: NaiveDate) {
*self.imp().date.borrow_mut() = date; *self.imp().date.borrow_mut() = date;
self.redraw(); self.redraw();
} }
fn redraw(&self) { fn redraw(&self) {
let date = self.imp().date.borrow().clone(); let date = self.imp().date.borrow().clone();
self.imp().label.borrow_mut().set_text(&format!( self.imp()
"{:?}, {:?} {}, {}", .label
date.weekday(), .borrow_mut()
date.month(), .set_text(&date.format("%Y %B %d").to_string());
date.day(),
date.year()
));
} }
} }

View File

@ -4,7 +4,6 @@ use crate::{
}; };
use glib::Object; use glib::Object;
use gtk::{prelude::*, subclass::prelude::*}; use gtk::{prelude::*, subclass::prelude::*};
use ifc::IFC;
/* /*
#[derive(PartialEq)] #[derive(PartialEq)]
@ -59,19 +58,19 @@ impl Events {
pub fn set_events(&self, events: YearlyEvents, next_event: solstices::Event) { pub fn set_events(&self, events: YearlyEvents, next_event: solstices::Event) {
self.imp() self.imp()
.spring_equinox .spring_equinox
.update_date(IFC::from(events.spring_equinox.date_naive())); .update_date(events.spring_equinox.date_naive());
self.imp() self.imp()
.summer_solstice .summer_solstice
.update_date(IFC::from(events.summer_solstice.date_naive())); .update_date(events.summer_solstice.date_naive());
self.imp() self.imp()
.autumn_equinox .autumn_equinox
.update_date(IFC::from(events.autumn_equinox.date_naive())); .update_date(events.autumn_equinox.date_naive());
self.imp() self.imp()
.winter_solstice .winter_solstice
.update_date(IFC::from(events.winter_solstice.date_naive())); .update_date(events.winter_solstice.date_naive());
self.imp().spring_equinox.remove_css_class("highlight"); self.imp().spring_equinox.remove_css_class("highlight");
self.imp().summer_solstice.remove_css_class("highlight"); self.imp().summer_solstice.remove_css_class("highlight");

View File

@ -1,13 +1,13 @@
use chrono::{Datelike, Local, Utc};
use geo_types::{Latitude, Longitude};
use glib::Sender;
use gtk::prelude::*;
use ifc::IFC;
use std::{ use std::{
env, env,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use async_std::channel::Sender;
use chrono::{Datelike, Local, Utc};
use geo_types::{Latitude, Longitude};
use gtk::prelude::*;
mod app_window; mod app_window;
use app_window::ApplicationWindow; use app_window::ApplicationWindow;
@ -102,14 +102,18 @@ pub fn main() {
let now = Local::now(); let now = Local::now();
let state = State { let state = State {
date: IFC::from(now.date_naive().with_year(now.year() + 10000).unwrap()), date: now.date_naive(),
next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(), next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(),
events: EVENTS.yearly_events(now.year()).unwrap(), events: EVENTS.yearly_events(now.year()).unwrap(),
transit: Some(transit), transit: Some(transit),
}; };
if let Some(ref gtk_tx) = *core.tx.read().unwrap() { let gtk_tx = core.tx.read().unwrap().clone();
let _ = gtk_tx.send(Message::Refresh(state.clone()));
if let Some(gtk_tx) = gtk_tx {
println!("sending message");
let state = state.clone();
let _ = gtk_tx.send(Message::Refresh(state)).await;
std::thread::sleep(std::time::Duration::from_secs(60)); std::thread::sleep(std::time::Duration::from_secs(60));
} else { } else {
std::thread::sleep(std::time::Duration::from_secs(1)); std::thread::sleep(std::time::Duration::from_secs(1));
@ -119,14 +123,23 @@ pub fn main() {
}); });
app.connect_activate(move |app| { app.connect_activate(move |app| {
let (gtk_tx, gtk_rx) = let (gtk_tx, gtk_rx) = async_std::channel::unbounded();
gtk::glib::MainContext::channel::<Message>(gtk::glib::Priority::DEFAULT); // gtk::glib::MainContext::channel::<Message>(gtk::glib::Priority::DEFAULT);
*core.tx.write().unwrap() = Some(gtk_tx); *core.tx.write().unwrap() = Some(gtk_tx);
let window = ApplicationWindow::new(app); let window = ApplicationWindow::new(app);
window.window.present(); window.window.present();
glib::spawn_future_local(async move {
loop {
println!("spawn_future_local");
let Message::Refresh(state) = gtk_rx.recv().await.unwrap();
println!("Message::Refresh");
window.update_state(state);
}
});
/*
gtk_rx.attach(None, { gtk_rx.attach(None, {
let window = window.clone(); let window = window.clone();
move |msg| { move |msg| {
@ -136,6 +149,7 @@ pub fn main() {
glib::ControlFlow::Continue glib::ControlFlow::Continue
} }
}); });
*/
}); });
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();

View File

@ -1,7 +1,8 @@
use std::collections::HashMap;
use chrono::prelude::*; use chrono::prelude::*;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde_derive::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap;
// http://astropixels.com/ephemeris/soleq2001.html // http://astropixels.com/ephemeris/soleq2001.html
const SOLSTICE_TEXT: &str = " const SOLSTICE_TEXT: &str = "

View File

@ -2,11 +2,11 @@ use crate::{
solstices::{Event, YearlyEvents}, solstices::{Event, YearlyEvents},
soluna_client::SunMoon, soluna_client::SunMoon,
}; };
use ifc::IFC; use chrono::NaiveDate;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct State { pub struct State {
pub date: IFC, pub date: NaiveDate,
pub next_event: Event, pub next_event: Event,
pub events: YearlyEvents, pub events: YearlyEvents,
pub transit: Option<SunMoon>, pub transit: Option<SunMoon>,