From a3a1a46afdd2dbb906b540589e173123a31ad890 Mon Sep 17 00:00:00 2001 From: kutesir Date: Thu, 9 Jul 2026 02:39:35 +0300 Subject: [PATCH] habits: clarify the custom coffee reminder row (KC-58) The custom-slot row just said 'Coffee' -- identical-looking to the card's own 'Coffee reminders' title, with no affordance signaling it's an editable, user-nameable 5th slot (distinct from the 4 fixed Morning/Midday/Afternoon/ Evening ones). Added a small pencil + 'YOUR OWN REMINDER' label above the field; changed the default from pre-filled 'Coffee' to empty so the placeholder ('Name it, e.g. "Second coffee"') actually does its job. NotificationManager falls back to 'Coffee' for the notification text only if the user never typed a name. Co-Authored-By: Claude Opus 4.8 --- KisaniCal/ISSUES.md | 22 +++++++++++ KisaniCal/Managers/NotificationManager.swift | 5 ++- KisaniCal/Views/SettingsView.swift | 39 ++++++++++++-------- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/KisaniCal/ISSUES.md b/KisaniCal/ISSUES.md index 76ed4b7..8f3950c 100644 --- a/KisaniCal/ISSUES.md +++ b/KisaniCal/ISSUES.md @@ -1965,3 +1965,25 @@ how every other color in the app is centralized, and is accessible from any file. Files: `DesignTokens.swift`, `SettingsView.swift`, `OnboardingView.swift`. + +--- + +## KC-58 — Custom coffee reminder row was unlabeled/confusing + +**Status:** Implemented (not build-verified) +**Reported by:** User (screenshot: last row in "Coffee reminders" just said +"Coffee" — indistinguishable from the card's own title, no hint it's an +editable custom slot) + +### Fix +- The custom-reminder row now has a small "✎ YOUR OWN REMINDER" label above + it, so it reads as a distinct, nameable 5th slot rather than a redundant + duplicate of the "Coffee reminders" card title. +- Default label changed from the confusing pre-filled "Coffee" to empty, so + the field's placeholder ("Name it, e.g. \"Second coffee\"") actually guides + the user instead of looking like a static, already-filled-in option. +- `NotificationManager` falls back to "Coffee" for the notification title only + if the user never actually typed a name (empty string), so an un-customized + custom reminder still reads sensibly if enabled. + +Files: `SettingsView.swift`, `NotificationManager.swift`. diff --git a/KisaniCal/Managers/NotificationManager.swift b/KisaniCal/Managers/NotificationManager.swift index 17345a1..5a6a379 100644 --- a/KisaniCal/Managers/NotificationManager.swift +++ b/KisaniCal/Managers/NotificationManager.swift @@ -265,7 +265,10 @@ final class NotificationManager: NSObject, ObservableObject, @unchecked Sendable habitType: "coffee" ) } - let customLabel = ud.string(forKey: "coffeeCustomLabel") ?? "Coffee" + // Empty until the user names it (the field's placeholder guides that) — + // fall back to a sensible default rather than an empty notification title. + let rawCustomLabel = ud.string(forKey: "coffeeCustomLabel") ?? "" + let customLabel = rawCustomLabel.isEmpty ? "Coffee" : rawCustomLabel addDaily( id: "\(Self.habitPrefix).coffee.custom", enabled: coffeeOn && (ud.object(forKey: "coffeeCustomEnabled") as? Bool ?? false), diff --git a/KisaniCal/Views/SettingsView.swift b/KisaniCal/Views/SettingsView.swift index 8fa63cd..1140048 100644 --- a/KisaniCal/Views/SettingsView.swift +++ b/KisaniCal/Views/SettingsView.swift @@ -916,7 +916,7 @@ private struct HabitRemindersSheet: View { @AppStorage("coffeeReminderEnabled", store: UserDefaults.kisani) private var coffeeReminderEnabled = false @AppStorage("coffeeCustomEnabled", store: UserDefaults.kisani) private var coffeeCustomEnabled = false - @AppStorage("coffeeCustomLabel", store: UserDefaults.kisani) private var coffeeCustomLabel = "Coffee" + @AppStorage("coffeeCustomLabel", store: UserDefaults.kisani) private var coffeeCustomLabel = "" @AppStorage("coffeeCustomHour", store: UserDefaults.kisani) private var coffeeCustomHour = 16 @AppStorage("coffeeCustomMinute", store: UserDefaults.kisani) private var coffeeCustomMinute = 30 @@ -1020,22 +1020,29 @@ private struct HabitRemindersSheet: View { defaultMinute: 0, defaultEnabled: slot == "Morning") } Divider().background(AppColors.border(cs)).padding(.leading, 14) - HStack(spacing: 11) { - TextField("Custom label", text: $coffeeCustomLabel) - .font(AppFonts.sans(12.5)).foregroundColor(AppColors.text(cs)) - Spacer() - if coffeeCustomEnabled { - DatePicker("", selection: Binding( - get: { Calendar.current.date(bySettingHour: coffeeCustomHour, minute: coffeeCustomMinute, second: 0, of: Date()) ?? Date() }, - set: { v in - let c = Calendar.current.dateComponents([.hour, .minute], from: v) - coffeeCustomHour = c.hour ?? coffeeCustomHour - coffeeCustomMinute = c.minute ?? coffeeCustomMinute - } - ), displayedComponents: .hourAndMinute) - .labelsHidden().tint(AppColors.accent) + VStack(alignment: .leading, spacing: 5) { + HStack(spacing: 4) { + Image(systemName: "pencil").font(.system(size: 9)) + Text("YOUR OWN REMINDER").font(AppFonts.mono(8, weight: .bold)) + } + .foregroundColor(AppColors.text3(cs)) + HStack(spacing: 11) { + TextField("Name it, e.g. \"Second coffee\"", text: $coffeeCustomLabel) + .font(AppFonts.sans(12.5)).foregroundColor(AppColors.text(cs)) + Spacer() + if coffeeCustomEnabled { + DatePicker("", selection: Binding( + get: { Calendar.current.date(bySettingHour: coffeeCustomHour, minute: coffeeCustomMinute, second: 0, of: Date()) ?? Date() }, + set: { v in + let c = Calendar.current.dateComponents([.hour, .minute], from: v) + coffeeCustomHour = c.hour ?? coffeeCustomHour + coffeeCustomMinute = c.minute ?? coffeeCustomMinute + } + ), displayedComponents: .hourAndMinute) + .labelsHidden().tint(AppColors.accent) + } + Toggle("", isOn: $coffeeCustomEnabled).labelsHidden().tint(AppColors.accent).scaleEffect(0.85) } - Toggle("", isOn: $coffeeCustomEnabled).labelsHidden().tint(AppColors.accent).scaleEffect(0.85) } .padding(.horizontal, 14).padding(.vertical, 9) }