From 3ada2fc17fd1bc8f4203eaa6fde2ea23d49b87a4 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 12 Jul 2026 09:48:34 +0000 Subject: feat(widget): forward IsOverdue from TimelineItem to WidgetItem API --- internal/handlers/widget.go | 11 ++++++----- internal/handlers/widget_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ internal/models/widget.go | 1 + 3 files changed, 47 insertions(+), 5 deletions(-) (limited to 'internal') diff --git a/internal/handlers/widget.go b/internal/handlers/widget.go index dc10db6..f8a63a0 100644 --- a/internal/handlers/widget.go +++ b/internal/handlers/widget.go @@ -32,11 +32,12 @@ func WidgetAuthMiddleware(token string, next http.Handler) http.Handler { // Exported for testability. func TimelineItemToWidgetItem(item models.TimelineItem) models.WidgetItem { wi := models.WidgetItem{ - ID: item.ID, - Title: item.Title, - Source: item.Source, - IsAllDay: item.IsAllDay, - URL: item.URL, + ID: item.ID, + Title: item.Title, + Source: item.Source, + IsAllDay: item.IsAllDay, + IsOverdue: item.IsOverdue, + URL: item.URL, } switch item.Type { diff --git a/internal/handlers/widget_test.go b/internal/handlers/widget_test.go index 6d741d2..06e1749 100644 --- a/internal/handlers/widget_test.go +++ b/internal/handlers/widget_test.go @@ -170,6 +170,46 @@ func TestTimelineItemToWidgetItem_AllDayTask_KeepsFloatingBehavior(t *testing.T) } } +// TestTimelineItemToWidgetItem_ForwardsIsOverdue proves the 2026-07-12 +// overdue-badge fix: TimelineItem.IsOverdue (already computed correctly by +// ComputeDaySection, confirmed by the earlier fix that made overdue tasks +// appear in the timeline at all) must be forwarded onto WidgetItem so the +// Android client can render it distinctly -- previously it was silently +// dropped, so an overdue task looked identical to a normal one on the +// widget. +func TestTimelineItemToWidgetItem_ForwardsIsOverdue(t *testing.T) { + item := models.TimelineItem{ + ID: "overdue-1", + Title: "Pay the water bill", + Source: "doot", + Type: models.TimelineItemTypeTask, + Time: time.Now(), + IsOverdue: true, + } + + wi := TimelineItemToWidgetItem(item) + + if !wi.IsOverdue { + t.Error("expected IsOverdue to be forwarded as true") + } +} + +func TestTimelineItemToWidgetItem_NotOverdueByDefault(t *testing.T) { + item := models.TimelineItem{ + ID: "today-1", + Title: "Water the plants", + Source: "doot", + Type: models.TimelineItemTypeTask, + Time: time.Now(), + } + + wi := TimelineItemToWidgetItem(item) + + if wi.IsOverdue { + t.Error("expected IsOverdue to be false when the source item isn't overdue") + } +} + func TestHandleWidgetComplete_NonCompletable(t *testing.T) { h := &Handler{} body := `{"id":"x","source":"calendar"}` diff --git a/internal/models/widget.go b/internal/models/widget.go index 8d0bdd6..e2876b0 100644 --- a/internal/models/widget.go +++ b/internal/models/widget.go @@ -13,6 +13,7 @@ type WidgetItem struct { Start *time.Time `json:"start,omitempty"` // nil = no specific time (floating task) End *time.Time `json:"end,omitempty"` IsAllDay bool `json:"is_all_day"` + IsOverdue bool `json:"is_overdue"` URL string `json:"url,omitempty"` Completable bool `json:"completable"` // true = doot task (checkbox shown) } -- cgit v1.2.3