Skip to content

Commit 82f72c8

Browse files
VirInvictusclaude
andcommitted
v0.6.14 — Patch D reframed: visible row separators + recurrence icon
The original Patch D plan was "day-band grouping in the main task list." Walking through it surfaced a scope problem: Today is single-day by definition (every row would read "Today"), Logbook already has day-bands (Slice C2), and Agenda is the explicit "everything across days" view. Day-band grouping inside Today / Inbox / Anytime would duplicate Agenda; the only sensible target was Upcoming, which is a single-view scope. Reframed Patch D as two smaller polish wins that address what the screenshot actually showed: - Visible row separators. GtkListView's show-separators=true was on, but the default separator on dark themes was so faint the rows read as a wall of text. v0.6.14 adds a 1px @borders-tinted bottom border to each task row, constrained by :has(.atrium-task-row) so kanban / agenda card rows don't inherit. - Recurrence icon. Tasks with a non-NULL repeat_rule now show a small view-refresh-symbolic at the row's right edge with a "Repeating task" tooltip. Derived from data — the original screenshot bug was the fixture shoving emoji into title strings (#9a, fixed in Patch A); the icon now reads correctness from repeat_rule regardless of what the title says. Code: - atrium/src/ui/task_object.rs — new `repeating: bool` glib property on AtriumTask, computed at construction and on refresh_from from `task.repeat_rule.is_some()`. - atrium/src/ui/task_list.rs — row factory `setup` appends a gtk::Image after the deadline pill (preserves the existing next_sibling chain so other bind logic stays unchanged). `bind` sets initial visibility from the property and connects connect_repeating_notify for live updates. Handler stashed under atrium-repeating-handler and disconnected on unbind. - data/style.css — .atrium-task-repeating styling (smaller icon size, dim opacity, picks up the row-state tint when overdue or today). Plus the row-separator rule constrained by :has(.atrium-task-row) so it only affects the main task list. Closes the four-patch screenshot-cleanup arc: - v0.6.11 Patch A — eight quick wins - v0.6.12 Patch B — state-aware row treatment - v0.6.13 Patch C — Inspector Notes placeholder - v0.6.14 Patch D — row separators + recurrence icon VERSION / Cargo.toml / patchnotes / AppStream metainfo bump to 0.6.14. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 67bca87 commit 82f72c8

8 files changed

Lines changed: 146 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ default-members = ["atrium"]
44
resolver = "2"
55

66
[workspace.package]
7-
version = "0.6.13"
7+
version = "0.6.14"
88
edition = "2024"
99
license = "MIT"
1010
authors = ["Brandon LaRocque"]

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.6.13
1+
0.6.14

atrium/src/ui/task_list.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,12 +325,22 @@ where
325325
deadline.add_css_class("atrium-task-deadline");
326326
deadline.add_css_class("dim-label");
327327

328+
// v0.6.14 — small recurrence icon for tasks whose
329+
// `repeat_rule` is set. Lives at the tail of the row so the
330+
// existing next_sibling chain in `bind` doesn't shift.
331+
let repeat_icon = gtk::Image::from_icon_name("view-refresh-symbolic");
332+
repeat_icon.set_tooltip_text(Some("Repeating task"));
333+
repeat_icon.set_visible(false);
334+
repeat_icon.add_css_class("atrium-task-repeating");
335+
repeat_icon.add_css_class("dim-label");
336+
328337
row.append(&check);
329338
row.append(&title_stack);
330339
row.append(&tags);
331340
row.append(&context);
332341
row.append(&schedule);
333342
row.append(&deadline);
343+
row.append(&repeat_icon);
334344

335345
item.set_child(Some(&row));
336346
});
@@ -376,6 +386,10 @@ where
376386
.next_sibling()
377387
.and_downcast::<gtk::Label>()
378388
.expect("deadline");
389+
let repeat_icon = deadline
390+
.next_sibling()
391+
.and_downcast::<gtk::Image>()
392+
.expect("repeat icon");
379393

380394
// Title bindings: model → display label is one-way. The
381395
// entry is populated from the label only when edit mode
@@ -474,6 +488,16 @@ where
474488
}
475489
});
476490

491+
// v0.6.14 — show the repeat icon for tasks whose
492+
// `repeat_rule` is set. Initial visibility from the
493+
// property; notify keeps it in sync when the user adds /
494+
// removes a repeat rule via the Inspector.
495+
repeat_icon.set_visible(task.repeating());
496+
let repeat_icon_for_notify = repeat_icon.clone();
497+
let repeating_handler = task.connect_repeating_notify(move |t| {
498+
repeat_icon_for_notify.set_visible(t.repeating());
499+
});
500+
477501
// Phase 11 — .queued CSS class dims sequential-project
478502
// rows past the first incomplete one. Window populates the
479503
// `queued` property on each AtriumTask before it lands in
@@ -592,6 +616,7 @@ where
592616
row.set_data("atrium-context-handler", context_handler);
593617
row.set_data("atrium-area-color-handler", area_color_handler);
594618
row.set_data("atrium-row-state-handler", state_handler);
619+
row.set_data("atrium-repeating-handler", repeating_handler);
595620
row.set_data("atrium-task-obj", task.clone());
596621
row.set_data("atrium-check", check.clone());
597622
row.set_data("atrium-title-stack", title_stack.clone());
@@ -798,11 +823,17 @@ where
798823
task.disconnect(handler);
799824
}
800825
if let (Some(task), Some(handler)) = (
801-
task_obj,
826+
task_obj.clone(),
802827
row.steal_data::<glib::SignalHandlerId>("atrium-row-state-handler"),
803828
) {
804829
task.disconnect(handler);
805830
}
831+
if let (Some(task), Some(handler)) = (
832+
task_obj,
833+
row.steal_data::<glib::SignalHandlerId>("atrium-repeating-handler"),
834+
) {
835+
task.disconnect(handler);
836+
}
806837
// Title entry: disconnect the activate + focus-leave
807838
// handlers, drop the controllers, drop the cached
808839
// widget references. The next bind builds fresh.

atrium/src/ui/task_object.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ mod imp {
7070
/// into a CSS class. See `classify_row_state`.
7171
#[property(get, set)]
7272
pub row_state: RefCell<String>,
73+
/// True when the underlying task has a non-NULL repeat_rule.
74+
/// The row factory shows a small ⟳ icon to the right of the
75+
/// title for repeating tasks (v0.6.14, Patch D polish).
76+
#[property(get, set)]
77+
pub repeating: Cell<bool>,
7378
}
7479

7580
#[glib::object_subclass]
@@ -109,6 +114,7 @@ impl AtriumTask {
109114
obj.set_position(task.position);
110115
obj.set_tag_names_csv(format_tag_names(pills));
111116
obj.set_row_state(classify_row_state(task));
117+
obj.set_repeating(task.repeat_rule.is_some());
112118
obj
113119
}
114120

@@ -140,6 +146,10 @@ impl AtriumTask {
140146
if self.row_state() != new_state {
141147
self.set_row_state(new_state);
142148
}
149+
let new_repeating = task.repeat_rule.is_some();
150+
if self.repeating() != new_repeating {
151+
self.set_repeating(new_repeating);
152+
}
143153
}
144154
}
145155

data/io.github.virinvictus.atrium.metainfo.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,22 @@
9090
capture against. Phase 9 task. -->
9191

9292
<releases>
93+
<release version="0.6.14" date="2026-05-08">
94+
<description>
95+
<p>Patch D, reframed — visible row separators and a
96+
derived recurrence icon. The original "day-band
97+
grouping in the main task list" plan didn't fit
98+
any view well (Today is single-day; Logbook and
99+
Agenda already group); reframed as two smaller
100+
polish wins. Row separators get a 1px
101+
@borders-tinted bottom border so the rows read as
102+
distinct items rather than a wall of text. Tasks
103+
with a repeat_rule show a small refresh icon at
104+
the row's right edge — derived from data, not from
105+
title text. Closes the four-patch
106+
screenshot-cleanup arc that started at v0.6.11.</p>
107+
</description>
108+
</release>
93109
<release version="0.6.13" date="2026-05-08">
94110
<description>
95111
<p>Patch C — Inspector Notes placeholder. The Notes

data/style.css

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,3 +657,40 @@ listview.navigation-sidebar > row:selected,
657657
color: inherit;
658658
font-weight: inherit;
659659
}
660+
661+
/* ============================================================================
662+
* v0.6.14 — recurrence icon + visible row separators.
663+
* ============================================================================ */
664+
665+
/* The repeat icon at the tail of a row. Smaller than a regular
666+
* symbolic icon and quiet — it's a state indicator, not an action.
667+
* Matches the dim-label colour by default; gains the row-state tint
668+
* when the task is overdue or today (mirrors the date-pill pattern). */
669+
.atrium-task-repeating {
670+
-gtk-icon-size: 14px;
671+
opacity: 0.65;
672+
margin-start: 4px;
673+
}
674+
.atrium-task-row-overdue .atrium-task-repeating {
675+
color: alpha(@error_color, 0.85);
676+
opacity: 0.9;
677+
}
678+
.atrium-task-row-today .atrium-task-repeating {
679+
color: alpha(@warning_color, 0.85);
680+
opacity: 0.9;
681+
}
682+
683+
/* GtkListView's `show-separators=true` is on (window.ui), but the
684+
* default separator on dark themes is so faint it reads as "no
685+
* separator at all" (the user's screenshot showed the rows running
686+
* together as a wall of text). Bump the separator's contrast a hair
687+
* so it reads as a real divider without becoming a heavy gridline.
688+
* We target the listview in `task_list_view` specifically by
689+
* constraining to rows that contain our `.atrium-task-row` Box —
690+
* otherwise the kanban / agenda card rows would inherit too. */
691+
listview > row:has(.atrium-task-row) {
692+
border-bottom: 1px solid alpha(@borders, 0.3);
693+
}
694+
listview > row:has(.atrium-task-row):last-child {
695+
border-bottom: none;
696+
}

patchnotes.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,50 @@
11
# Atrium — Patch Notes
22

3+
## v0.6.14 (2026-05-08) — Patch D (reframed): visible row separators + recurrence icon
4+
5+
The original Patch D was "day-band grouping in the main task list."
6+
Walking through the implementation surfaced a scope problem: the
7+
Today list is a single-day view by definition (every row would
8+
read "Today"), Logbook already has day-bands (Slice C2), and Agenda
9+
is the explicit "everything across days" view. Day-band grouping
10+
inside Today / Inbox / Anytime would duplicate Agenda; the only
11+
sensible target was Upcoming, which is a single-view scope rather
12+
than a main-list-wide change.
13+
14+
Reframed Patch D as two smaller polish wins that actually address
15+
what the screenshot showed:
16+
17+
- **Visible row separators.** `GtkListView`'s `show-separators=true`
18+
was on (window.ui) but the default separator on dark themes was
19+
so faint that 20+ rows read as a wall of text. v0.6.14 adds a
20+
1px `@borders`-tinted bottom border to each task row (constrained
21+
by `:has(.atrium-task-row)` so kanban / agenda card rows don't
22+
inherit). The eye now has a clear stride between rows without the
23+
list looking like a heavy table.
24+
25+
- **Recurrence icon (#9b).** Tasks whose `repeat_rule` is set now
26+
show a small `view-refresh-symbolic` icon at the right edge of
27+
the row, with a tooltip "Repeating task." The icon is a derived
28+
state cue — the original screenshot bug was the *fixture* shoving
29+
emoji into title strings (#9a, fixed in Patch A); the icon now
30+
reads correctness from `repeat_rule` regardless of what the title
31+
says. New `repeating: bool` glib property on `AtriumTask`,
32+
computed at construction + on `refresh_from`. The row factory
33+
appends a `gtk::Image` after the deadline pill (preserves the
34+
existing `next_sibling` chain so other bind logic stays
35+
unchanged) and toggles its visibility via
36+
`connect_repeating_notify`. Handler stashed under
37+
`atrium-repeating-handler` and disconnected on unbind. The icon
38+
picks up the row-state tint when the task is overdue or today,
39+
matching the date-pill pattern from Patch B.
40+
41+
This closes the four-patch screenshot-cleanup arc:
42+
- v0.6.11 Patch A — eight quick wins (eight files, low risk).
43+
- v0.6.12 Patch B — state-aware row treatment (the biggest visual
44+
win; overdue red / today amber / upcoming accent).
45+
- v0.6.13 Patch C — Inspector Notes placeholder.
46+
- v0.6.14 Patch D — visible row separators + recurrence icon.
47+
348
## v0.6.13 (2026-05-08) — Patch C: Inspector Notes placeholder
449

550
Small focused patch off the screenshot-cleanup arc. The Inspector

0 commit comments

Comments
 (0)