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

This commit is contained in:
Matt Bruce 2026-02-01 20:16:04 -06:00
parent ab703bf6f5
commit eb6d77487e
5 changed files with 364 additions and 107 deletions

View File

@ -189,6 +189,10 @@
"comment" : "A caption displayed alongside the slider in the \"Next Arc Duration\" section of the arc renewal sheet.",
"isCommentAutoGenerated" : true
},
"2-minute breathing pause" : {
"comment" : "Title of a habit preset within the \"Mindfulness\" category, focusing on a 2-minute breathing pause.",
"isCommentAutoGenerated" : true
},
"2pm 5pm" : {
"comment" : "Time range description for \"Afternoon\".",
"isCommentAutoGenerated" : true
@ -228,6 +232,10 @@
"comment" : "Tip text indicating that 21 days is when habits start to stick.",
"isCommentAutoGenerated" : true
},
"A brief afternoon pause to recenter." : {
"comment" : "Note for the \"Afternoon Reset\" ritual preset, describing its purpose.",
"isCommentAutoGenerated" : true
},
"A calm mind sets the tone for a calm day." : {
"comment" : "Notes for the \"Morning Meditation\" ritual preset.",
"isCommentAutoGenerated" : true
@ -280,6 +288,14 @@
}
}
},
"A quick check-in with yourself." : {
"comment" : "Note for the \"Midday Self-Check\" ritual preset.",
"isCommentAutoGenerated" : true
},
"A quick midday review to maintain momentum." : {
"comment" : "Notes for a ritual preset focused on maintaining momentum during a midday review.",
"isCommentAutoGenerated" : true
},
"A week of activity shows commitment!" : {
"comment" : "Tip suggesting that a week of activity indicates strong commitment to habits.",
"isCommentAutoGenerated" : true
@ -360,12 +376,36 @@
"comment" : "Tip to consider adding more habits to build momentum.",
"isCommentAutoGenerated" : true
},
"Adjust afternoon priorities" : {
"comment" : "Habit title for a ritual preset focused on maintaining productivity by reviewing and adjusting priorities during the afternoon.",
"isCommentAutoGenerated" : true
},
"Adjust if needed" : {
"comment" : "Habit title that encourages users to adjust their habits if necessary.",
"isCommentAutoGenerated" : true
},
"After 9pm" : {
"comment" : "Time range description for the \"Night\" time of day.",
"isCommentAutoGenerated" : true
},
"Afternoon" : {
},
"Afternoon Break" : {
"comment" : "Title of a ritual preset focused on taking a break in the afternoon.",
"isCommentAutoGenerated" : true
},
"Afternoon Deep Work" : {
"comment" : "Title of a ritual preset focused on an afternoon focused work session.",
"isCommentAutoGenerated" : true
},
"Afternoon Energy" : {
"comment" : "Title of a ritual preset focused on building healthy afternoon eating habits.",
"isCommentAutoGenerated" : true
},
"Afternoon Reset" : {
"comment" : "Title of a ritual preset that encourages centering oneself in the afternoon.",
"isCommentAutoGenerated" : true
},
"All" : {
"comment" : "Title for the \"All\" option in the history ritual filter picker.",
@ -393,6 +433,10 @@
"comment" : "Name of a habit within a Self-Care Ritual Preset.",
"isCommentAutoGenerated" : true
},
"Apply night cream" : {
"comment" : "Title of a habit preset within the \"Night Skincare\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Apply sunscreen" : {
"comment" : "Name of a habit within a self-care ritual preset.",
"isCommentAutoGenerated" : true
@ -415,11 +459,23 @@
},
"Arc History" : {
},
"Avoid heavy foods" : {
"comment" : "Habit title for a ritual preset focused on healthy evening eating habits, encouraging the user to avoid heavy foods.",
"isCommentAutoGenerated" : true
},
"Back" : {
"comment" : "A button label that says \"Back\".",
"isCommentAutoGenerated" : true
},
"Beat the slump" : {
"comment" : "Subtitle for a time preference option that encourages users to build habits in the afternoon.",
"isCommentAutoGenerated" : true
},
"Beat the slump with a reminder when it's time for your afternoon ritual" : {
"comment" : "Personalized description based on the user's selected time preference, for the \"afternoon\" case.",
"isCommentAutoGenerated" : true
},
"Before 11am" : {
"comment" : "Time range description for the \"Morning\" time of day.",
"isCommentAutoGenerated" : true
@ -439,14 +495,6 @@
"comment" : "Habit title for a mindfulness ritual that involves scanning the body for tension.",
"isCommentAutoGenerated" : true
},
"Bookend your day" : {
"comment" : "Subtitle for the \"Both\" option in the \"Time of Day\" section of the onboarding screen.",
"isCommentAutoGenerated" : true
},
"Both" : {
"comment" : "Text for a user preference to start and end their day with a ritual.",
"isCommentAutoGenerated" : true
},
"Box breathing (4-4-4-4)" : {
"comment" : "Description of a habit within a ritual preset, focusing on a specific breathing technique.",
"isCommentAutoGenerated" : true
@ -485,6 +533,10 @@
"comment" : "Title of a ritual preset focused on using breath to reduce stress and increase focus.",
"isCommentAutoGenerated" : true
},
"Bring awareness to your midday meal." : {
"comment" : "Notes for a ritual preset focused on mindful eating during lunch.",
"isCommentAutoGenerated" : true
},
"Browse All Presets" : {
"comment" : "A button label that takes the user to the preset library.",
"isCommentAutoGenerated" : true
@ -493,6 +545,10 @@
"comment" : "A button that, when tapped, presents a sheet displaying a list of available ritual presets.",
"isCommentAutoGenerated" : true
},
"Build healthy evening eating habits." : {
"comment" : "Notes for a ritual preset focused on healthy evening eating habits.",
"isCommentAutoGenerated" : true
},
"Build lasting habits through focused, time-bound journeys" : {
"comment" : "A description of the functionality of the app.",
"isCommentAutoGenerated" : true
@ -525,10 +581,18 @@
"comment" : "A label for the name of a category.",
"isCommentAutoGenerated" : true
},
"Center yourself" : {
"comment" : "Description of a ritual preset focused on centering oneself in the afternoon.",
"isCommentAutoGenerated" : true
},
"Change into comfortable clothes" : {
"comment" : "Habit title for a ritual preset that encourages dressing in comfortable clothes for the evening.",
"isCommentAutoGenerated" : true
},
"Chew slowly and taste" : {
"comment" : "Habit title for a mindfulness ritual focused on savoring food.",
"isCommentAutoGenerated" : true
},
"Choose Habit Icon" : {
"comment" : "The title of the icon picker sheet.",
"isCommentAutoGenerated" : true
@ -547,6 +611,10 @@
},
"Clear All Completions" : {
},
"Clear quick tasks" : {
"comment" : "Title of a habit preset within a \"Afternoon Deep Work\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Clear your desk" : {
"comment" : "Title of a habit preset for a productivity ritual.",
@ -556,6 +624,10 @@
"comment" : "Habit title for reviewing and clearing the user's inbox.",
"isCommentAutoGenerated" : true
},
"Close distracting apps" : {
"comment" : "Habit title for closing distracting apps during a focused work session.",
"isCommentAutoGenerated" : true
},
"Close loops, plan ahead" : {
"comment" : "Note for a ritual preset focused on closing daily tasks and planning for the next day.",
"isCommentAutoGenerated" : true
@ -576,6 +648,10 @@
"comment" : "Notes for a ritual preset focused on breaking up a day with midday activity.",
"isCommentAutoGenerated" : true
},
"Combat the afternoon energy dip with healthy habits." : {
"comment" : "Notes for a ritual preset focused on building healthy habits in the afternoon.",
"isCommentAutoGenerated" : true
},
"Coming up later:" : {
"comment" : "A label for a section of a view that lists rituals scheduled for times after the current time of day.",
"isCommentAutoGenerated" : true
@ -883,16 +959,8 @@
"comment" : "The header text for the \"Details\" section of the ritual edit sheet.",
"isCommentAutoGenerated" : true
},
"Digital Detox" : {
"comment" : "Title of a ritual preset that encourages disconnecting from screens to reconnect.",
"isCommentAutoGenerated" : true
},
"Dim lights 1 hour before bed" : {
"comment" : "Habit title for dimming lights one hour before bedtime.",
"isCommentAutoGenerated" : true
},
"Disconnect to reconnect" : {
"comment" : "Theme for the \"Digital Detox\" ritual preset.",
"Dim the lights" : {
"comment" : "Habit title from the \"Morning Hydration\" ritual preset, encouraging the user to dim the lights in their home.",
"isCommentAutoGenerated" : true
},
"Done" : {
@ -933,10 +1001,18 @@
"comment" : "Title of a habit within a preset ritual.",
"isCommentAutoGenerated" : true
},
"Drink herbal tea" : {
"comment" : "Title of a habit within a ritual preset, translated to a language other than English.",
"isCommentAutoGenerated" : true
},
"Drink water" : {
"comment" : "Habit title for drinking water.",
"isCommentAutoGenerated" : true
},
"Drink water or green tea" : {
"comment" : "Title of a habit within a ritual preset focused on healthy evening eating habits.",
"isCommentAutoGenerated" : true
},
"Duration" : {
"comment" : "A label displayed above the slider that controls the duration of a ritual.",
"isCommentAutoGenerated" : true
@ -963,14 +1039,22 @@
}
}
},
"Early bedtime" : {
"comment" : "Habit title for a ritual preset that encourages going to bed early.",
"isCommentAutoGenerated" : true
},
"Eat a healthy breakfast" : {
"comment" : "Title of a habit within a ritual preset, related to eating a healthy breakfast.",
"isCommentAutoGenerated" : true
},
"Eat a healthy snack" : {
"comment" : "Title of a habit in a ritual preset library.",
"isCommentAutoGenerated" : true
},
"Eat dinner before 7pm" : {
"comment" : "Habit title for a ritual preset that encourages eating dinner before 7 PM.",
"isCommentAutoGenerated" : true
},
"Eat without screens" : {
"comment" : "Title of a habit preset within the \"Mindful Lunch\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Edit" : {
"comment" : "A button label that translates to \"Edit\".",
"isCommentAutoGenerated" : true
@ -1009,6 +1093,10 @@
"comment" : "A string representation of a date, formatted to show the date only.",
"isCommentAutoGenerated" : true
},
"Enjoy a beverage mindfully" : {
"comment" : "Habit title for enjoying a beverage mindfully during a self-care ritual.",
"isCommentAutoGenerated" : true
},
"Enjoy this moment. Your next ritual will appear when it's time." : {
"comment" : "A motivational message displayed below the \"All caught up\" section in the \"Today\" view when there are no active rituals scheduled for the current time of day.",
"isCommentAutoGenerated" : true
@ -1017,8 +1105,8 @@
"comment" : "Description of a ritual scheduling option when the ritual should be visible in the Today view after 5pm.",
"isCommentAutoGenerated" : true
},
"Evening Reflection" : {
"comment" : "Title of a ritual preset that encourages users to reflect on their day.",
"Evening Nutrition" : {
"comment" : "Title of a ritual preset focused on healthy evening eating habits.",
"isCommentAutoGenerated" : true
},
"Evening Reset" : {
@ -1059,6 +1147,10 @@
"comment" : "Tip provided in the \"Completion\" insight card when the user has a high completion rate.",
"isCommentAutoGenerated" : true
},
"Eye cream" : {
"comment" : "Title of a habit preset within the \"Night Skincare\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Feel better each day" : {
"comment" : "Subtitle for the \"Health\" onboarding goal.",
"isCommentAutoGenerated" : true
@ -1174,8 +1266,8 @@
"comment" : "The text for the \"Get Started\" button in the welcome screen.",
"isCommentAutoGenerated" : true
},
"Give your mind a break from screens." : {
"comment" : "Notes for a ritual preset focused on giving the mind a break from screens.",
"Give yourself permission to rest." : {
"comment" : "Description of a habit in the \"Afternoon Break\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Good morning" : {
@ -1276,10 +1368,6 @@
}
}
},
"Have a real conversation" : {
"comment" : "Habit title for a ritual preset that encourages having a real conversation with someone.",
"isCommentAutoGenerated" : true
},
"Health" : {
"comment" : "Display name for the \"Health\" onboarding goal.",
"isCommentAutoGenerated" : true
@ -1296,6 +1384,10 @@
"comment" : "Title of the history view.",
"isCommentAutoGenerated" : true
},
"How are you feeling?" : {
"comment" : "Theme of a ritual preset for a quick check-in with yourself during the midday.",
"isCommentAutoGenerated" : true
},
"How to add" : {
"comment" : "CTA button label to show widget setup steps.",
"localizations" : {
@ -1377,6 +1469,10 @@
"comment" : "Description of the \"Active\" insight card, indicating the number of active rituals.",
"isCommentAutoGenerated" : true
},
"Include vegetables" : {
"comment" : "Habit title within a \"Health\" preset ritual, encouraging the user to include vegetables in their meals.",
"isCommentAutoGenerated" : true
},
"Insights" : {
"localizations" : {
"en" : {
@ -1465,10 +1561,18 @@
"comment" : "Habit within a RitualPreset related to creating a buffer between your day and sleep.",
"isCommentAutoGenerated" : true
},
"Listen to calming music" : {
"comment" : "Habit title for listening to calming music as part of a self-care ritual.",
"isCommentAutoGenerated" : true
},
"Longest streak" : {
"comment" : "Label for the longest streak breakdown item.",
"isCommentAutoGenerated" : true
},
"Look out a window" : {
"comment" : "Description of a habit preset related to taking a break outside.",
"isCommentAutoGenerated" : true
},
"Manage ritual categories" : {
"comment" : "Title of a navigation row in the Settings view that takes the user to a view managing ritual categories.",
"isCommentAutoGenerated" : true
@ -1482,15 +1586,27 @@
},
"Midday check-in" : {
},
"Midday Check-In" : {
"comment" : "Title of a ritual preset focused on maintaining momentum during the midday.",
"isCommentAutoGenerated" : true
},
"Midday Movement" : {
"comment" : "Title of a ritual preset that encourages regular physical activity during the day.",
"isCommentAutoGenerated" : true
},
"Midday Self-Check" : {
"comment" : "Title of a ritual preset that encourages a quick check-in with oneself during the midday.",
"isCommentAutoGenerated" : true
},
"Milestones" : {
"comment" : "A label displayed above the list of milestones.",
"isCommentAutoGenerated" : true
},
"Mindful Lunch" : {
"comment" : "Title of a ritual preset focused on mindful eating during lunch.",
"isCommentAutoGenerated" : true
},
"Mindful minute" : {
"localizations" : {
"en" : {
@ -1631,6 +1747,18 @@
"comment" : "Name for the time of day after 9pm.",
"isCommentAutoGenerated" : true
},
"Night Reflection" : {
"comment" : "Title of a ritual preset focused on closing the day with awareness and intention.",
"isCommentAutoGenerated" : true
},
"Night Skincare" : {
"comment" : "Title for a self-care ritual preset focused on nighttime skincare.",
"isCommentAutoGenerated" : true
},
"Nighttime skincare for rejuvenation." : {
"comment" : "Notes for the \"Night Skincare\" ritual preset.",
"isCommentAutoGenerated" : true
},
"No active arc" : {
"comment" : "A description shown when a ritual does not have an active arc.",
"isCommentAutoGenerated" : true
@ -1644,10 +1772,6 @@
},
"No active rituals to remind" : {
},
"No caffeine after 2pm" : {
"comment" : "Habit title for not consuming caffeine after 2 PM.",
"isCommentAutoGenerated" : true
},
"No completed arcs yet." : {
"comment" : "A message displayed when a ritual has no completed arcs.",
@ -1665,6 +1789,10 @@
"comment" : "A message displayed when no icons match the current search term.",
"isCommentAutoGenerated" : true
},
"No meetings block" : {
"comment" : "Description of a habit within a \"Afternoon Deep Work\" ritual preset.",
"isCommentAutoGenerated" : true
},
"No Past Rituals" : {
"comment" : "A description displayed when the user has no past rituals.",
"isCommentAutoGenerated" : true
@ -1695,8 +1823,8 @@
}
}
},
"No screens 1 hour before bed" : {
"comment" : "Habit title in a RitualPreset related to a \"Digital Detox\" ritual, encouraging users to avoid screens one hour before bedtime.",
"No screens in bed" : {
"comment" : "Habit title for a ritual preset that advises against using electronic devices in bed.",
"isCommentAutoGenerated" : true
},
"None" : {
@ -1751,10 +1879,26 @@
}
}
},
"Notice hunger and fullness" : {
"comment" : "Habit preset title that encourages users to pay attention to their hunger and fullness during meals.",
"isCommentAutoGenerated" : true
},
"Notice your mood" : {
"comment" : "Title of a habit preset in the \"Self-Care\" category, related to noticing one's mood.",
"isCommentAutoGenerated" : true
},
"Notice your posture" : {
"comment" : "Habit title in the \"Morning Meditation\" ritual preset, encouraging users to focus on their posture.",
"isCommentAutoGenerated" : true
},
"Notifications disabled in Settings" : {
"comment" : "Subtitle text for the reminder toggle when notifications are disabled in settings.",
"isCommentAutoGenerated" : true
},
"Nourish mindfully" : {
"comment" : "Theme for a ritual preset focused on nourishing oneself mindfully.",
"isCommentAutoGenerated" : true
},
"Nurture yourself" : {
"comment" : "Subtitle for the Self-Care goal in the onboarding screen.",
"isCommentAutoGenerated" : true
@ -1782,6 +1926,14 @@
"comment" : "Display name for the \"Past\" tab in the Rituals view.",
"isCommentAutoGenerated" : true
},
"Pause and nourish" : {
"comment" : "Theme of a ritual preset focused on practicing mindfulness during a midday meal.",
"isCommentAutoGenerated" : true
},
"Pause and recharge" : {
"comment" : "Description of a ritual preset for taking a break and recharging.",
"isCommentAutoGenerated" : true
},
"Perfect day! You crushed it." : {
"comment" : "A motivational message displayed when a user achieves 100% completion on a ritual.",
"isCommentAutoGenerated" : true
@ -1820,6 +1972,10 @@
}
}
},
"Power through" : {
"comment" : "Title of a ritual preset focused on focused afternoon work sessions.",
"isCommentAutoGenerated" : true
},
"Practice gratitude" : {
"comment" : "Habit title for a ritual preset focused on practicing gratitude.",
"isCommentAutoGenerated" : true
@ -1849,14 +2005,22 @@
"Preload 6 Months Demo Data" : {
},
"Prepare clothes for Monday" : {
"comment" : "Habit within a ritual preset to prepare clothes for Monday.",
"Prepare clothes" : {
"comment" : "Title of a habit preset in the \"Self-Care\" category, related to preparing for the next day.",
"isCommentAutoGenerated" : true
},
"Prepare for a fresh week" : {
"comment" : "Title of a ritual preset that encourages users to plan and prepare for the upcoming week.",
"isCommentAutoGenerated" : true
},
"Prepare for deep rest" : {
"comment" : "Subtitle for the \"Night\" time preference option in the onboarding screen.",
"isCommentAutoGenerated" : true
},
"Prepare for rest with a reminder when it's time for your night ritual" : {
"comment" : "Personalized description for the \"night\" ritual time preference in the \"NotificationStepView\".",
"isCommentAutoGenerated" : true
},
"Preset Library" : {
"comment" : "The title of the preset library sheet.",
"isCommentAutoGenerated" : true
@ -1895,6 +2059,14 @@
"comment" : "A section header for quick start actions.",
"isCommentAutoGenerated" : true
},
"Quick stretching break" : {
"comment" : "Title of a habit within a ritual preset, specifically for a habit related to stretching.",
"isCommentAutoGenerated" : true
},
"Rate your energy level" : {
"comment" : "Title of a habit in a ritual preset, related to self-care.",
"isCommentAutoGenerated" : true
},
"Read 10 pages" : {
"localizations" : {
"en" : {
@ -1917,10 +2089,6 @@
}
}
},
"Read a physical book" : {
"comment" : "Habit title for reading a physical book as part of a RitualPreset.",
"isCommentAutoGenerated" : true
},
"Real" : {
"comment" : "The text for the \"Real\" option in the time of day picker.",
"isCommentAutoGenerated" : true
@ -1963,6 +2131,10 @@
"comment" : "Habit title for releasing shoulder tension during mindfulness practice.",
"isCommentAutoGenerated" : true
},
"Release tension" : {
"comment" : "Title of a habit preset within the \"Mindfulness\" category, related to releasing tension.",
"isCommentAutoGenerated" : true
},
"Reload Widget Timelines" : {
},
@ -1974,6 +2146,14 @@
"comment" : "Title of a toggle in the settings view that controls whether reminders are enabled.",
"isCommentAutoGenerated" : true
},
"Remove makeup" : {
"comment" : "Title of a habit preset under the \"Night Skincare\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Repair and restore" : {
"comment" : "Note for the \"Night Skincare\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Reset Setup Wizard" : {
"comment" : "Title of a navigation row in the Settings view that resets the setup wizard state.",
"localizations" : {
@ -2013,6 +2193,10 @@
"comment" : "Habit title for reviewing their habits from the previous week.",
"isCommentAutoGenerated" : true
},
"Review morning progress" : {
"comment" : "Title of a habit within the \"Midday Check-In\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Review your day and set up tomorrow for success." : {
"comment" : "Notes for a ritual preset focused on closing loops and planning ahead for the next day.",
"isCommentAutoGenerated" : true
@ -2180,8 +2364,20 @@
"comment" : "A prompt for searching through habit icons.",
"isCommentAutoGenerated" : true
},
"Select all that apply" : {
"comment" : "A description below the list of time preference cards, instructing the user to select which times they prefer.",
"isCommentAutoGenerated" : true
},
"Self-Care" : {
},
"Set a 90-minute timer" : {
"comment" : "Habit title for a ritual preset focused on productivity, involving setting a 90-minute timer.",
"isCommentAutoGenerated" : true
},
"Set afternoon intention" : {
"comment" : "Habit preset title for setting an intention for the afternoon.",
"isCommentAutoGenerated" : true
},
"Set an intention for the day" : {
"comment" : "Habit title for a ritual preset focused on setting an intention for the day.",
@ -2195,6 +2391,10 @@
"comment" : "Habit title for setting a phone to \"Do Not Disturb\" during a ritual.",
"isCommentAutoGenerated" : true
},
"Set up for a focused afternoon work session." : {
"comment" : "Habit title for a ritual preset focused on productivity, specifically for an afternoon work session.",
"isCommentAutoGenerated" : true
},
"Set up for focus" : {
"comment" : "Theme of the \"Deep Work Prep\" ritual preset.",
"isCommentAutoGenerated" : true
@ -2363,9 +2563,25 @@
"comment" : "Subtitle for the \"Morning\" option in the \"Time of Day\" section of the onboarding screen.",
"isCommentAutoGenerated" : true
},
"Stay centered through the day" : {
"comment" : "Subtitle for a time preference option that focuses on staying centered throughout the day.",
"isCommentAutoGenerated" : true
},
"Stay centered with a reminder when it's time for your midday ritual" : {
"comment" : "Personalized description based on the user's selected time preference, for a \"midday\" ritual.",
"isCommentAutoGenerated" : true
},
"Stay on track" : {
"comment" : "Headline on the notification permission screen during onboarding."
},
"Step away from work" : {
"comment" : "Habit title for \"Step away from work\" in the \"Afternoon Break\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Step outside for fresh air" : {
"comment" : "Habit title for a ritual preset focused on maintaining good health, encouraging the user to step outside for fresh air.",
"isCommentAutoGenerated" : true
},
"Streak" : {
"comment" : "Title of a section in the Insight Cards view, related to streaks of consecutive perfect days.",
"isCommentAutoGenerated" : true
@ -2396,8 +2612,8 @@
"comment" : "Habit title for a ritual preset focused on health, encouraging users to stretch while working at their desk.",
"isCommentAutoGenerated" : true
},
"Sunday evening ritual to start Monday strong." : {
"comment" : "Description of a ritual preset that serves as a weekly reset to help users start their week on a positive note.",
"Sunday ritual to start Monday strong." : {
"comment" : "Description of a ritual preset for starting a new week with a sense of accomplishment.",
"isCommentAutoGenerated" : true
},
"Take 5 deep breaths" : {
@ -2649,8 +2865,9 @@
"comment" : "Description of a feature card in the \"WhatsNextStepView\" that explains how to manage all your rituals, regardless of the time they were created.",
"isCommentAutoGenerated" : true
},
"We'll remind you at the perfect times for your morning and evening rituals" : {
"comment" : "Description for notification permission screen when user selected both morning and evening rituals."
"We'll remind you at the perfect times for your rituals throughout the day" : {
"comment" : "Personalized description based on the user's selected time preference, indicating that reminders will be set at the perfect times for each ritual throughout the day.",
"isCommentAutoGenerated" : true
},
"Weekly average" : {
"comment" : "Caption for the 7-Day Avg insight card."
@ -2761,6 +2978,10 @@
}
}
},
"Work on one important task" : {
"comment" : "Title of a habit preset within a \"Productivity\" ritual preset.",
"isCommentAutoGenerated" : true
},
"Write 3 things you're grateful for" : {
"comment" : "Title of a habit within a RitualPreset focused on gratitude practice.",
"isCommentAutoGenerated" : true

View File

@ -51,32 +51,40 @@ enum OnboardingGoal: String, CaseIterable, Identifiable {
/// User's preferred time for building habits.
enum OnboardingTimePreference: String, CaseIterable, Identifiable {
case morning
case midday
case afternoon
case evening
case both
case night
var id: String { rawValue }
var displayName: String {
switch self {
case .morning: return String(localized: "Morning")
case .midday: return String(localized: "Midday")
case .afternoon: return String(localized: "Afternoon")
case .evening: return String(localized: "Evening")
case .both: return String(localized: "Both")
case .night: return String(localized: "Night")
}
}
var subtitle: String {
switch self {
case .morning: return String(localized: "Start your day right")
case .midday: return String(localized: "Stay centered through the day")
case .afternoon: return String(localized: "Beat the slump")
case .evening: return String(localized: "Wind down with intention")
case .both: return String(localized: "Bookend your day")
case .night: return String(localized: "Prepare for deep rest")
}
}
var symbolName: String {
switch self {
case .morning: return "sunrise.fill"
case .evening: return "moon.fill"
case .both: return "circle.righthalf.filled"
case .midday: return "sun.max.fill"
case .afternoon: return "sun.horizon.fill"
case .evening: return "sunset.fill"
case .night: return "moon.zzz.fill"
}
}
@ -84,8 +92,10 @@ enum OnboardingTimePreference: String, CaseIterable, Identifiable {
var timeOfDayFilters: [TimeOfDay] {
switch self {
case .morning: return [.morning]
case .midday: return [.midday]
case .afternoon: return [.afternoon]
case .evening: return [.evening]
case .both: return [.morning, .evening]
case .night: return [.night]
}
}
}
@ -111,6 +121,16 @@ enum OnboardingPresetRecommender {
return matchingPresets.first ?? categoryPresets.first
}
/// Returns the recommended preset for a given goal and specific time of day.
/// - Parameters:
/// - goal: The user's selected goal
/// - timeOfDay: The specific time of day
/// - Returns: A ritual preset, or nil if none matches
static func recommendedPreset(for goal: OnboardingGoal, timeOfDay: TimeOfDay) -> RitualPreset? {
let categoryPresets = RitualPresetLibrary.presets(for: goal.presetCategory)
return categoryPresets.first { $0.timeOfDay == timeOfDay }
}
/// Returns all recommended presets when user selects "Both" for time.
/// - Parameter goal: The user's selected goal
/// - Returns: Morning and evening presets for the goal

View File

@ -4,7 +4,7 @@ import Bedrock
/// The notification permission screen where users can enable reminders.
/// Shown after the first check-in to maximize conversion after experiencing value.
struct NotificationStepView: View {
let selectedTime: OnboardingTimePreference?
let selectedTimes: Set<OnboardingTimePreference>
let reminderScheduler: ReminderScheduler
let onComplete: () -> Void
@ -15,16 +15,26 @@ struct NotificationStepView: View {
/// Personalized description based on the user's selected time preference
private var personalizedDescription: String {
switch selectedTime {
case .morning:
return String(localized: "Get a gentle nudge each morning to start your day right")
case .evening:
return String(localized: "Wind down with a reminder when it's time for your evening ritual")
case .both:
return String(localized: "We'll remind you at the perfect times for your morning and evening rituals")
case nil:
if selectedTimes.isEmpty {
return String(localized: "Get a gentle reminder when it's time for your rituals")
}
if selectedTimes.count == 1, let first = selectedTimes.first {
switch first {
case .morning:
return String(localized: "Get a gentle nudge each morning to start your day right")
case .midday:
return String(localized: "Stay centered with a reminder when it's time for your midday ritual")
case .afternoon:
return String(localized: "Beat the slump with a reminder when it's time for your afternoon ritual")
case .evening:
return String(localized: "Wind down with a reminder when it's time for your evening ritual")
case .night:
return String(localized: "Prepare for rest with a reminder when it's time for your night ritual")
}
}
return String(localized: "We'll remind you at the perfect times for your rituals throughout the day")
}
var body: some View {
@ -186,7 +196,7 @@ struct NotificationStepView: View {
.ignoresSafeArea()
NotificationStepView(
selectedTime: .morning,
selectedTimes: [.morning],
reminderScheduler: ReminderScheduler(),
onComplete: {}
)

View File

@ -11,7 +11,7 @@ struct SetupWizardView: View {
@State private var currentStep: WizardStep = .welcome
@State private var selectedGoals: [OnboardingGoal] = []
@State private var selectedTime: OnboardingTimePreference?
@State private var selectedTimes: Set<OnboardingTimePreference> = []
// Track created rituals during onboarding
@State private var createdRituals: [Ritual] = []
@ -33,11 +33,6 @@ struct SetupWizardView: View {
case whatsNext = 6
}
/// Whether the user selected "Both" for time preference
private var isBothMode: Bool {
selectedTime == .both
}
/// The first ritual that was created (for first check-in)
private var firstCreatedRitual: Ritual? {
createdRituals.first
@ -104,7 +99,7 @@ struct SetupWizardView: View {
case .timeSelection:
TimeSelectionStepView(
selectedTime: $selectedTime,
selectedTimes: $selectedTimes,
onContinue: handleTimeSelectionContinue
)
@ -131,7 +126,7 @@ struct SetupWizardView: View {
case .notifications:
NotificationStepView(
selectedTime: selectedTime,
selectedTimes: selectedTimes,
reminderScheduler: reminderScheduler,
onComplete: { advanceToWhatsNext() }
)
@ -273,26 +268,22 @@ struct SetupWizardView: View {
// MARK: - Time Selection Handler
private func handleTimeSelectionContinue() {
guard let time = selectedTime, !selectedGoals.isEmpty else { return }
guard !selectedTimes.isEmpty, !selectedGoals.isEmpty else { return }
var presets: [RitualPreset] = []
for goal in selectedGoals {
switch time {
case .morning:
if let preset = OnboardingPresetRecommender.recommendedPreset(for: goal, time: .morning) {
// Collect all unique filters from all selected time preferences
let allFilters = selectedTimes.reduce(into: Set<TimeOfDay>()) { result, preference in
preference.timeOfDayFilters.forEach { result.insert($0) }
}
// Sort filters to maintain a logical order (morning -> night)
let sortedFilters = allFilters.sorted { $0.rawValue < $1.rawValue }
for filter in sortedFilters {
if let preset = OnboardingPresetRecommender.recommendedPreset(for: goal, timeOfDay: filter) {
presets.append(preset)
}
case .evening:
if let preset = OnboardingPresetRecommender.recommendedPreset(for: goal, time: .evening) {
presets.append(preset)
}
case .both:
if let morningPreset = OnboardingPresetRecommender.recommendedPreset(for: goal, time: .morning) {
presets.append(morningPreset)
}
if let eveningPreset = OnboardingPresetRecommender.recommendedPreset(for: goal, time: .evening) {
presets.append(eveningPreset)
}
}
}

View File

@ -3,7 +3,7 @@ import Bedrock
/// The time selection screen where users choose when they want to build habits.
struct TimeSelectionStepView: View {
@Binding var selectedTime: OnboardingTimePreference?
@Binding var selectedTimes: Set<OnboardingTimePreference>
let onContinue: () -> Void
@State private var animateCards = false
@ -19,19 +19,22 @@ struct TimeSelectionStepView: View {
.typography(.title2Bold)
.foregroundStyle(AppTextColors.primary)
.multilineTextAlignment(.center)
Text(String(localized: "Select all that apply"))
.typography(.subheading)
.foregroundStyle(AppTextColors.secondary)
}
.padding(.horizontal, Design.Spacing.large)
// Time preference cards
ScrollView(showsIndicators: false) {
VStack(spacing: Design.Spacing.medium) {
ForEach(Array(OnboardingTimePreference.allCases.enumerated()), id: \.element.id) { index, time in
TimeCardView(
time: time,
isSelected: selectedTime == time,
isSelected: selectedTimes.contains(time),
onTap: {
withAnimation(.easeInOut(duration: Design.Animation.quick)) {
selectedTime = time
}
toggleSelection(time)
}
)
.opacity(animateCards ? 1 : 0)
@ -43,11 +46,13 @@ struct TimeSelectionStepView: View {
}
}
.padding(.horizontal, Design.Spacing.large)
.padding(.bottom, Design.Spacing.large)
}
Spacer()
// Continue button (only shown when a time is selected)
if selectedTime != nil {
// Continue button (only shown when at least one time is selected)
if !selectedTimes.isEmpty {
Button(action: onContinue) {
Text(String(localized: "Continue"))
.typography(.heading)
@ -62,13 +67,23 @@ struct TimeSelectionStepView: View {
.transition(.move(edge: .bottom).combined(with: .opacity))
}
}
.animation(.easeInOut(duration: Design.Animation.quick), value: selectedTime != nil)
.animation(.easeInOut(duration: Design.Animation.quick), value: !selectedTimes.isEmpty)
.onAppear {
withAnimation {
animateCards = true
}
}
}
private func toggleSelection(_ time: OnboardingTimePreference) {
withAnimation(.easeInOut(duration: Design.Animation.quick)) {
if selectedTimes.contains(time) {
selectedTimes.remove(time)
} else {
selectedTimes.insert(time)
}
}
}
}
/// A single time preference card.
@ -131,7 +146,7 @@ private struct TimeCardView: View {
.ignoresSafeArea()
TimeSelectionStepView(
selectedTime: .constant(nil),
selectedTimes: .constant([]),
onContinue: {}
)
}