Add Apple Watch app (TickTick-style) + midnight period notifications

WenzaWatch (new watchOS target, embed disabled until the watchOS platform is
installed — see project.yml note):
- Today list of actionable tasks (dated today/overdue + recurring occurrences),
  tap-to-complete with haptics, and add-via-dictation.
- Reads/writes the same tasks through the shared iCloud KV store that
  CloudSyncManager mirrors on the phone; watch entitlement uses the iOS app's
  kvstore identifier so they share one store. New tasks include all required
  TaskItem keys so the phone decodes them.
- NOTE: not compiled here (watchOS SDK absent on this machine); iOS build
  verified green with the embed commented out.

Period notifications: day/week/month/year now all fire at midnight (00:00),
adding the daily "One more day passed." (Pretty Progress style).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kutesir
2026-06-16 23:50:37 +03:00
parent bcb66ef691
commit cb0dc3e271
7 changed files with 413 additions and 45 deletions

View File

@@ -136,7 +136,7 @@ final class NotificationManager: NSObject, ObservableObject, @unchecked Sendable
// MARK: - Period milestones ("one more week / month / year passed")
private static let periodIds = ["kisani.period.week", "kisani.period.month", "kisani.period.year"]
private static let periodIds = ["kisani.period.day", "kisani.period.week", "kisani.period.month", "kisani.period.year"]
/// Recurring nudges at the close of each week, month, and year. Fixed identifiers
/// + remove-then-add keep them de-duplicated across reschedules. Disabled (and
@@ -155,17 +155,21 @@ final class NotificationManager: NSObject, ObservableObject, @unchecked Sendable
trigger: UNCalendarNotificationTrigger(dateMatching: comps, repeats: true)))
}
// End of week Sunday 20:00
var week = DateComponents(); week.weekday = 1; week.hour = 20; week.minute = 0
add(Self.periodIds[0], "This Week", "One more week passed.", week)
// Every midnight a new day began
var day = DateComponents(); day.hour = 0; day.minute = 0
add(Self.periodIds[0], "Today", "One more day passed.", day)
// End of month 1st of the next month, 09:00
var month = DateComponents(); month.day = 1; month.hour = 9; month.minute = 0
add(Self.periodIds[1], "This Month", "One more month passed.", month)
// Start of the week (Mon 00:00) the week that just ended
var week = DateComponents(); week.weekday = 2; week.hour = 0; week.minute = 0
add(Self.periodIds[1], "This Week", "One more week passed.", week)
// End of year Jan 1, 09:00
var year = DateComponents(); year.month = 1; year.day = 1; year.hour = 9; year.minute = 0
add(Self.periodIds[2], "This Year", "One more year passed.", year)
// 1st of the month, 00:00 the month that just ended
var month = DateComponents(); month.day = 1; month.hour = 0; month.minute = 0
add(Self.periodIds[2], "This Month", "One more month passed.", month)
// Jan 1, 00:00 the year that just ended
var year = DateComponents(); year.month = 1; year.day = 1; year.hour = 0; year.minute = 0
add(Self.periodIds[3], "This Year", "One more year passed.", year)
}
// MARK: - Recurring task completion confirmation