Replace trigger dropdown with fullscreen dialog (#26)
* fix #24: Replace trigger dropdown with fullscreen dialog * Update button heights
This commit is contained in:
parent
6121b7b941
commit
e4ce89aca9
@ -1,60 +0,0 @@
|
|||||||
package de.timklge.karooreminder
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
|
||||||
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.MenuAnchorType
|
|
||||||
import androidx.compose.material3.OutlinedTextField
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
|
|
||||||
|
|
||||||
data class DropdownOption(val id: String, val name: String)
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun Dropdown(label: String, options: List<DropdownOption>, selected: DropdownOption, onSelect: (selectedOption: DropdownOption) -> Unit) {
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
ExposedDropdownMenuBox(
|
|
||||||
expanded = expanded,
|
|
||||||
onExpandedChange = { expanded = it },
|
|
||||||
) {
|
|
||||||
OutlinedTextField(
|
|
||||||
readOnly = true,
|
|
||||||
value = selected.name,
|
|
||||||
onValueChange = { },
|
|
||||||
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryEditable, true).fillMaxWidth(),
|
|
||||||
label = { Text(label) },
|
|
||||||
trailingIcon = {
|
|
||||||
ExposedDropdownMenuDefaults.TrailingIcon(
|
|
||||||
expanded = expanded
|
|
||||||
)
|
|
||||||
},
|
|
||||||
colors = ExposedDropdownMenuDefaults.textFieldColors()
|
|
||||||
)
|
|
||||||
ExposedDropdownMenu(
|
|
||||||
expanded = expanded,
|
|
||||||
onDismissRequest = { expanded = false },
|
|
||||||
) {
|
|
||||||
options.forEach { option ->
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(option.name, style = MaterialTheme.typography.bodyLarge) },
|
|
||||||
onClick = {
|
|
||||||
expanded = false
|
|
||||||
onSelect(option)
|
|
||||||
},
|
|
||||||
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
@ -45,6 +46,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
@ -57,8 +59,6 @@ import com.maxkeppeler.sheets.color.models.ColorSelection
|
|||||||
import com.maxkeppeler.sheets.color.models.ColorSelectionMode
|
import com.maxkeppeler.sheets.color.models.ColorSelectionMode
|
||||||
import com.maxkeppeler.sheets.color.models.MultipleColors
|
import com.maxkeppeler.sheets.color.models.MultipleColors
|
||||||
import com.maxkeppeler.sheets.color.models.SingleColor
|
import com.maxkeppeler.sheets.color.models.SingleColor
|
||||||
import de.timklge.karooreminder.Dropdown
|
|
||||||
import de.timklge.karooreminder.DropdownOption
|
|
||||||
import de.timklge.karooreminder.R
|
import de.timklge.karooreminder.R
|
||||||
import de.timklge.karooreminder.ReminderTrigger
|
import de.timklge.karooreminder.ReminderTrigger
|
||||||
import de.timklge.karooreminder.streamUserProfile
|
import de.timklge.karooreminder.streamUserProfile
|
||||||
@ -83,6 +83,7 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
|||||||
var autoDismiss by remember { mutableStateOf(reminder.isAutoDismiss) }
|
var autoDismiss by remember { mutableStateOf(reminder.isAutoDismiss) }
|
||||||
var deleteDialogVisible by remember { mutableStateOf(false) }
|
var deleteDialogVisible by remember { mutableStateOf(false) }
|
||||||
var toneDialogVisible by remember { mutableStateOf(false) }
|
var toneDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
var triggerDialogVisible by remember { mutableStateOf(false) }
|
||||||
var selectedTone by remember { mutableStateOf(reminder.tone) }
|
var selectedTone by remember { mutableStateOf(reminder.tone) }
|
||||||
var autoDismissSeconds by remember { mutableStateOf(reminder.autoDismissSeconds.toString()) }
|
var autoDismissSeconds by remember { mutableStateOf(reminder.autoDismissSeconds.toString()) }
|
||||||
var selectedTrigger by remember { mutableStateOf(reminder.trigger) }
|
var selectedTrigger by remember { mutableStateOf(reminder.trigger) }
|
||||||
@ -108,31 +109,15 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
|||||||
|
|
||||||
OutlinedTextField(value = text, onValueChange = { text = it }, label = { Text("Text") }, modifier = Modifier.fillMaxWidth(), singleLine = true)
|
OutlinedTextField(value = text, onValueChange = { text = it }, label = { Text("Text") }, modifier = Modifier.fillMaxWidth(), singleLine = true)
|
||||||
|
|
||||||
apply {
|
FilledTonalButton(modifier = Modifier
|
||||||
val dropdownOptions = ReminderTrigger.entries.toList().map { unit -> DropdownOption(unit.id, unit.label) }
|
.fillMaxWidth()
|
||||||
val dropdownInitialSelection by remember(selectedTrigger) {
|
.height(60.dp),
|
||||||
mutableStateOf(dropdownOptions.find { option -> option.id == selectedTrigger.id }!!)
|
onClick = {
|
||||||
}
|
triggerDialogVisible = true
|
||||||
Dropdown(label = "Trigger", options = dropdownOptions, selected = dropdownInitialSelection) { selectedOption ->
|
}) {
|
||||||
val previousTrigger = selectedTrigger
|
Icon(Icons.Default.Build, contentDescription = "Change Trigger", modifier = Modifier.size(20.dp))
|
||||||
selectedTrigger = ReminderTrigger.entries.find { entry -> entry.id == selectedOption.id }!!
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
|
Text("Trigger: ${selectedTrigger.label}")
|
||||||
if (selectedTrigger != previousTrigger) {
|
|
||||||
duration = when (selectedTrigger) {
|
|
||||||
ReminderTrigger.ELAPSED_TIME -> 30.toString()
|
|
||||||
ReminderTrigger.DISTANCE -> 10.toString()
|
|
||||||
ReminderTrigger.HR_LIMIT_MAXIMUM_EXCEEDED -> 160.toString()
|
|
||||||
ReminderTrigger.POWER_LIMIT_MAXIMUM_EXCEEDED -> 200.toString()
|
|
||||||
ReminderTrigger.HR_LIMIT_MINIMUM_EXCEEDED -> 60.toString()
|
|
||||||
ReminderTrigger.POWER_LIMIT_MINIMUM_EXCEEDED -> 100.toString()
|
|
||||||
ReminderTrigger.SPEED_LIMIT_MAXIMUM_EXCEEDED -> 40.toString()
|
|
||||||
ReminderTrigger.SPEED_LIMIT_MINIMUM_EXCEEDED -> 20.toString()
|
|
||||||
ReminderTrigger.CADENCE_LIMIT_MAXIMUM_EXCEEDED -> 120.toString()
|
|
||||||
ReminderTrigger.CADENCE_LIMIT_MINIMUM_EXCEEDED -> 60.toString()
|
|
||||||
ReminderTrigger.ENERGY_OUTPUT -> 200.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlinedTextField(value = duration, modifier = Modifier.fillMaxWidth(),
|
OutlinedTextField(value = duration, modifier = Modifier.fillMaxWidth(),
|
||||||
@ -187,19 +172,20 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
|||||||
)
|
)
|
||||||
|
|
||||||
FilledTonalButton(modifier = Modifier
|
FilledTonalButton(modifier = Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth()
|
||||||
|
.height(60.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
colorDialogState.show()
|
colorDialogState.show()
|
||||||
}) {
|
}) {
|
||||||
Surface(shape = CircleShape, color = Color(ContextCompat.getColor(ctx, selectedColor?.colorRes ?: R.color.hRed)),
|
Surface(shape = CircleShape, color = Color(ContextCompat.getColor(ctx, selectedColor?.colorRes ?: R.color.hRed)),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(40.dp)
|
.height(30.dp)
|
||||||
.shadow(5.dp, CircleShape)
|
.shadow(5.dp, CircleShape)
|
||||||
.width(40.dp), content = {})
|
.width(30.dp), content = {})
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(5.dp))
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
|
|
||||||
Text("Change Color")
|
Text("Color")
|
||||||
}
|
}
|
||||||
|
|
||||||
FilledTonalButton(modifier = Modifier
|
FilledTonalButton(modifier = Modifier
|
||||||
@ -208,9 +194,9 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
|||||||
onClick = {
|
onClick = {
|
||||||
toneDialogVisible = true
|
toneDialogVisible = true
|
||||||
}) {
|
}) {
|
||||||
Icon(Icons.Default.Build, contentDescription = "Change Tone")
|
Icon(painterResource(R.drawable.volume), contentDescription = "Tone", modifier = Modifier.size(20.dp))
|
||||||
Spacer(modifier = Modifier.width(5.dp))
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
Text("Change Tone")
|
Text("Tone: ${selectedTone.displayName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
@ -280,6 +266,50 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
|||||||
title = { Text("Delete reminder") }, text = { Text("Really delete this reminder?") })
|
title = { Text("Delete reminder") }, text = { Text("Really delete this reminder?") })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (triggerDialogVisible){
|
||||||
|
Dialog(onDismissRequest = { triggerDialogVisible = false }) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(10.dp),
|
||||||
|
shape = RoundedCornerShape(10.dp),
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.padding(5.dp)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||||
|
|
||||||
|
ReminderTrigger.entries.forEach { trigger ->
|
||||||
|
Row(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
selectedTrigger = trigger
|
||||||
|
triggerDialogVisible = false
|
||||||
|
}, verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
RadioButton(selected = selectedTrigger == trigger, onClick = {
|
||||||
|
selectedTrigger = trigger
|
||||||
|
triggerDialogVisible = false
|
||||||
|
})
|
||||||
|
|
||||||
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
|
Text(
|
||||||
|
text = trigger.label,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (trigger == ReminderTrigger.ENERGY_OUTPUT){
|
||||||
|
Text(
|
||||||
|
text = "Powermeter required",
|
||||||
|
color = Color.Gray,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (toneDialogVisible){
|
if (toneDialogVisible){
|
||||||
Dialog(onDismissRequest = { toneDialogVisible = false }) {
|
Dialog(onDismissRequest = { toneDialogVisible = false }) {
|
||||||
var dialogSelectedTone by remember { mutableStateOf(selectedTone) }
|
var dialogSelectedTone by remember { mutableStateOf(selectedTone) }
|
||||||
@ -287,8 +317,8 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi
|
|||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(16.dp),
|
.padding(10.dp),
|
||||||
shape = RoundedCornerShape(16.dp),
|
shape = RoundedCornerShape(10.dp),
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier
|
Column(modifier = Modifier
|
||||||
.padding(5.dp)
|
.padding(5.dp)
|
||||||
|
|||||||
BIN
app/src/main/res/drawable/volume.png
Normal file
BIN
app/src/main/res/drawable/volume.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Loading…
x
Reference in New Issue
Block a user