diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml index 75ec576054..9b9a87f3d4 100644 --- a/lawnchair/res/values/strings.xml +++ b/lawnchair/res/values/strings.xml @@ -46,7 +46,7 @@ App Info Restart Lawnchair Experimental Features - + Font Customization @@ -138,11 +138,12 @@ Bold Extra Bold Black - + Reset Dynamic + Swatches Presets Custom RGB @@ -193,7 +194,7 @@ Reset Custom Icons All custom icons will be reset. Do you want to continue? - + Rounded Corners Allow Overlap @@ -246,7 +247,7 @@ Show on Home Screen At a Glance can be manually added by placing the "Lawnchair" widget. - + Search Bar @@ -271,11 +272,11 @@ App Website App required. - + - Hidden Apps + Hidden Apps Background Opacity Search @@ -287,7 +288,7 @@ App Drawer Columns Row Height - + Max. Folder Columns Max. Folder Rows - + Double Tap @@ -341,7 +342,7 @@ Share Lens Clear All - + Screen Corner Radius Custom Screen Corner Radius When you swipe up to open Recents, the current app follows your finger, shrinking into a card. Use this slider to adjust the corner radius of the card when it’s nearly full-screen such that it matches the corners of your screen. @@ -355,7 +356,7 @@ Twitter GitHub Discord - + Product Design & Development Development diff --git a/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt index 33d0f181ec..a69b42a221 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/FolderPreferences.kt @@ -38,10 +38,7 @@ fun FolderPreferences() { val prefs = preferenceManager() val prefs2 = preferenceManager2() PreferenceGroup(heading = stringResource(id = R.string.general_label)) { - ColorPreference( - preference = prefs2.folderColor, - label = stringResource(id = R.string.folder_preview_bg_color_label), - ) + ColorPreference(preference = prefs2.folderColor) SliderPreference( label = stringResource(id = R.string.folder_preview_bg_opacity_label), adapter = prefs2.folderPreviewBackgroundOpacity.getAdapter(), diff --git a/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt index a8573d6099..651246aa18 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/GeneralPreferences.kt @@ -141,10 +141,7 @@ fun GeneralPreferences() { PreferenceGroup(heading = stringResource(id = R.string.colors)) { ThemePreference() - ColorPreference( - preference = prefs2.accentColor, - label = stringResource(id = R.string.accent_color), - ) + ColorPreference(preference = prefs2.accentColor) } PreferenceGroup(heading = stringResource(id = R.string.notification_dots)) { @@ -153,20 +150,14 @@ fun GeneralPreferences() { NotificationDotsPreference(enabled = enabled, serviceEnabled = serviceEnabled) if (enabled && serviceEnabled) { val showNotificationCountAdapter = prefs2.showNotificationCount.getAdapter() - ColorPreference( - preference = prefs2.notificationDotColor, - label = stringResource(id = R.string.notification_dots_color), - ) + ColorPreference(preference = prefs2.notificationDotColor) SwitchPreference( adapter = showNotificationCountAdapter, label = stringResource(id = R.string.show_notification_count), ) ExpandAndShrink(visible = showNotificationCountAdapter.state.value) { DividerColumn { - ColorPreference( - preference = prefs2.notificationDotTextColor, - label = stringResource(id = R.string.notification_dots_text_color), - ) + ColorPreference(preference = prefs2.notificationDotTextColor) NotificationDotColorContrastWarnings( dotColor = prefs2.notificationDotColor.asState().value, dotTextColor = prefs2.notificationDotTextColor.asState().value, diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreference.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreference.kt index 17d80d5fad..46a21388d3 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreference.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreference.kt @@ -22,6 +22,8 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.datastore.preferences.core.Preferences import app.lawnchair.preferences.PreferenceAdapter import app.lawnchair.preferences.getAdapter import app.lawnchair.theme.color.ColorOption @@ -36,20 +38,19 @@ import com.patrykmichalik.opto.domain.Preference * @see ColorSelection */ @Composable -fun ColorPreference( - preference: Preference, - label: String, -) { - val adapter: PreferenceAdapter = preference.getAdapter() +fun ColorPreference(preference: Preference>) { + val modelList = ColorPreferenceModelList.INSTANCE.get(LocalContext.current) + val model = modelList[preference.key.name] + val adapter: PreferenceAdapter = model.prefObject.getAdapter() val navController = LocalNavController.current PreferenceTemplate( - title = { Text(text = label) }, + title = { Text(text = stringResource(id = model.labelRes)) }, endWidget = { ColorDot(adapter.state.value.colorPreferenceEntry) }, description = { Text(text = adapter.state.value.colorPreferenceEntry.label()) }, - modifier = Modifier.clickable { navController.navigate(route = "/colorSelection/${preference.key}/") }, + modifier = Modifier.clickable { navController.navigate(route = "/colorSelection/${model.prefObject.key.name}/") }, ) } diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreferenceModel.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreferenceModel.kt new file mode 100644 index 0000000000..c1138822e0 --- /dev/null +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreferenceModel.kt @@ -0,0 +1,12 @@ +package app.lawnchair.ui.preferences.components.colorpreference + +import androidx.annotation.StringRes +import androidx.datastore.preferences.core.Preferences +import app.lawnchair.theme.color.ColorOption +import com.patrykmichalik.opto.domain.Preference + +data class ColorPreferenceModel( + val prefObject: Preference>, + @StringRes val labelRes: Int, + val dynamicEntries: List> +) diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreferenceModelList.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreferenceModelList.kt new file mode 100644 index 0000000000..f1da33bc86 --- /dev/null +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorPreferenceModelList.kt @@ -0,0 +1,54 @@ +package app.lawnchair.ui.preferences.components.colorpreference + +import android.content.Context +import app.lawnchair.preferences2.PreferenceManager2 +import com.android.launcher3.R +import com.android.launcher3.util.MainThreadInitializedObject + +class ColorPreferenceModelList(context: Context) { + private val models = mutableMapOf() + + init { + val prefs = PreferenceManager2.getInstance(context) + registerModel( + ColorPreferenceModel( + prefObject = prefs.accentColor, + labelRes = R.string.accent_color, + dynamicEntries = dynamicColors, + ) + ) + registerModel( + ColorPreferenceModel( + prefObject = prefs.notificationDotColor, + labelRes = R.string.notification_dots_color, + dynamicEntries = dynamicColorsWithDefault, + ) + ) + registerModel( + ColorPreferenceModel( + prefObject = prefs.notificationDotTextColor, + labelRes = R.string.notification_dots_text_color, + dynamicEntries = dynamicColorsWithDefault, + ) + ) + registerModel( + ColorPreferenceModel( + prefObject = prefs.folderColor, + labelRes = R.string.folder_preview_bg_color_label, + dynamicEntries = dynamicColorsWithDefault, + ) + ) + } + + operator fun get(key: String): ColorPreferenceModel { + return models[key] ?: throw IllegalArgumentException("Unknown key: $key") + } + + private fun registerModel(model: ColorPreferenceModel) { + models[model.prefObject.key.name] = model + } + + companion object { + val INSTANCE = MainThreadInitializedObject(::ColorPreferenceModelList) + } +} diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSelectionPreference.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSelectionPreference.kt index ef3a91bcd1..f4b48398a3 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSelectionPreference.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSelectionPreference.kt @@ -1,22 +1,26 @@ package app.lawnchair.ui.preferences.components.colorpreference +import android.content.Context +import android.graphics.Color import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.animateContentSize import androidx.compose.foundation.layout.* -import androidx.compose.material3.Text import androidx.compose.material3.Button +import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.navigation.NavGraphBuilder import androidx.navigation.NavType import androidx.navigation.navArgument import app.lawnchair.preferences.getAdapter -import app.lawnchair.preferences2.preferenceManager2 import app.lawnchair.theme.color.ColorOption -import app.lawnchair.ui.preferences.components.* +import app.lawnchair.ui.preferences.components.BottomSpacer +import app.lawnchair.ui.preferences.components.Chip +import app.lawnchair.ui.preferences.components.PreferenceLayout import app.lawnchair.ui.preferences.components.colorpreference.pickers.CustomColorPicker import app.lawnchair.ui.preferences.components.colorpreference.pickers.PresetsList import app.lawnchair.ui.preferences.components.colorpreference.pickers.SwatchGrid @@ -41,31 +45,12 @@ fun NavGraphBuilder.colorSelectionGraph(route: String) { val args = backStackEntry.arguments!! val prefKey = args.getString("prefKey")!! - val preferenceManager2 = preferenceManager2() - val pref = when (prefKey) { - preferenceManager2.accentColor.key.name -> preferenceManager2.accentColor - preferenceManager2.notificationDotColor.key.name -> preferenceManager2.notificationDotColor - preferenceManager2.notificationDotTextColor.key.name -> preferenceManager2.notificationDotTextColor - preferenceManager2.folderColor.key.name -> preferenceManager2.folderColor - else -> return@composable - } - val label = when (prefKey) { - preferenceManager2.accentColor.key.name -> stringResource(id = R.string.accent_color) - preferenceManager2.notificationDotColor.key.name -> stringResource(id = R.string.notification_dots_color) - preferenceManager2.notificationDotTextColor.key.name -> stringResource(id = R.string.notification_dots_text_color) - preferenceManager2.folderColor.key.name -> stringResource(id = R.string.folder_preview_bg_color_label) - else -> return@composable - } - val dynamicEntries = when (prefKey) { - preferenceManager2.folderColor.key.name, - preferenceManager2.notificationDotColor.key.name, - preferenceManager2.notificationDotTextColor.key.name -> dynamicColorsWithDefault - else -> dynamicColors - } + val modelList = ColorPreferenceModelList.INSTANCE.get(LocalContext.current) + val model = modelList[prefKey] ColorSelection( - label = label, - preference = pref, - dynamicEntries = dynamicEntries, + label = stringResource(id = model.labelRes), + preference = model.prefObject, + dynamicEntries = model.dynamicEntries, ) } } @@ -79,26 +64,39 @@ fun ColorSelection( dynamicEntries: List> = dynamicColors, staticEntries: List> = staticColors, ) { - val adapter = preference.getAdapter() - val appliedColor by adapter - val selectedColor = remember { mutableStateOf(appliedColor) } + val appliedColor = adapter.state.value + val context = LocalContext.current + val selectedColor = remember { mutableStateOf(appliedColor.forCustomPicker(context)) } + val selectedColorApplied = derivedStateOf { + appliedColor is ColorOption.CustomColor && appliedColor.color == selectedColor.value + } val defaultTabIndex = when { dynamicEntries.any { it.value == appliedColor } -> 0 staticEntries.any { it.value == appliedColor } -> 1 else -> 2 } + val onPresetClick = { option: ColorOption -> + selectedColor.value = option.forCustomPicker(context) + adapter.onChange(newValue = option) + } + + val pagerState = rememberPagerState(defaultTabIndex) PreferenceLayout( label = label, bottomBar = { + if (pagerState.currentPage == 0) { + BottomSpacer() + return@PreferenceLayout + } Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.End ) { Button( - enabled = selectedColor.value != appliedColor, - onClick = { adapter.onChange(newValue = selectedColor.value) }, + enabled = !selectedColorApplied.value, + onClick = { adapter.onChange(newValue = ColorOption.CustomColor(selectedColor.value)) }, modifier = Modifier .fillMaxWidth() .padding(all = 16.dp), @@ -109,74 +107,72 @@ fun ColorSelection( } }, ) { - - val pagerState = rememberPagerState(defaultTabIndex) val scope = rememberCoroutineScope() val scrollToPage = { page: Int -> scope.launch { pagerState.animateScrollToPage(page) } } Column { - Row( horizontalArrangement = Arrangement.spacedBy(space = 8.dp), modifier = Modifier.padding(horizontal = 16.dp), ) { Chip( - label = stringResource(id = R.string.dynamic), + label = stringResource(id = R.string.presets), onClick = { scrollToPage(0) }, currentOffset = pagerState.currentPage + pagerState.currentPageOffset, page = 0, ) Chip( - label = stringResource(id = R.string.presets), + label = stringResource(id = R.string.custom), onClick = { scrollToPage(1) }, currentOffset = pagerState.currentPage + pagerState.currentPageOffset, page = 1, ) - Chip( - label = stringResource(id = R.string.custom), - onClick = { scrollToPage(2) }, - currentOffset = pagerState.currentPage + pagerState.currentPageOffset, - page = 2, - ) } HorizontalPager( - count = 3, + count = 2, state = pagerState, verticalAlignment = Alignment.Top, modifier = Modifier.animateContentSize(), ) { page -> when (page) { 0 -> { - PresetsList( - dynamicEntries = dynamicEntries, - onPresetClick = { selectedColor.value = it }, - isPresetSelected = { it == selectedColor.value }, - ) + Column { + PresetsList( + dynamicEntries = dynamicEntries, + onPresetClick = onPresetClick, + isPresetSelected = { it == appliedColor }, + ) + SwatchGrid( + modifier = Modifier.padding(top = 12.dp), + contentModifier = Modifier.padding( + start = 16.dp, + top = 20.dp, + end = 16.dp, + bottom = 16.dp, + ), + entries = staticEntries, + onSwatchClick = onPresetClick, + isSwatchSelected = { it == appliedColor }, + ) + } } 1 -> { - SwatchGrid( - modifier = Modifier.padding(top = 12.dp), - contentModifier = Modifier.padding( - start = 16.dp, - top = 20.dp, - end = 16.dp, - bottom = 16.dp, - ), - entries = staticEntries, - onSwatchClick = { selectedColor.value = it }, - isSwatchSelected = { it == selectedColor.value }, - ) - } - 2 -> { CustomColorPicker( - selectedColorOption = selectedColor.value, + selectedColor = selectedColor.value, onSelect = { selectedColor.value = it }, ) } } } - } } } + +private fun ColorOption.forCustomPicker(context: Context): Int { + val color = colorPreferenceEntry.lightColor(context) + if (color == 0) { + return Color.BLACK + } + return color +} diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSlider.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSlider.kt index a61011d989..b8ec95f2a1 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSlider.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/ColorSlider.kt @@ -117,13 +117,12 @@ fun HsbColorSlider( } PreferenceTemplate( - modifier = Modifier.padding(horizontal = 8.dp), title = { Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, modifier = Modifier - .padding(horizontal = 6.dp) + .padding(horizontal = 16.dp) .fillMaxWidth() .padding(top = 16.dp), ) { @@ -161,7 +160,7 @@ fun HsbColorSlider( modifier = Modifier .fillMaxWidth() .padding(bottom = 8.dp) - .padding(horizontal = 6.dp) + .padding(horizontal = 16.dp) .requiredHeight(24.dp) .clip(RoundedCornerShape(6.dp)) .background(brush = Brush.horizontalGradient(brushColors)), @@ -176,6 +175,7 @@ fun HsbColorSlider( colors = SliderDefaults.colors(), modifier = Modifier .height(24.dp) + .padding(horizontal = 8.dp) .fillMaxWidth(), ) } diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/CustomColorPicker.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/CustomColorPicker.kt index 3772034a51..3325cf45f0 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/CustomColorPicker.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/CustomColorPicker.kt @@ -2,7 +2,7 @@ package app.lawnchair.ui.preferences.components.colorpreference.pickers import android.content.ClipData import android.content.ClipboardManager -import android.content.Context +import android.graphics.Color as AndroidColor import android.graphics.Color.argb import android.widget.Toast import androidx.compose.animation.Crossfade @@ -58,13 +58,11 @@ import kotlinx.coroutines.launch @Composable fun CustomColorPicker( modifier: Modifier = Modifier, - selectedColorOption: ColorOption, - onSelect: (ColorOption) -> Unit, + selectedColor: Int, + onSelect: (Int) -> Unit, ) { - val focusManager = LocalFocusManager.current - val selectedColor = selectedColorOption.colorPreferenceEntry.lightColor(LocalContext.current) val selectedColorCompose = Color(selectedColor) val textFieldValue = remember { @@ -76,7 +74,6 @@ fun CustomColorPicker( } Column(modifier = modifier) { - PreferenceGroup( heading = stringResource(id = R.string.hex), modifier = Modifier.padding(top = 8.dp), @@ -104,7 +101,7 @@ fun CustomColorPicker( textFieldValue.value = newValue.copy(text = newText) val newColor = colorStringToIntColor(colorString = newText) if (newColor != null) { - onSelect(ColorOption.CustomColor(newColor)) + onSelect(newColor) } }, ) @@ -128,7 +125,7 @@ fun CustomColorPicker( horizontalArrangement = Arrangement.spacedBy(space = 8.dp), modifier = Modifier .padding(horizontal = 16.dp) - .padding(top = 12.dp), + .padding(top = 16.dp), ) { Chip( label = stringResource(id = R.string.hsb), @@ -276,12 +273,12 @@ private fun HexColorPicker( private fun HsvColorPicker( selectedColor: Int, onSelectedColorChange: () -> Unit, - onSliderValuesChange: (ColorOption.CustomColor) -> Unit, + onSliderValuesChange: (Int) -> Unit, ) { - - var hue by remember { mutableStateOf(intColorToHsvColorArray(selectedColor)[0]) } - var saturation by remember { mutableStateOf(intColorToHsvColorArray(selectedColor)[1]) } - var brightness by remember { mutableStateOf(intColorToHsvColorArray(selectedColor)[2]) } + val hsv = remember { intColorToHsvColorArray(selectedColor) } + var hue by remember { mutableStateOf(hsv[0]) } + var saturation by remember { mutableStateOf(hsv[1]) } + var brightness by remember { mutableStateOf(hsv[2]) } val coroutineScope = rememberCoroutineScope() fun updateColor( @@ -296,12 +293,10 @@ private fun HsvColorPicker( if (newBrightness != null) brightness = newBrightness onSliderValuesChange( - ColorOption.CustomColor( - hsvValuesToIntColor( - hue = newHue ?: hue, - saturation = newSaturation ?: saturation, - brightness = newBrightness ?: brightness, - ), + hsvValuesToIntColor( + hue = newHue ?: hue, + saturation = newSaturation ?: saturation, + brightness = newBrightness ?: brightness, ), ) } @@ -347,7 +342,7 @@ private fun RgbColorPicker( selectedColor: Int, selectedColorCompose: Color = Color(selectedColor), onSelectedColorChange: () -> Unit, - onSliderValuesChange: (ColorOption.CustomColor) -> Unit, + onSliderValuesChange: (Int) -> Unit, ) { var red by remember { mutableStateOf(selectedColor.red) } @@ -367,13 +362,11 @@ private fun RgbColorPicker( if (newBlue != null) blue = newBlue onSliderValuesChange( - ColorOption.CustomColor( - argb( - 255, - newRed ?: red, - newGreen ?: green, - newBlue ?: blue, - ), + argb( + 255, + newRed ?: red, + newGreen ?: green, + newBlue ?: blue, ), ) } diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/PresetsList.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/PresetsList.kt index 847505c270..4dd3268559 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/PresetsList.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/PresetsList.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.key import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import app.lawnchair.theme.color.ColorOption import app.lawnchair.ui.preferences.components.PreferenceDivider @@ -19,8 +20,8 @@ import app.lawnchair.ui.preferences.components.PreferenceGroup import app.lawnchair.ui.preferences.components.PreferenceTemplate import app.lawnchair.ui.preferences.components.colorpreference.ColorDot import app.lawnchair.ui.preferences.components.colorpreference.ColorPreferenceEntry +import com.android.launcher3.R -@OptIn(ExperimentalMaterial3Api::class) @Composable fun PresetsList( dynamicEntries: List>, @@ -29,6 +30,7 @@ fun PresetsList( ) { PreferenceGroup( + heading = stringResource(id = R.string.dynamic), modifier = Modifier.padding(top = 12.dp), showDividers = false, ) { diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/SwatchGrid.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/SwatchGrid.kt index 89a4b04bc9..d223d65fca 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/SwatchGrid.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/colorpreference/pickers/SwatchGrid.kt @@ -15,9 +15,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import app.lawnchair.ui.preferences.components.PreferenceGroup import app.lawnchair.ui.preferences.components.colorpreference.ColorPreferenceEntry +import com.android.launcher3.R object SwatchGridDefaults { val GutterSize = 12.dp @@ -38,6 +40,7 @@ fun SwatchGrid( val gutter = SwatchGridDefaults.GutterSize PreferenceGroup( + heading = stringResource(id = R.string.swatches), modifier = modifier, showDividers = false, ) {