From 80fbbd7895552f914fa271fd017c8b7dab190734 Mon Sep 17 00:00:00 2001 From: kutesir Date: Thu, 9 Jul 2026 14:17:18 +0300 Subject: [PATCH] tasks: replace category text pill with TickTick-style icon glyphs (KC-62) Every task row was tagging itself "Reminder" via a text badge for the default category, adding no information. Swapped for icon-only glyphs (nil for the generic .reminder case) folded into the existing alarm/ repeat indicator row; countdown/date info was already present or redundant with the leading time-track, so no separate countdown text was added. Co-Authored-By: Claude Opus 4.8 --- KisaniCal/ISSUES.md | 47 +++++++++++++++++++++++++++++++++ KisaniCal/Models/TaskItem.swift | 12 +++++++++ KisaniCal/Views/TodayView.swift | 37 +++++++++++++++++--------- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/KisaniCal/ISSUES.md b/KisaniCal/ISSUES.md index 08aee99..17b8eec 100644 --- a/KisaniCal/ISSUES.md +++ b/KisaniCal/ISSUES.md @@ -2118,3 +2118,50 @@ Not build-verified (no iOS runtime here). Self-reviewed: balanced braces/ parens confirmed per-file. `StopCountdownIntent` needs to land in the KisaniCalWidgets target (already covered by `project.yml`'s `sources: -path: KisaniCalWidgets` glob — no project.yml change needed). + +## KC-62 — Task row category pill replaced with TickTick-style icon glyphs + +Status: Implemented (not build-verified — no iOS runtime here) +Reported by: User, from device screenshots ("reminder labeling a bit too +much, let's do it just like TickTick... show countdown info too") +Area: Today (task rows, both the top mini-timeline and the Tomorrow/Next 7 +Days/Later list) + +### Description +Every task row rendered a `TagChip` text badge showing `task.category +.rawValue` — for the vast majority of tasks (the default `.reminder` +category) this just says "Reminder" on nearly every row, adding no real +information. Confirmed only 2 call sites exist app-wide (`grep -rn +"TagChip(" KisaniCal/Views/*.swift`), both in `TodayView.swift` — Matrix and +Calendar don't render this pill at all, so "everywhere" (user's chosen +scope) resolves to these two. + +### Change +- Added `TaskCategory.glyph: String?` (`TaskItem.swift`) — maps each + category to a small SF Symbol, `nil` for `.reminder` (the generic default + stays unmarked, matching TickTick's "no badge unless it says something" + density): `.birthday → gift.fill`, `.domain → briefcase.fill`, `.annual → + calendar`, `.custom → tag.fill`. +- **`TaskRowView`** (Tomorrow/Next 7 Days/Later rows — matches the user's + screenshot exactly): removed the `TagChip` call outright and folded the + category glyph into the row's existing ⏰/↻ icon `HStack`. This row + already carried a countdown (`countdownLabel(to:)`) next to the due date, + so "show countdown info too" was already satisfied — no countdown change + needed here. +- **`TodayTLRow`** (top mini-timeline — Overdue/Today/Next 3 Days/Upcoming): + same glyph swap, and while in there also added the ⏰/↻ indicators this + row was missing (it only had the category pill before). No standalone + countdown text added here — the leading time-track column already shows + either the time-of-day or the short date (`MMM d`) for non-today entries, + so a duplicate "in X days" string would be redundant clutter in an already + dense timeline row. + +Files: `KisaniCal/Models/TaskItem.swift`, `KisaniCal/Views/TodayView.swift`. + +### Note +Not build-verified (no iOS runtime here). Self-reviewed: balanced braces/ +parens confirmed per-file (`TaskItem.swift` has one pre-existing stray `(` +imbalance confirmed via `git stash` to predate this change — a comment +artifact, not introduced here). `TagChip` itself is left intact in +`SharedComponents.swift` since it's a generic shared component, just no +longer called from these two sites. diff --git a/KisaniCal/Models/TaskItem.swift b/KisaniCal/Models/TaskItem.swift index 39b6a35..4d71bdd 100644 --- a/KisaniCal/Models/TaskItem.swift +++ b/KisaniCal/Models/TaskItem.swift @@ -104,6 +104,18 @@ enum TaskCategory: String, Codable { case domain = "Domain" case annual = "Annual" case custom = "Custom" + + /// Icon-only glyph for task rows — `.reminder` is the generic default + /// and stays unmarked so the badge only appears when it adds information. + var glyph: String? { + switch self { + case .reminder: return nil + case .birthday: return "gift.fill" + case .domain: return "briefcase.fill" + case .annual: return "calendar" + case .custom: return "tag.fill" + } + } } enum TaskColor: String, Codable { diff --git a/KisaniCal/Views/TodayView.swift b/KisaniCal/Views/TodayView.swift index 491a2af..90b7961 100644 --- a/KisaniCal/Views/TodayView.swift +++ b/KisaniCal/Views/TodayView.swift @@ -564,11 +564,25 @@ private struct TodayTLRow: View { } } Spacer(minLength: 0) - TagChip( - text: entry.task.category.rawValue, - color: entry.color, - bg: entry.task.quadrant.softColor - ) + // TickTick-style — icon only, no text badge; date/time already + // shown in the leading time-track column for this row. + HStack(spacing: 5) { + if let glyph = entry.task.category.glyph { + Image(systemName: glyph) + .font(.system(size: 11)) + .foregroundColor(entry.color) + } + if entry.task.reminderDate != nil || entry.task.constantReminder { + Image(systemName: "alarm") + .font(.system(size: 11)) + .foregroundColor(AppColors.text3(cs)) + } + if entry.task.isRecurring { + Image(systemName: "repeat") + .font(.system(size: 11)) + .foregroundColor(AppColors.text3(cs)) + } + } Button(action: onToggle) { ZStack { RoundedRectangle(cornerRadius: 5, style: .continuous) @@ -1357,8 +1371,13 @@ struct TaskRowView: View { Spacer() - // ⏰ reminder · 🔁 recurring indicators + // ⏰ reminder · 🔁 recurring · tag icon indicators (TickTick-style — icon only, no text badge) HStack(spacing: 5) { + if let glyph = task.category.glyph { + Image(systemName: glyph) + .font(.system(size: 11)) + .foregroundColor(task.quadrant.color) + } if task.reminderDate != nil || task.constantReminder { Image(systemName: "alarm") .font(.system(size: 11)) @@ -1370,12 +1389,6 @@ struct TaskRowView: View { .foregroundColor(AppColors.text3(cs)) } } - - TagChip( - text: task.category.rawValue, - color: task.quadrant.color, - bg: task.quadrant.softColor - ) .padding(.trailing, 9) } .frame(minHeight: 48)