Commit Graph

13 Commits

Author SHA1 Message Date
Robin Kutesa
0483bc04ea Rename 'Today' shortcut to 'Tasks', move to first position
Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 03:54:58 +03:00
Robin Kutesa
0c48ca888b Fix: tapping task notification now marks it complete
Tap body → marks complete + navigates to tasks.
Swipe action 'Mark Complete' → marks complete without opening app.
TaskViewModel.reload() called on foreground to sync UserDefaults changes
made while app was backgrounded.

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 03:52:10 +03:00
Robin Kutesa
43fb8f7036 Fix stale notification count and add deeplink navigation
Evening check-in no longer embeds the urgent task count in the body —
repeating notifications bake that value at schedule time so it always
shows a stale number. Replaced with a generic prompt.

didReceive now routes notification taps via ShortcutHandler:
'workout' deeplink → Workout tab, everything else → Today tab.

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 02:31:41 +03:00
Robin Kutesa
a49d5fea35 Show overdue + today task count on app icon badge
updateBadge() counts all incomplete tasks with a due date earlier
than tomorrow (i.e. overdue or due today) and calls setBadgeCount().
Called inside reschedule() so the badge updates on foreground, task
changes, and workout set completions — same triggers as notifications.

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 02:25:35 +03:00
Robin Kutesa
8f8825ac04 Add tooltip coach mark tutorial for new users
- TutorialManager: tracks 4 steps (NLP, Calendar, Matrix, Workout)
  persisted via AppStorage; shown once then never again
- TutorialView: fullscreen overlay with even-odd spotlight cutout,
  animated accent border, ultraThinMaterial callout card, pill progress
  dots, Next/Get started button, and Skip
- TutorialFrameKey: PreferenceKey collects CGRect for each anchor index;
  .tutorialAnchor() modifier wired to FAB (step 0) and all 4 tab buttons
- Callout auto-positions above or below the spotlight based on screen half
- ContentView collects frames via onPreferenceChange and layers the overlay

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 02:23:12 +03:00
Robin Kutesa
409b4f8ee6 Mark NotificationManager @unchecked Sendable
Needed because self is captured in @Sendable closures passed to
UNUserNotificationCenter callbacks. Safe: the only mutable state
(isAuthorized) is exclusively written on the main thread.

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 02:03:01 +03:00
Robin Kutesa
fc6d5a91bd Fix all NotificationManager concurrency warnings
- Remove @MainActor from class (caused all Sendable/isolation cascade)
- Keep @MainActor only on reschedule() where VM access is needed
- Snapshot tasks in reschedule() so scheduleTasks() never captures
  a non-Sendable TaskViewModel across async boundaries
- Capture center locally in scheduleTasks() to avoid @MainActor
  property access inside the @Sendable getPendingNotificationRequests callback
- Mark UNUserNotificationCenterDelegate methods nonisolated to satisfy
  protocol conformance without actor crossing

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 02:02:04 +03:00
Robin Kutesa
7b23493f6f Fix MainActor isolation in NotificationManager; var→let in AuthManager
Snapshot WorkoutViewModel's schedule/programs/progress before the
async getNotificationSettings callback so scheduleWorkout receives
plain value types instead of MainActor-isolated properties.
Also fix unused-mutation warning: email in handleApple changed to let.

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 01:54:20 +03:00
Robin Kutesa
d424a2a814 Clear demo data, namespace storage by user, add profile setup
- Remove all personal sampleTasks from TaskViewModel (tasks start empty)
- Namespace UserDefaults keys by Apple ID for task and workout data isolation
- Add ProfileSetupView for name capture after first Sign in with Apple
- Add updateDisplayName() to AuthManager
- Route to ProfileSetupView when user has no display name yet

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 01:31:55 +03:00
Robin Kutesa
ea869f51b0 feat: Sign in with Apple authentication
- AuthManager: native AuthenticationServices, session in Keychain
- AuthView: branded screen with Apple Sign In button
- App gates ContentView behind auth; animates on sign-in/out
- Settings: Account section shows name/email + Sign Out button
- Entitlements: added com.apple.developer.applesignin

Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
2026-06-01 00:44:02 +03:00
kutesir
cab5c4ef05 feat: home screen quick actions (long press app icon)
Adds four UIApplicationShortcutItems registered dynamically at launch:
  • Add Task — opens the add-task sheet immediately, any tab
  • Today — switches to the Today tab
  • Calendar — switches to the Calendar tab
  • Workout — switches to the Workout tab (only registered if the
    workout tab is enabled in settings; re-registers when the setting changes)

Cold-launch and foreground-activation paths both handled via AppDelegate.
ShortcutHandler singleton bridges UIKit callbacks to SwiftUI via @Published.
2026-05-30 02:38:15 +03:00
kutesir
1d4d7f07c5 Add task persistence and per-task reminder notifications
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.
2026-05-29 10:33:55 +03:00
kutesir
f67429de0b Initial commit: KisaniCal iOS app
Task management, Eisenhower matrix, workout logging with persistence,
and calendar with 6 view modes (Month, List, Year, Week, 3 Day, Day).
Custom floating tab bar, dynamic calendar icon, and workout data seeded.
2026-05-27 02:09:44 +03:00