diff --git a/app/src/main/java/app/closer/ui/onboarding/OnboardingScreen.kt b/app/src/main/java/app/closer/ui/onboarding/OnboardingScreen.kt index 481ee8ba..01660e33 100644 --- a/app/src/main/java/app/closer/ui/onboarding/OnboardingScreen.kt +++ b/app/src/main/java/app/closer/ui/onboarding/OnboardingScreen.kt @@ -143,7 +143,7 @@ fun OnboardingScreen( ) 2 -> ValueSlide( visual = { GrowerVisual() }, - headline = "Grow closer", + headline = "Grow Closer", body = "Every answer opens a real conversation. Not a quiz — a moment." ) else -> CtaSlide(onNavigate = onNavigate) diff --git a/app/src/main/java/app/closer/ui/settings/SettingsScreen.kt b/app/src/main/java/app/closer/ui/settings/SettingsScreen.kt index 06d74dca..60c734b1 100644 --- a/app/src/main/java/app/closer/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/app/closer/ui/settings/SettingsScreen.kt @@ -100,7 +100,9 @@ fun SettingsSubpage( ) } }, - colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent) + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background + ) ) } ) { padding -> content(padding) } @@ -197,7 +199,9 @@ fun SettingsScreen( color = SettingsInk ) }, - colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent) + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background + ) ) } ) { padding -> @@ -394,81 +398,72 @@ fun SettingsScreen( Spacer(Modifier.height(4.dp)) - // General section - Card( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = SettingsCard) - ) { - Column { - SettingsRow( - icon = Icons.Filled.Done, - label = "Answer History", - onClick = { onNavigate(AppRoute.ANSWER_HISTORY) } - ) - Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) - SettingsRow( - icon = Icons.AutoMirrored.Filled.TrendingUp, - label = "Your Progress", - onClick = { onNavigate(AppRoute.YOUR_PROGRESS) } - ) - Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) - SettingsRow( - icon = Icons.Filled.Palette, - label = "Appearance", - onClick = { onNavigate(AppRoute.APPEARANCE) } - ) - Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) - SettingsRow( - icon = Icons.Filled.Notifications, - label = "Notifications", - onClick = { onNavigate(AppRoute.NOTIFICATIONS) } - ) - Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) - SettingsRow( - icon = Icons.Filled.Star, - label = "Subscription", - onClick = { onNavigate(AppRoute.SUBSCRIPTION) } - ) - Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) - SettingsRow( - icon = Icons.Filled.Lock, - label = "Privacy & Terms", - onClick = { onNavigate(AppRoute.PRIVACY) } - ) - } + SettingsSection(title = "For the two of you") { + SettingsRow( + icon = Icons.Filled.Done, + label = "Answer History", + subtitle = "Revisit the moments you have shared", + onClick = { onNavigate(AppRoute.ANSWER_HISTORY) } + ) + SettingsSectionDivider() + SettingsRow( + icon = Icons.AutoMirrored.Filled.TrendingUp, + label = "Your Progress", + subtitle = "See patterns, check-ins, and growth", + onClick = { onNavigate(AppRoute.YOUR_PROGRESS) } + ) } - Spacer(Modifier.height(8.dp)) + SettingsSection(title = "Your rhythm") { + SettingsRow( + icon = Icons.Filled.Notifications, + label = "Notifications", + subtitle = "Set gentle reminders that fit your day", + onClick = { onNavigate(AppRoute.NOTIFICATIONS) } + ) + SettingsSectionDivider() + SettingsRow( + icon = Icons.Filled.Palette, + label = "Appearance", + subtitle = "Make Closer feel comfortable to open", + onClick = { onNavigate(AppRoute.APPEARANCE) } + ) + } - // Security - Card( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = SettingsCard) - ) { + SettingsSection(title = "Premium") { + SettingsRow( + icon = Icons.Filled.Favorite, + label = "Subscription", + subtitle = "Manage one plan for both partners", + onClick = { onNavigate(AppRoute.SUBSCRIPTION) }, + tint = SettingsPrimaryDeep + ) + } + + SettingsSection(title = "Privacy and safety") { SettingsRow( icon = Icons.Filled.Lock, label = "Security", + subtitle = "Recovery phrase and account protection", onClick = { onNavigate(AppRoute.SECURITY) } ) + SettingsSectionDivider() + SettingsRow( + icon = Icons.Filled.Lock, + label = "Privacy & Terms", + subtitle = "Your data, policies, and legal details", + onClick = { onNavigate(AppRoute.PRIVACY) } + ) } - Spacer(Modifier.height(8.dp)) - // Account lifecycle - Card( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = SettingsCard) - ) { - Column { - SettingsRow( - icon = Icons.Filled.Warning, - label = "Delete account", - onClick = { onNavigate(AppRoute.DELETE_ACCOUNT) }, - tint = SettingsDanger - ) - } + SettingsSection(title = "Account") { + SettingsRow( + icon = Icons.Filled.Warning, + label = "Delete account", + subtitle = "Permanently remove your Closer account", + onClick = { onNavigate(AppRoute.DELETE_ACCOUNT) }, + tint = SettingsDanger + ) } Spacer(Modifier.height(8.dp)) @@ -500,6 +495,7 @@ fun SettingsScreen( private fun SettingsRow( icon: ImageVector, label: String, + subtitle: String? = null, onClick: () -> Unit, tint: androidx.compose.ui.graphics.Color = SettingsMuted ) { @@ -507,19 +503,32 @@ private fun SettingsRow( modifier = Modifier .fillMaxWidth() .clickable(onClick = onClick) - .padding(horizontal = 16.dp, vertical = 14.dp), + .padding(horizontal = 16.dp, vertical = if (subtitle == null) 14.dp else 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp) ) { Icon(icon, contentDescription = null, tint = tint) - Text( - text = label, - style = MaterialTheme.typography.bodyLarge, - color = if (tint == SettingsMuted) SettingsInk else tint, + Column( modifier = Modifier.weight(1f), - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) + verticalArrangement = Arrangement.spacedBy(2.dp) + ) { + Text( + text = label, + style = MaterialTheme.typography.bodyLarge, + color = if (tint == SettingsMuted) SettingsInk else tint, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + subtitle?.let { + Text( + text = it, + style = MaterialTheme.typography.bodySmall, + color = SettingsMuted, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } Icon( Icons.AutoMirrored.Filled.ArrowForwardIos, contentDescription = null, diff --git a/iphone/Closer/Settings/SettingsViews.swift b/iphone/Closer/Settings/SettingsViews.swift index 110d713f..db80f073 100644 --- a/iphone/Closer/Settings/SettingsViews.swift +++ b/iphone/Closer/Settings/SettingsViews.swift @@ -14,132 +14,136 @@ struct SettingsView: View { var body: some View { NavigationStack { List { - // Profile section Section { - VStack(spacing: CloserSpacing.sm) { - Circle() - .fill(Color.closerPrimary.opacity(0.2)) - .frame(width: 72, height: 72) - .overlay( - Text(initials) - .font(CloserFont.title1) - .foregroundColor(.closerPrimary) + if isLoggedInAnonymously { + NavigationLink { + SignUpView() + } label: { + SettingsProfileHeader( + initials: initials, + name: appState.currentUser?.displayName ?? "You", + detail: "Create an account to save your Closer space" ) - - Text(appState.currentUser?.displayName ?? "You") - .font(CloserFont.title3) - .foregroundColor(.closerText) - - if let email = appState.currentUser?.email { - Text(email) - .font(CloserFont.callout) - .foregroundColor(.closerTextSecondary) - } - } - .frame(maxWidth: .infinity) - .padding(.vertical) - } - - // Connection - Section("Connection") { - if let partner = appState.currentPartner { - HStack { - Circle() - .fill(Color.closerSuccess) - .frame(width: 12, height: 12) - Text("Connected with \(partner.displayName ?? "Partner")") - .font(CloserFont.body) } } else { - Button(action: { isPairingActive = true }) { - Label("Pair with Partner", systemImage: "link") - } - } - - NavigationLink { - CreateInviteView() - } label: { - Label("Invite Partner", systemImage: "square.and.arrow.up") - } - } - - // Account - Section("Account") { - if !isLoggedInAnonymously { NavigationLink { EditProfileView() } label: { - Label("Edit Profile", systemImage: "person") + SettingsProfileHeader( + initials: initials, + name: appState.currentUser?.displayName ?? "You", + detail: appState.currentUser?.email ?? "Edit your profile" + ) } } - + } + + Section("For the two of you") { + if let partner = appState.currentPartner { + SettingsLinkLabel( + icon: "heart.fill", + title: "Connected with \(partner.displayName ?? "Partner")", + subtitle: "Your shared Closer space is active", + tint: .closerPrimary + ) + } else { + Button(action: { isPairingActive = true }) { + SettingsLinkLabel( + icon: "heart", + title: "Invite your partner", + subtitle: "Start answering together", + tint: .closerPrimary + ) + } + .buttonStyle(.plain) + } + + NavigationLink { + AnswerHistoryView() + } label: { + SettingsLinkLabel( + icon: "checkmark.circle", + title: "Answer History", + subtitle: "Revisit the moments you have shared" + ) + } + } + + Section("Your rhythm") { + NavigationLink { + NavigationSettingsView() + } label: { + SettingsLinkLabel( + icon: "bell.badge", + title: "Notifications", + subtitle: "Set gentle reminders that fit your day" + ) + } + } + + Section("Premium") { Button { showPaywall = true } label: { PremiumSettingsCTA() } .disabled(isLoggedInAnonymously) - - if isLoggedInAnonymously { - NavigationLink { - SignUpView() - } label: { - Label("Create Account (Save Data)", systemImage: "lock") - } - } + .buttonStyle(.plain) } - - // Notifications - Section("Notifications") { - Toggle("Push Notifications", isOn: .constant(true)) - Toggle("Daily Question Reminders", isOn: .constant(true)) - Toggle("Partner Activity", isOn: .constant(true)) - Toggle("Gentle Reminders", isOn: .constant(true)) - - NavigationLink { - NavigationSettingsView() - } label: { - Label("Notification Settings", systemImage: "bell.badge") - } - } - - // Privacy - Section("Privacy") { - NavigationLink { - Text("Privacy Policy") - } label: { - Label("Privacy Policy", systemImage: "hand.raised") - } - - NavigationLink { - Text("Terms of Service") - } label: { - Label("Terms of Service", systemImage: "doc.text") - } - + + Section("Privacy and safety") { NavigationLink { DataExportView() } label: { - Label("Export Data", systemImage: "square.and.arrow.up") + SettingsLinkLabel( + icon: "square.and.arrow.up", + title: "Export Data", + subtitle: "Download a copy of your Closer data" + ) + } + + NavigationLink { + Text("Privacy Policy") + } label: { + SettingsLinkLabel( + icon: "hand.raised", + title: "Privacy Policy", + subtitle: "How your data is handled" + ) + } + + NavigationLink { + Text("Terms of Service") + } label: { + SettingsLinkLabel( + icon: "doc.text", + title: "Terms of Service", + subtitle: "The agreement for using Closer" + ) } - - Toggle("Share Anonymous Usage Data", isOn: .constant(true)) } - - // Support + Section("Support") { NavigationLink { HelpCenterView() } label: { - Label("Help Center", systemImage: "questionmark.circle") + SettingsLinkLabel( + icon: "questionmark.circle", + title: "Help Center", + subtitle: "Answers for common questions" + ) } - + NavigationLink { Text("Contact Us") } label: { - Label("Contact Us", systemImage: "envelope") + SettingsLinkLabel( + icon: "envelope", + title: "Contact Us", + subtitle: "Get help from the Closer team" + ) } - + HStack { Label("Version", systemImage: "info.circle") Spacer() @@ -148,13 +152,12 @@ struct SettingsView: View { .foregroundColor(.closerTextSecondary) } } - - // Danger zone - Section { + + Section("Account") { Button(role: .destructive, action: { showLogoutConfirm = true }) { Label("Sign Out", systemImage: "rectangle.portrait.and.arrow.right") } - + Button(role: .destructive, action: { showDeleteConfirm = true }) { Label("Delete Account", systemImage: "trash") } @@ -795,6 +798,64 @@ struct PaywallView: View { } } +// MARK: - Settings Row Helpers + +struct SettingsProfileHeader: View { + let initials: String + let name: String + let detail: String + + var body: some View { + VStack(spacing: CloserSpacing.sm) { + Circle() + .fill(Color.closerPrimary.opacity(0.18)) + .frame(width: 72, height: 72) + .overlay( + Text(initials) + .font(CloserFont.title1) + .foregroundColor(.closerPrimary) + ) + + Text(name) + .font(CloserFont.title3) + .foregroundColor(.closerText) + + Text(detail) + .font(CloserFont.callout) + .foregroundColor(.closerTextSecondary) + .multilineTextAlignment(.center) + } + .frame(maxWidth: .infinity) + .padding(.vertical) + } +} + +struct SettingsLinkLabel: View { + let icon: String + let title: String + let subtitle: String + var tint: Color = .closerTextSecondary + + var body: some View { + HStack(spacing: CloserSpacing.md) { + Image(systemName: icon) + .font(.headline) + .foregroundColor(tint) + .frame(width: 28) + + VStack(alignment: .leading, spacing: 2) { + Text(title) + .font(CloserFont.body) + .foregroundColor(.closerText) + Text(subtitle) + .font(CloserFont.caption) + .foregroundColor(.closerTextSecondary) + } + } + .padding(.vertical, CloserSpacing.xs) + } +} + // MARK: - Premium Settings CTA struct PremiumSettingsCTA: View {