Compare commits

...

3 Commits

8 changed files with 102 additions and 29 deletions

35
Cargo.lock generated
View File

@ -335,12 +335,14 @@ dependencies = [
"fluent", "fluent",
"fluent-ergonomics", "fluent-ergonomics",
"futures", "futures",
"gdk4",
"geo-types", "geo-types",
"gio", "gio",
"glib", "glib",
"gtk4", "gtk4",
"ifc", "ifc",
"lazy_static", "lazy_static",
"libadwaita",
"memorycache", "memorycache",
"reqwest", "reqwest",
"serde", "serde",
@ -1263,6 +1265,39 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libadwaita"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab9c0843f9f23ff25634df2743690c3a1faffe0a190e60c490878517eb81abf"
dependencies = [
"bitflags 1.3.2",
"gdk-pixbuf",
"gdk4",
"gio",
"glib",
"gtk4",
"libadwaita-sys",
"libc",
"pango",
]
[[package]]
name = "libadwaita-sys"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4231cb2499a9f0c4cdfa4885414b33e39901ddcac61150bc0bb4ff8a57ede404"
dependencies = [
"gdk4-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"gtk4-sys",
"libc",
"pango-sys",
"system-deps",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.147" version = "0.2.147"

View File

@ -6,6 +6,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
adw = { version = "0.4", package = "libadwaita", features = [ "v1_2" ] }
cairo-rs = { version = "0.17" } cairo-rs = { version = "0.17" }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
fluent-ergonomics = { path = "../fluent-ergonomics/" } fluent-ergonomics = { path = "../fluent-ergonomics/" }
@ -14,6 +15,7 @@ futures = { version = "0.3" }
geo-types = { path = "../geo-types/" } geo-types = { path = "../geo-types/" }
gio = { version = "0.17" } gio = { version = "0.17" }
glib = { version = "0.17" } glib = { version = "0.17" }
gdk = { version = "0.6", package = "gdk4" }
gtk = { version = "0.6", package = "gtk4" } gtk = { version = "0.6", package = "gtk4" }
ifc = { path = "../ifc/" } ifc = { path = "../ifc/" }
lazy_static = { version = "1.4" } lazy_static = { version = "1.4" }

View File

@ -2,19 +2,20 @@ use crate::{
components::{Date, TransitClock}, components::{Date, TransitClock},
types::State, types::State,
}; };
use adw::prelude::AdwApplicationWindowExt;
use gtk::prelude::*; use gtk::prelude::*;
#[derive(Clone)] #[derive(Clone)]
pub struct ApplicationWindow { pub struct ApplicationWindow {
pub window: gtk::ApplicationWindow, pub window: adw::ApplicationWindow,
pub date_label: Date, pub date_label: Date,
pub next_event: gtk::Label, pub next_event: gtk::Label,
pub transit_clock: TransitClock, pub transit_clock: TransitClock,
} }
impl ApplicationWindow { impl ApplicationWindow {
pub fn new(app: &gtk::Application) -> Self { pub fn new(app: &adw::Application) -> Self {
let window = gtk::ApplicationWindow::new(app); let window = adw::ApplicationWindow::new(app);
let layout = gtk::Box::builder() let layout = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical) .orientation(gtk::Orientation::Vertical)
@ -38,7 +39,7 @@ impl ApplicationWindow {
let transit_clock = TransitClock::new(); let transit_clock = TransitClock::new();
layout.append(&transit_clock); layout.append(&transit_clock);
window.set_child(Some(&layout)); window.set_content(Some(&layout));
Self { Self {
window, window,

View File

@ -43,6 +43,7 @@ impl TransitClock {
s.set_draw_func({ s.set_draw_func({
let s = s.clone(); let s = s.clone();
move |_, context, width, height| { move |_, context, width, height| {
let style_context = WidgetExt::style_context(&s);
let center_x = width as f64 / 2.; let center_x = width as f64 / 2.;
let center_y = height as f64 / 2.; let center_y = height as f64 / 2.;
let radius = width.min(height) as f64 / 2. * 0.9; let radius = width.min(height) as f64 / 2. * 0.9;
@ -51,20 +52,35 @@ impl TransitClock {
let sunrise = info.sunrise - NaiveTime::from_hms_opt(0, 0, 0).unwrap(); let sunrise = info.sunrise - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
let sunset = info.sunset - NaiveTime::from_hms_opt(0, 0, 0).unwrap(); let sunset = info.sunset - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
PieChart::new() let night_color = style_context.lookup_color("dark_5").unwrap();
let day_color = style_context.lookup_color("blue_1").unwrap();
PieChart::new(&style_context)
.center(center_x, center_y) .center(center_x, center_y)
.radius(radius) .radius(radius)
.rotation(-PI / 2.) .rotation(-PI / 2.)
.wedges( .wedges(
vec![Wedge { vec![
Wedge {
start_angle: (PI * 2.) * sunset.num_seconds() as f64 / full_day, start_angle: (PI * 2.) * sunset.num_seconds() as f64 / full_day,
end_angle: (PI * 2.) * sunrise.num_seconds() as f64 / full_day, end_angle: (PI * 2.) * sunrise.num_seconds() as f64 / full_day,
color: Color { color: Color {
r: 0.1, r: night_color.red() as f64,
g: 0.1, g: night_color.green() as f64,
b: 0.8, b: night_color.blue() as f64,
}, },
}] },
Wedge {
start_angle: (PI * 2.) * sunrise.num_seconds() as f64
/ full_day,
end_angle: (PI * 2.) * sunset.num_seconds() as f64 / full_day,
color: Color {
r: day_color.red() as f64,
g: day_color.green() as f64,
b: day_color.blue() as f64,
},
},
]
.into_iter(), .into_iter(),
) )
.draw(context); .draw(context);

View File

@ -1,4 +1,5 @@
use cairo::Context; use cairo::Context;
use gtk::{gdk::RGBA, prelude::*, StyleContext};
use std::f64::consts::PI; use std::f64::consts::PI;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -21,16 +22,19 @@ pub struct PieChart {
center_x: f64, center_x: f64,
center_y: f64, center_y: f64,
radius: f64, radius: f64,
border_color: RGBA,
} }
impl PieChart { impl PieChart {
pub fn new() -> Self { pub fn new(style_context: &StyleContext) -> Self {
Self { Self {
rotation: 0., rotation: 0.,
wedges: vec![], wedges: vec![],
center_x: 0., center_x: 0.,
center_y: 0., center_y: 0.,
radius: 0., radius: 0.,
border_color: style_context.lookup_color("theme_fg_color").unwrap(),
} }
} }
@ -81,7 +85,11 @@ impl PieChart {
}, },
); );
context.set_source_rgb(1., 1., 1.); context.set_source_rgb(
self.border_color.red() as f64,
self.border_color.green() as f64,
self.border_color.blue() as f64,
);
context.arc(self.center_x, self.center_y, self.radius, 0., 2. * PI); context.arc(self.center_x, self.center_y, self.radius, 0., 2. * PI);
let _ = context.stroke(); let _ = context.stroke();
} }

View File

@ -70,7 +70,7 @@ pub struct Core {
} }
pub fn main() { pub fn main() {
let app = gtk::Application::builder() let app = adw::Application::builder()
.application_id("com.luminescent-dreams.dashboard") .application_id("com.luminescent-dreams.dashboard")
.resource_base_path("/com/luminescent-dreams/dashboard") .resource_base_path("/com/luminescent-dreams/dashboard")
.build(); .build();
@ -94,8 +94,9 @@ pub fn main() {
async move { async move {
let soluna_client = SolunaClient::new(); let soluna_client = SolunaClient::new();
loop {
let transit = soluna_client let transit = soluna_client
.request(latitude, longitude, Local::now()) .request(latitude.clone(), longitude.clone(), Local::now())
.await; .await;
let now = Local::now(); let now = Local::now();
@ -104,11 +105,11 @@ pub fn main() {
next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(), next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(),
transit: Some(transit), transit: Some(transit),
}; };
loop {
if let Some(ref gtk_tx) = *core.tx.read().unwrap() { if let Some(ref gtk_tx) = *core.tx.read().unwrap() {
let _ = gtk_tx.send(Message::Refresh(state.clone())); let _ = gtk_tx.send(Message::Refresh(state.clone()));
} }
std::thread::sleep(std::time::Duration::from_secs(300)); std::thread::sleep(std::time::Duration::from_secs(60));
} }
} }
}); });

View File

@ -1,7 +1,7 @@
// 41.78, -71.41 // 41.78, -71.41
// https://api.solunar.org/solunar/41.78,-71.41,20211029,-4 // https://api.solunar.org/solunar/41.78,-71.41,20211029,-4
use chrono::{DateTime, Duration, NaiveTime, Offset, TimeZone, Utc}; use chrono::{DateTime, Duration, Local, NaiveTime, Offset, TimeZone, Timelike, Utc};
use geo_types::{Latitude, Longitude}; use geo_types::{Latitude, Longitude};
use memorycache::MemoryCache; use memorycache::MemoryCache;
use reqwest; use reqwest;
@ -111,7 +111,16 @@ impl SolunaClient {
.and_then(|header| header.to_str().ok()) .and_then(|header| header.to_str().ok())
.and_then(|expiration| DateTime::parse_from_rfc2822(expiration).ok()) .and_then(|expiration| DateTime::parse_from_rfc2822(expiration).ok())
.map(|dt_local| DateTime::<Utc>::from(dt_local)) .map(|dt_local| DateTime::<Utc>::from(dt_local))
.unwrap_or(Utc::now() + Duration::seconds(3600)); .unwrap_or(
Local::now()
.with_hour(0)
.and_then(|dt| dt.with_minute(0))
.and_then(|dt| dt.with_second(0))
.and_then(|dt| dt.with_nanosecond(0))
.map(|dt| dt.with_timezone(&Utc))
.unwrap()
+ Duration::days(1),
);
let soluna: SunMoonJs = response.json().await.unwrap(); let soluna: SunMoonJs = response.json().await.unwrap();
(expiration, soluna) (expiration, soluna)
}) })

View File

@ -23,6 +23,7 @@
pkgs.mkShell { pkgs.mkShell {
name = "ld-tools-devshell"; name = "ld-tools-devshell";
buildInputs = [ buildInputs = [
pkgs.libadwaita
pkgs.clang pkgs.clang
pkgs.entr pkgs.entr
pkgs.glade pkgs.glade