From b7127e75a91e62a3449d503ffd32bd89461bf0c0 Mon Sep 17 00:00:00 2001 From: Sad Ellie Date: Sun, 9 Apr 2023 00:24:30 +0300 Subject: [PATCH] Better theming options: - Improved UI/UX - Added ability to pick color scheme --- .../java/com/sadellie/unitto/UnittoApp.kt | 3 +- core/base/src/main/res/values/strings.xml | 7 +- .../unitto/core/ui/common/SegmentedButton.kt | 106 +++++++++++ .../unitto/data/userprefs/UserPreferences.kt | 39 ++-- .../feature/settings/SettingsViewModel.kt | 10 ++ .../unitto/feature/settings/ThemesScreen.kt | 170 ++++++++++++++---- .../settings/components/ColorCheckbox.kt | 133 ++++++++++++++ .../settings/navigation/SettingsNavigation.kt | 4 +- 8 files changed, 417 insertions(+), 55 deletions(-) create mode 100644 core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SegmentedButton.kt create mode 100644 feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/ColorCheckbox.kt diff --git a/app/src/main/java/com/sadellie/unitto/UnittoApp.kt b/app/src/main/java/com/sadellie/unitto/UnittoApp.kt index cc1bb5f9..4bd03aff 100644 --- a/app/src/main/java/com/sadellie/unitto/UnittoApp.kt +++ b/app/src/main/java/com/sadellie/unitto/UnittoApp.kt @@ -63,7 +63,8 @@ internal fun UnittoApp() { // Anything below will not be called if theming mode is still loading from DataStore themingMode = userPrefs.value.themingMode ?: return, dynamicThemeEnabled = userPrefs.value.enableDynamicTheme, - amoledThemeEnabled = userPrefs.value.enableAmoledTheme + amoledThemeEnabled = userPrefs.value.enableAmoledTheme, + customColor = userPrefs.value.customColor ) val navController = rememberNavController() val sysUiController = rememberSystemUiController() diff --git a/core/base/src/main/res/values/strings.xml b/core/base/src/main/res/values/strings.xml index ab3740f5..1665a142 100644 --- a/core/base/src/main/res/values/strings.xml +++ b/core/base/src/main/res/values/strings.xml @@ -1064,9 +1064,9 @@ tf Millinewton mN - attonewton + Attonewton aN - dyne + Dyne dyn Joule/meter J/m @@ -1317,10 +1317,13 @@ Light Dark Color theme + Pick a theming mode AMOLED Dark Use black background for dark themes Dynamic colors Use colors from your wallpaper + Color scheme + Selected color Loading… diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SegmentedButton.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SegmentedButton.kt new file mode 100644 index 00000000..097cd368 --- /dev/null +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SegmentedButton.kt @@ -0,0 +1,106 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.core.ui.common + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.contentColorFor +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.unit.dp + +private val GroupRowContainerHeight = 40.dp +private val GroupRowItemMinWidth = 58.dp + +@Composable +fun SegmentedButtonRow( + modifier: Modifier = Modifier, + content: @Composable RowScope.() -> Unit +) { + OutlinedCard( + modifier = modifier, + shape = CircleShape + ) { + Row( + modifier = Modifier + .height(GroupRowContainerHeight) + .widthIn(min = GroupRowItemMinWidth), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + content() + } + } +} + +@Composable +fun RowScope.SegmentedButton( + onClick: () -> Unit, + selected: Boolean, + modifier: Modifier = Modifier, + enabled: Boolean = true, + content: @Composable () -> Unit, +) { + val containerColor = + if (selected) + MaterialTheme.colorScheme.secondaryContainer + else + MaterialTheme.colorScheme.surface + OutlinedButton( + modifier = modifier.weight(1f), + onClick = onClick, + shape = RectangleShape, + colors = ButtonDefaults.outlinedButtonColors( + containerColor = containerColor, + contentColor = contentColorFor(containerColor) + ), + enabled = enabled, + contentPadding = PaddingValues(horizontal = 12.dp) + ) { + AnimatedVisibility(visible = selected) { + Row { + Icon( + modifier = Modifier.size(18.dp), + imageVector = Icons.Default.Check, + contentDescription = null + ) + Spacer(Modifier.width(8.dp)) + } + } + content() + } +} diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt index 5942b3ff..9511a071 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt +++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt @@ -18,12 +18,14 @@ package com.sadellie.unitto.data.userprefs +import androidx.compose.ui.graphics.Color import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.emptyPreferences import androidx.datastore.preferences.core.intPreferencesKey +import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import com.sadellie.unitto.core.base.OutputFormat import com.sadellie.unitto.core.base.Separator @@ -47,6 +49,7 @@ import javax.inject.Inject * still loading. * @property enableDynamicTheme Use dynamic color scheme * @property enableAmoledTheme Use amoled color scheme + * @property customColor Generate custom color scheme from this color. * @property digitsPrecision Current [PRECISIONS]. Number of digits in fractional part * @property separator Current [Separator] that used to separate thousands * @property outputFormat Current [OutputFormat] that is applied to converted value (not input) @@ -64,6 +67,7 @@ data class UserPreferences( val themingMode: ThemingMode? = null, val enableDynamicTheme: Boolean = false, val enableAmoledTheme: Boolean = false, + val customColor: Color = Color.Unspecified, val digitsPrecision: Int = 3, val separator: Int = Separator.SPACES, val outputFormat: Int = OutputFormat.PLAIN, @@ -90,6 +94,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS val THEMING_MODE = stringPreferencesKey("THEMING_MODE_PREF_KEY") val ENABLE_DYNAMIC_THEME = booleanPreferencesKey("ENABLE_DYNAMIC_THEME_PREF_KEY") val ENABLE_AMOLED_THEME = booleanPreferencesKey("ENABLE_AMOLED_THEME_PREF_KEY") + val CUSTOM_COLOR = longPreferencesKey("CUSTOM_COLOR_PREF_KEY") val DIGITS_PRECISION = intPreferencesKey("DIGITS_PRECISION_PREF_KEY") val SEPARATOR = intPreferencesKey("SEPARATOR_PREF_KEY") val OUTPUT_FORMAT = intPreferencesKey("OUTPUT_FORMAT_PREF_KEY") @@ -117,20 +122,14 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS val themingMode: ThemingMode = preferences[PrefsKeys.THEMING_MODE]?.let { ThemingMode.valueOf(it) } ?: ThemingMode.AUTO - val enableDynamicTheme: Boolean = - preferences[PrefsKeys.ENABLE_DYNAMIC_THEME] ?: false - val enableAmoledTheme: Boolean = - preferences[PrefsKeys.ENABLE_AMOLED_THEME] ?: false - val digitsPrecision: Int = - preferences[PrefsKeys.DIGITS_PRECISION] ?: 3 - val separator: Int = - preferences[PrefsKeys.SEPARATOR] ?: Separator.SPACES - val outputFormat: Int = - preferences[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN - val latestLeftSideUnit: String = - preferences[PrefsKeys.LATEST_LEFT_SIDE] ?: MyUnitIDS.kilometer - val latestRightSideUnit: String = - preferences[PrefsKeys.LATEST_RIGHT_SIDE] ?: MyUnitIDS.mile + val enableDynamicTheme: Boolean = preferences[PrefsKeys.ENABLE_DYNAMIC_THEME] ?: false + val enableAmoledTheme: Boolean = preferences[PrefsKeys.ENABLE_AMOLED_THEME] ?: false + val customColor: Color = preferences[PrefsKeys.CUSTOM_COLOR]?.let { Color(it.toULong()) } ?: Color.Unspecified + val digitsPrecision: Int = preferences[PrefsKeys.DIGITS_PRECISION] ?: 3 + val separator: Int = preferences[PrefsKeys.SEPARATOR] ?: Separator.SPACES + val outputFormat: Int = preferences[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN + val latestLeftSideUnit: String = preferences[PrefsKeys.LATEST_LEFT_SIDE] ?: MyUnitIDS.kilometer + val latestRightSideUnit: String = preferences[PrefsKeys.LATEST_RIGHT_SIDE] ?: MyUnitIDS.mile val shownUnitGroups: List = preferences[PrefsKeys.SHOWN_UNIT_GROUPS]?.let { list -> // Everything is in hidden (nothing in shown) @@ -157,6 +156,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS themingMode = themingMode, enableDynamicTheme = enableDynamicTheme, enableAmoledTheme = enableAmoledTheme, + customColor = customColor, digitsPrecision = digitsPrecision, separator = separator, outputFormat = outputFormat, @@ -253,6 +253,17 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS } } + /** + * Update preference on custom color scheme. + * + * @param color New custom color value. + */ + suspend fun updateCustomColor(color: Color) { + dataStore.edit { preferences -> + preferences[PrefsKeys.CUSTOM_COLOR] = color.value.toLong() + } + } + /** * Update preference on starting screen route. * diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt index 6f4ebfc4..92cb1f5c 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt @@ -18,6 +18,7 @@ package com.sadellie.unitto.feature.settings +import androidx.compose.ui.graphics.Color import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sadellie.unitto.core.ui.Formatter @@ -75,6 +76,15 @@ class SettingsViewModel @Inject constructor( } } + /** + * @see UserPreferencesRepository.updateCustomColor + */ + fun updateCustomColor(color: Color) { + viewModelScope.launch { + userPrefsRepository.updateCustomColor(color) + } + } + /** * @see UserPreferencesRepository.updateDigitsPrecision */ diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/ThemesScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/ThemesScreen.kt index 03c28cd3..8f40a7a0 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/ThemesScreen.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/ThemesScreen.kt @@ -24,77 +24,123 @@ import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Colorize import androidx.compose.material.icons.filled.DarkMode import androidx.compose.material.icons.filled.Palette import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import com.sadellie.unitto.core.ui.R +import com.sadellie.unitto.core.ui.common.Header import com.sadellie.unitto.core.ui.common.NavigateUpButton import com.sadellie.unitto.core.ui.common.UnittoListItem import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar +import com.sadellie.unitto.feature.settings.components.ColorSelector +import com.sadellie.unitto.core.ui.common.SegmentedButton +import com.sadellie.unitto.core.ui.common.SegmentedButtonRow import io.github.sadellie.themmo.ThemingMode import io.github.sadellie.themmo.ThemmoController @Composable -internal fun ThemesScreen( +internal fun ThemesRoute( navigateUpAction: () -> Unit = {}, themmoController: ThemmoController, viewModel: SettingsViewModel ) { + ThemesScreen( + navigateUpAction = navigateUpAction, + currentThemingMode = themmoController.currentThemingMode, + onThemeChange = { + themmoController.setThemingMode(it) + viewModel.updateThemingMode(it) + }, + isDynamicThemeEnabled = themmoController.isDynamicThemeEnabled, + onDynamicThemeChange = { + themmoController.enableDynamicTheme(it) + viewModel.updateDynamicTheme(it) + }, + isAmoledThemeEnabled = themmoController.isAmoledThemeEnabled, + onAmoledThemeChange = { + themmoController.enableAmoledTheme(it) + viewModel.updateAmoledTheme(it) + }, + selectedColor = themmoController.currentCustomColor, + onColorChange = { + themmoController.setCustomColor(it) + viewModel.updateCustomColor(it) + } + ) +} + +@Composable +private fun ThemesScreen( + navigateUpAction: () -> Unit, + currentThemingMode: ThemingMode, + onThemeChange: (ThemingMode) -> Unit, + isDynamicThemeEnabled: Boolean, + onDynamicThemeChange: (Boolean) -> Unit, + isAmoledThemeEnabled: Boolean, + onAmoledThemeChange: (Boolean) -> Unit, + selectedColor: Color, + onColorChange: (Color) -> Unit, +) { + val themingModes by remember { + mutableStateOf( + mapOf( + ThemingMode.AUTO to R.string.force_auto_mode, + ThemingMode.FORCE_LIGHT to R.string.force_light_mode, + ThemingMode.FORCE_DARK to R.string.force_dark_mode + ) + ) + } + UnittoScreenWithLargeTopBar( title = stringResource(R.string.theme_setting), navigationIcon = { NavigateUpButton(navigateUpAction) } ) { paddingValues -> LazyColumn(contentPadding = paddingValues) { item { - UnittoListItem( + ListItem( leadingContent = { Icon( Icons.Default.Palette, stringResource(R.string.color_theme), ) }, - label = stringResource(R.string.color_theme), - allOptions = mapOf( - ThemingMode.AUTO to stringResource(R.string.force_auto_mode), - ThemingMode.FORCE_LIGHT to stringResource(R.string.force_light_mode), - ThemingMode.FORCE_DARK to stringResource(R.string.force_dark_mode) - ), - selected = themmoController.currentThemingMode, - onSelectedChange = { - themmoController.setThemingMode(it) - viewModel.updateThemingMode(it) - } + headlineContent = { Text(stringResource(R.string.color_theme)) }, + supportingContent = { Text(stringResource(R.string.color_theme_support)) }, ) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - item { - UnittoListItem( - leadingContent = { - Icon( - Icons.Default.Colorize, - stringResource(R.string.enable_dynamic_colors), - ) - }, - label = stringResource(R.string.enable_dynamic_colors), - supportContent = stringResource(R.string.enable_dynamic_colors_support), - switchState = themmoController.isDynamicThemeEnabled, - onSwitchChange = { - themmoController.enableDynamicTheme(it) - viewModel.updateDynamicTheme(it) - } - ) + item { + SegmentedButtonRow( + modifier = Modifier.padding(56.dp, 8.dp, 24.dp, 2.dp) + ) { + themingModes.forEach { (mode, stringRes) -> + SegmentedButton( + onClick = { onThemeChange(mode) }, + selected = currentThemingMode == mode, + content = { Text(stringResource(stringRes)) } + ) + } } } item { AnimatedVisibility( - visible = (themmoController.currentThemingMode != ThemingMode.FORCE_LIGHT), + visible = currentThemingMode != ThemingMode.FORCE_LIGHT, enter = expandVertically() + fadeIn(), exit = shrinkVertically() + fadeOut(), ) { @@ -107,14 +153,66 @@ internal fun ThemesScreen( }, label = stringResource(R.string.force_amoled_mode), supportContent = stringResource(R.string.force_amoled_mode_support), - switchState = themmoController.isAmoledThemeEnabled, - onSwitchChange = { - themmoController.enableAmoledTheme(it) - viewModel.updateAmoledTheme(it) - } + switchState = isAmoledThemeEnabled, + onSwitchChange = onAmoledThemeChange + ) + } + } + + item { Header(stringResource(R.string.color_scheme)) } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + item { + UnittoListItem( + leadingContent = { + Icon( + Icons.Default.Colorize, + stringResource(R.string.enable_dynamic_colors), + ) + }, + label = stringResource(R.string.enable_dynamic_colors), + supportContent = stringResource(R.string.enable_dynamic_colors_support), + switchState = isDynamicThemeEnabled, + onSwitchChange = onDynamicThemeChange + ) + } + } + + item { + AnimatedVisibility( + visible = !isDynamicThemeEnabled, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut(), + ) { + ListItem( + headlineContent = { Text(stringResource(R.string.selected_color)) }, + supportingContent = { + ColorSelector( + modifier = Modifier.padding(top = 12.dp), + selected = selectedColor, + onItemClick = onColorChange + ) + }, + modifier = Modifier.padding(start = 40.dp) ) } } } } } + +@Preview +@Composable +private fun Preview() { + ThemesScreen( + navigateUpAction = {}, + currentThemingMode = ThemingMode.AUTO, + onThemeChange = {}, + isDynamicThemeEnabled = false, + onDynamicThemeChange = {}, + isAmoledThemeEnabled = false, + onAmoledThemeChange = {}, + selectedColor = Color.Unspecified, + onColorChange = {} + ) +} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/ColorCheckbox.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/ColorCheckbox.kt new file mode 100644 index 00000000..d3585466 --- /dev/null +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/ColorCheckbox.kt @@ -0,0 +1,133 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.feature.settings.components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance +import androidx.compose.ui.unit.dp + +@Composable +internal fun ColorSelector( + modifier: Modifier = Modifier, + selected: Color, + onItemClick: (Color) -> Unit, +) { + val colorSchemes: List by remember { + mutableStateOf( + listOf( + Color(0xFFE91E63), + Color(0xFFFF9800), + Color(0xFF4CAF50), + Color(0xFF2196F3), + Color(0xFF9C27B0), + Color(0xFF5C76AA), + Color(0xFF756FAA), + Color(0xFF9E6C2A), + ) + ) + } + + LazyRow( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + // Default, Unitto colors + item { + ColorCheckbox( + color = Color(0xFF186c31), + selected = Color.Unspecified == selected, + onClick = { onItemClick(Color.Unspecified) } + ) + } + colorSchemes.forEach { + item { + ColorCheckbox( + color = it, + selected = it == selected, + onClick = { onItemClick(it) } + ) + } + } + } +} + +@Composable +private fun ColorCheckbox( + color: Color, + selected: Boolean, + onClick: () -> Unit +) { + Box( + modifier = Modifier + .clickable(onClick = onClick) + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp), + RoundedCornerShape(25) + ) + .width(72.dp) + .aspectRatio(1f), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .background(color, CircleShape) + .size(54.dp) + .border(1.dp, Color.Black.copy(0.5f), CircleShape) + ) + AnimatedVisibility( + visible = selected, + enter = fadeIn(tween(250)) + scaleIn(tween(150)), + exit = fadeOut(tween(250)) + scaleOut(tween(150)), + ) { + Icon( + imageVector = Icons.Default.Check, + contentDescription = null, + tint = if (color.luminance() > 0.5) Color.Black else Color.White, + ) + } + } +} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt index 9949afb9..cc2a874e 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt @@ -28,7 +28,7 @@ import com.sadellie.unitto.core.base.TopLevelDestinations import com.sadellie.unitto.feature.settings.AboutScreen import com.sadellie.unitto.feature.settings.SettingsScreen import com.sadellie.unitto.feature.settings.SettingsViewModel -import com.sadellie.unitto.feature.settings.ThemesScreen +import com.sadellie.unitto.feature.settings.ThemesRoute import com.sadellie.unitto.feature.settings.ThirdPartyLicensesScreen import com.sadellie.unitto.feature.settings.UnitGroupsScreen import io.github.sadellie.themmo.ThemmoController @@ -63,7 +63,7 @@ fun NavGraphBuilder.settingGraph( } composable(themesRoute) { - ThemesScreen( + ThemesRoute( navigateUpAction = { navController.navigateUp() }, themmoController = themmoController, viewModel = settingsViewModel