Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2026-01-27 15:06:33 -06:00
parent 69e548b13c
commit ee347bb402
2 changed files with 28 additions and 9 deletions

View File

@ -65,7 +65,7 @@ enum RitualPresetLibrary {
title: String(localized: "Morning Hydration"),
theme: String(localized: "Start your day refreshed"),
notes: String(localized: "Build the habit of hydrating first thing in the morning."),
durationDays: 21,
durationDays: 28,
timeOfDay: .morning,
iconName: "drop.fill",
category: PresetCategory.health.rawValue,
@ -113,7 +113,7 @@ enum RitualPresetLibrary {
title: String(localized: "Deep Work Prep"),
theme: String(localized: "Set up for focus"),
notes: String(localized: "Create the conditions for uninterrupted deep work."),
durationDays: 21,
durationDays: 28,
timeOfDay: .morning,
iconName: "brain",
category: PresetCategory.productivity.rawValue,
@ -143,7 +143,7 @@ enum RitualPresetLibrary {
title: String(localized: "Focus Reset"),
theme: String(localized: "Regain clarity"),
notes: String(localized: "When you feel scattered, use this to refocus."),
durationDays: 14,
durationDays: 28,
timeOfDay: .anytime,
iconName: "target",
category: PresetCategory.productivity.rawValue,
@ -162,7 +162,7 @@ enum RitualPresetLibrary {
title: String(localized: "Morning Meditation"),
theme: String(localized: "Start with stillness"),
notes: String(localized: "A calm mind sets the tone for a calm day."),
durationDays: 30,
durationDays: 28,
timeOfDay: .morning,
iconName: "figure.mind.and.body",
category: PresetCategory.mindfulness.rawValue,
@ -176,7 +176,7 @@ enum RitualPresetLibrary {
title: String(localized: "Gratitude Practice"),
theme: String(localized: "Find the good"),
notes: String(localized: "Shift your focus to what's going well."),
durationDays: 21,
durationDays: 28,
timeOfDay: .evening,
iconName: "heart.text.square.fill",
category: PresetCategory.mindfulness.rawValue,
@ -190,7 +190,7 @@ enum RitualPresetLibrary {
title: String(localized: "Breathwork"),
theme: String(localized: "Calm your nervous system"),
notes: String(localized: "Use breath to reduce stress and increase focus."),
durationDays: 14,
durationDays: 28,
timeOfDay: .anytime,
iconName: "wind",
category: PresetCategory.mindfulness.rawValue,
@ -238,7 +238,7 @@ enum RitualPresetLibrary {
title: String(localized: "Digital Detox"),
theme: String(localized: "Disconnect to reconnect"),
notes: String(localized: "Give your mind a break from screens."),
durationDays: 21,
durationDays: 28,
timeOfDay: .evening,
iconName: "iphone.slash",
category: PresetCategory.selfCare.rawValue,
@ -267,7 +267,7 @@ enum RitualPresetLibrary {
title: String(localized: "Weekly Reset"),
theme: String(localized: "Prepare for a fresh week"),
notes: String(localized: "Sunday evening ritual to start Monday strong."),
durationDays: 12,
durationDays: 28,
timeOfDay: .evening,
iconName: "arrow.counterclockwise.circle.fill",
category: PresetCategory.selfCare.rawValue,

View File

@ -32,6 +32,9 @@ final class RitualStore: RitualStoreProviding {
/// Ritual that needs renewal prompt (arc just completed)
var ritualNeedingRenewal: Ritual?
/// Rituals that have been dismissed for renewal this session
private var dismissedRenewalRituals: Set<PersistentIdentifier> = []
init(
modelContext: ModelContext,
seedService: RitualSeedProviding,
@ -213,7 +216,7 @@ final class RitualStore: RitualStoreProviding {
/// Checks for rituals that need renewal and triggers the prompt.
func checkForCompletedArcs() {
for ritual in currentRituals {
if isArcCompleted(ritual) {
if isArcCompleted(ritual) && !dismissedRenewalRituals.contains(ritual.persistentModelID) {
ritualNeedingRenewal = ritual
break
}
@ -226,6 +229,9 @@ final class RitualStore: RitualStoreProviding {
/// - durationDays: Duration for the new arc (defaults to ritual's default)
/// - copyHabits: Whether to copy habits from the previous arc
func renewArc(for ritual: Ritual, durationDays: Int? = nil, copyHabits: Bool = true) {
// Clear dismissed status since user is taking action
dismissedRenewalRituals.remove(ritual.persistentModelID)
// Mark current arc as inactive
if let currentArc = ritual.currentArc {
currentArc.isActive = false
@ -266,6 +272,9 @@ final class RitualStore: RitualStoreProviding {
/// Ends a ritual without renewal (marks it as having no active arc).
func endArc(for ritual: Ritual) {
// Clear dismissed status since user is taking action
dismissedRenewalRituals.remove(ritual.persistentModelID)
if let currentArc = ritual.currentArc {
currentArc.isActive = false
saveContext()
@ -274,6 +283,9 @@ final class RitualStore: RitualStoreProviding {
/// Dismisses the renewal prompt without taking action.
func dismissRenewalPrompt() {
if let ritual = ritualNeedingRenewal {
dismissedRenewalRituals.insert(ritual.persistentModelID)
}
ritualNeedingRenewal = nil
}
@ -760,6 +772,13 @@ final class RitualStore: RitualStoreProviding {
ritual.timeOfDay = timeOfDay
ritual.iconName = iconName
ritual.category = category
// Also update the current arc's end date if duration changed
if let currentArc = ritual.currentArc, currentArc.durationDays != durationDays {
let newEndDate = calendar.date(byAdding: .day, value: durationDays - 1, to: currentArc.startDate) ?? currentArc.endDate
currentArc.endDate = newEndDate
}
saveContext()
}