diff --git a/app/src/main/java/app/closer/core/navigation/AppNavigation.kt b/app/src/main/java/app/closer/core/navigation/AppNavigation.kt index aab0d89b..c7143d82 100644 --- a/app/src/main/java/app/closer/core/navigation/AppNavigation.kt +++ b/app/src/main/java/app/closer/core/navigation/AppNavigation.kt @@ -66,6 +66,7 @@ import app.closer.ui.questions.QuestionComposerScreen import app.closer.ui.questions.QuestionPackLibraryScreen import app.closer.ui.questions.QuestionThreadScreen import app.closer.ui.settings.AccountScreen +import app.closer.ui.settings.AppearanceScreen import app.closer.ui.settings.DeleteAccountScreen import app.closer.ui.settings.NotificationSettingsScreen import app.closer.ui.settings.PrivacyScreen @@ -424,6 +425,9 @@ fun AppNavigation( composable(route = AppRoute.ACCOUNT) { AccountScreen(onNavigate = navigateRoute) } + composable(route = AppRoute.APPEARANCE) { + AppearanceScreen(onNavigate = navigateRoute) + } composable(route = AppRoute.NOTIFICATIONS) { NotificationSettingsScreen(onNavigate = navigateRoute) } diff --git a/app/src/main/java/app/closer/core/navigation/AppRoute.kt b/app/src/main/java/app/closer/core/navigation/AppRoute.kt index 9bab157e..2b52c84d 100644 --- a/app/src/main/java/app/closer/core/navigation/AppRoute.kt +++ b/app/src/main/java/app/closer/core/navigation/AppRoute.kt @@ -30,6 +30,7 @@ object AppRoute { const val SETTINGS = "settings" const val ACCOUNT = "account" const val NOTIFICATIONS = "notifications" + const val APPEARANCE = "appearance" const val PRIVACY = "privacy" const val SUBSCRIPTION = "subscription" const val RELATIONSHIP_SETTINGS = "relationship_settings" diff --git a/app/src/main/java/app/closer/ui/settings/AppearanceScreen.kt b/app/src/main/java/app/closer/ui/settings/AppearanceScreen.kt new file mode 100644 index 00000000..1806ce7a --- /dev/null +++ b/app/src/main/java/app/closer/ui/settings/AppearanceScreen.kt @@ -0,0 +1,156 @@ +package app.closer.ui.settings + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawingPadding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Divider +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import app.closer.domain.repository.ThemeMode + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AppearanceScreen( + onNavigate: (String) -> Unit = {}, + viewModel: SettingsViewModel = hiltViewModel() +) { + val state by viewModel.uiState.collectAsState() + + Scaffold( + containerColor = Color.Transparent, + modifier = Modifier.background(SettingsBackgroundBrush), + topBar = { + TopAppBar( + title = { Text("Appearance", color = SettingsInk) }, + navigationIcon = { + IconButton(onClick = { onNavigate("back") }) { + Icon( + Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = "Back", + tint = SettingsInk + ) + } + }, + colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent) + ) + } + ) { padding -> + Column( + modifier = Modifier + .fillMaxSize() + .safeDrawingPadding() + .navigationBarsPadding() + .verticalScroll(rememberScrollState()) + .padding(padding) + .padding(horizontal = 16.dp, vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = "Theme", + style = MaterialTheme.typography.labelLarge, + color = SettingsMuted, + modifier = Modifier.padding(horizontal = 4.dp, vertical = 4.dp) + ) + + Card( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(16.dp), + colors = CardDefaults.cardColors(containerColor = SettingsCard) + ) { + Column { + ThemeOptionRow( + label = "Device default", + description = "Match your device's light or dark setting", + selected = state.themeMode == ThemeMode.DEVICE, + onClick = { viewModel.setThemeMode(ThemeMode.DEVICE) } + ) + Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) + ThemeOptionRow( + label = "Light", + description = "Always use light mode", + selected = state.themeMode == ThemeMode.LIGHT, + onClick = { viewModel.setThemeMode(ThemeMode.LIGHT) } + ) + Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) + ThemeOptionRow( + label = "Dark", + description = "Always use dark mode", + selected = state.themeMode == ThemeMode.DARK, + onClick = { viewModel.setThemeMode(ThemeMode.DARK) } + ) + } + } + + Spacer(Modifier.height(8.dp)) + + Text( + text = "Changes apply instantly across the whole app.", + style = MaterialTheme.typography.bodySmall, + color = SettingsMuted, + modifier = Modifier.padding(horizontal = 4.dp) + ) + } + } +} + +@Composable +private fun ThemeOptionRow( + label: String, + description: String, + selected: Boolean, + onClick: () -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + RadioButton(selected = selected, onClick = onClick) + Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { + Text( + text = label, + style = MaterialTheme.typography.bodyLarge, + color = SettingsInk + ) + Text( + text = description, + style = MaterialTheme.typography.bodySmall, + color = SettingsMuted + ) + } + } +} 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 f06330bc..7626a0f1 100644 --- a/app/src/main/java/app/closer/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/app/closer/ui/settings/SettingsScreen.kt @@ -25,6 +25,7 @@ import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.FavoriteBorder import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.Notifications +import androidx.compose.material.icons.filled.Palette import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Star import androidx.compose.material.icons.filled.Warning @@ -39,7 +40,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.RadioButton import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar @@ -60,7 +60,6 @@ import android.content.Context import androidx.compose.ui.platform.LocalContext import app.closer.core.navigation.AppRoute import app.closer.core.navigation.ExternalLinks -import app.closer.domain.repository.ThemeMode import app.closer.ui.settings.SettingsDanger import app.closer.ui.settings.SettingsInk import app.closer.ui.settings.SettingsMuted @@ -326,44 +325,6 @@ fun SettingsScreen( Spacer(Modifier.height(4.dp)) - Text( - text = "Appearance", - style = MaterialTheme.typography.labelLarge, - color = SettingsMuted, - modifier = Modifier.padding(horizontal = 4.dp, vertical = 4.dp) - ) - - Card( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = SettingsCard) - ) { - Column { - ThemeModeRow( - label = "Device", - description = "Match your device appearance", - selected = state.themeMode == ThemeMode.DEVICE, - onClick = { viewModel.setThemeMode(ThemeMode.DEVICE) } - ) - Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) - ThemeModeRow( - label = "Light", - description = "Always use light mode", - selected = state.themeMode == ThemeMode.LIGHT, - onClick = { viewModel.setThemeMode(ThemeMode.LIGHT) } - ) - Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 0.5.dp) - ThemeModeRow( - label = "Dark", - description = "Always use dark mode", - selected = state.themeMode == ThemeMode.DARK, - onClick = { viewModel.setThemeMode(ThemeMode.DARK) } - ) - } - } - - Spacer(Modifier.height(4.dp)) - // General section Card( modifier = Modifier.fillMaxWidth(), @@ -377,6 +338,12 @@ fun SettingsScreen( onClick = { onNavigate(AppRoute.ANSWER_HISTORY) } ) 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", @@ -469,37 +436,6 @@ fun SettingsScreen( } } -@Composable -private fun ThemeModeRow( - label: String, - description: String, - selected: Boolean, - onClick: () -> Unit -) { - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onClick) - .padding(horizontal = 16.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) - ) { - RadioButton(selected = selected, onClick = onClick) - Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { - Text( - text = label, - style = MaterialTheme.typography.bodyLarge, - color = SettingsInk - ) - Text( - text = description, - style = MaterialTheme.typography.bodySmall, - color = SettingsMuted - ) - } - } -} - @Composable private fun SettingsRow( icon: ImageVector,