Extract common color logic to ColorPreference
This commit is contained in:
@@ -1,140 +1,38 @@
|
||||
package app.lawnchair.ui.preferences.components
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Close
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.lawnchair.preferences.getAdapter
|
||||
import app.lawnchair.preferences.preferenceManager
|
||||
import app.lawnchair.ui.theme.getDefaultAccentColor
|
||||
import com.android.launcher3.R
|
||||
import com.google.accompanist.insets.navigationBarsPadding
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
val accentColorEntries = listOf(
|
||||
ColorPreferenceEntry(
|
||||
value = 0,
|
||||
lightColor = { LocalContext.current.getDefaultAccentColor(false) },
|
||||
darkColor = { LocalContext.current.getDefaultAccentColor(true) }
|
||||
),
|
||||
AccentColorEntry(value = 0xFFF44336),
|
||||
AccentColorEntry(value = 0xFF673AB7),
|
||||
AccentColorEntry(value = 0xFF2196F3),
|
||||
AccentColorEntry(value = 0xFF4CAF50),
|
||||
AccentColorEntry(value = 0xFFFF9800),
|
||||
)
|
||||
|
||||
@Composable
|
||||
@ExperimentalMaterialApi
|
||||
@ExperimentalAnimationApi
|
||||
fun AccentColorPreference(showDivider: Boolean) {
|
||||
val sheetState = rememberBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var accentColor by preferenceManager().accentColor.getAdapter()
|
||||
val defaultAccentColor = context.getDefaultAccentColor(false)
|
||||
|
||||
val presets = listOf(
|
||||
defaultAccentColor,
|
||||
0xFFF44336.toInt(),
|
||||
0xFF673AB7.toInt(),
|
||||
0xFF2196F3.toInt(),
|
||||
0xFF4CAF50.toInt(),
|
||||
0xFFFF9800.toInt()
|
||||
ColorPreference(
|
||||
adapter = preferenceManager().accentColor.getAdapter(),
|
||||
label = stringResource(id = R.string.accent_color),
|
||||
entries = accentColorEntries,
|
||||
showDivider = showDivider
|
||||
)
|
||||
|
||||
fun applyAccentColor(newColor: Int) {
|
||||
accentColor = if (newColor == defaultAccentColor) 0 else newColor
|
||||
}
|
||||
|
||||
PreferenceTemplate(height = 52.dp, showDivider = showDivider) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clickable { scope.launch { sheetState.show() } }
|
||||
.padding(start = 16.dp, end = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.accent_color),
|
||||
style = MaterialTheme.typography.subtitle1,
|
||||
color = MaterialTheme.colors.onBackground
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheet(sheetState = sheetState) {
|
||||
val initialNewAccentColor = if (accentColor == 0) defaultAccentColor else accentColor
|
||||
var newAccentColor by remember { mutableStateOf(initialNewAccentColor) }
|
||||
|
||||
Column(modifier = Modifier.navigationBarsPadding()) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.height(56.dp)
|
||||
.padding(start = 8.dp, end = 16.dp),
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.width(40.dp)
|
||||
.height(40.dp)
|
||||
.clip(CircleShape)
|
||||
.clickable { scope.launch { sheetState.hide() } }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Close,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.onSurface
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.requiredWidth(8.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.accent_color),
|
||||
style = MaterialTheme.typography.h6
|
||||
)
|
||||
}
|
||||
Row(modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
|
||||
presets.forEachIndexed { index, it ->
|
||||
ColorSwatch(
|
||||
color = it,
|
||||
onClick = { newAccentColor = it },
|
||||
modifier = Modifier.weight(1F),
|
||||
isSelected = it == newAccentColor
|
||||
)
|
||||
if (index != presets.size - 1) Spacer(modifier = Modifier.requiredWidth(12.dp))
|
||||
}
|
||||
}
|
||||
Button(
|
||||
shape = MaterialTheme.shapes.small,
|
||||
onClick = {
|
||||
applyAccentColor(newAccentColor)
|
||||
scope.launch {
|
||||
sheetState.hide()
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.align(Alignment.End)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.done))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ExperimentalAnimationApi
|
||||
fun ColorSwatch(color: Int, onClick: (Int) -> Unit, modifier: Modifier = Modifier, isSelected: Boolean) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.aspectRatio(1F)
|
||||
.clip(CircleShape)
|
||||
.background(color = Color(color))
|
||||
.clickable { onClick(color) }, contentAlignment = Alignment.Center
|
||||
) {
|
||||
AnimatedCheck(
|
||||
visible = isSelected,
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
}
|
||||
class AccentColorEntry(value: Long) : ColorPreferenceEntry<Int>(value.toInt(), { value.toInt() })
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package app.lawnchair.ui.preferences.components
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Close
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.lawnchair.preferences.PreferenceAdapter
|
||||
import app.lawnchair.ui.theme.lightenColor
|
||||
import com.android.launcher3.R
|
||||
import com.google.accompanist.insets.navigationBarsPadding
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
@ExperimentalMaterialApi
|
||||
@ExperimentalAnimationApi
|
||||
fun <T> ColorPreference(
|
||||
adapter: PreferenceAdapter<T>,
|
||||
label: String,
|
||||
entries: List<ColorPreferenceEntry<T>>,
|
||||
showDivider: Boolean
|
||||
) {
|
||||
val sheetState = rememberBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
|
||||
val scope = rememberCoroutineScope()
|
||||
var currentColor by adapter
|
||||
|
||||
fun applyColor(newColor: T) {
|
||||
currentColor = newColor
|
||||
}
|
||||
|
||||
PreferenceTemplate(height = 52.dp, showDivider = showDivider) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clickable { scope.launch { sheetState.show() } }
|
||||
.padding(start = 16.dp, end = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = MaterialTheme.typography.subtitle1,
|
||||
color = MaterialTheme.colors.onBackground
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheet(sheetState = sheetState) {
|
||||
var newColor by remember { mutableStateOf(currentColor) }
|
||||
|
||||
Column(modifier = Modifier.navigationBarsPadding()) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.height(56.dp)
|
||||
.padding(start = 8.dp, end = 16.dp),
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.width(40.dp)
|
||||
.height(40.dp)
|
||||
.clip(CircleShape)
|
||||
.clickable { scope.launch { sheetState.hide() } }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Close,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.onSurface
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.requiredWidth(8.dp))
|
||||
Text(
|
||||
text = label,
|
||||
style = MaterialTheme.typography.h6
|
||||
)
|
||||
}
|
||||
Row(modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
|
||||
entries.forEachIndexed { index, it ->
|
||||
ColorSwatch(
|
||||
entry = it,
|
||||
onClick = { newColor = it.value },
|
||||
modifier = Modifier.weight(1F),
|
||||
isSelected = it.value == newColor
|
||||
)
|
||||
if (index != entries.lastIndex) Spacer(modifier = Modifier.requiredWidth(12.dp))
|
||||
}
|
||||
}
|
||||
Button(
|
||||
shape = MaterialTheme.shapes.small,
|
||||
onClick = {
|
||||
applyColor(newColor)
|
||||
scope.launch {
|
||||
sheetState.hide()
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.align(Alignment.End)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.done))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ExperimentalAnimationApi
|
||||
fun <T> ColorSwatch(
|
||||
entry: ColorPreferenceEntry<T>,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
isSelected: Boolean
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.aspectRatio(1F)
|
||||
.clip(CircleShape)
|
||||
.background(color = Color(entry.lightColor()))
|
||||
.clickable { onClick() },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
AnimatedCheck(
|
||||
visible = isSelected,
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
open class ColorPreferenceEntry<T>(
|
||||
val value: T,
|
||||
val lightColor: @Composable () -> Int,
|
||||
val darkColor: @Composable () -> Int = { lightenColor(lightColor()) },
|
||||
)
|
||||
Reference in New Issue
Block a user