Compare commits

...

2 Commits

2 changed files with 21 additions and 88 deletions

View File

@ -84,14 +84,7 @@ struct SettingsView: View {
SettingsSectionHeader(title: "Display", systemImage: "eye", accentColor: AppAccent.primary)
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
// True Mirror (premium)
premiumToggle(
title: String(localized: "True Mirror"),
subtitle: String(localized: "Shows horizontally flipped preview like a real mirror"),
isOn: $viewModel.isMirrorFlipped,
accessibilityHint: String(localized: "Flips the camera preview horizontally")
)
SettingsToggle(
title: String(localized: "Grid Overlay"),
subtitle: String(localized: "Shows rule of thirds grid for composition"),
@ -100,6 +93,14 @@ struct SettingsView: View {
)
.accessibilityHint(String(localized: "Shows a grid overlay to help compose your shot"))
// True Mirror (premium)
premiumToggle(
title: String(localized: "True Mirror"),
subtitle: String(localized: "Shows horizontally flipped preview like a real mirror"),
isOn: $viewModel.isMirrorFlipped,
accessibilityHint: String(localized: "Flips the camera preview horizontally")
)
// Skin Smoothing (premium)
premiumToggle(
title: String(localized: "Skin Smoothing"),
@ -114,8 +115,6 @@ struct SettingsView: View {
SettingsSectionHeader(title: "Capture", systemImage: "photo.on.rectangle", accentColor: AppAccent.primary)
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
// Timer Selection
timerPicker
SettingsToggle(
title: String(localized: "Auto-Save"),
@ -124,6 +123,10 @@ struct SettingsView: View {
accentColor: AppAccent.primary
)
.accessibilityHint(String(localized: "When enabled, photos and videos are saved immediately after capture"))
// Timer Selection
timerPicker
}
// MARK: - Pro Section
@ -514,82 +517,12 @@ struct SettingsView: View {
// MARK: - iCloud Sync Section
private var iCloudSyncSection: some View {
VStack(alignment: .leading, spacing: Design.Spacing.small) {
// Sync toggle
Toggle(isOn: $viewModel.iCloudEnabled) {
VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
Text(String(localized: "Sync Settings"))
.font(.system(size: Design.BaseFontSize.medium, weight: .medium))
.foregroundStyle(.white)
Text(viewModel.iCloudAvailable
? String(localized: "Sync settings across all your devices")
: String(localized: "Sign in to iCloud to enable sync"))
.font(.system(size: Design.BaseFontSize.body))
.foregroundStyle(.white.opacity(Design.Opacity.medium))
}
}
.tint(AppAccent.primary)
.padding(.vertical, Design.Spacing.xSmall)
.disabled(!viewModel.iCloudAvailable)
.accessibilityHint(String(localized: "Syncs settings across all your devices via iCloud"))
// Sync status (show when enabled and available)
if viewModel.iCloudEnabled && viewModel.iCloudAvailable {
HStack(spacing: Design.Spacing.small) {
Image(systemName: syncStatusIcon)
.font(.system(size: Design.BaseFontSize.body))
.foregroundStyle(syncStatusColor)
Text(syncStatusText)
.font(.system(size: Design.BaseFontSize.caption))
.foregroundStyle(.white.opacity(Design.Opacity.medium))
Spacer()
Button {
viewModel.forceSync()
} label: {
Text(String(localized: "Sync Now"))
.font(.system(size: Design.BaseFontSize.caption, weight: .medium))
.foregroundStyle(AppAccent.primary)
}
}
.padding(.top, Design.Spacing.xSmall)
}
}
}
// MARK: - Sync Status Helpers
private var syncStatusIcon: String {
if !viewModel.hasCompletedInitialSync {
return "arrow.triangle.2.circlepath"
}
return viewModel.syncStatus.isEmpty ? "checkmark.icloud" : "icloud"
}
private var syncStatusColor: Color {
if !viewModel.hasCompletedInitialSync {
return AppStatus.warning
}
return AppStatus.success
}
private var syncStatusText: String {
if !viewModel.hasCompletedInitialSync {
return String(localized: "Syncing...")
}
if let lastSync = viewModel.lastSyncDate {
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .abbreviated
return String(localized: "Last synced \(formatter.localizedString(for: lastSync, relativeTo: Date()))")
}
return viewModel.syncStatus.isEmpty
? String(localized: "Synced")
: viewModel.syncStatus
iCloudSyncSettingsView(
viewModel: viewModel,
accentColor: AppAccent.primary,
successColor: AppStatus.success,
warningColor: AppStatus.warning
)
}
// MARK: - Acknowledgments Section
@ -680,7 +613,7 @@ struct SettingsView: View {
title: "Enable Debug Premium",
subtitle: "Unlock all premium features for testing",
isOn: $viewModel.isDebugPremiumEnabled,
accentColor: AppStatus.warning
accentColor: AppAccent.primary
)
// Icon Generator

View File

@ -38,7 +38,7 @@ enum TimerOption: String, CaseIterable, Identifiable {
/// Premium features are automatically reset to defaults when user doesn't have premium.
@MainActor
@Observable
final class SettingsViewModel: RingLightConfigurable {
final class SettingsViewModel: RingLightConfigurable, CloudSyncable {
// MARK: - Ring Size Limits