diff --git a/Andromida/App/Localization/Localizable.xcstrings b/Andromida/App/Localization/Localizable.xcstrings index b037eb8..4d15420 100644 --- a/Andromida/App/Localization/Localizable.xcstrings +++ b/Andromida/App/Localization/Localizable.xcstrings @@ -1682,7 +1682,6 @@ } }, "Branding Preview" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -2101,7 +2100,6 @@ } }, "Clear All Completions" : { - "extractionState" : "stale", "localizations" : { "es-MX" : { "stringUnit" : { @@ -2352,7 +2350,6 @@ } }, "Complete First Active Arc (Test Renewal)" : { - "extractionState" : "stale", "localizations" : { "es-MX" : { "stringUnit" : { @@ -2949,7 +2946,6 @@ } }, "Debug" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -3957,7 +3953,6 @@ } }, "Generate the app icon" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -4471,7 +4466,6 @@ } }, "Icon Generator" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -6094,7 +6088,6 @@ } }, "Preload 6 Months Demo Data" : { - "extractionState" : "stale", "localizations" : { "es-MX" : { "stringUnit" : { @@ -6219,7 +6212,6 @@ } }, "Preview launch and icon" : { - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -6337,7 +6329,6 @@ }, "Real" : { "comment" : "The text for the \"Real\" option in the time of day picker.", - "extractionState" : "stale", "isCommentAutoGenerated" : true, "localizations" : { "es-MX" : { @@ -6356,7 +6347,6 @@ }, "Real Time (%@)" : { "comment" : "Text displayed in the debug picker to indicate whether it is showing the real time or a simulated time.", - "extractionState" : "stale", "isCommentAutoGenerated" : true, "localizations" : { "es-MX" : { @@ -6468,7 +6458,6 @@ } }, "Reload Widget Timelines" : { - "extractionState" : "stale", "localizations" : { "es-MX" : { "stringUnit" : { @@ -6558,7 +6547,6 @@ }, "Reset Setup Wizard" : { "comment" : "Title of a navigation row in the Settings view that resets the setup wizard state.", - "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -7245,7 +7233,6 @@ }, "Simulate Foreground Refresh" : { "comment" : "Title of a settings option that simulates a foreground refresh of the app.", - "extractionState" : "stale", "isCommentAutoGenerated" : true, "localizations" : { "es-MX" : { @@ -7264,7 +7251,6 @@ }, "Simulate Time of Day" : { "comment" : "A label for the time of day picker.", - "extractionState" : "stale", "isCommentAutoGenerated" : true, "localizations" : { "es-MX" : { @@ -8513,7 +8499,6 @@ }, "Trigger Test Notification (5s)" : { "comment" : "Title of a settings option that triggers a test local notification.", - "extractionState" : "stale", "isCommentAutoGenerated" : true, "localizations" : { "es-MX" : { diff --git a/Andromida/App/Views/Settings/SettingsView.swift b/Andromida/App/Views/Settings/SettingsView.swift index 712525c..f010ccb 100644 --- a/Andromida/App/Views/Settings/SettingsView.swift +++ b/Andromida/App/Views/Settings/SettingsView.swift @@ -24,6 +24,8 @@ struct SettingsView: View { isOn: remindersBinding, accentColor: AppAccent.primary ) + + SettingsDivider(color: AppBorder.subtle) SettingsToggle( title: String(localized: "Haptics"), @@ -31,6 +33,8 @@ struct SettingsView: View { isOn: $store.hapticsEnabled, accentColor: AppAccent.primary ) + + SettingsDivider(color: AppBorder.subtle) SettingsToggle( title: String(localized: "Sound"), @@ -53,10 +57,12 @@ struct SettingsView: View { ) if let categoryStore { + SettingsDivider(color: AppBorder.subtle) + SettingsNavigationRow( title: String(localized: "Categories"), subtitle: String(localized: "Manage ritual categories"), - backgroundColor: AppSurface.primary + backgroundColor: .clear ) { CategoryListView(store: categoryStore) } @@ -88,7 +94,7 @@ struct SettingsView: View { SettingsNavigationRow( title: String(localized: "Rituals mission"), subtitle: String(localized: "Why arcs keep habits grounded"), - backgroundColor: AppSurface.primary + backgroundColor: .clear ) { SettingsAboutView() } @@ -105,15 +111,17 @@ struct SettingsView: View { SettingsNavigationRow( title: String(localized: "Icon Generator"), subtitle: String(localized: "Generate the app icon"), - backgroundColor: AppSurface.primary + backgroundColor: .clear ) { IconGeneratorView(config: .rituals, appName: "Rituals") } + + SettingsDivider(color: AppBorder.subtle) SettingsNavigationRow( title: String(localized: "Branding Preview"), subtitle: String(localized: "Preview launch and icon"), - backgroundColor: AppSurface.primary + backgroundColor: .clear ) { BrandingPreviewView( iconConfig: .rituals, @@ -121,8 +129,10 @@ struct SettingsView: View { appName: "Rituals" ) } + + SettingsDivider(color: AppBorder.subtle) - SettingsRow( + SettingsDebugActionRow( systemImage: "arrow.counterclockwise", title: String(localized: "Reset Setup Wizard"), iconColor: AppStatus.warning @@ -133,7 +143,9 @@ struct SettingsView: View { } if let ritualStore { - SettingsRow( + SettingsDivider(color: AppBorder.subtle) + + SettingsDebugActionRow( systemImage: "calendar.badge.plus", title: String(localized: "Preload 6 Months Demo Data"), iconColor: AppStatus.info @@ -142,7 +154,9 @@ struct SettingsView: View { } .accessibilityIdentifier("settings.debug.preloadDemoData") - SettingsRow( + SettingsDivider(color: AppBorder.subtle) + + SettingsDebugActionRow( systemImage: "checkmark.circle.badge.xmark", title: String(localized: "Complete First Active Arc (Test Renewal)"), iconColor: AppStatus.success @@ -150,7 +164,9 @@ struct SettingsView: View { ritualStore.simulateArcCompletion() } - SettingsRow( + SettingsDivider(color: AppBorder.subtle) + + SettingsDebugActionRow( systemImage: "trash", title: String(localized: "Clear All Completions"), iconColor: AppStatus.error @@ -158,7 +174,9 @@ struct SettingsView: View { ritualStore.clearAllCompletions() } - SettingsRow( + SettingsDivider(color: AppBorder.subtle) + + SettingsDebugActionRow( systemImage: "bell.badge", title: String(localized: "Trigger Test Notification (5s)"), iconColor: AppStatus.info @@ -167,7 +185,9 @@ struct SettingsView: View { } } - SettingsRow( + SettingsDivider(color: AppBorder.subtle) + + SettingsDebugActionRow( systemImage: "arrow.clockwise", title: String(localized: "Simulate Foreground Refresh"), iconColor: AppStatus.info @@ -175,7 +195,9 @@ struct SettingsView: View { UserDefaults.standard.set(true, forKey: "debugForegroundRefreshNextForeground") } - SettingsRow( + SettingsDivider(color: AppBorder.subtle) + + SettingsDebugActionRow( systemImage: "widget.small", title: String(localized: "Reload Widget Timelines"), iconColor: AppAccent.primary @@ -184,7 +206,11 @@ struct SettingsView: View { } if let ritualStore { - TimeOfDayDebugPicker(store: ritualStore) + SettingsDivider(color: AppBorder.subtle) + + SettingsCardRow { + TimeOfDayDebugPicker(store: ritualStore) + } } } #endif @@ -257,6 +283,37 @@ extension SettingsView { // MARK: - Debug Time of Day Picker #if DEBUG +private struct SettingsDebugActionRow: View { + let systemImage: String + let title: String + let iconColor: Color + let action: () -> Void + + var body: some View { + SettingsCardRow { + Button(action: action) { + HStack(spacing: Design.Spacing.medium) { + SymbolIcon(systemImage, size: .inline, color: .white) + .frame(width: Design.Size.iconContainerSmall, height: Design.Size.iconContainerSmall) + .background(iconColor.opacity(Design.Opacity.heavy)) + .clipShape(.rect(cornerRadius: Design.CornerRadius.xSmall)) + + Text(title).styled(.subheading) + + Spacer() + + SymbolIcon.chevron() + } + .padding(.vertical, Design.Spacing.medium) + .padding(.horizontal, Design.Spacing.medium) + .background(Color(.secondarySystemGroupedBackground)) + .clipShape(.rect(cornerRadius: Design.CornerRadius.small)) + } + .buttonStyle(.plain) + } + } +} + /// Debug picker for simulating different times of day private struct TimeOfDayDebugPicker: View { @Bindable var store: RitualStore @@ -328,7 +385,6 @@ private struct TimeOfDayDebugPicker: View { } } } - .padding(.horizontal, Design.Spacing.medium) } } #endif diff --git a/README.md b/README.md index 32bc6ad..12d591d 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ Andromida/ - **Theming**: App-specific color providers + `AppSurface`, `AppAccent`, etc. - **Branding**: AppLaunchView, AppIconConfig, LaunchScreenConfig -- **Settings UI**: SettingsToggle, SettingsSlider, SettingsSegmentedPicker, SettingsCard +- **Settings UI**: `SettingsCard` owns row insets; use `SettingsDivider` between rows, `SettingsCardRow` for custom rows, and `SettingsNavigationRow(backgroundColor: .clear)` for in-card navigation - **Cloud Sync**: iCloud sync for settings using CloudSyncManager - **Onboarding**: Custom `SetupWizardView` flow (Sherpa integration pending)