Skip to main content

max / goingson

Clear got's lints, which nothing had ever run got and go-mcp are binaries nothing depends on, so the sweep's default-members selection never compiled them. Ten findings on first contact, all mechanical except two: the pane match names Pane::Timer rather than wildcarding it, so a pane added later has to say whether it scrolls, and build_timer takes its summary by slice.
Author: Max Johnson <me@maxj.phd> · 2026-08-12 17:06 UTC
Signed with PGP, not checked
Commit: 8f1a547d0c224a30dd654360bb96cd4917aee812
Parent: 533280b
2 files changed, +18 insertions, -19 deletions
@@ -436,6 +436,7 @@
436 436 /// - `.field { box-shadow }` -- makeover owns the resting and invalid bevels;
437 437 /// GO's are `.field--ghost` (deliberately borderless in toolbars) and the
438 438 /// `:focus` ring on an invalid field, which makeover draws no arm for.
439 + ///
439 440 /// The caret's two entries were here until makeover-webview 0.31.0, which emits
440 441 /// the leading space and the reserved box itself. Both of GO's rules are gone
441 442 /// with them: a reviewed pairing is a claim about who owns a property, and it
@@ -304,7 +304,7 @@
304 304 } = load(db, self.ready_only)?;
305 305 self.projects = build_projects(&projects, &tasks);
306 306 self.events = build_events(events);
307 - self.timer = build_timer(active_timer, time_summary, sessions, &tasks);
307 + self.timer = build_timer(active_timer, &time_summary, sessions, &tasks);
308 308 self.contacts = build_contacts(contacts);
309 309 self.rows = build_board(projects, ready.as_deref().unwrap_or(&tasks));
310 310 let open = self
@@ -331,7 +331,9 @@
331 331 Pane::Projects => (&mut self.proj_state, self.projects.len()),
332 332 Pane::Events => (&mut self.event_state, self.events.len()),
333 333 Pane::Contacts => (&mut self.contact_state, self.contacts.len()),
334 - _ => return,
334 + // Named rather than a wildcard, so a pane added later has to come
335 + // here and say whether it scrolls instead of silently not doing it.
336 + Pane::Timer => return,
335 337 };
336 338 if len == 0 {
337 339 return;
@@ -423,11 +425,10 @@
423 425 /// so the Timer pane buckets time exactly as the Day view does.
424 426 fn local_midnight_utc(date: NaiveDate) -> chrono::DateTime<Utc> {
425 427 let naive = date.and_hms_opt(0, 0, 0).expect("midnight is always valid");
426 - Local
427 - .from_local_datetime(&naive)
428 - .earliest()
429 - .map(|dt| dt.with_timezone(&Utc))
430 - .unwrap_or_else(|| Utc.from_utc_datetime(&naive))
428 + Local.from_local_datetime(&naive).earliest().map_or_else(
429 + || Utc.from_utc_datetime(&naive),
430 + |dt| dt.with_timezone(&Utc),
431 + )
431 432 }
432 433
433 434 fn is_open(t: &Task) -> bool {
@@ -551,7 +552,7 @@
551 552 /// session's task id back to its description and project for display.
552 553 fn build_timer(
553 554 active: Option<(TimeSession, String)>,
554 - summary: Vec<TimeTrackingSummary>,
555 + summary: &[TimeTrackingSummary],
555 556 sessions: Vec<TimeSession>,
556 557 tasks: &[Task],
557 558 ) -> TimerView {
@@ -564,7 +565,7 @@
564 565 // the desktop Day view does. "Today" is matched on the UTC date the query
565 566 // buckets by, same as the app.
566 567 let today = Utc::now().format("%Y-%m-%d").to_string();
567 - let panel = roll_up_time_summary(&summary, &today);
568 + let panel = roll_up_time_summary(summary, &today);
568 569
569 570 // Most recent finished sessions, newest first.
570 571 let mut finished: Vec<TimeSession> = sessions
@@ -583,9 +584,7 @@
583 584 .with_timezone(&Local)
584 585 .format("%b %-d")
585 586 .to_string(),
586 - task: task
587 - .map(|t| t.description.clone())
588 - .unwrap_or_else(|| "(unknown task)".to_string()),
587 + task: task.map_or_else(|| "(unknown task)".to_string(), |t| t.description.clone()),
589 588 project: task.and_then(|t| t.project_name.clone()),
590 589 minutes: s.duration_minutes.unwrap_or_else(|| s.elapsed_minutes()),
591 590 }
@@ -822,7 +821,7 @@
822 821 }
823 822 }
824 823
825 - fn row_item<'a>(p: Theme, row: &'a Row) -> ListItem<'a> {
824 + fn row_item(p: Theme, row: &Row) -> ListItem<'_> {
826 825 match row {
827 826 Row::Header { name, open } => {
828 827 let line = Line::from(vec![
@@ -900,7 +899,7 @@
900 899 }
901 900 }
902 901
903 - fn project_item<'a>(p: Theme, row: &'a ProjectRow) -> ListItem<'a> {
902 + fn project_item(p: Theme, row: &ProjectRow) -> ListItem<'_> {
904 903 let status_color = match row.status {
905 904 ProjectStatus::Active => p.status_success,
906 905 ProjectStatus::OnHold => p.status_warning,
@@ -935,7 +934,7 @@
935 934 ListItem::new(line)
936 935 }
937 936
938 - fn event_item<'a>(p: Theme, row: &'a EventRow) -> ListItem<'a> {
937 + fn event_item(p: Theme, row: &EventRow) -> ListItem<'_> {
939 938 match row {
940 939 EventRow::DayHeader { label, count } => {
941 940 let line = Line::from(vec![
@@ -981,7 +980,7 @@
981 980 }
982 981 }
983 982
984 - fn contact_item<'a>(p: Theme, c: &'a Contact) -> ListItem<'a> {
983 + fn contact_item(p: Theme, c: &Contact) -> ListItem<'_> {
985 984 let mut spans = vec![
986 985 Span::raw(" "),
987 986 Span::styled(
@@ -1156,9 +1155,8 @@
1156 1155 let base = home.join("Library/Application Support");
1157 1156
1158 1157 #[cfg(not(target_os = "macos"))]
1159 - let base = std::env::var_os("XDG_DATA_HOME")
1160 - .map(PathBuf::from)
1161 - .unwrap_or_else(|| home.join(".local/share"));
1158 + let base =
1159 + std::env::var_os("XDG_DATA_HOME").map_or_else(|| home.join(".local/share"), PathBuf::from);
1162 1160
1163 1161 Some(base.join("com.goingson.app").join("goingson.db"))
1164 1162 }