Several changes to implement more streamlined UX.
This commit is contained in:
@@ -41,6 +41,8 @@ android {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
applicationIdSuffix '.release'
|
||||
versionNameSuffix 'release'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
@@ -64,6 +66,7 @@ android {
|
||||
}
|
||||
}
|
||||
namespace 'com.sockenklaus.batterytracker'
|
||||
flavorDimensions
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -26,6 +26,6 @@ interface ChargeDao {
|
||||
@Query("SELECT * FROM batteries WHERE id = :id")
|
||||
fun getBatteryAndCharges(id: Int): Flow<BatteryAndCharges>
|
||||
|
||||
@Query("SELECT * FROM charges WHERE battery_id = :id ORDER BY date DESC")
|
||||
@Query("SELECT * FROM charges WHERE battery_id = :id ORDER BY created_at DESC")
|
||||
fun getChargesByBatteryId(id: Int): Flow<List<Charge>>
|
||||
}
|
||||
@@ -37,6 +37,10 @@ fun BatteryTracker() {
|
||||
val state: MainViewModel = viewModel()
|
||||
state.init()
|
||||
|
||||
/**
|
||||
* TODO Is there a smarter way to work with Scaffold? Is it possible to change the
|
||||
* components of the Scaffold from within the composables?
|
||||
*/
|
||||
Scaffold(
|
||||
scaffoldState = state.scaffoldState,
|
||||
|
||||
@@ -67,20 +71,6 @@ fun BatteryTracker() {
|
||||
route = Routes.HOME,
|
||||
state = state,
|
||||
)
|
||||
|
||||
NavListItem(
|
||||
icon = Icons.Default.BatteryChargingFull,
|
||||
textId = R.string.nav_add_charge,
|
||||
route = Routes.ADD_CHARGE,
|
||||
state = state,
|
||||
)
|
||||
|
||||
NavListItem(
|
||||
icon = Icons.Default.BatteryFull,
|
||||
textId = R.string.nav_add_battery,
|
||||
route = Routes.ADD_BATTERY,
|
||||
state = state,
|
||||
)
|
||||
}
|
||||
) {
|
||||
NavHost(
|
||||
@@ -92,9 +82,23 @@ fun BatteryTracker() {
|
||||
state.currentScreen = Routes.HOME
|
||||
Home(state.navController)
|
||||
}
|
||||
composable(Routes.ADD_CHARGE) {
|
||||
state.currentScreen = Routes.ADD_CHARGE
|
||||
AddCharge(state.navController)
|
||||
composable(
|
||||
route = Routes.ADD_CHARGE
|
||||
){
|
||||
AddCharge(
|
||||
navController = state.navController
|
||||
)
|
||||
}
|
||||
composable(
|
||||
route = "${Routes.ADD_CHARGE}/{batteryId}",
|
||||
arguments = listOf(navArgument("batteryId"){ type = NavType.IntType })
|
||||
) {
|
||||
val id = it.arguments?.getInt("batteryId")
|
||||
state.currentScreen = "${Routes.ADD_CHARGE} for Battery ${state.getBatteryName(id = id)}"
|
||||
AddCharge(
|
||||
batteryId = id,
|
||||
navController = state.navController
|
||||
)
|
||||
}
|
||||
composable(Routes.ADD_BATTERY) {
|
||||
state.currentScreen = Routes.ADD_BATTERY
|
||||
@@ -108,6 +112,7 @@ fun BatteryTracker() {
|
||||
state.currentScreen = Routes.BATTERY_DETAILS + ": " + state.getBatteryName(id = id)
|
||||
BatteryDetails(
|
||||
batteryId = id ,
|
||||
navController = state.navController
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,10 @@ import java.util.*
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun AddCharge(navController: NavController){
|
||||
fun AddCharge(
|
||||
batteryId: Int? = null,
|
||||
navController: NavController
|
||||
){
|
||||
val outerPadding = 16.dp
|
||||
val innerPadding = 16.dp
|
||||
|
||||
@@ -43,6 +46,12 @@ fun AddCharge(navController: NavController){
|
||||
val model: AddChargeViewModel = viewModel()
|
||||
val batteries by model.batteries.observeAsState(emptyList())
|
||||
|
||||
if(batteryId != null && batteries.any { it.id == batteryId }) {
|
||||
model.batteryName = TextFieldValue(
|
||||
text = batteries.find { it.id == batteryId }!!.name
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
Modifier.padding(outerPadding)
|
||||
) {
|
||||
@@ -51,11 +60,12 @@ fun AddCharge(navController: NavController){
|
||||
onExpandedChange = { bIdExpanded = !bIdExpanded}
|
||||
) {
|
||||
|
||||
val filteringOptions = batteries.filter { it.name.contains(model.batteryId.text, ignoreCase = true)}
|
||||
val filteringOptions = batteries.filter { it.name.contains(model.batteryName.text, ignoreCase = true)}
|
||||
OutlinedTextField(
|
||||
value = model.batteryId,
|
||||
enabled = batteryId == null,
|
||||
value = model.batteryName,
|
||||
onValueChange = {
|
||||
model.batteryId = it
|
||||
model.batteryName = it
|
||||
model.batteryHasError = false
|
||||
model.batteryHelper = R.string.helper_required
|
||||
bIdExpanded = filteringOptions.size > 1
|
||||
@@ -82,7 +92,7 @@ fun AddCharge(navController: NavController){
|
||||
for (filteringOption in filteringOptions) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
model.batteryId = TextFieldValue(
|
||||
model.batteryName = TextFieldValue(
|
||||
text = filteringOption.name,
|
||||
selection = TextRange(filteringOption.name.length)
|
||||
)
|
||||
@@ -134,11 +144,11 @@ fun AddCharge(navController: NavController){
|
||||
ExtendedFloatingActionButton(
|
||||
text = { Text(stringResource(R.string.button_save_charge)) },
|
||||
onClick = {
|
||||
if(!batteries.any{ it.name == model.batteryId.text }){
|
||||
if(!batteries.any{ it.name == model.batteryName.text }){
|
||||
model.batteryHasError = true
|
||||
model.batteryHelper = R.string.helper_battery_not_found
|
||||
}
|
||||
if(model.batteryId.text.isBlank()){
|
||||
if(model.batteryName.text.isBlank()){
|
||||
model.batteryHasError = true
|
||||
model.batteryHelper = R.string.helper_required
|
||||
}
|
||||
@@ -146,8 +156,12 @@ fun AddCharge(navController: NavController){
|
||||
model.chargeHasError = true
|
||||
}
|
||||
|
||||
if(!model.batteryHasError && !model.chargeHasError && model.saveCharge(batteries, model.batteryId.text, model.charge, model.date)){
|
||||
navController.navigate(Routes.HOME)
|
||||
if(!model.batteryHasError && !model.chargeHasError && model.saveCharge(batteries, model.batteryName.text, model.charge, model.date)){
|
||||
val id = model.getBatId(
|
||||
batteries,
|
||||
model.batteryName.text
|
||||
)
|
||||
navController.navigate("${Routes.BATTERY_DETAILS}/${id}")
|
||||
}
|
||||
},
|
||||
icon = { Icon(Icons.Default.Save, "Icon Save") },
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package com.sockenklaus.batterytracker.ui.composables
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.runtime.*
|
||||
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.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.sockenklaus.batterytracker.R
|
||||
import com.sockenklaus.batterytracker.room.entities.Battery
|
||||
import com.sockenklaus.batterytracker.room.entities.Charge
|
||||
import com.sockenklaus.batterytracker.ui.AppBarTitle
|
||||
@@ -26,14 +28,16 @@ import java.util.*
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun BatteryDetails(
|
||||
batteryId: Int? = null
|
||||
batteryId: Int?,
|
||||
navController: NavController
|
||||
){
|
||||
val model: BatteryDetailsViewModel = viewModel()
|
||||
val battery by model.battery.collectAsState(Battery(name = ""))
|
||||
val charges: List<Charge> by model.charges.collectAsState(emptyList())
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
){
|
||||
|
||||
val outputFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.GERMANY)
|
||||
@@ -50,8 +54,17 @@ fun BatteryDetails(
|
||||
Divider(Modifier.padding(horizontal = 16.dp))
|
||||
}
|
||||
}
|
||||
|
||||
ExtendedFloatingActionButton(
|
||||
text = { Text(stringResource(R.string.add_charge)) },
|
||||
onClick = {
|
||||
navController.navigate("${Routes.ADD_CHARGE}/${battery.id}")
|
||||
},
|
||||
icon = { Icon(Icons.Default.Add, "Icon Add") },
|
||||
modifier = Modifier.align(Alignment.BottomEnd)
|
||||
.padding(16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@@ -76,6 +89,6 @@ fun DetailsTopAppBar(
|
||||
) {
|
||||
Icon(Icons.Default.ArrowBack, null)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.sockenklaus.batterytracker.ui.composables
|
||||
|
||||
import android.inputmethodservice.Keyboard
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
@@ -8,9 +7,13 @@ import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.runtime.*
|
||||
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.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -33,14 +36,20 @@ fun Home(
|
||||
|
||||
val filteredList = batteries.filter { it.name.contains(filterText, ignoreCase = true) }
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
){
|
||||
Column(
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = 16.dp)
|
||||
.fillMaxHeight()
|
||||
) {
|
||||
MyOutlinedTextFieldWithSuffix(
|
||||
value = filterText,
|
||||
onValueChange = { filterText = it },
|
||||
labelId = R.string.hint_filter_batteries,
|
||||
modifier = Modifier.padding(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = 16.dp,
|
||||
start = 16.dp,
|
||||
end = 16.dp
|
||||
@@ -75,6 +84,16 @@ fun Home(
|
||||
}
|
||||
}
|
||||
}
|
||||
ExtendedFloatingActionButton(
|
||||
text = { Text(stringResource(R.string.nav_add_battery)) },
|
||||
icon = { Icon(Icons.Default.Add, contentDescription = "Add Battery") },
|
||||
onClick = {
|
||||
navController.navigate(Routes.ADD_BATTERY)
|
||||
},
|
||||
modifier = Modifier.padding(16.dp)
|
||||
.align(Alignment.BottomEnd)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.sockenklaus.batterytracker.ui.models
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
@@ -23,7 +22,7 @@ class AddChargeViewModel(application: Application) : AndroidViewModel(applicatio
|
||||
private val db = BatteryTrackerDB.getInstance(application)
|
||||
var batteries: LiveData<List<Battery>> = db.batteryDao().getBatteries().asLiveData()
|
||||
|
||||
var batteryId by mutableStateOf(TextFieldValue(""))
|
||||
var batteryName by mutableStateOf(TextFieldValue(""))
|
||||
var date: LocalDate by mutableStateOf(LocalDate.now())
|
||||
var charge by mutableStateOf("")
|
||||
|
||||
@@ -32,6 +31,14 @@ class AddChargeViewModel(application: Application) : AndroidViewModel(applicatio
|
||||
|
||||
var chargeHasError by mutableStateOf(false)
|
||||
|
||||
fun getBatId(
|
||||
batteries: List<Battery>,
|
||||
name: String
|
||||
) : Int? {
|
||||
|
||||
return batteries.find { it.name == name }?.id
|
||||
}
|
||||
|
||||
fun saveCharge(
|
||||
batteryList: List<Battery>,
|
||||
batteryName: String,
|
||||
|
||||
@@ -7,9 +7,6 @@ import com.sockenklaus.batterytracker.room.entities.Battery
|
||||
import com.sockenklaus.batterytracker.room.entities.Charge
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class BatteryDetailsViewModel(
|
||||
application: Application,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<string name="nav_header_title">Navigation</string>
|
||||
<string name="nav_home">Home</string>
|
||||
<string name="nav_add_charge">Add Charge</string>
|
||||
<string name="add_charge">Add Charge</string>
|
||||
<string name="nav_add_battery">Add Battery</string>
|
||||
|
||||
<string name="battery_id">Battery ID</string>
|
||||
|
||||
Reference in New Issue
Block a user