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