Add AI-powered mental wellness features: Reflection Companion, Pattern Tags, Weekly Digest
Three new Foundation Models features to deepen user engagement with mental wellness: 1. AI Reflection Companion — personalized feedback after completing guided reflections, referencing the user's actual words with personality-pack-adapted tone 2. Mood Pattern Tags — auto-extracts theme tags (work, family, stress, etc.) from notes and reflections, displayed as colored pills on entries 3. Weekly Emotional Digest — BGTask-scheduled Sunday digest with headline, summary, highlight, and intention; shown as card in Insights tab with notification All features: on-device (zero cost), premium-gated, iOS 26+ with graceful degradation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import BackgroundTasks
|
||||
class BGTask {
|
||||
static let updateDBMissingID = "com.88oakapps.reflect.dbUpdateMissing"
|
||||
static let weatherRetryID = "com.88oakapps.reflect.weatherRetry"
|
||||
static let weeklyDigestID = "com.88oakapps.reflect.weeklyDigest"
|
||||
|
||||
@MainActor
|
||||
class func runFillInMissingDatesTask(task: BGProcessingTask) {
|
||||
@@ -55,6 +56,65 @@ class BGTask {
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class func runWeeklyDigestTask(task: BGProcessingTask) {
|
||||
BGTask.scheduleWeeklyDigest()
|
||||
|
||||
task.expirationHandler = {
|
||||
task.setTaskCompleted(success: false)
|
||||
}
|
||||
|
||||
if #available(iOS 26, *) {
|
||||
Task {
|
||||
guard !IAPManager.shared.shouldShowPaywall else {
|
||||
task.setTaskCompleted(success: true)
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let digest = try await FoundationModelsDigestService.shared.generateWeeklyDigest()
|
||||
|
||||
// Send local notification with the headline
|
||||
let personalityPack = UserDefaultsStore.personalityPackable()
|
||||
LocalNotification.scheduleDigestNotification(headline: digest.headline, personalityPack: personalityPack)
|
||||
|
||||
task.setTaskCompleted(success: true)
|
||||
} catch {
|
||||
print("Weekly digest generation failed: \(error)")
|
||||
task.setTaskCompleted(success: false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
task.setTaskCompleted(success: true)
|
||||
}
|
||||
}
|
||||
|
||||
class func scheduleWeeklyDigest() {
|
||||
let request = BGProcessingTaskRequest(identifier: BGTask.weeklyDigestID)
|
||||
request.requiresNetworkConnectivity = false
|
||||
request.requiresExternalPower = false
|
||||
|
||||
// Schedule for next Sunday at 7 PM
|
||||
let calendar = Calendar.current
|
||||
var components = calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date())
|
||||
components.weekday = 1 // Sunday
|
||||
components.hour = 19
|
||||
components.minute = 0
|
||||
|
||||
var nextSunday = calendar.date(from: components) ?? Date()
|
||||
if nextSunday <= Date() {
|
||||
nextSunday = calendar.date(byAdding: .weekOfYear, value: 1, to: nextSunday)!
|
||||
}
|
||||
|
||||
request.earliestBeginDate = nextSunday
|
||||
|
||||
do {
|
||||
try BGTaskScheduler.shared.submit(request)
|
||||
} catch {
|
||||
print("Could not schedule weekly digest: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
class func scheduleBackgroundProcessing() {
|
||||
let request = BGProcessingTaskRequest(identifier: BGTask.updateDBMissingID)
|
||||
request.requiresNetworkConnectivity = false
|
||||
|
||||
Reference in New Issue
Block a user