Model list arrow flips when open; temperatures in a fixed order; bigger avatar; clock font, weight and digit width as settings; Cancel at the top of the event form, Esc cancels it
This commit is contained in:
+37
-12
@@ -349,12 +349,28 @@ fn sync_settings() -> (String, String, String, bool) {
|
||||
(agenda_settings::account(), agenda_settings::server(), agenda_settings::contacts_server(), agenda_settings::birthdays())
|
||||
}
|
||||
|
||||
// whether the card has a form to type into: then it keeps the keyboard and stays open
|
||||
// the sky now and whether it's day, once the weather is known (the home pill takes its colour from it)
|
||||
pub fn sky() -> Option<(parse::Sky, bool)> {
|
||||
Forecast::read().weather.as_ref().map(|weather| (parse::sky(weather.code), weather.is_day))
|
||||
}
|
||||
|
||||
// the event form closes without saving
|
||||
fn cancel() {
|
||||
Agenda::write().form = None;
|
||||
}
|
||||
|
||||
// Esc in the card: closes the event form if it's open (then true), else leaves it to the card
|
||||
pub fn escape() -> bool {
|
||||
let open = Agenda::read().form.is_some();
|
||||
|
||||
if open {
|
||||
cancel();
|
||||
}
|
||||
|
||||
open
|
||||
}
|
||||
|
||||
// whether the card has a form to type into: then it keeps the keyboard and stays open
|
||||
pub fn typing() -> bool {
|
||||
Agenda::read().form.is_some()
|
||||
}
|
||||
@@ -1202,18 +1218,18 @@ fn top_row(clock: &Clock, width: f32, shapes: &mut Vec<Box<dyn Shape>>) -> Box<d
|
||||
|
||||
// the big clock, and the weather beside it; `y` is where the row starts in the card
|
||||
fn middle_row(clock: &Clock, forecast: &Forecast, width: f32, today: i64, y: f32, shapes: &mut Vec<Box<dyn Shape>>) -> Box<dyn Widget> {
|
||||
let theme = theme::now();
|
||||
let gap = settings::gap();
|
||||
|
||||
let seconds_today = clock.now.rem_euclid(86_400);
|
||||
let (hour, minute, second) = (seconds_today / 3_600, seconds_today % 3_600 / 60, seconds_today % 60);
|
||||
let time = if settings::seconds() { format!("{hour:02}:{minute:02}:{second:02}") } else { format!("{hour:02}:{minute:02}") };
|
||||
|
||||
let clock_w = (settings::clock_size() * font::letter_width() * time.chars().count() as f32).min(width / 2.0);
|
||||
let letter = if settings::clock_letter_width() > 0.0 { settings::clock_letter_width() } else { font::letter_width() };
|
||||
let clock_w = (settings::clock_size() * letter * time.chars().count() as f32).min(width / 2.0);
|
||||
let weather_w = (width - clock_w - gap).max(0.0);
|
||||
let height = middle_h();
|
||||
|
||||
let big = Rectangle::new().width(clock_w).height(height).align_child(Start, Center).child(Text::new(time).size(settings::clock_size()).weight(Weight::Bold).color(theme.text).tight());
|
||||
let big = Rectangle::new().width(clock_w).height(height).align_child(Start, Center).child(clock_text(time));
|
||||
let weather = weather(forecast, weather_w, today, (clock_w + gap, y + (height - weather_h()) / 2.0), shapes);
|
||||
|
||||
Box::new(
|
||||
@@ -1224,6 +1240,14 @@ fn middle_row(clock: &Clock, forecast: &Forecast, width: f32, today: i64, y: f32
|
||||
)
|
||||
}
|
||||
|
||||
// the big clock's digits in its own font and weight
|
||||
fn clock_text(time: String) -> Text {
|
||||
let digits = Text::new(time).size(settings::clock_size()).weight(settings::clock_weight().min(1000) as u16).color(theme::now().text).tight();
|
||||
let family = settings::clock_font();
|
||||
|
||||
if family.trim().is_empty() { digits } else { digits.font(family.trim()) }
|
||||
}
|
||||
|
||||
// the weather now over the coming days, at `origin` in the card
|
||||
fn weather(forecast: &Forecast, width: f32, today: i64, origin: (f32, f32), shapes: &mut Vec<Box<dyn Shape>>) -> Rectangle {
|
||||
let theme = theme::now();
|
||||
@@ -1749,6 +1773,7 @@ fn event_form(agenda: &Agenda, form: &Form, width: f32, origin: (f32, f32), shap
|
||||
};
|
||||
|
||||
let mut top: Vec<Box<dyn Widget>> = vec![Box::new(Text::new(heading).size(text::heading()).weight(Weight::Bold).color(theme.text))];
|
||||
let mut actions: Vec<Box<dyn Widget>> = Vec::new();
|
||||
|
||||
if form.editing.is_some() {
|
||||
let words = match (form.confirm, series) {
|
||||
@@ -1758,11 +1783,16 @@ fn event_form(agenda: &Agenda, form: &Form, width: f32, origin: (f32, f32), shap
|
||||
};
|
||||
|
||||
let button = button_size();
|
||||
let at = (origin.0 + width - choice_width(words, button / 2.0 + 6.0), origin.1 + (pods::header_height() - button) / 2.0);
|
||||
let cancel_w = choice_width("Cancel", 0.0);
|
||||
let at = (origin.0 + width - cancel_w - gap - choice_width(words, button / 2.0 + 6.0), origin.1 + (pods::header_height() - button) / 2.0);
|
||||
|
||||
top.push(Box::new(icon_chip(words, form.confirm, Glyph::Trash, at, shapes, remove)));
|
||||
actions.push(Box::new(icon_chip(words, form.confirm, Glyph::Trash, at, shapes, remove)));
|
||||
}
|
||||
|
||||
// Cancel at the top, where it's always in sight (Esc does the same)
|
||||
actions.push(Box::new(pods::chip("Cancel", None, cancel)));
|
||||
top.push(Box::new(Row::new(actions).gap(gap).align(Center)));
|
||||
|
||||
let mut parts: Vec<Box<dyn Widget>> = vec![
|
||||
Box::new(Rectangle::new().width(width).height(pods::header_height()).child(Row::new(top).width(width).justify(SpaceBetween).align(Center))),
|
||||
Box::new(field(title, width)),
|
||||
@@ -1839,12 +1869,7 @@ fn event_form(agenda: &Agenda, form: &Form, width: f32, origin: (f32, f32), shap
|
||||
parts.push(Box::new(wrapped(problem.clone(), overlays::low_battery(), width)));
|
||||
}
|
||||
|
||||
let buttons: Vec<Box<dyn Widget>> = vec![
|
||||
Box::new(choice(if form.saving { "Saving…" } else { "Save" }, true, None, save)),
|
||||
Box::new(pods::chip("Cancel", None, || Agenda::write().form = None)),
|
||||
];
|
||||
|
||||
parts.push(Box::new(Row::new(buttons).gap(gap).align(Center)));
|
||||
parts.push(Box::new(choice(if form.saving { "Saving…" } else { "Save" }, true, None, save)));
|
||||
|
||||
Box::new(Rectangle::new().width(width).height(calendar_h()).child(Column::new(parts).gap(gap)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user