Merge pull request #3330 from gannonlawlor/android/theme-setup
Uncomment theme colors and use them in bottomsheet
This commit is contained in:
@ -3,15 +3,39 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AddCircle
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
@ -20,7 +44,10 @@ import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.*
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
import androidx.compose.ui.platform.ViewConfiguration
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
@ -31,9 +58,12 @@ import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import com.dokar.chiptextfield.*
|
||||
import com.dokar.chiptextfield.Chip
|
||||
import com.dokar.chiptextfield.ChipTextField
|
||||
import com.dokar.chiptextfield.ChipTextFieldDefaults
|
||||
import com.dokar.chiptextfield.ChipTextFieldState
|
||||
import com.dokar.chiptextfield.rememberChipTextFieldState
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import java.util.*
|
||||
|
||||
|
||||
//@Composable
|
||||
@ -99,216 +129,229 @@ import java.util.*
|
||||
//}
|
||||
|
||||
@Composable
|
||||
fun CircleIcon(colorHex: String){
|
||||
val chipColors = LabelChipColors.fromHex(colorHex)
|
||||
val viewConfiguration = LocalViewConfiguration.current
|
||||
val viewConfigurationOverride = remember(viewConfiguration) {
|
||||
ViewConfigurationOverride(
|
||||
base = viewConfiguration,
|
||||
minimumTouchTargetSize = DpSize(24.dp, 24.dp)
|
||||
)
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalViewConfiguration provides viewConfigurationOverride) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(start = 10.dp, end = 2.dp)
|
||||
.padding(vertical = 7.dp)
|
||||
) {
|
||||
Canvas(modifier = Modifier.size(12.dp), onDraw = {
|
||||
drawCircle(color = chipColors.containerColor)
|
||||
})
|
||||
fun CircleIcon(colorHex: String) {
|
||||
val chipColors = LabelChipColors.fromHex(colorHex)
|
||||
val viewConfiguration = LocalViewConfiguration.current
|
||||
val viewConfigurationOverride = remember(viewConfiguration) {
|
||||
ViewConfigurationOverride(
|
||||
base = viewConfiguration,
|
||||
minimumTouchTargetSize = DpSize(24.dp, 24.dp)
|
||||
)
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalViewConfiguration provides viewConfigurationOverride) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(start = 10.dp, end = 2.dp)
|
||||
.padding(vertical = 7.dp)
|
||||
) {
|
||||
Canvas(modifier = Modifier.size(12.dp), onDraw = {
|
||||
drawCircle(color = chipColors.containerColor)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun <T : Chip> CloseButton(
|
||||
state: ChipTextFieldState<T>,
|
||||
chip: T,
|
||||
modifier: Modifier = Modifier,
|
||||
backgroundColor: Color = Color.Transparent,
|
||||
strokeColor: Color = Color.White,
|
||||
startPadding: Dp = 0.dp,
|
||||
endPadding: Dp = 4.dp
|
||||
state: ChipTextFieldState<T>,
|
||||
chip: T,
|
||||
modifier: Modifier = Modifier,
|
||||
backgroundColor: Color = Color.Transparent,
|
||||
strokeColor: Color = Color.White,
|
||||
startPadding: Dp = 0.dp,
|
||||
endPadding: Dp = 4.dp
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.padding(start = startPadding, end = endPadding)
|
||||
) {
|
||||
CloseButtonImpl(
|
||||
onClick = { state.removeChip(chip) },
|
||||
backgroundColor = backgroundColor,
|
||||
strokeColor = strokeColor
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = modifier
|
||||
.padding(start = startPadding, end = endPadding)
|
||||
) {
|
||||
CloseButtonImpl(
|
||||
onClick = { state.removeChip(chip) },
|
||||
backgroundColor = backgroundColor,
|
||||
strokeColor = strokeColor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class ViewConfigurationOverride(
|
||||
base: ViewConfiguration,
|
||||
override val doubleTapMinTimeMillis: Long = base.doubleTapMinTimeMillis,
|
||||
override val doubleTapTimeoutMillis: Long = base.doubleTapTimeoutMillis,
|
||||
override val longPressTimeoutMillis: Long = base.longPressTimeoutMillis,
|
||||
override val touchSlop: Float = base.touchSlop,
|
||||
override val minimumTouchTargetSize: DpSize = base.minimumTouchTargetSize
|
||||
base: ViewConfiguration,
|
||||
override val doubleTapMinTimeMillis: Long = base.doubleTapMinTimeMillis,
|
||||
override val doubleTapTimeoutMillis: Long = base.doubleTapTimeoutMillis,
|
||||
override val longPressTimeoutMillis: Long = base.longPressTimeoutMillis,
|
||||
override val touchSlop: Float = base.touchSlop,
|
||||
override val minimumTouchTargetSize: DpSize = base.minimumTouchTargetSize
|
||||
) : ViewConfiguration
|
||||
|
||||
@Composable
|
||||
private fun CloseButtonImpl(
|
||||
onClick: () -> Unit,
|
||||
backgroundColor: Color,
|
||||
strokeColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit,
|
||||
backgroundColor: Color,
|
||||
strokeColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val padding = with(LocalDensity.current) { 6.dp.toPx() }
|
||||
val strokeWidth = with(LocalDensity.current) { 1.2.dp.toPx() }
|
||||
val viewConfiguration = LocalViewConfiguration.current
|
||||
val viewConfigurationOverride = remember(viewConfiguration) {
|
||||
ViewConfigurationOverride(
|
||||
base = viewConfiguration,
|
||||
minimumTouchTargetSize = DpSize(24.dp, 24.dp)
|
||||
)
|
||||
}
|
||||
CompositionLocalProvider(LocalViewConfiguration provides viewConfigurationOverride) {
|
||||
Canvas(
|
||||
modifier = modifier
|
||||
.size(18.dp)
|
||||
.clip(CircleShape)
|
||||
.background(backgroundColor)
|
||||
.clickable(onClick = onClick)
|
||||
) {
|
||||
drawLine(
|
||||
color = strokeColor,
|
||||
start = Offset(padding, padding),
|
||||
end = Offset(size.width - padding, size.height - padding),
|
||||
strokeWidth = strokeWidth
|
||||
)
|
||||
drawLine(
|
||||
color = strokeColor,
|
||||
start = Offset(padding, size.height - padding),
|
||||
end = Offset(size.width - padding, padding),
|
||||
strokeWidth = strokeWidth
|
||||
)
|
||||
val padding = with(LocalDensity.current) { 6.dp.toPx() }
|
||||
val strokeWidth = with(LocalDensity.current) { 1.2.dp.toPx() }
|
||||
val viewConfiguration = LocalViewConfiguration.current
|
||||
val viewConfigurationOverride = remember(viewConfiguration) {
|
||||
ViewConfigurationOverride(
|
||||
base = viewConfiguration,
|
||||
minimumTouchTargetSize = DpSize(24.dp, 24.dp)
|
||||
)
|
||||
}
|
||||
CompositionLocalProvider(LocalViewConfiguration provides viewConfigurationOverride) {
|
||||
Canvas(
|
||||
modifier = modifier
|
||||
.size(18.dp)
|
||||
.clip(CircleShape)
|
||||
.background(backgroundColor)
|
||||
.clickable(onClick = onClick)
|
||||
) {
|
||||
drawLine(
|
||||
color = strokeColor,
|
||||
start = Offset(padding, padding),
|
||||
end = Offset(size.width - padding, size.height - padding),
|
||||
strokeWidth = strokeWidth
|
||||
)
|
||||
drawLine(
|
||||
color = strokeColor,
|
||||
start = Offset(padding, size.height - padding),
|
||||
end = Offset(size.width - padding, padding),
|
||||
strokeWidth = strokeWidth
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LabelChipView(label: SavedItemLabel) : Chip(label.name) {
|
||||
val label = label
|
||||
val label = label
|
||||
}
|
||||
|
||||
fun findOrCreateLabel(labelsViewModel: LabelsViewModel, labels: List<SavedItemLabel>, name: String): SavedItemLabel {
|
||||
val found = labels.find { it.name == name }
|
||||
if (found != null) {
|
||||
return found
|
||||
}
|
||||
return labelsViewModel.createNewSavedItemLabelWithTemp(name, LabelSwatchHelper.random())
|
||||
fun findOrCreateLabel(
|
||||
labelsViewModel: LabelsViewModel,
|
||||
labels: List<SavedItemLabel>,
|
||||
name: String
|
||||
): SavedItemLabel {
|
||||
val found = labels.find { it.name == name }
|
||||
if (found != null) {
|
||||
return found
|
||||
}
|
||||
return labelsViewModel.createNewSavedItemLabelWithTemp(name, LabelSwatchHelper.random())
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class,
|
||||
ExperimentalMaterial3Api::class
|
||||
@OptIn(
|
||||
ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class,
|
||||
ExperimentalMaterial3Api::class
|
||||
)
|
||||
fun LabelsSelectionSheetContent(
|
||||
isLibraryMode: Boolean,
|
||||
labels: List<SavedItemLabel>,
|
||||
initialSelectedLabels: List<SavedItemLabel>,
|
||||
labelsViewModel: LabelsViewModel,
|
||||
onCancel: () -> Unit,
|
||||
onSave: (List<SavedItemLabel>) -> Unit,
|
||||
onCreateLabel: (String, String) -> Unit
|
||||
isLibraryMode: Boolean,
|
||||
labels: List<SavedItemLabel>,
|
||||
initialSelectedLabels: List<SavedItemLabel>,
|
||||
labelsViewModel: LabelsViewModel,
|
||||
onCancel: () -> Unit,
|
||||
onSave: (List<SavedItemLabel>) -> Unit,
|
||||
onCreateLabel: (String, String) -> Unit
|
||||
) {
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
|
||||
val state = rememberChipTextFieldState(initialSelectedLabels.map {
|
||||
LabelChipView(it)
|
||||
})
|
||||
val state = rememberChipTextFieldState(initialSelectedLabels.map {
|
||||
LabelChipView(it)
|
||||
})
|
||||
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
var filterTextValue by remember { mutableStateOf(TextFieldValue()) }
|
||||
val onFilterTextValueChange: (TextFieldValue) -> Unit = { filterTextValue = it }
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
var filterTextValue by remember { mutableStateOf(TextFieldValue()) }
|
||||
val onFilterTextValueChange: (TextFieldValue) -> Unit = { filterTextValue = it }
|
||||
|
||||
val filteredLabels = labels.filter { label ->
|
||||
val text = filterTextValue.text.toLowerCase(Locale.current)
|
||||
val result = (text.isEmpty() || label.name.toLowerCase(Locale.current).startsWith(text))
|
||||
val alreadySelected = state.chips.map { it.label.name }.contains(label.name)
|
||||
result && !alreadySelected
|
||||
}
|
||||
val filteredLabels = labels.filter { label ->
|
||||
val text = filterTextValue.text.toLowerCase(Locale.current)
|
||||
val result = (text.isEmpty() || label.name.toLowerCase(Locale.current).startsWith(text))
|
||||
val alreadySelected = state.chips.map { it.label.name }.contains(label.name)
|
||||
result && !alreadySelected
|
||||
}
|
||||
|
||||
val currentLabel = labels.find {
|
||||
val text = filterTextValue.text.toLowerCase(Locale.current)
|
||||
it.name.toLowerCase(Locale.current) == text
|
||||
}
|
||||
val currentLabel = labels.find {
|
||||
val text = filterTextValue.text.toLowerCase(Locale.current)
|
||||
it.name.toLowerCase(Locale.current) == text
|
||||
}
|
||||
|
||||
val titleText = if (isLibraryMode)
|
||||
stringResource(R.string.label_selection_sheet_title) else
|
||||
stringResource(R.string.label_selection_sheet_title_alt)
|
||||
val titleText = if (isLibraryMode)
|
||||
stringResource(R.string.label_selection_sheet_title) else
|
||||
stringResource(R.string.label_selection_sheet_title_alt)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background),
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 5.dp)
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background),
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 5.dp)
|
||||
) {
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
TextButton(onClick = onCancel) {
|
||||
Text(text = stringResource(R.string.label_selection_sheet_action_cancel))
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
TextButton(onClick = onCancel) {
|
||||
Text(text = stringResource(R.string.label_selection_sheet_action_cancel))
|
||||
}
|
||||
|
||||
Text(titleText, fontWeight = FontWeight.ExtraBold)
|
||||
Text(titleText, fontWeight = FontWeight.ExtraBold)
|
||||
|
||||
TextButton(onClick = { onSave(state.chips.map { it.label }) }) {
|
||||
Text(text = if (isLibraryMode)
|
||||
stringResource(R.string.label_selection_sheet_action_search) else
|
||||
stringResource(R.string.label_selection_sheet_action_save))
|
||||
}
|
||||
}
|
||||
|
||||
ChipTextField(
|
||||
state = state,
|
||||
value = filterTextValue,
|
||||
onValueChange = onFilterTextValueChange,
|
||||
onSubmit = {
|
||||
if (isLibraryMode) {
|
||||
currentLabel?.let {
|
||||
LabelChipView(it)
|
||||
TextButton(onClick = { onSave(state.chips.map { it.label }) }) {
|
||||
Text(
|
||||
text = if (isLibraryMode)
|
||||
stringResource(R.string.label_selection_sheet_action_search) else
|
||||
stringResource(R.string.label_selection_sheet_action_save)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LabelChipView(findOrCreateLabel(labelsViewModel = labelsViewModel, labels = labels, name = it.text))
|
||||
}
|
||||
},
|
||||
chipLeadingIcon = { chip -> CircleIcon(colorHex = chip.label.color) },
|
||||
chipTrailingIcon = { chip -> CloseButton(state, chip) },
|
||||
interactionSource = interactionSource,
|
||||
chipStyle = ChipTextFieldDefaults.chipStyle(
|
||||
shape = androidx.compose.material.MaterialTheme.shapes.medium,
|
||||
unfocusedBorderWidth = 0.dp,
|
||||
focusedTextColor = Color(0xFFAEAEAF),
|
||||
focusedBorderColor = Color(0xFF2A2A2A),
|
||||
focusedBackgroundColor = Color(0xFF2A2A2A)
|
||||
),
|
||||
colors = androidx.compose.material.TextFieldDefaults.textFieldColors(
|
||||
textColor = Color(0xFFAEAEAF),
|
||||
backgroundColor = Color(0xFF3D3D3D)
|
||||
),
|
||||
contentPadding = PaddingValues(10.dp),
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = 45.dp)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 10.dp)
|
||||
.focusRequester(focusRequester)
|
||||
|
||||
ChipTextField(
|
||||
state = state,
|
||||
value = filterTextValue,
|
||||
onValueChange = onFilterTextValueChange,
|
||||
onSubmit = {
|
||||
if (isLibraryMode) {
|
||||
currentLabel?.let {
|
||||
LabelChipView(it)
|
||||
}
|
||||
} else {
|
||||
LabelChipView(
|
||||
findOrCreateLabel(
|
||||
labelsViewModel = labelsViewModel,
|
||||
labels = labels,
|
||||
name = it.text
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
chipLeadingIcon = { chip -> CircleIcon(colorHex = chip.label.color) },
|
||||
chipTrailingIcon = { chip -> CloseButton(state, chip) },
|
||||
interactionSource = interactionSource,
|
||||
chipStyle = ChipTextFieldDefaults.chipStyle(
|
||||
shape = androidx.compose.material.MaterialTheme.shapes.medium,
|
||||
unfocusedBorderWidth = 0.dp,
|
||||
focusedTextColor = Color(0xFFAEAEAF),
|
||||
focusedBorderColor = Color(0xFF2A2A2A),
|
||||
focusedBackgroundColor = Color(0xFF2A2A2A)
|
||||
),
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
textColor = MaterialTheme.colorScheme.onBackground,
|
||||
backgroundColor = MaterialTheme.colorScheme.background
|
||||
),
|
||||
contentPadding = PaddingValues(10.dp),
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = 45.dp)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 10.dp)
|
||||
.focusRequester(focusRequester)
|
||||
// .onFocusEvent {
|
||||
// val text = filterTextValue.text
|
||||
// if (it.hasFocus) {
|
||||
@ -316,78 +359,88 @@ fun LabelsSelectionSheetContent(
|
||||
// onFilterTextValueChange(filterTextValue.copy(selection = TextRange(selection)))
|
||||
// }
|
||||
// }
|
||||
)
|
||||
|
||||
if (!isLibraryMode && filterTextValue.text.isNotEmpty() && currentLabel == null) {
|
||||
val context = LocalContext.current
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
val labelName = filterTextValue.text.trim()
|
||||
when(labelsViewModel.validateLabelName(labelName)) {
|
||||
LabelsViewModel.Error.LabelNameTooLong -> {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.label_selection_sheet_label_too_long_error_msg,
|
||||
labelsViewModel.labelNameMaxLength),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
null -> {
|
||||
val label = findOrCreateLabel(
|
||||
labelsViewModel = labelsViewModel,
|
||||
labels = labels,
|
||||
name = labelName
|
||||
)
|
||||
|
||||
state.addChip(LabelChipView(label))
|
||||
filterTextValue = TextFieldValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(horizontal = 10.dp)
|
||||
.padding(top = 10.dp, bottom = 5.dp)
|
||||
)
|
||||
{
|
||||
Icon(
|
||||
imageVector = Icons.Filled.AddCircle,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(end = 8.dp)
|
||||
)
|
||||
Text(text = stringResource(R.string.label_selection_sheet_text_create, filterTextValue.text.trim()))
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredLabels.isNotEmpty()) {
|
||||
FlowRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(10.dp)
|
||||
.padding(bottom = 55.dp)
|
||||
) {
|
||||
filteredLabels.forEach { label ->
|
||||
val chipColors = LabelChipColors.fromHex(label.color)
|
||||
|
||||
LabelChip(
|
||||
name = label.name,
|
||||
colors = chipColors,
|
||||
modifier = Modifier
|
||||
.padding(end = 10.dp, bottom = 10.dp)
|
||||
.clickable {
|
||||
state.addChip(LabelChipView(label))
|
||||
filterTextValue = TextFieldValue()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (!isLibraryMode && filterTextValue.text.isNotEmpty() && currentLabel == null) {
|
||||
val context = LocalContext.current
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
val labelName = filterTextValue.text.trim()
|
||||
when (labelsViewModel.validateLabelName(labelName)) {
|
||||
LabelsViewModel.Error.LabelNameTooLong -> {
|
||||
Toast
|
||||
.makeText(
|
||||
context,
|
||||
context.getString(
|
||||
R.string.label_selection_sheet_label_too_long_error_msg,
|
||||
labelsViewModel.labelNameMaxLength
|
||||
),
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
}
|
||||
|
||||
null -> {
|
||||
val label = findOrCreateLabel(
|
||||
labelsViewModel = labelsViewModel,
|
||||
labels = labels,
|
||||
name = labelName
|
||||
)
|
||||
|
||||
state.addChip(LabelChipView(label))
|
||||
filterTextValue = TextFieldValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(horizontal = 10.dp)
|
||||
.padding(top = 10.dp, bottom = 5.dp)
|
||||
)
|
||||
{
|
||||
Icon(
|
||||
imageVector = Icons.Filled.AddCircle,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(end = 8.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(
|
||||
R.string.label_selection_sheet_text_create,
|
||||
filterTextValue.text.trim()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredLabels.isNotEmpty()) {
|
||||
FlowRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(10.dp)
|
||||
.padding(bottom = 55.dp)
|
||||
) {
|
||||
filteredLabels.forEach { label ->
|
||||
val chipColors = LabelChipColors.fromHex(label.color)
|
||||
|
||||
LabelChip(
|
||||
name = label.name,
|
||||
colors = chipColors,
|
||||
modifier = Modifier
|
||||
.padding(end = 10.dp, bottom = 10.dp)
|
||||
.clickable {
|
||||
state.addChip(LabelChipView(label))
|
||||
filterTextValue = TextFieldValue()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
state.focusTextField()
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
state.focusTextField()
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,63 +2,67 @@ package app.omnivore.omnivore.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
//
|
||||
val md_theme_light_primary = Color(0xFF745B00)
|
||||
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
|
||||
//val md_theme_light_primaryContainer = Color(0xFFFFE08C)
|
||||
//val md_theme_light_onPrimaryContainer = Color(0xFF241A00)
|
||||
//val md_theme_light_secondary = Color(0xFF6D5E00)
|
||||
//val md_theme_light_onSecondary = Color(0xFFFFFFFF)
|
||||
//val md_theme_light_secondaryContainer = Color(0xFFFCE365)
|
||||
//val md_theme_light_onSecondaryContainer = Color(0xFF211B00)
|
||||
//val md_theme_light_tertiary = Color(0xFF4B670A)
|
||||
//val md_theme_light_onTertiary = Color(0xFFFFFFFF)
|
||||
//val md_theme_light_tertiaryContainer = Color(0xFFCBEF86)
|
||||
//val md_theme_light_onTertiaryContainer = Color(0xFF141F00)
|
||||
//val md_theme_light_error = Color(0xFFBA1A1A)
|
||||
//val md_theme_light_errorContainer = Color(0xFFFFDAD6)
|
||||
//val md_theme_light_onError = Color(0xFFFFFFFF)
|
||||
//val md_theme_light_onErrorContainer = Color(0xFF410002)
|
||||
//val md_theme_light_background = Color(0xFFF7FFED)
|
||||
//val md_theme_light_onBackground = Color(0xFF032100)
|
||||
//val md_theme_light_surface = Color(0xFFF7FFED)
|
||||
//val md_theme_light_onSurface = Color(0xFF032100)
|
||||
//val md_theme_light_surfaceVariant = Color(0xFFEBE1CF)
|
||||
//val md_theme_light_onSurfaceVariant = Color(0xFF4C4639)
|
||||
//val md_theme_light_outline = Color(0xFF7E7667)
|
||||
//val md_theme_light_inverseOnSurface = Color(0xFFCBFFB5)
|
||||
//val md_theme_light_inverseSurface = Color(0xFF083900)
|
||||
//val md_theme_light_inversePrimary = Color(0xFFEFC125)
|
||||
//val md_theme_light_shadow = Color(0xFF000000)
|
||||
//val md_theme_light_surfaceTint = Color(0xFF745B00)
|
||||
//
|
||||
val md_theme_light_primaryContainer = Color(0xFFFFDDB3)
|
||||
val md_theme_light_onPrimaryContainer = Color(0xFF291800)
|
||||
val md_theme_light_secondary = Color(0xFF6F5B40)
|
||||
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
|
||||
val md_theme_light_secondaryContainer = Color(0xFFFBDEBC)
|
||||
val md_theme_light_onSecondaryContainer = Color(0xFF271904)
|
||||
val md_theme_light_tertiary = Color(0xFF51643F)
|
||||
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
|
||||
val md_theme_light_tertiaryContainer = Color(0xFFD4EABB)
|
||||
val md_theme_light_onTertiaryContainer = Color(0xFF102004)
|
||||
val md_theme_light_error = Color(0xFFBA1A1A)
|
||||
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
|
||||
val md_theme_light_onError = Color(0xFFFFFFFF)
|
||||
val md_theme_light_onErrorContainer = Color(0xFF410002)
|
||||
val md_theme_light_background = Color(0xFFFFFBFF)
|
||||
val md_theme_light_onBackground = Color(0xFF1F1B16)
|
||||
val md_theme_light_surface = Color(0xFFFFFBFF)
|
||||
val md_theme_light_onSurface = Color(0xFF1F1B16)
|
||||
val md_theme_light_surfaceVariant = Color(0xFFF0E0CF)
|
||||
val md_theme_light_onSurfaceVariant = Color(0xFF4F4539)
|
||||
val md_theme_light_outline = Color(0xFF817567)
|
||||
val md_theme_light_inverseOnSurface = Color(0xFFF9EFE7)
|
||||
val md_theme_light_inverseSurface = Color(0xFF34302A)
|
||||
val md_theme_light_inversePrimary = Color(0xFFFFB951)
|
||||
val md_theme_light_shadow = Color(0xFF000000)
|
||||
val md_theme_light_surfaceTint = Color(0xFF825500)
|
||||
val md_theme_light_outlineVariant = Color(0xFFD3C4B4)
|
||||
val md_theme_light_scrim = Color(0xFF000000)
|
||||
|
||||
val md_theme_dark_primary = Color(0xFFEFC125)
|
||||
val md_theme_dark_onPrimary = Color(0xFF3D2F00)
|
||||
//val md_theme_dark_primaryContainer = Color(0xFF584400)
|
||||
//val md_theme_dark_onPrimaryContainer = Color(0xFFFFE08C)
|
||||
//val md_theme_dark_secondary = Color(0xFFDEC64C)
|
||||
//val md_theme_dark_onSecondary = Color(0xFF393000)
|
||||
//val md_theme_dark_secondaryContainer = Color(0xFF524600)
|
||||
//val md_theme_dark_onSecondaryContainer = Color(0xFFFCE365)
|
||||
//val md_theme_dark_tertiary = Color(0xFFB0D36D)
|
||||
//val md_theme_dark_onTertiary = Color(0xFF243600)
|
||||
//val md_theme_dark_tertiaryContainer = Color(0xFF364E00)
|
||||
//val md_theme_dark_onTertiaryContainer = Color(0xFFCBEF86)
|
||||
//val md_theme_dark_error = Color(0xFFFFB4AB)
|
||||
//val md_theme_dark_errorContainer = Color(0xFF93000A)
|
||||
//val md_theme_dark_onError = Color(0xFF690005)
|
||||
//val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
|
||||
//val md_theme_dark_background = Color(0xFF032100)
|
||||
//val md_theme_dark_onBackground = Color(0xFFB4F39B)
|
||||
//val md_theme_dark_surface = Color(0xFF032100)
|
||||
//val md_theme_dark_onSurface = Color(0xFFB4F39B)
|
||||
//val md_theme_dark_surfaceVariant = Color(0xFF4C4639)
|
||||
//val md_theme_dark_onSurfaceVariant = Color(0xFFCFC5B4)
|
||||
//val md_theme_dark_outline = Color(0xFF989080)
|
||||
//val md_theme_dark_inverseOnSurface = Color(0xFF032100)
|
||||
//val md_theme_dark_inverseSurface = Color(0xFFB4F39B)
|
||||
//val md_theme_dark_inversePrimary = Color(0xFF745B00)
|
||||
//val md_theme_dark_shadow = Color(0xFF000000)
|
||||
//val md_theme_dark_surfaceTint = Color(0xFFEFC125)
|
||||
//
|
||||
//val seed = Color(0xFFE2B513)
|
||||
val md_theme_dark_primaryContainer = Color(0xFF633F00)
|
||||
val md_theme_dark_onPrimaryContainer = Color(0xFFFFDDB3)
|
||||
val md_theme_dark_secondary = Color(0xFFDDC2A1)
|
||||
val md_theme_dark_onSecondary = Color(0xFF3E2D16)
|
||||
val md_theme_dark_secondaryContainer = Color(0xFF56442A)
|
||||
val md_theme_dark_onSecondaryContainer = Color(0xFFFBDEBC)
|
||||
val md_theme_dark_tertiary = Color(0xFFB8CEA1)
|
||||
val md_theme_dark_onTertiary = Color(0xFF243515)
|
||||
val md_theme_dark_tertiaryContainer = Color(0xFF3A4C2A)
|
||||
val md_theme_dark_onTertiaryContainer = Color(0xFFD4EABB)
|
||||
val md_theme_dark_error = Color(0xFFFFB4AB)
|
||||
val md_theme_dark_errorContainer = Color(0xFF93000A)
|
||||
val md_theme_dark_onError = Color(0xFF690005)
|
||||
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
|
||||
val md_theme_dark_background = Color(0xFF1F1B16)
|
||||
val md_theme_dark_onBackground = Color(0xFFEAE1D9)
|
||||
val md_theme_dark_surface = Color(0xFF1F1B16)
|
||||
val md_theme_dark_onSurface = Color(0xFFEAE1D9)
|
||||
val md_theme_dark_surfaceVariant = Color(0xFF4F4539)
|
||||
val md_theme_dark_onSurfaceVariant = Color(0xFFD3C4B4)
|
||||
val md_theme_dark_outline = Color(0xFF9C8F80)
|
||||
val md_theme_dark_inverseOnSurface = Color(0xFF1F1B16)
|
||||
val md_theme_dark_inverseSurface = Color(0xFFEAE1D9)
|
||||
val md_theme_dark_inversePrimary = Color(0xFF825500)
|
||||
val md_theme_dark_shadow = Color(0xFF000000)
|
||||
val md_theme_dark_surfaceTint = Color(0xFFFFB951)
|
||||
val md_theme_dark_outlineVariant = Color(0xFF4F4539)
|
||||
val md_theme_dark_scrim = Color(0xFF000000)
|
||||
|
||||
|
||||
val seed = Color(0xFF825500)
|
||||
|
||||
@ -2,32 +2,88 @@ package app.omnivore.omnivore.ui.theme
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
private val LightColors = lightColorScheme(
|
||||
primary = md_theme_light_primary,
|
||||
onPrimary = md_theme_light_onPrimary,
|
||||
primary = md_theme_light_primary,
|
||||
onPrimary = md_theme_light_onPrimary,
|
||||
primaryContainer = md_theme_light_primaryContainer,
|
||||
onPrimaryContainer = md_theme_light_onPrimaryContainer,
|
||||
secondary = md_theme_light_secondary,
|
||||
onSecondary = md_theme_light_onSecondary,
|
||||
secondaryContainer = md_theme_light_secondaryContainer,
|
||||
onSecondaryContainer = md_theme_light_onSecondaryContainer,
|
||||
tertiary = md_theme_light_tertiary,
|
||||
onTertiary = md_theme_light_onTertiary,
|
||||
tertiaryContainer = md_theme_light_tertiaryContainer,
|
||||
onTertiaryContainer = md_theme_light_onTertiaryContainer,
|
||||
error = md_theme_light_error,
|
||||
errorContainer = md_theme_light_errorContainer,
|
||||
onError = md_theme_light_onError,
|
||||
onErrorContainer = md_theme_light_onErrorContainer,
|
||||
background = md_theme_light_background,
|
||||
onBackground = md_theme_light_onBackground,
|
||||
surface = md_theme_light_surface,
|
||||
onSurface = md_theme_light_onSurface,
|
||||
surfaceVariant = md_theme_light_surfaceVariant,
|
||||
onSurfaceVariant = md_theme_light_onSurfaceVariant,
|
||||
outline = md_theme_light_outline,
|
||||
inverseOnSurface = md_theme_light_inverseOnSurface,
|
||||
inverseSurface = md_theme_light_inverseSurface,
|
||||
inversePrimary = md_theme_light_inversePrimary,
|
||||
surfaceTint = md_theme_light_surfaceTint,
|
||||
outlineVariant = md_theme_light_outlineVariant,
|
||||
scrim = md_theme_light_scrim,
|
||||
)
|
||||
|
||||
|
||||
private val DarkColors = darkColorScheme(
|
||||
primary = md_theme_dark_primary,
|
||||
onPrimary = md_theme_dark_onPrimary,
|
||||
primary = md_theme_dark_primary,
|
||||
onPrimary = md_theme_dark_onPrimary,
|
||||
primaryContainer = md_theme_dark_primaryContainer,
|
||||
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
|
||||
secondary = md_theme_dark_secondary,
|
||||
onSecondary = md_theme_dark_onSecondary,
|
||||
secondaryContainer = md_theme_dark_secondaryContainer,
|
||||
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
|
||||
tertiary = md_theme_dark_tertiary,
|
||||
onTertiary = md_theme_dark_onTertiary,
|
||||
tertiaryContainer = md_theme_dark_tertiaryContainer,
|
||||
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
|
||||
error = md_theme_dark_error,
|
||||
errorContainer = md_theme_dark_errorContainer,
|
||||
onError = md_theme_dark_onError,
|
||||
onErrorContainer = md_theme_dark_onErrorContainer,
|
||||
background = md_theme_dark_background,
|
||||
onBackground = md_theme_dark_onBackground,
|
||||
surface = md_theme_dark_surface,
|
||||
onSurface = md_theme_dark_onSurface,
|
||||
surfaceVariant = md_theme_dark_surfaceVariant,
|
||||
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
|
||||
outline = md_theme_dark_outline,
|
||||
inverseOnSurface = md_theme_dark_inverseOnSurface,
|
||||
inverseSurface = md_theme_dark_inverseSurface,
|
||||
inversePrimary = md_theme_dark_inversePrimary,
|
||||
surfaceTint = md_theme_dark_surfaceTint,
|
||||
outlineVariant = md_theme_dark_outlineVariant,
|
||||
scrim = md_theme_dark_scrim,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun OmnivoreTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
useDynamicTheme: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S,
|
||||
content: @Composable () -> Unit
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
useDynamicTheme: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val colorScheme = if (darkTheme) DarkColors else LightColors
|
||||
val colorScheme = if (darkTheme) DarkColors else LightColors
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
// shapes = Shapes,
|
||||
content = content
|
||||
)
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user