Start working on a moon phase clock
Some checks failed
Monorepo build / test-all (push) Failing after 6s
Monorepo build / build-flake (push) Failing after 6s

This commit was merged in pull request #438.
This commit is contained in:
2026-08-31 10:06:21 -04:00
parent f48d09f681
commit 6e8aa13ed0
7 changed files with 116 additions and 11 deletions

1
Cargo.lock generated
View File

@@ -857,6 +857,7 @@ dependencies = [
"reqwest",
"serde",
"serde_json",
"thiserror 2.0.19",
"tokio",
"unic-langid",
]

View File

@@ -27,6 +27,7 @@ tokio = { version = "1", features = ["full"] }
unic-langid = { version = "0.9" }
async-trait.workspace = true
jiff.workspace = true
thiserror.workspace = true
[build-dependencies]
glib-build-tools = "0.18"

View File

@@ -1,5 +1,5 @@
use crate::{
components::{Date, Events, SunClock, TransitCard},
components::{Date, Events, MoonClock, SunClock, TransitCard},
types::State,
};
use adw::prelude::AdwApplicationWindowExt;
@@ -14,7 +14,8 @@ pub struct ApplicationWindow {
pub sun_card: TransitCard,
pub moon_card: TransitCard,
pub sun_clock: SunClock,
pub moon_clock: SunClock,
pub moon_clock: MoonClock,
pub moon_phase: gtk::Label,
}
impl ApplicationWindow {
@@ -51,7 +52,7 @@ impl ApplicationWindow {
let events = Events::default();
layout.append(&events);
let (sun_card, moon_card) = {
let (sun_card, moon_card, moon_phase) = {
let row = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.hexpand(true)
@@ -60,14 +61,23 @@ impl ApplicationWindow {
.build();
let sun_card = TransitCard::default();
sun_card.set_hexpand(true);
sun_card.set_vexpand(false);
row.append(&sun_card);
let moon_section = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.build();
let moon_card = TransitCard::default();
moon_card.set_hexpand(true);
row.append(&moon_card);
moon_section.append(&moon_card);
let phase = gtk::Label::builder().build();
moon_section.append(&phase);
row.append(&moon_section);
layout.append(&row);
(sun_card, moon_card)
(sun_card, moon_card, phase)
};
let (sun_clock, moon_clock) = {
@@ -79,7 +89,7 @@ impl ApplicationWindow {
let sun_clock = SunClock::default();
row.append(&sun_clock);
let moon_clock = SunClock::default();
let moon_clock = MoonClock::default();
row.append(&moon_clock);
layout.append(&row);
@@ -96,6 +106,7 @@ impl ApplicationWindow {
moon_card,
sun_clock,
moon_clock,
moon_phase,
}
}
@@ -104,11 +115,13 @@ impl ApplicationWindow {
self.events.set_events(state.events, state.next_event);
if let Some(transit) = state.sun_stats {
self.sun_card.update_transit(transit.clone().into());
self.sun_clock.update_transit(transit.clone().into());
self.moon_clock.update_transit(transit.into());
self.sun_clock.update_transit(transit.into());
}
if let Some(transit) = state.moon_stats {
println!("transit phase: {}", transit.phase);
self.moon_card.update_transit(transit.clone().into());
self.moon_clock.update_transit(transit.clone().into());
self.moon_phase.set_text(&format!("{}", transit.phase));
}
}
}

View File

@@ -8,4 +8,4 @@ mod label;
pub use label::Label;
mod transit;
pub use transit::{SunClock, TransitCard};
pub use transit::{MoonClock, SunClock, TransitCard};

View File

@@ -129,7 +129,6 @@ impl Default for SunClock {
.second(0)
.build()
.unwrap();
println!("today: {:?}", today);
#[allow(deprecated)]
let style_context = WidgetExt::style_context(&s);
@@ -198,3 +197,57 @@ impl SunClock {
self.queue_draw();
}
}
#[derive(Default)]
pub struct MoonClockPrivate {
info: Rc<RefCell<Option<MoonStats>>>,
}
#[glib::object_subclass]
impl ObjectSubclass for MoonClockPrivate {
const NAME: &'static str = "MoonClock";
type Type = MoonClock;
type ParentType = gtk::DrawingArea;
}
impl ObjectImpl for MoonClockPrivate {}
impl WidgetImpl for MoonClockPrivate {}
impl DrawingAreaImpl for MoonClockPrivate {}
glib::wrapper! {
pub struct MoonClock(ObjectSubclass<MoonClockPrivate>) @extends gtk::DrawingArea, gtk::Widget;
}
impl Default for MoonClock {
fn default() -> Self {
let s: Self = Object::builder().build();
s.set_width_request(500);
s.set_height_request(500);
s.set_draw_func({
let s = s.clone();
move |_, context, width, height| {
#[allow(deprecated)]
let style_context = WidgetExt::style_context(&s);
let center_x = width as f64 / 2.;
let center_y = height as f64 / 2.;
let radius = width.min(height) as f64 / 2. * 0.9;
if let Some(ref info) = *s.imp().info.borrow() {
context.set_source_rgb(0., 0., 0.);
context.arc(center_x, center_y, radius, 0., 2. * PI);
let _ = context.fill();
}
}
});
s
}
}
impl MoonClock {
pub fn update_transit(&self, transit_info: MoonStats) {
*self.imp().info.borrow_mut() = Some(transit_info);
self.queue_draw();
}
}

View File

@@ -1,6 +1,7 @@
use async_trait::async_trait;
use chrono::NaiveTime;
use geo_types::{Latitude, Longitude};
use thiserror::Error;
mod mock_client;
use jiff::Timestamp;
@@ -41,3 +42,39 @@ pub enum LunarPhase {
LastQuarter,
WaningCrescent,
}
impl std::fmt::Display for LunarPhase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
LunarPhase::NewMoon => f.write_str("New Moon"),
LunarPhase::WaxingCrescent => f.write_str("Waxing Crescent"),
LunarPhase::FirstQuarter => f.write_str("First Quarter"),
LunarPhase::WaxingGibbous => f.write_str("Waxing Gibbous"),
LunarPhase::FullMoon => f.write_str("Full Moon"),
LunarPhase::WaningGibbous => f.write_str("Waning Gibbous"),
LunarPhase::LastQuarter => f.write_str("Last Quarter"),
LunarPhase::WaningCrescent => f.write_str("Waning Crescent"),
}
}
}
#[derive(Debug, Error)]
#[error("Error parsing the moon phase")]
pub struct LunarPhaseParseError;
impl std::str::FromStr for LunarPhase {
type Err = LunarPhaseParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"NewMoon" => Ok(LunarPhase::NewMoon),
"Waxing Crescent" => Ok(LunarPhase::WaxingCrescent),
"First Quarter" => Ok(LunarPhase::FirstQuarter),
"Waxing Gibbous" => Ok(LunarPhase::WaxingGibbous),
"Full Moon" => Ok(LunarPhase::FullMoon),
"Waning Gibbous" => Ok(LunarPhase::WaningGibbous),
"Last Quarter" => Ok(LunarPhase::LastQuarter),
"Waning Crescent" => Ok(LunarPhase::WaningCrescent),
_ => Err(LunarPhaseParseError),
}
}
}

View File

@@ -65,7 +65,7 @@ impl SunriseSunsetClient {
let moon_stats = MoonStats {
rise: body.moonrise.map(|t| t.parse().unwrap()),
set: body.moonset.map(|t| t.parse().unwrap()),
phase: LunarPhase::NewMoon,
phase: body.moon_phase.parse().unwrap(),
};
let new_cache = Cache {