Tasks now survive app restarts via UserDefaults JSON. Each task with a
due time fires a notification at that exact time; date-only tasks fire
at 9am on the due date. Completing or deleting a task cancels its
pending notification. ContentView now reschedules on any task change.
- Widget extension: 16.0 → 17.0 (containerBackground/widget API require 17)
- xcodegen re-run picks up FloatingTabState.swift (was on disk but
not registered in project.pbxproj after previous xcodegen run)
- KisaniCalWidget: 3 sizes sharing the app's design language
Small: date badge + kisaniCAL. wordmark + task count
Medium: badge + task list (3 items) + workout row
Large: badge + full task list (6 items) + workout row
- WidgetDataStore (Shared/): lightweight Codable types for App Group
UserDefaults cross-process data exchange
- WidgetBridge: TaskViewModel/WorkoutViewModel extensions that sync
data into App Group and call WidgetCenter.reloadAllTimelines()
- ContentView: calls syncWidget() on appear and scene becoming active
- project.yml + entitlements updated; project regenerated via xcodegen
7 rows of dots fill left-to-right, top-to-bottom as sets complete.
Filled dots: AppColors.green solid. Empty: green at 12% opacity.
Also: strip emoji from completion banner, tighten copy.
Sheet was 500pt tall with ~145pt of content, leaving ~355pt blank.
Dropping to height(150) makes the sheet hug its content and sit flush
above the keyboard like the reference design.
Break SplashCalendarCard body into monthHeader/weekdayRow/dayGrid
computed vars and extract SplashWeekRow to help the type-checker.
Rename DayCell -> SplashDayCell to avoid collision with CalendarView.
Using self.programs on the RHS of activeSections assignment violated
Swift's two-phase init rule (self is partially initialized). Use local
`migrated` array instead, then assign programs and activeSections in
the correct order.
Replace the emoji tile on CalendarWorkoutBlock and WorkoutSessionSheet
header with WorkoutSectionBar — a stack of N horizontal segments, one
per workout section. No emojis, no custom per-program images.
UserDefaults retained the old 🔥/💥 emojis from before the sample data
was cleaned. On init, replace those emojis in loaded programs and persist
the result so they don't reappear after restart.
WorkoutTodayBanner: progress ring replaces emoji cell as the lead
visual. Card background is now surface/border, not blue-tinted.
StreakBannerView: strip gradient, dot trail, and "Don't break the
chain". Replace with clean number + 7-tick week bar.
ProgressRingCard: "Keep going 🔥" / "Workout complete! 🎉" removed;
replaced with "N sets remaining" / "All sets done".
Sample programs: 🔥 Shoulders & Arms -> 🔄, 💥 Full Body -> 🏋️.
Emoji picker: 🔥 replaced with 🫀 (heart/cardio) as last option.
Replace full-form AddTaskSheet with a compact NL input sheet.
Type "meeting today at 1500" — the words "today" and "at 1500"
highlight inline in blue, the toolbar shows "Today, 15:00", and
the mic button becomes a submit arrow when the title is non-empty.
Parser handles: today/tomorrow, weekday names (mon–sun),
times as at 3pm / at 15:00 / at 1500 / 3:30pm.
Clean title strips the date tokens before saving.
Sheet uses height(500) detent so it floats above the keyboard.
iPadLayout was rendering TodayView without workoutVM, crashing with
a fatal EnvironmentObject error on any device where hSizeClass goes
.regular (iPad, iPhone Plus/Max in landscape). Rewrote to use proper
NavigationSplitView with List(selection:) driving the detail column.
Also caches calendarIcon as a static func + @State instead of
recomputing UIGraphicsImageRenderer on every body evaluation.