diff --git a/Andromida/App/Localization/Localizable.xcstrings b/Andromida/App/Localization/Localizable.xcstrings index b6460c2..46d18aa 100644 --- a/Andromida/App/Localization/Localizable.xcstrings +++ b/Andromida/App/Localization/Localizable.xcstrings @@ -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 diff --git a/Andromida/App/Models/OnboardingGoal.swift b/Andromida/App/Models/OnboardingGoal.swift index 8775c3c..057a9bd 100644 --- a/Andromida/App/Models/OnboardingGoal.swift +++ b/Andromida/App/Models/OnboardingGoal.swift @@ -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] } } } @@ -110,6 +120,16 @@ enum OnboardingPresetRecommender { // Return first matching preset, or first category preset as fallback 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 diff --git a/Andromida/App/Views/Onboarding/NotificationStepView.swift b/Andromida/App/Views/Onboarding/NotificationStepView.swift index 1fb1f95..f6b13a8 100644 --- a/Andromida/App/Views/Onboarding/NotificationStepView.swift +++ b/Andromida/App/Views/Onboarding/NotificationStepView.swift @@ -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 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: {} ) diff --git a/Andromida/App/Views/Onboarding/SetupWizardView.swift b/Andromida/App/Views/Onboarding/SetupWizardView.swift index f064bdf..82bcd5e 100644 --- a/Andromida/App/Views/Onboarding/SetupWizardView.swift +++ b/Andromida/App/Views/Onboarding/SetupWizardView.swift @@ -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 = [] // 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()) { 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) - } } } diff --git a/Andromida/App/Views/Onboarding/TimeSelectionStepView.swift b/Andromida/App/Views/Onboarding/TimeSelectionStepView.swift index 97d384d..0b40846 100644 --- a/Andromida/App/Views/Onboarding/TimeSelectionStepView.swift +++ b/Andromida/App/Views/Onboarding/TimeSelectionStepView.swift @@ -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 let onContinue: () -> Void @State private var animateCards = false @@ -19,35 +19,40 @@ 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 - VStack(spacing: Design.Spacing.medium) { - ForEach(Array(OnboardingTimePreference.allCases.enumerated()), id: \.element.id) { index, time in - TimeCardView( - time: time, - isSelected: selectedTime == time, - onTap: { - withAnimation(.easeInOut(duration: Design.Animation.quick)) { - selectedTime = time + ScrollView(showsIndicators: false) { + VStack(spacing: Design.Spacing.medium) { + ForEach(Array(OnboardingTimePreference.allCases.enumerated()), id: \.element.id) { index, time in + TimeCardView( + time: time, + isSelected: selectedTimes.contains(time), + onTap: { + toggleSelection(time) } - } - ) - .opacity(animateCards ? 1 : 0) - .offset(y: animateCards ? 0 : 20) - .animation( - .easeOut(duration: 0.4).delay(Double(index) * 0.1), - value: animateCards - ) + ) + .opacity(animateCards ? 1 : 0) + .offset(y: animateCards ? 0 : 20) + .animation( + .easeOut(duration: 0.4).delay(Double(index) * 0.1), + value: animateCards + ) + } } + .padding(.horizontal, Design.Spacing.large) + .padding(.bottom, Design.Spacing.large) } - .padding(.horizontal, 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: {} ) }