Merge develop -> main: full session (KC-51 through KC-71) #28
@@ -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`.
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user