Merge branch 'auto-capitalize' of socrates/batterytracker into master
This commit is contained in:
@@ -16,7 +16,7 @@ interface BatteryDao {
|
||||
@Update
|
||||
fun updateBattery(battery: Battery): Int
|
||||
|
||||
@Query("Select * FROM batteries ORDER BY name ASC")
|
||||
@Query("Select * FROM batteries ORDER BY name COLLATE NOCASE ASC")
|
||||
fun getBatteries(): Flow<List<Battery>>
|
||||
|
||||
@Query("Select * FROM batteries WHERE id = :id")
|
||||
|
||||
@@ -53,7 +53,7 @@ fun BatteryTracker() {
|
||||
)
|
||||
}
|
||||
}
|
||||
) { _ ->
|
||||
) {
|
||||
ModalDrawer(
|
||||
drawerState = state.scaffoldState.drawerState,
|
||||
drawerContent = {
|
||||
|
||||
@@ -10,7 +10,9 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.toUpperCase
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
@@ -19,6 +21,7 @@ import com.sockenklaus.batterytracker.ui.Routes
|
||||
import com.sockenklaus.batterytracker.ui.composables.util.MyOutlinedTextFieldWithSuffix
|
||||
import com.sockenklaus.batterytracker.ui.models.AddBatteryViewModel
|
||||
import com.sockenklaus.batterytracker.util.validateDecimal
|
||||
import java.util.*
|
||||
|
||||
@Composable
|
||||
fun AddBattery(navController: NavController){
|
||||
@@ -32,22 +35,46 @@ fun AddBattery(navController: NavController){
|
||||
Modifier.padding(outerPadding)
|
||||
) {
|
||||
|
||||
MyOutlinedTextFieldWithSuffix(
|
||||
value = model.batteryName,
|
||||
onValueChange = { value ->
|
||||
model.batteryName = value
|
||||
model.batteryHasError = false
|
||||
model.batteryHelperId = R.string.helper_required
|
||||
if(batteries.any{ it.name.equals(value, ignoreCase = true) }){
|
||||
model.batteryHasError = true
|
||||
model.batteryHelperId = R.string.helper_battery_not_unique
|
||||
}
|
||||
},
|
||||
labelId = R.string.hint_enter_battery_name,
|
||||
leadingIcon = { Icon(Icons.Default.Tag, "Icon Tag") },
|
||||
isError = model.batteryHasError,
|
||||
helperTextId = model.batteryHelperId
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
){
|
||||
|
||||
MyOutlinedTextFieldWithSuffix(
|
||||
value = model.batteryName,
|
||||
onValueChange = { value ->
|
||||
model.batteryName = value
|
||||
model.batteryHasError = false
|
||||
model.batteryHelperId = R.string.helper_required
|
||||
if(batteries.any{ it.name.equals(value, ignoreCase = true) }){
|
||||
model.batteryHasError = true
|
||||
model.batteryHelperId = R.string.helper_battery_not_unique
|
||||
}
|
||||
},
|
||||
labelId = R.string.hint_enter_battery_name,
|
||||
leadingIcon = { Icon(Icons.Default.Tag, "Icon Tag") },
|
||||
isError = model.batteryHasError,
|
||||
helperTextId = model.batteryHelperId,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
capitalization = if(model.switchAutoCap) KeyboardCapitalization.Characters else KeyboardCapitalization.None,
|
||||
autoCorrect = false,
|
||||
keyboardType = KeyboardType.Ascii
|
||||
)
|
||||
)
|
||||
|
||||
Column() {
|
||||
Switch(
|
||||
checked = model.switchAutoCap,
|
||||
onCheckedChange = { model.switchAutoCap = !model.switchAutoCap }
|
||||
)
|
||||
Text(
|
||||
text = "Auto-Cap.",
|
||||
style = MaterialTheme.typography.caption
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Spacer(Modifier.size(innerPadding))
|
||||
|
||||
@@ -59,7 +86,8 @@ fun AddBattery(navController: NavController){
|
||||
labelId = R.string.hint_enter_declared_capacity,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||
leadingIcon = { Icon(Icons.Default.BatteryFull, "Icon Battery Full") },
|
||||
suffix = "Ah"
|
||||
suffix = "Ah",
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
Spacer(Modifier.size(outerPadding))
|
||||
|
||||
@@ -110,7 +110,8 @@ fun AddCharge(navController: NavController){
|
||||
leadingIcon = { Icon(Icons.Default.BatteryChargingFull, "Icon Battery Charging Full") },
|
||||
isError = model.chargeHasError,
|
||||
helperTextId = R.string.helper_required,
|
||||
suffix = "Ah"
|
||||
suffix = "Ah",
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Spacer(Modifier.size(innerPadding))
|
||||
|
||||
@@ -30,7 +30,9 @@ fun Home(
|
||||
|
||||
val filteredList = batteries.filter { it.name.contains(filterText, ignoreCase = true) }
|
||||
|
||||
Column {
|
||||
Column(
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
) {
|
||||
MyOutlinedTextFieldWithSuffix(
|
||||
value = filterText,
|
||||
onValueChange = { filterText = it },
|
||||
@@ -40,6 +42,7 @@ fun Home(
|
||||
start = 16.dp,
|
||||
end = 16.dp
|
||||
)
|
||||
.fillMaxWidth()
|
||||
)
|
||||
|
||||
LazyColumn(
|
||||
|
||||
@@ -21,90 +21,6 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.sockenklaus.batterytracker.ui.theme.Gray500
|
||||
|
||||
/*@Composable
|
||||
fun TopAppBar(
|
||||
title: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
navigationIcon: @Composable (() -> Unit)? = null,
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
backgroundColor: Color = MaterialTheme.colors.primarySurface,
|
||||
contentColor: Color = contentColorFor(backgroundColor),
|
||||
elevation: Dp = AppBarDefaults.TopAppBarElevation
|
||||
) {
|
||||
AppBar(
|
||||
backgroundColor,
|
||||
contentColor,
|
||||
elevation,
|
||||
AppBarDefaults.ContentPadding,
|
||||
RectangleShape,
|
||||
modifier
|
||||
) {
|
||||
if (navigationIcon == null) {
|
||||
Spacer(Modifier.width(16.dp - 4.dp))
|
||||
} else {
|
||||
Row(Modifier.fillMaxHeight().width(72.dp - 4.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentAlpha provides ContentAlpha.high,
|
||||
content = navigationIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
Modifier.fillMaxHeight().weight(1f),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
ProvideTextStyle(value = MaterialTheme.typography.h6) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentAlpha provides ContentAlpha.high,
|
||||
content = title
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
|
||||
Row(
|
||||
Modifier.fillMaxHeight(),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
content = actions
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
private fun AppBar(
|
||||
backgroundColor: Color,
|
||||
contentColor: Color,
|
||||
elevation: Dp,
|
||||
contentPadding: PaddingValues,
|
||||
shape: Shape,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
Surface(
|
||||
color = backgroundColor,
|
||||
contentColor = contentColor,
|
||||
elevation = elevation,
|
||||
shape = shape,
|
||||
modifier = modifier
|
||||
) {
|
||||
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
|
||||
Row(
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(contentPadding)
|
||||
.height(56.dp),
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
fun MyOutlinedTextFieldWithSuffix(
|
||||
@@ -142,69 +58,72 @@ fun MyOutlinedTextFieldWithSuffix(
|
||||
Gray500
|
||||
}
|
||||
|
||||
BasicTextField(
|
||||
value = value,
|
||||
modifier = modifier
|
||||
Column() {
|
||||
BasicTextField(
|
||||
value = value,
|
||||
modifier = modifier
|
||||
.padding(top = 8.dp)
|
||||
|
||||
.background(colors.backgroundColor(enabled).value, shape)
|
||||
.defaultMinSize(
|
||||
minWidth = TextFieldDefaults.MinWidth,
|
||||
minHeight = TextFieldDefaults.MinHeight
|
||||
),
|
||||
onValueChange = onValueChange,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = mergedTextStyle,
|
||||
cursorBrush = SolidColor(colors.cursorColor(isError).value),
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
interactionSource = interactionSource,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
OutlinedTextFieldDecorationBox(
|
||||
value = value,
|
||||
visualTransformation = visualTransformation,
|
||||
innerTextField = {
|
||||
Row {
|
||||
val alignModifier = Modifier.alignByBaseline()
|
||||
Box(alignModifier.weight(1f)){
|
||||
innerTextField()
|
||||
onValueChange = onValueChange,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = mergedTextStyle,
|
||||
cursorBrush = SolidColor(colors.cursorColor(isError).value),
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
interactionSource = interactionSource,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
OutlinedTextFieldDecorationBox(
|
||||
value = value,
|
||||
visualTransformation = visualTransformation,
|
||||
innerTextField = {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
val alignModifier = Modifier.alignByBaseline()
|
||||
Box(alignModifier){
|
||||
innerTextField()
|
||||
}
|
||||
Text(
|
||||
suffix,
|
||||
alignModifier,
|
||||
colors.trailingIconColor(enabled = enabled, isError = isError).value
|
||||
)
|
||||
}
|
||||
Text(
|
||||
suffix,
|
||||
alignModifier,
|
||||
colors.trailingIconColor(enabled = enabled, isError = isError).value
|
||||
},
|
||||
placeholder = placeholder,
|
||||
label = { Text(stringResource(labelId)) },
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
singleLine = singleLine,
|
||||
enabled = enabled,
|
||||
isError = isError,
|
||||
interactionSource = interactionSource,
|
||||
colors = colors,
|
||||
border = {
|
||||
TextFieldDefaults.BorderBox(
|
||||
enabled,
|
||||
isError,
|
||||
interactionSource,
|
||||
colors,
|
||||
shape
|
||||
)
|
||||
}
|
||||
},
|
||||
placeholder = placeholder,
|
||||
label = { Text(stringResource(labelId)) },
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
singleLine = singleLine,
|
||||
enabled = enabled,
|
||||
isError = isError,
|
||||
interactionSource = interactionSource,
|
||||
colors = colors,
|
||||
border = {
|
||||
TextFieldDefaults.BorderBox(
|
||||
enabled,
|
||||
isError,
|
||||
interactionSource,
|
||||
colors,
|
||||
shape
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
Text(
|
||||
text = if(helperTextId != null) stringResource(helperTextId) else "",
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = helperTextColor,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
Text(
|
||||
text = if(helperTextId != null) stringResource(helperTextId) else "",
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = helperTextColor,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ class AddBatteryViewModel(application: Application): AndroidViewModel(applicatio
|
||||
var batteryName by mutableStateOf("")
|
||||
var batteryHasError by mutableStateOf(false)
|
||||
var batteryHelperId by mutableStateOf(R.string.helper_required)
|
||||
var switchAutoCap by mutableStateOf(true)
|
||||
|
||||
var declaredCapacity by mutableStateOf("")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user