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