refactor more bottom sheets
This commit is contained in:
@@ -1,16 +1,22 @@
|
||||
package de.mm20.launcher2.ui.common
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.DockedSearchBar
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -18,6 +24,8 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
@@ -32,81 +40,122 @@ import de.mm20.launcher2.ui.ktx.toPixels
|
||||
|
||||
@Composable
|
||||
fun SearchablePicker(
|
||||
expanded: Boolean,
|
||||
value: SavableSearchable?,
|
||||
onValueChanged: (SavableSearchable?) -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
val viewModel: SearchablePickerVM = viewModel()
|
||||
DismissableBottomSheet(expanded = expanded, onDismissRequest = onDismissRequest) {
|
||||
val viewModel: SearchablePickerVM = viewModel()
|
||||
|
||||
DismissableBottomSheet(onDismissRequest = onDismissRequest) {
|
||||
Column(
|
||||
val colorSurface = MaterialTheme.colorScheme.surfaceContainerLow
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(it)
|
||||
) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 12.dp),
|
||||
value = viewModel.searchQuery,
|
||||
onValueChange = { viewModel.onSearchQueryChanged(it) },
|
||||
leadingIcon = {
|
||||
Icon(painterResource(R.drawable.search_24px), null)
|
||||
},
|
||||
placeholder = {
|
||||
Text(stringResource(R.string.search_bar_placeholder))
|
||||
},
|
||||
singleLine = true,
|
||||
.fillMaxSize(),
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp + WindowInsets.navigationBars.asPaddingValues()
|
||||
.calculateBottomPadding(),
|
||||
top = 16.dp,
|
||||
)
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
items(viewModel.items) {
|
||||
val iconSize = 32.dp.toPixels()
|
||||
val icon by remember(it.key) {
|
||||
viewModel.getIcon(
|
||||
it,
|
||||
iconSize.toInt()
|
||||
)
|
||||
}.collectAsStateWithLifecycle(null)
|
||||
val selected = it.key == value?.key
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp),
|
||||
shape = MaterialTheme.shapes.small,
|
||||
border = BorderStroke(1.dp, if (selected) MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.outline),
|
||||
color = if (selected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface,
|
||||
onClick = { onValueChanged(it) }) {
|
||||
Row(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
ShapedLauncherIcon(
|
||||
icon = { icon },
|
||||
size = 32.dp,
|
||||
)
|
||||
Text(
|
||||
text = it.label,
|
||||
modifier = Modifier.weight(1f).padding(horizontal = 16.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
if (selected) {
|
||||
Icon(
|
||||
painterResource(R.drawable.check_circle_24px_filled),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
) {
|
||||
stickyHeader {
|
||||
DockedSearchBar(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.drawBehind {
|
||||
drawRect(
|
||||
brush = Brush.verticalGradient(
|
||||
0.5f to colorSurface,
|
||||
0.5f to colorSurface.copy(alpha = 0f),
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
.padding(bottom = 16.dp),
|
||||
expanded = false,
|
||||
onExpandedChange = {},
|
||||
inputField = {
|
||||
SearchBarDefaults.InputField(
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
painterResource(R.drawable.search_24px),
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (viewModel.searchQuery.isNotEmpty()) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
viewModel.onSearchQueryChanged("")
|
||||
}) {
|
||||
Icon(painterResource(R.drawable.close_24px), null)
|
||||
}
|
||||
}
|
||||
},
|
||||
onSearch = {},
|
||||
expanded = false,
|
||||
onExpandedChange = {},
|
||||
query = viewModel.searchQuery,
|
||||
onQueryChange = {
|
||||
viewModel.onSearchQueryChanged(it)
|
||||
},
|
||||
placeholder = {
|
||||
Text(stringResource(R.string.search_bar_placeholder))
|
||||
},
|
||||
)
|
||||
}
|
||||
) {
|
||||
}
|
||||
}
|
||||
items(viewModel.items) {
|
||||
val iconSize = 32.dp.toPixels()
|
||||
val icon by remember(it.key) {
|
||||
viewModel.getIcon(
|
||||
it,
|
||||
iconSize.toInt()
|
||||
)
|
||||
}.collectAsStateWithLifecycle(null)
|
||||
val selected = it.key == value?.key
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp),
|
||||
shape = MaterialTheme.shapes.small,
|
||||
border = BorderStroke(
|
||||
1.dp,
|
||||
if (selected) MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.outline
|
||||
),
|
||||
color = if (selected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface,
|
||||
onClick = { onValueChanged(it) }) {
|
||||
Row(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
ShapedLauncherIcon(
|
||||
icon = { icon },
|
||||
size = 32.dp,
|
||||
)
|
||||
Text(
|
||||
text = it.label,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 16.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
if (selected) {
|
||||
Icon(
|
||||
painterResource(R.drawable.check_circle_24px_filled),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,7 +67,7 @@ import kotlinx.coroutines.CancellationException
|
||||
fun DismissableBottomSheet(
|
||||
expanded: Boolean = true,
|
||||
onDismissRequest: () -> Unit,
|
||||
content: @Composable (contentPadding: PaddingValues) -> Unit,
|
||||
content: @Composable (contentPadding: PaddingValues) -> Unit,
|
||||
) {
|
||||
DismissableBottomSheet(
|
||||
state = expanded,
|
||||
|
||||
@@ -272,19 +272,18 @@ fun CustomizeSearchableSheet(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pickIcon) {
|
||||
DismissableBottomSheet(
|
||||
onDismissRequest = { viewModel.closeIconPicker() },
|
||||
) {
|
||||
IconPicker(
|
||||
searchable = searchable,
|
||||
onSelect = {
|
||||
viewModel.pickIcon(it)
|
||||
viewModel.closeIconPicker()
|
||||
},
|
||||
contentPadding = it,
|
||||
)
|
||||
}
|
||||
DismissableBottomSheet(
|
||||
expanded = pickIcon,
|
||||
onDismissRequest = { viewModel.closeIconPicker() },
|
||||
) {
|
||||
IconPicker(
|
||||
searchable = searchable,
|
||||
onSelect = {
|
||||
viewModel.pickIcon(it)
|
||||
viewModel.closeIconPicker()
|
||||
},
|
||||
contentPadding = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
@@ -123,19 +124,18 @@ fun NotesWidget(
|
||||
}
|
||||
},
|
||||
)
|
||||
if (showConflictResolveSheet) {
|
||||
NoteWidgetConflictResolveSheet(
|
||||
localContent = widget.config.storedText,
|
||||
fileContent = text.text,
|
||||
onResolve = {
|
||||
viewModel.resolveFileContentConflict(context, it)
|
||||
showConflictResolveSheet = false
|
||||
},
|
||||
onDismissRequest = {
|
||||
showConflictResolveSheet = false
|
||||
}
|
||||
)
|
||||
}
|
||||
NoteWidgetConflictResolveSheet(
|
||||
expanded = showConflictResolveSheet,
|
||||
localContent = widget.config.storedText,
|
||||
fileContent = text.text,
|
||||
onResolve = {
|
||||
viewModel.resolveFileContentConflict(context, it)
|
||||
showConflictResolveSheet = false
|
||||
},
|
||||
onDismissRequest = {
|
||||
showConflictResolveSheet = false
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
Column {
|
||||
@@ -374,44 +374,44 @@ fun NotesWidget(
|
||||
}
|
||||
}
|
||||
|
||||
if (readWriteErrorSheetText != null) {
|
||||
NoteReadWriteErrorSheet(
|
||||
message = readWriteErrorSheetText!!,
|
||||
onDismiss = { readWriteErrorSheetText = null },
|
||||
onRelink = {
|
||||
linkFileLauncher.launch(
|
||||
context.getString(
|
||||
R.string.notes_widget_export_filename,
|
||||
ZonedDateTime.now().format(
|
||||
DateTimeFormatter.ISO_INSTANT
|
||||
)
|
||||
NoteReadWriteErrorSheet(
|
||||
message = readWriteErrorSheetText,
|
||||
onDismiss = { readWriteErrorSheetText = null },
|
||||
onRelink = {
|
||||
linkFileLauncher.launch(
|
||||
context.getString(
|
||||
R.string.notes_widget_export_filename,
|
||||
ZonedDateTime.now().format(
|
||||
DateTimeFormatter.ISO_INSTANT
|
||||
)
|
||||
)
|
||||
},
|
||||
onUnlink = {
|
||||
viewModel.unlinkFile(context)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
onUnlink = {
|
||||
viewModel.unlinkFile(context)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NoteWidgetConflictResolveSheet(
|
||||
expanded: Boolean,
|
||||
localContent: String,
|
||||
fileContent: String,
|
||||
onResolve: (LinkedFileConflictStrategy) -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
var selectedStrategy by remember { mutableStateOf<LinkedFileConflictStrategy?>(null) }
|
||||
DismissableBottomSheet(
|
||||
expanded = expanded,
|
||||
onDismissRequest = onDismissRequest,
|
||||
|
||||
) {
|
||||
var selectedStrategy by remember { mutableStateOf<LinkedFileConflictStrategy?>(null) }
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it),
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding(),
|
||||
) {
|
||||
|
||||
Text(
|
||||
@@ -538,19 +538,24 @@ fun SelectableNoteContent(
|
||||
|
||||
@Composable
|
||||
fun NoteReadWriteErrorSheet(
|
||||
message: String,
|
||||
message: String?,
|
||||
onDismiss: () -> Unit,
|
||||
onRelink: () -> Unit,
|
||||
onUnlink: () -> Unit,
|
||||
) {
|
||||
DismissableBottomSheet(
|
||||
state = message,
|
||||
expanded = { it != null },
|
||||
onDismissRequest = onDismiss,
|
||||
) {
|
||||
) { message ->
|
||||
message ?: return@DismissableBottomSheet
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it)
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding()
|
||||
) {
|
||||
Text(
|
||||
text = message,
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -51,7 +52,8 @@ fun CorePaletteColorPreference(
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth()
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(MaterialTheme.shapes.extraSmall)
|
||||
.clickable(
|
||||
onClick = { showDialog = true },
|
||||
@@ -62,7 +64,9 @@ fun CorePaletteColorPreference(
|
||||
) {
|
||||
ColorSwatch(
|
||||
color = Color(value ?: defaultValue),
|
||||
modifier = Modifier.padding(end = 20.dp).size(48.dp),
|
||||
modifier = Modifier
|
||||
.padding(end = 20.dp)
|
||||
.size(48.dp),
|
||||
)
|
||||
|
||||
Text(
|
||||
@@ -74,78 +78,79 @@ fun CorePaletteColorPreference(
|
||||
)
|
||||
}
|
||||
|
||||
if (showDialog) {
|
||||
var currentValue by remember { mutableStateOf(value) }
|
||||
DismissableBottomSheet(onDismissRequest = {
|
||||
var currentValue by remember { mutableStateOf(value) }
|
||||
DismissableBottomSheet(
|
||||
expanded = showDialog,
|
||||
onDismissRequest = {
|
||||
onValueChange(currentValue)
|
||||
showDialog = false
|
||||
}) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it)
|
||||
) {
|
||||
SwitchPreference(
|
||||
icon = R.drawable.rule_settings_24px,
|
||||
title = stringResource(R.string.theme_color_scheme_system_default),
|
||||
value = currentValue == null,
|
||||
onValueChanged = {
|
||||
currentValue = if (it) null else defaultValue
|
||||
},
|
||||
containerColor = Color.Transparent,
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding()
|
||||
) {
|
||||
SwitchPreference(
|
||||
icon = R.drawable.rule_settings_24px,
|
||||
title = stringResource(R.string.theme_color_scheme_system_default),
|
||||
value = currentValue == null,
|
||||
onValueChanged = {
|
||||
currentValue = if (it) null else defaultValue
|
||||
},
|
||||
containerColor = Color.Transparent,
|
||||
)
|
||||
AnimatedVisibility(
|
||||
currentValue != null,
|
||||
enter = expandVertically(
|
||||
expandFrom = Alignment.Top,
|
||||
),
|
||||
exit = shrinkVertically(
|
||||
shrinkTowards = Alignment.Top,
|
||||
)
|
||||
AnimatedVisibility(
|
||||
currentValue != null,
|
||||
enter = expandVertically(
|
||||
expandFrom = Alignment.Top,
|
||||
),
|
||||
exit = shrinkVertically(
|
||||
shrinkTowards = Alignment.Top,
|
||||
) {
|
||||
Column {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(bottom = 24.dp)
|
||||
)
|
||||
) {
|
||||
Column {
|
||||
val colorPickerState = rememberHctColorPickerState(
|
||||
initialColor = Color(value ?: defaultValue),
|
||||
onColorChanged = {
|
||||
currentValue = it.toArgb()
|
||||
}
|
||||
)
|
||||
HctColorPicker(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterHorizontally),
|
||||
state = colorPickerState,
|
||||
)
|
||||
|
||||
if (autoGenerate != null) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(bottom = 24.dp)
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
val colorPickerState = rememberHctColorPickerState(
|
||||
initialColor = Color(value ?: defaultValue),
|
||||
onColorChanged = {
|
||||
currentValue = it.toArgb()
|
||||
}
|
||||
)
|
||||
HctColorPicker(
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterHorizontally),
|
||||
state = colorPickerState,
|
||||
)
|
||||
|
||||
if (autoGenerate != null) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = {
|
||||
val autoGenerated = autoGenerate()
|
||||
currentValue = autoGenerated
|
||||
if (autoGenerated != null) {
|
||||
colorPickerState.setColor(Color(autoGenerated))
|
||||
}
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = {
|
||||
val autoGenerated = autoGenerate()
|
||||
currentValue = autoGenerated
|
||||
if (autoGenerated != null) {
|
||||
colorPickerState.setColor(Color(autoGenerated))
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.wand_stars_20px), null,
|
||||
modifier = Modifier
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.theme_color_scheme_autogenerate))
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.wand_stars_20px), null,
|
||||
modifier = Modifier
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.theme_color_scheme_autogenerate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
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.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
@@ -74,7 +75,8 @@ fun ThemeColorPreference(
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth()
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(MaterialTheme.shapes.extraSmall)
|
||||
.clickable(
|
||||
onClick = { showDialog = true },
|
||||
@@ -85,7 +87,9 @@ fun ThemeColorPreference(
|
||||
) {
|
||||
ColorSwatch(
|
||||
color = Color((value ?: defaultValue).get(corePalette)),
|
||||
modifier = Modifier.padding(end = 20.dp).size(48.dp),
|
||||
modifier = Modifier
|
||||
.padding(end = 20.dp)
|
||||
.size(48.dp),
|
||||
)
|
||||
|
||||
Text(
|
||||
@@ -97,337 +101,338 @@ fun ThemeColorPreference(
|
||||
)
|
||||
}
|
||||
|
||||
if (showDialog) {
|
||||
var currentValue by remember { mutableStateOf(value) }
|
||||
var currentValue by remember { mutableStateOf(value) }
|
||||
|
||||
val actualValue = currentValue ?: defaultValue
|
||||
DismissableBottomSheet(onDismissRequest = {
|
||||
DismissableBottomSheet(
|
||||
expanded = showDialog,
|
||||
onDismissRequest = {
|
||||
onValueChange(currentValue)
|
||||
showDialog = false
|
||||
}) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it),
|
||||
val actualValue = currentValue ?: defaultValue
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding(),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.ConnectedSpaceBetween)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.ConnectedSpaceBetween)
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualValue is ColorRef,
|
||||
onCheckedChange = {
|
||||
if (actualValue is ColorRef) return@ToggleButton
|
||||
currentValue = defaultValue
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedLeadingButtonShapes()
|
||||
) {
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualValue is ColorRef,
|
||||
onCheckedChange = {
|
||||
if (actualValue is ColorRef) return@ToggleButton
|
||||
currentValue = defaultValue
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedLeadingButtonShapes()
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualValue is ColorRef) R.drawable.check_20px else R.drawable.palette_20px
|
||||
),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.theme_color_scheme_palette_color))
|
||||
}
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualValue is StaticColor,
|
||||
onCheckedChange = {
|
||||
currentValue = StaticColor(actualValue.get(corePalette))
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedTrailingButtonShapes()
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualValue is StaticColor) R.drawable.check_20px else R.drawable.colorize_20px
|
||||
),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.theme_color_scheme_custom_color))
|
||||
}
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualValue is ColorRef) R.drawable.check_20px else R.drawable.palette_20px
|
||||
),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.theme_color_scheme_palette_color))
|
||||
}
|
||||
AnimatedContent(
|
||||
actualValue,
|
||||
label = "AnimatedContent",
|
||||
contentKey = { it is StaticColor }
|
||||
) { themeColor ->
|
||||
Column {
|
||||
if (themeColor is StaticColor) {
|
||||
val colorPickerState = rememberHctColorPickerState(
|
||||
initialColor = Color(themeColor.color),
|
||||
onColorChanged = {
|
||||
currentValue = StaticColor(it.toArgb())
|
||||
}
|
||||
)
|
||||
HctColorPicker(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 24.dp)
|
||||
.align(Alignment.CenterHorizontally),
|
||||
state = colorPickerState
|
||||
)
|
||||
} else if (themeColor is ColorRef) {
|
||||
val hct = Hct.fromInt(corePalette.get(themeColor.color))
|
||||
val hue = hct.hue.toFloat()
|
||||
val chroma = hct.chroma.toFloat()
|
||||
var tone by remember(value == null) { mutableStateOf(themeColor.tone.toFloat()) }
|
||||
Row(
|
||||
modifier = Modifier.padding(top = 24.dp, bottom = 8.dp)
|
||||
) {
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Primary)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Primary,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Primary,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Secondary)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Secondary,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Secondary,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Tertiary)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Tertiary,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Tertiary,
|
||||
)
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualValue is StaticColor,
|
||||
onCheckedChange = {
|
||||
currentValue = StaticColor(actualValue.get(corePalette))
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedTrailingButtonShapes()
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualValue is StaticColor) R.drawable.check_20px else R.drawable.colorize_20px
|
||||
),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.theme_color_scheme_custom_color))
|
||||
}
|
||||
}
|
||||
AnimatedContent(
|
||||
actualValue,
|
||||
label = "AnimatedContent",
|
||||
contentKey = { it is StaticColor }
|
||||
) { themeColor ->
|
||||
Column {
|
||||
if (themeColor is StaticColor) {
|
||||
val colorPickerState = rememberHctColorPickerState(
|
||||
initialColor = Color(themeColor.color),
|
||||
onColorChanged = {
|
||||
currentValue = StaticColor(it.toArgb())
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
) {
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Neutral)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Neutral,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Neutral,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.NeutralVariant)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.NeutralVariant,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.NeutralVariant,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Error)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Error,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Error,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
)
|
||||
HctColorPicker(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 24.dp)
|
||||
.align(Alignment.CenterHorizontally),
|
||||
state = colorPickerState
|
||||
)
|
||||
} else if (themeColor is ColorRef) {
|
||||
val hct = Hct.fromInt(corePalette.get(themeColor.color))
|
||||
val hue = hct.hue.toFloat()
|
||||
val chroma = hct.chroma.toFloat()
|
||||
var tone by remember(value == null) { mutableStateOf(themeColor.tone.toFloat()) }
|
||||
Row(
|
||||
modifier = Modifier.padding(top = 24.dp, bottom = 8.dp)
|
||||
) {
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Primary)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "T",
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier.weight(1f),
|
||||
value = tone,
|
||||
valueRange = 0f..100f,
|
||||
onValueChange = {
|
||||
tone = it
|
||||
currentValue = themeColor.copy(tone = it.roundToInt())
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Primary,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
track = {
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(20.dp)
|
||||
) {
|
||||
drawRoundRect(
|
||||
brush = Brush.horizontalGradient(
|
||||
colors = listOf(
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
0f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
10f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
20f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
30f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
40f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
50f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
60f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
70f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
80f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
90f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
100f
|
||||
),
|
||||
)
|
||||
),
|
||||
style = Fill,
|
||||
cornerRadius = CornerRadius(
|
||||
10.dp.toPx(),
|
||||
10.dp.toPx()
|
||||
selected = themeColor.color == CorePaletteColor.Primary,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Secondary)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Secondary,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Secondary,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Tertiary)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Tertiary,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Tertiary,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
) {
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Neutral)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Neutral,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Neutral,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.NeutralVariant)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.NeutralVariant,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.NeutralVariant,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ColorSwatch(
|
||||
color = Color(
|
||||
corePalette
|
||||
.get(CorePaletteColor.Error)
|
||||
.atTone(tone.toInt())
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
.clickable {
|
||||
currentValue = ColorRef(
|
||||
CorePaletteColor.Error,
|
||||
tone.roundToInt()
|
||||
)
|
||||
},
|
||||
selected = themeColor.color == CorePaletteColor.Error,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "T",
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier.weight(1f),
|
||||
value = tone,
|
||||
valueRange = 0f..100f,
|
||||
onValueChange = {
|
||||
tone = it
|
||||
currentValue = themeColor.copy(tone = it.roundToInt())
|
||||
},
|
||||
track = {
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(20.dp)
|
||||
) {
|
||||
drawRoundRect(
|
||||
brush = Brush.horizontalGradient(
|
||||
colors = listOf(
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
0f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
10f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
20f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
30f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
40f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
50f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
60f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
70f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
80f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
90f
|
||||
),
|
||||
Color.hct(
|
||||
hue,
|
||||
chroma,
|
||||
100f
|
||||
),
|
||||
)
|
||||
),
|
||||
style = Fill,
|
||||
cornerRadius = CornerRadius(
|
||||
10.dp.toPx(),
|
||||
10.dp.toPx()
|
||||
)
|
||||
}
|
||||
},
|
||||
thumb = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 2.dp, horizontal = 8.dp)
|
||||
.size(16.dp)
|
||||
.shadow(1.dp, CircleShape)
|
||||
.clip(CircleShape)
|
||||
.background(Color.White)
|
||||
)
|
||||
}
|
||||
)
|
||||
Text(
|
||||
text = tone.roundToInt().toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = { currentValue = null }
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.restart_alt_20px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
},
|
||||
thumb = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 2.dp, horizontal = 8.dp)
|
||||
.size(16.dp)
|
||||
.shadow(1.dp, CircleShape)
|
||||
.clip(CircleShape)
|
||||
.background(Color.White)
|
||||
)
|
||||
}
|
||||
)
|
||||
Text(
|
||||
text = tone.roundToInt().toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Text(stringResource(R.string.preference_restore_default))
|
||||
}
|
||||
}
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = { currentValue = null }
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.restart_alt_20px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_restore_default))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,8 +285,9 @@ fun GesturePreference(
|
||||
}
|
||||
}
|
||||
|
||||
if (value is GestureAction.Launch && (showAppPicker || app == null)) {
|
||||
if (value is GestureAction.Launch) {
|
||||
SearchablePicker(
|
||||
expanded = (showAppPicker || app == null),
|
||||
onDismissRequest = {
|
||||
showAppPicker = false
|
||||
if (app == null) onValueChanged(GestureAction.NoAction)
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Row
|
||||
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.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
@@ -298,142 +299,141 @@ fun SearchBarStylePreference(
|
||||
) {
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
Preference(title = title, summary = summary, onClick = { showDialog = true })
|
||||
if (showDialog && value != null) {
|
||||
val styles = remember {
|
||||
SearchBarStyle.entries
|
||||
|
||||
DismissableBottomSheet(
|
||||
expanded = showDialog,
|
||||
onDismissRequest = {
|
||||
showDialog = false
|
||||
}
|
||||
) {
|
||||
val styles = SearchBarStyle.entries
|
||||
|
||||
val darkColors =
|
||||
LocalPreferDarkContentOverWallpaper.current && colors == SearchBarColors.Auto || colors == SearchBarColors.Dark
|
||||
|
||||
DismissableBottomSheet(
|
||||
onDismissRequest = {
|
||||
showDialog = false
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding(),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
for (style in styles) {
|
||||
Column {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(
|
||||
when (style) {
|
||||
SearchBarStyle.Transparent -> R.string.preference_search_bar_style_transparent
|
||||
SearchBarStyle.Solid -> R.string.preference_search_bar_style_solid
|
||||
SearchBarStyle.Hidden -> R.string.preference_search_bar_style_hidden
|
||||
}
|
||||
),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
IconButton(
|
||||
onClick = {
|
||||
onStyleChanged(style)
|
||||
for (style in styles) {
|
||||
Column {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(
|
||||
when (style) {
|
||||
SearchBarStyle.Transparent -> R.string.preference_search_bar_style_transparent
|
||||
SearchBarStyle.Solid -> R.string.preference_search_bar_style_solid
|
||||
SearchBarStyle.Hidden -> R.string.preference_search_bar_style_hidden
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (style == value) R.drawable.check_circle_24px_filled
|
||||
else R.drawable.circle_24px
|
||||
),
|
||||
contentDescription = null,
|
||||
tint = if (style == value) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
IconButton(
|
||||
onClick = {
|
||||
onStyleChanged(style)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (style == value) R.drawable.check_circle_24px_filled
|
||||
else R.drawable.circle_24px
|
||||
),
|
||||
contentDescription = null,
|
||||
tint = if (style == value) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.border(
|
||||
if (style == value) 4.dp else 2.dp,
|
||||
if (style == value) MaterialTheme.colorScheme.primary else Color.Transparent,
|
||||
MaterialTheme.shapes.medium,
|
||||
)
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
.background(
|
||||
when {
|
||||
style != SearchBarStyle.Transparent -> MaterialTheme.colorScheme.inverseSurface
|
||||
LocalDarkTheme.current != darkColors -> MaterialTheme.colorScheme.surfaceContainer
|
||||
else -> MaterialTheme.colorScheme.inverseSurface
|
||||
}
|
||||
)
|
||||
.height(IntrinsicSize.Min)
|
||||
) {
|
||||
SearchBar(
|
||||
modifier = Modifier
|
||||
.padding(16.dp),
|
||||
level = SearchBarLevel.Resting,
|
||||
style = style,
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
darkColors = darkColors,
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.border(
|
||||
if (style == value) 4.dp else 2.dp,
|
||||
if (style == value) MaterialTheme.colorScheme.primary else Color.Transparent,
|
||||
MaterialTheme.shapes.medium,
|
||||
)
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
.background(
|
||||
when {
|
||||
style != SearchBarStyle.Transparent -> MaterialTheme.colorScheme.inverseSurface
|
||||
LocalDarkTheme.current != darkColors -> MaterialTheme.colorScheme.surfaceContainer
|
||||
else -> MaterialTheme.colorScheme.inverseSurface
|
||||
}
|
||||
)
|
||||
.height(IntrinsicSize.Min)
|
||||
.fillMaxSize()
|
||||
.clickable {
|
||||
onStyleChanged(style)
|
||||
}
|
||||
)
|
||||
}
|
||||
if (style == SearchBarStyle.Transparent) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.ConnectedSpaceBetween)
|
||||
) {
|
||||
SearchBar(
|
||||
modifier = Modifier
|
||||
.padding(16.dp),
|
||||
level = SearchBarLevel.Resting,
|
||||
style = style,
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
darkColors = darkColors,
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clickable {
|
||||
onStyleChanged(style)
|
||||
}
|
||||
)
|
||||
}
|
||||
if (style == SearchBarStyle.Transparent) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.ConnectedSpaceBetween)
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = colors == SearchBarColors.Auto,
|
||||
onCheckedChange = {
|
||||
onColorsChanged(SearchBarColors.Auto)
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedLeadingButtonShapes(),
|
||||
) {
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = colors == SearchBarColors.Auto,
|
||||
onCheckedChange = {
|
||||
onColorsChanged(SearchBarColors.Auto)
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedLeadingButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.auto_awesome_20dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = colors == SearchBarColors.Light,
|
||||
onCheckedChange = {
|
||||
onColorsChanged(SearchBarColors.Light)
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedMiddleButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.light_mode_24px),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = colors == SearchBarColors.Dark,
|
||||
onCheckedChange = {
|
||||
onColorsChanged(SearchBarColors.Dark)
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedTrailingButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.dark_mode_24px),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
painterResource(R.drawable.auto_awesome_20dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = colors == SearchBarColors.Light,
|
||||
onCheckedChange = {
|
||||
onColorsChanged(SearchBarColors.Light)
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedMiddleButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.light_mode_24px),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = colors == SearchBarColors.Dark,
|
||||
onCheckedChange = {
|
||||
onColorsChanged(SearchBarColors.Dark)
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedTrailingButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.dark_mode_24px),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package de.mm20.launcher2.ui.settings.search
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
@@ -397,27 +398,29 @@ fun SearchSettingsScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
if (showFilterEditor) {
|
||||
DismissableBottomSheet(
|
||||
expanded = showFilterEditor,
|
||||
onDismissRequest = { showFilterEditor = false }) {
|
||||
val filters by viewModel.searchFilters.collectAsStateWithLifecycle()
|
||||
DismissableBottomSheet(onDismissRequest = { showFilterEditor = false }) {
|
||||
Column(
|
||||
modifier = Modifier.padding(it)
|
||||
) {
|
||||
AnimatedVisibility(filters.allowNetwork) {
|
||||
SmallMessage(
|
||||
modifier = Modifier.padding(bottom = 16.dp),
|
||||
icon = R.drawable.warning_24px,
|
||||
text = stringResource(R.string.filter_settings_network_warning)
|
||||
)
|
||||
}
|
||||
SearchFilters(
|
||||
filters = filters,
|
||||
onFiltersChange = {
|
||||
viewModel.setSearchFilters(it)
|
||||
},
|
||||
settings = true,
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding()
|
||||
) {
|
||||
AnimatedVisibility(filters.allowNetwork) {
|
||||
SmallMessage(
|
||||
modifier = Modifier.padding(bottom = 16.dp),
|
||||
icon = R.drawable.warning_24px,
|
||||
text = stringResource(R.string.filter_settings_network_warning)
|
||||
)
|
||||
}
|
||||
SearchFilters(
|
||||
filters = filters,
|
||||
onFiltersChange = {
|
||||
viewModel.setSearchFilters(it)
|
||||
},
|
||||
settings = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ import de.mm20.launcher2.themes.shapes.Shape as ThemeShape
|
||||
@Serializable
|
||||
data class ShapeSchemeSettingsRoute(
|
||||
@Serializable(with = UUIDSerializer::class) val id: UUID
|
||||
): NavKey
|
||||
) : NavKey
|
||||
|
||||
@Composable
|
||||
fun ShapeSchemeSettingsScreen(themeId: UUID) {
|
||||
@@ -463,20 +463,38 @@ fun ShapePreference(
|
||||
)
|
||||
}
|
||||
|
||||
if (showDialog) {
|
||||
val maxRadius = (24 * factor).toInt()
|
||||
val maxRadius = (24 * factor).toInt()
|
||||
|
||||
val baseTopStart = ((baseShape.radii?.get(0) ?: 12) * factor).toInt()
|
||||
val baseTopEnd = ((baseShape.radii?.get(1) ?: 12) * factor).toInt()
|
||||
val baseBottomEnd = ((baseShape.radii?.get(2) ?: 12) * factor).toInt()
|
||||
val baseBottomStart = ((baseShape.radii?.get(3) ?: 12) * factor).toInt()
|
||||
val baseTopStart = ((baseShape.radii?.get(0) ?: 12) * factor).toInt()
|
||||
val baseTopEnd = ((baseShape.radii?.get(1) ?: 12) * factor).toInt()
|
||||
val baseBottomEnd = ((baseShape.radii?.get(2) ?: 12) * factor).toInt()
|
||||
val baseBottomStart = ((baseShape.radii?.get(3) ?: 12) * factor).toInt()
|
||||
|
||||
|
||||
var currentCornerStyle by remember(shape) { mutableStateOf(shape?.corners) }
|
||||
var currentTopStart by remember(shape) { mutableStateOf(shape?.radii?.get(0)) }
|
||||
var currentTopEnd by remember(shape) { mutableStateOf(shape?.radii?.get(1)) }
|
||||
var currentBottomEnd by remember(shape) { mutableStateOf(shape?.radii?.get(2)) }
|
||||
var currentBottomStart by remember(shape) { mutableStateOf(shape?.radii?.get(3)) }
|
||||
var currentCornerStyle by remember(shape) { mutableStateOf(shape?.corners) }
|
||||
var currentTopStart by remember(shape) { mutableStateOf(shape?.radii?.get(0)) }
|
||||
var currentTopEnd by remember(shape) { mutableStateOf(shape?.radii?.get(1)) }
|
||||
var currentBottomEnd by remember(shape) { mutableStateOf(shape?.radii?.get(2)) }
|
||||
var currentBottomStart by remember(shape) { mutableStateOf(shape?.radii?.get(3)) }
|
||||
|
||||
DismissableBottomSheet(
|
||||
expanded = showDialog,
|
||||
onDismissRequest = {
|
||||
showDialog = false
|
||||
onValueChange(
|
||||
ThemeShape(
|
||||
corners = currentCornerStyle,
|
||||
radii = if (currentTopStart != null || currentTopEnd != null || currentBottomEnd != null || currentBottomStart != null) {
|
||||
intArrayOf(
|
||||
currentTopStart ?: baseTopStart,
|
||||
currentTopEnd ?: baseTopEnd,
|
||||
currentBottomEnd ?: baseBottomEnd,
|
||||
currentBottomStart ?: baseBottomStart,
|
||||
)
|
||||
} else null
|
||||
)
|
||||
)
|
||||
}) {
|
||||
|
||||
val actualCornerStyle = currentCornerStyle ?: baseShape.corners ?: CornerStyle.Rounded
|
||||
val actualTopStart = currentTopStart ?: baseTopStart
|
||||
@@ -484,241 +502,222 @@ fun ShapePreference(
|
||||
val actualBottomEnd = currentBottomEnd ?: baseBottomEnd
|
||||
val actualBottomStart = currentBottomStart ?: baseBottomStart
|
||||
|
||||
DismissableBottomSheet(
|
||||
onDismissRequest = {
|
||||
showDialog = false
|
||||
onValueChange(
|
||||
ThemeShape(
|
||||
corners = currentCornerStyle,
|
||||
radii = if (currentTopStart != null || currentTopEnd != null || currentBottomEnd != null || currentBottomStart != null) {
|
||||
intArrayOf(
|
||||
currentTopStart ?: baseTopStart,
|
||||
currentTopEnd ?: baseTopEnd,
|
||||
currentBottomEnd ?: baseBottomEnd,
|
||||
currentBottomStart ?: baseBottomStart,
|
||||
)
|
||||
} else null
|
||||
)
|
||||
)
|
||||
}) {
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it)
|
||||
.padding(bottom = 8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it)
|
||||
.padding(bottom = 8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
val previewShape = if ((currentCornerStyle ?: baseShape.corners
|
||||
?: CornerStyle.Rounded) == CornerStyle.Rounded
|
||||
) {
|
||||
val previewShape = if ((currentCornerStyle ?: baseShape.corners
|
||||
?: CornerStyle.Rounded) == CornerStyle.Rounded
|
||||
) {
|
||||
RoundedCornerShape(
|
||||
topStart = (currentTopStart ?: baseTopStart).dp,
|
||||
topEnd = (currentTopEnd ?: baseTopEnd).dp,
|
||||
bottomEnd = (currentBottomEnd ?: baseBottomEnd).dp,
|
||||
bottomStart = (currentBottomStart ?: baseBottomStart).dp
|
||||
RoundedCornerShape(
|
||||
topStart = (currentTopStart ?: baseTopStart).dp,
|
||||
topEnd = (currentTopEnd ?: baseTopEnd).dp,
|
||||
bottomEnd = (currentBottomEnd ?: baseBottomEnd).dp,
|
||||
bottomStart = (currentBottomStart ?: baseBottomStart).dp
|
||||
|
||||
)
|
||||
} else {
|
||||
CutCornerShape(
|
||||
topStart = (currentTopStart ?: baseTopStart).dp,
|
||||
topEnd = (currentTopEnd ?: baseTopEnd).dp,
|
||||
bottomEnd = (currentBottomEnd ?: baseBottomEnd).dp,
|
||||
bottomStart = (currentBottomStart ?: baseBottomStart).dp
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(max(96, maxRadius * 2).dp)
|
||||
.background(MaterialTheme.colorScheme.surfaceContainer, previewShape)
|
||||
.border(
|
||||
2.dp,
|
||||
MaterialTheme.colorScheme.primary,
|
||||
previewShape
|
||||
)
|
||||
} else {
|
||||
CutCornerShape(
|
||||
topStart = (currentTopStart ?: baseTopStart).dp,
|
||||
topEnd = (currentTopEnd ?: baseTopEnd).dp,
|
||||
bottomEnd = (currentBottomEnd ?: baseBottomEnd).dp,
|
||||
bottomStart = (currentBottomStart ?: baseBottomStart).dp
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.ConnectedSpaceBetween),
|
||||
) {
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualCornerStyle == CornerStyle.Rounded,
|
||||
onCheckedChange = {
|
||||
currentCornerStyle = CornerStyle.Rounded
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedLeadingButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualCornerStyle == CornerStyle.Rounded) R.drawable.check_20px else R.drawable.rounded_corner_alt_24px
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_cards_shape_rounded))
|
||||
}
|
||||
Box(
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualCornerStyle == CornerStyle.Cut,
|
||||
onCheckedChange = {
|
||||
currentCornerStyle = CornerStyle.Cut
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedTrailingButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualCornerStyle == CornerStyle.Cut) R.drawable.check_20px else R.drawable.cut_corner_20px
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_cards_shape_cut))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(max(96, maxRadius * 2).dp)
|
||||
.background(MaterialTheme.colorScheme.surfaceContainer, previewShape)
|
||||
.border(
|
||||
2.dp,
|
||||
MaterialTheme.colorScheme.primary,
|
||||
previewShape
|
||||
)
|
||||
.padding(end = 8.dp)
|
||||
.rotate(-90f)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualTopStart.toFloat(),
|
||||
onValueChange = {
|
||||
currentTopStart = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1
|
||||
)
|
||||
Text(
|
||||
text = actualTopStart.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier.padding(end = 8.dp)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualTopEnd.toFloat(),
|
||||
onValueChange = {
|
||||
currentTopEnd = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1,
|
||||
)
|
||||
Text(
|
||||
text = actualTopEnd.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.rotate(90f)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualBottomEnd.toFloat(),
|
||||
onValueChange = {
|
||||
currentBottomEnd = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1,
|
||||
)
|
||||
Text(
|
||||
text = actualBottomEnd.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.rotate(180f)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualBottomStart.toFloat(),
|
||||
onValueChange = {
|
||||
currentBottomStart = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1,
|
||||
)
|
||||
Text(
|
||||
text = actualBottomStart.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Row(
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = {
|
||||
currentTopStart = null
|
||||
currentTopEnd = null
|
||||
currentBottomEnd = null
|
||||
currentBottomStart = null
|
||||
currentCornerStyle = null
|
||||
onValueChange(null)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.restart_alt_20px), null,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.ConnectedSpaceBetween),
|
||||
) {
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualCornerStyle == CornerStyle.Rounded,
|
||||
onCheckedChange = {
|
||||
currentCornerStyle = CornerStyle.Rounded
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedLeadingButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualCornerStyle == CornerStyle.Rounded) R.drawable.check_20px else R.drawable.rounded_corner_alt_24px
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_cards_shape_rounded))
|
||||
}
|
||||
ToggleButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
checked = actualCornerStyle == CornerStyle.Cut,
|
||||
onCheckedChange = {
|
||||
currentCornerStyle = CornerStyle.Cut
|
||||
},
|
||||
shapes = ButtonGroupDefaults.connectedTrailingButtonShapes(),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(
|
||||
if (actualCornerStyle == CornerStyle.Cut) R.drawable.check_20px else R.drawable.cut_corner_20px
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = ToggleButtonDefaults.IconSpacing)
|
||||
.size(ToggleButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_cards_shape_cut))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.rotate(-90f)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualTopStart.toFloat(),
|
||||
onValueChange = {
|
||||
currentTopStart = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1
|
||||
)
|
||||
Text(
|
||||
text = actualTopStart.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier.padding(end = 8.dp)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualTopEnd.toFloat(),
|
||||
onValueChange = {
|
||||
currentTopEnd = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1,
|
||||
)
|
||||
Text(
|
||||
text = actualTopEnd.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.rotate(90f)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualBottomEnd.toFloat(),
|
||||
onValueChange = {
|
||||
currentBottomEnd = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1,
|
||||
)
|
||||
Text(
|
||||
text = actualBottomEnd.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.rounded_corner_24px),
|
||||
null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.rotate(180f)
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
value = actualBottomStart.toFloat(),
|
||||
onValueChange = {
|
||||
currentBottomStart = it.toInt()
|
||||
},
|
||||
valueRange = 0f..maxRadius.toFloat(),
|
||||
steps = maxRadius + 1,
|
||||
)
|
||||
Text(
|
||||
text = actualBottomStart.toString(),
|
||||
modifier = Modifier.width(32.dp),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = {
|
||||
currentTopStart = null
|
||||
currentTopEnd = null
|
||||
currentBottomEnd = null
|
||||
currentBottomStart = null
|
||||
currentCornerStyle = null
|
||||
onValueChange(null)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.restart_alt_20px), null,
|
||||
modifier = Modifier
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_restore_default))
|
||||
}
|
||||
Text(stringResource(R.string.preference_restore_default))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,20 @@ import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
@@ -758,47 +764,54 @@ private fun FontPreference(
|
||||
onClick = { showDialog = true },
|
||||
)
|
||||
|
||||
if (showDialog) {
|
||||
DismissableBottomSheet(
|
||||
expanded = showDialog,
|
||||
onDismissRequest = { showDialog = false },
|
||||
) {
|
||||
val fonts = remember { fontManager.getInstalledFonts() }
|
||||
DismissableBottomSheet(
|
||||
onDismissRequest = { showDialog = false },
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
top = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp + WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding(),
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
LazyColumn(contentPadding = it, verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
if (fonts.builtIn.isNotEmpty()) {
|
||||
item {
|
||||
FontPickerCategory(
|
||||
preview.ExtraShort,
|
||||
null,
|
||||
fonts.builtIn,
|
||||
onFontClick = {
|
||||
onValueChange(it)
|
||||
showDialog = false
|
||||
})
|
||||
}
|
||||
if (fonts.builtIn.isNotEmpty()) {
|
||||
item {
|
||||
FontPickerCategory(
|
||||
preview.ExtraShort,
|
||||
null,
|
||||
fonts.builtIn,
|
||||
onFontClick = {
|
||||
onValueChange(it)
|
||||
showDialog = false
|
||||
})
|
||||
}
|
||||
if (fonts.deviceDefault.isNotEmpty()) {
|
||||
item {
|
||||
FontPickerCategory(
|
||||
preview.ExtraShort,
|
||||
stringResource(R.string.font_category_device_default),
|
||||
fonts.deviceDefault,
|
||||
onFontClick = {
|
||||
onValueChange(it)
|
||||
showDialog = false
|
||||
})
|
||||
}
|
||||
}
|
||||
if (fonts.deviceDefault.isNotEmpty()) {
|
||||
item {
|
||||
FontPickerCategory(
|
||||
preview.ExtraShort,
|
||||
stringResource(R.string.font_category_device_default),
|
||||
fonts.deviceDefault,
|
||||
onFontClick = {
|
||||
onValueChange(it)
|
||||
showDialog = false
|
||||
})
|
||||
}
|
||||
if (fonts.generic.isNotEmpty()) {
|
||||
item {
|
||||
FontPickerCategory(
|
||||
preview.ExtraShort,
|
||||
stringResource(R.string.font_category_generic),
|
||||
fonts.generic,
|
||||
onFontClick = {
|
||||
onValueChange(it)
|
||||
showDialog = false
|
||||
})
|
||||
}
|
||||
}
|
||||
if (fonts.generic.isNotEmpty()) {
|
||||
item {
|
||||
FontPickerCategory(
|
||||
preview.ExtraShort,
|
||||
stringResource(R.string.font_category_generic),
|
||||
fonts.generic,
|
||||
onFontClick = {
|
||||
onValueChange(it)
|
||||
showDialog = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -951,209 +964,210 @@ private fun TextStylePreference(
|
||||
},
|
||||
onClick = { showDialog = true },
|
||||
)
|
||||
if (showDialog) {
|
||||
var fontFamily by remember(value) {
|
||||
mutableStateOf(value?.fontFamily)
|
||||
}
|
||||
var fontSize by remember(value) {
|
||||
mutableStateOf(value?.fontSize)
|
||||
}
|
||||
var lineHeight by remember(value) {
|
||||
mutableStateOf(value?.lineHeight)
|
||||
}
|
||||
var weight by remember(value) {
|
||||
mutableStateOf((value?.fontWeight as? ThemeFontWeight.Absolute)?.weight)
|
||||
}
|
||||
var letterSpacing by remember(value) {
|
||||
mutableStateOf(value?.letterSpacing)
|
||||
}
|
||||
var fontFamily by remember(value) {
|
||||
mutableStateOf(value?.fontFamily)
|
||||
}
|
||||
var fontSize by remember(value) {
|
||||
mutableStateOf(value?.fontSize)
|
||||
}
|
||||
var lineHeight by remember(value) {
|
||||
mutableStateOf(value?.lineHeight)
|
||||
}
|
||||
var weight by remember(value) {
|
||||
mutableStateOf((value?.fontWeight as? ThemeFontWeight.Absolute)?.weight)
|
||||
}
|
||||
var letterSpacing by remember(value) {
|
||||
mutableStateOf(value?.letterSpacing)
|
||||
}
|
||||
|
||||
DismissableBottomSheet(
|
||||
onDismissRequest = {
|
||||
onValueChange(
|
||||
ThemeTextStyle(
|
||||
fontFamily = fontFamily,
|
||||
fontSize = fontSize,
|
||||
lineHeight = lineHeight,
|
||||
fontWeight = weight?.let { ThemeFontWeight.Absolute(it) },
|
||||
letterSpacing = letterSpacing
|
||||
)
|
||||
DismissableBottomSheet(
|
||||
expanded = showDialog,
|
||||
onDismissRequest = {
|
||||
onValueChange(
|
||||
ThemeTextStyle(
|
||||
fontFamily = fontFamily,
|
||||
fontSize = fontSize,
|
||||
lineHeight = lineHeight,
|
||||
fontWeight = weight?.let { ThemeFontWeight.Absolute(it) },
|
||||
letterSpacing = letterSpacing
|
||||
)
|
||||
showDialog = false
|
||||
},
|
||||
) {
|
||||
)
|
||||
showDialog = false
|
||||
},
|
||||
) {
|
||||
|
||||
|
||||
val actualFontFamily = fontFamily
|
||||
?: parentValue?.fontFamily
|
||||
?: defaultValue?.fontFamily
|
||||
?: defaultValueParent?.fontFamily!!
|
||||
val actualFontSize = fontSize
|
||||
?: parentValue?.fontSize
|
||||
?: defaultValue?.fontSize
|
||||
?: defaultValueParent?.fontSize!!
|
||||
val actualLineHeight = lineHeight
|
||||
?: parentValue?.lineHeight
|
||||
?: defaultValue?.lineHeight
|
||||
?: defaultValueParent?.lineHeight!!
|
||||
val actualWeight = when {
|
||||
weight != null -> FontWeight(weight!!)
|
||||
parentValue?.fontWeight != null -> FontWeight(parentValue.fontWeight!!.weight)
|
||||
defaultValue?.fontWeight is ThemeFontWeight.Absolute -> FontWeight((defaultValue.fontWeight as ThemeFontWeight.Absolute).weight)
|
||||
defaultValue?.fontWeight is ThemeFontWeight.Relative &&
|
||||
defaultValueParent?.fontWeight is ThemeFontWeight.Absolute -> {
|
||||
FontWeight(
|
||||
(defaultValueParent.fontWeight as ThemeFontWeight.Absolute).weight +
|
||||
(defaultValue.fontWeight as ThemeFontWeight.Relative).relativeWeight
|
||||
)
|
||||
}
|
||||
|
||||
else -> FontWeight.Normal
|
||||
val actualFontFamily = fontFamily
|
||||
?: parentValue?.fontFamily
|
||||
?: defaultValue?.fontFamily
|
||||
?: defaultValueParent?.fontFamily!!
|
||||
val actualFontSize = fontSize
|
||||
?: parentValue?.fontSize
|
||||
?: defaultValue?.fontSize
|
||||
?: defaultValueParent?.fontSize!!
|
||||
val actualLineHeight = lineHeight
|
||||
?: parentValue?.lineHeight
|
||||
?: defaultValue?.lineHeight
|
||||
?: defaultValueParent?.lineHeight!!
|
||||
val actualWeight = when {
|
||||
weight != null -> FontWeight(weight!!)
|
||||
parentValue?.fontWeight != null -> FontWeight(parentValue.fontWeight!!.weight)
|
||||
defaultValue?.fontWeight is ThemeFontWeight.Absolute -> FontWeight((defaultValue.fontWeight as ThemeFontWeight.Absolute).weight)
|
||||
defaultValue?.fontWeight is ThemeFontWeight.Relative &&
|
||||
defaultValueParent?.fontWeight is ThemeFontWeight.Absolute -> {
|
||||
FontWeight(
|
||||
(defaultValueParent.fontWeight as ThemeFontWeight.Absolute).weight +
|
||||
(defaultValue.fontWeight as ThemeFontWeight.Relative).relativeWeight
|
||||
)
|
||||
}
|
||||
val actualLetterSpacing = letterSpacing
|
||||
?: parentValue?.letterSpacing
|
||||
?: defaultValue?.letterSpacing
|
||||
?: defaultValueParent?.letterSpacing!!
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(it),
|
||||
else -> FontWeight.Normal
|
||||
}
|
||||
val actualLetterSpacing = letterSpacing
|
||||
?: parentValue?.letterSpacing
|
||||
?: defaultValue?.letterSpacing
|
||||
?: defaultValueParent?.letterSpacing!!
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding(),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 200.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 200.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = previewTexts.TwoLines,
|
||||
textAlign = TextAlign.Center,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontFamily = fontFamilyOf(context, fonts[actualFontFamily]),
|
||||
fontSize = actualFontSize.sp,
|
||||
lineHeight = actualLineHeight.em,
|
||||
fontWeight = actualWeight,
|
||||
letterSpacing = actualLetterSpacing.em,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 16.dp)
|
||||
.fillMaxWidth()
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
for ((name, font) in fonts) {
|
||||
val f = remember(font) { fontFamilyOf(context, font) }
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.width(56.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = previewTexts.TwoLines,
|
||||
textAlign = TextAlign.Center,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontFamily = fontFamilyOf(context, fonts[actualFontFamily]),
|
||||
fontSize = actualFontSize.sp,
|
||||
lineHeight = actualLineHeight.em,
|
||||
fontWeight = actualWeight,
|
||||
letterSpacing = actualLetterSpacing.em,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 16.dp)
|
||||
.fillMaxWidth()
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
for ((name, font) in fonts) {
|
||||
val f = remember(font) { fontFamilyOf(context, font) }
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.width(56.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
|
||||
OutlinedIconToggleButton(
|
||||
modifier = Modifier.size(56.dp),
|
||||
checked = name == actualFontFamily,
|
||||
onCheckedChange = {
|
||||
if (it) fontFamily = name
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = previewTexts.ExtraShort,
|
||||
fontFamily = f,
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
OutlinedIconToggleButton(
|
||||
modifier = Modifier.size(56.dp),
|
||||
checked = name == actualFontFamily,
|
||||
onCheckedChange = {
|
||||
if (it) fontFamily = name
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = name.capitalize(LocaleList.current),
|
||||
text = previewTexts.ExtraShort,
|
||||
fontFamily = f,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.width(56.dp),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.MiddleEllipsis,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = name.capitalize(LocaleList.current),
|
||||
fontFamily = f,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.width(56.dp),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.MiddleEllipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SliderRow(
|
||||
icon = R.drawable.format_bold_24px,
|
||||
min = 100f,
|
||||
max = 900f,
|
||||
step = 100f,
|
||||
value = actualWeight.weight.toFloat(),
|
||||
onValueChange = { weight = it.toInt() },
|
||||
formatValue = {
|
||||
it.roundToInt().toString()
|
||||
}
|
||||
)
|
||||
SliderRow(
|
||||
icon = R.drawable.format_size_24px,
|
||||
min = floor((defaultValue?.fontSize ?: defaultValueParent?.fontSize)!! / 2f),
|
||||
max = ceil((defaultValue?.fontSize ?: defaultValueParent?.fontSize)!! * 2f),
|
||||
value = actualFontSize.toFloat(),
|
||||
onValueChange = {
|
||||
fontSize = it.roundToInt()
|
||||
},
|
||||
formatValue = {
|
||||
it.roundToInt().toString()
|
||||
}
|
||||
)
|
||||
SliderRow(
|
||||
icon = R.drawable.format_line_spacing_24px,
|
||||
min = 0.5f,
|
||||
max = 2f,
|
||||
step = 0.05f,
|
||||
value = actualLineHeight,
|
||||
onValueChange = { lineHeight = it },
|
||||
formatValue = {
|
||||
(it * 100).roundToInt().toString() + "%"
|
||||
}
|
||||
)
|
||||
SliderRow(
|
||||
icon = R.drawable.format_letter_spacing_24px,
|
||||
min = -0.25f,
|
||||
max = 1f,
|
||||
step = 0.01f,
|
||||
value = actualLetterSpacing,
|
||||
onValueChange = { letterSpacing = (it * 100f).roundToInt() / 100f },
|
||||
formatValue = {
|
||||
(it * 100).roundToInt().toString() + "%"
|
||||
}
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = {
|
||||
fontFamily = null
|
||||
fontSize = null
|
||||
lineHeight = null
|
||||
weight = null
|
||||
letterSpacing = null
|
||||
onValueChange(null)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.restart_alt_20px), null,
|
||||
modifier = Modifier
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_restore_default))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SliderRow(
|
||||
icon = R.drawable.format_bold_24px,
|
||||
min = 100f,
|
||||
max = 900f,
|
||||
step = 100f,
|
||||
value = actualWeight.weight.toFloat(),
|
||||
onValueChange = { weight = it.toInt() },
|
||||
formatValue = {
|
||||
it.roundToInt().toString()
|
||||
}
|
||||
)
|
||||
SliderRow(
|
||||
icon = R.drawable.format_size_24px,
|
||||
min = floor((defaultValue?.fontSize ?: defaultValueParent?.fontSize)!! / 2f),
|
||||
max = ceil((defaultValue?.fontSize ?: defaultValueParent?.fontSize)!! * 2f),
|
||||
value = actualFontSize.toFloat(),
|
||||
onValueChange = {
|
||||
fontSize = it.roundToInt()
|
||||
},
|
||||
formatValue = {
|
||||
it.roundToInt().toString()
|
||||
}
|
||||
)
|
||||
SliderRow(
|
||||
icon = R.drawable.format_line_spacing_24px,
|
||||
min = 0.5f,
|
||||
max = 2f,
|
||||
step = 0.05f,
|
||||
value = actualLineHeight,
|
||||
onValueChange = { lineHeight = it },
|
||||
formatValue = {
|
||||
(it * 100).roundToInt().toString() + "%"
|
||||
}
|
||||
)
|
||||
SliderRow(
|
||||
icon = R.drawable.format_letter_spacing_24px,
|
||||
min = -0.25f,
|
||||
max = 1f,
|
||||
step = 0.01f,
|
||||
value = actualLetterSpacing,
|
||||
onValueChange = { letterSpacing = (it * 100f).roundToInt() / 100f },
|
||||
formatValue = {
|
||||
(it * 100).roundToInt().toString() + "%"
|
||||
}
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.align(Alignment.End),
|
||||
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
|
||||
onClick = {
|
||||
fontFamily = null
|
||||
fontSize = null
|
||||
lineHeight = null
|
||||
weight = null
|
||||
letterSpacing = null
|
||||
onValueChange(null)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.restart_alt_20px), null,
|
||||
modifier = Modifier
|
||||
.padding(ButtonDefaults.IconSpacing)
|
||||
.size(ButtonDefaults.IconSize)
|
||||
)
|
||||
Text(stringResource(R.string.preference_restore_default))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user