Lots of work on charges list... lots of work to do...
This commit is contained in:
17
.idea/deploymentTargetDropDown.xml
generated
Normal file
17
.idea/deploymentTargetDropDown.xml
generated
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetDropDown">
|
||||||
|
<targetSelectedWithDropDown>
|
||||||
|
<Target>
|
||||||
|
<type value="QUICK_BOOT_TARGET" />
|
||||||
|
<deviceKey>
|
||||||
|
<Key>
|
||||||
|
<type value="VIRTUAL_DEVICE_PATH" />
|
||||||
|
<value value="C:\Android\.android\avd\Pixel_3a_API_30_x86.avd" />
|
||||||
|
</Key>
|
||||||
|
</deviceKey>
|
||||||
|
</Target>
|
||||||
|
</targetSelectedWithDropDown>
|
||||||
|
<timeTargetWasSelectedWithDropDown value="2022-11-16T20:26:11.531085900Z" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -11,12 +11,12 @@ android {
|
|||||||
release {
|
release {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileSdk 32
|
compileSdk 33
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.sockenklaus.batterytracker"
|
applicationId "com.sockenklaus.batterytracker"
|
||||||
minSdk 29
|
minSdk 29
|
||||||
targetSdk 32
|
targetSdk 33
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
|
||||||
@@ -63,6 +63,7 @@ android {
|
|||||||
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
namespace 'com.sockenklaus.batterytracker'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -87,8 +88,6 @@ dependencies {
|
|||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
|
||||||
|
|
||||||
//implementation 'com.google.android.material:compose-theme-adapter:1.1.22'
|
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.9.0'
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.5.1'
|
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
@@ -105,5 +104,4 @@ dependencies {
|
|||||||
|
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
package="com.sockenklaus.batterytracker">
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ interface BatteryDao {
|
|||||||
@Query("Select * FROM batteries ORDER BY name COLLATE NOCASE ASC")
|
@Query("Select * FROM batteries ORDER BY name COLLATE NOCASE ASC")
|
||||||
fun getBatteries(): Flow<List<Battery>>
|
fun getBatteries(): Flow<List<Battery>>
|
||||||
|
|
||||||
@Query("Select * FROM batteries WHERE id = :id")
|
@Query("SELECT * FROM batteries WHERE id = :id")
|
||||||
fun getBatteryById(id: Int): Flow<Battery>
|
fun getBatteryById(id: Int): Flow<Battery>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
|
|||||||
@@ -25,4 +25,7 @@ interface ChargeDao {
|
|||||||
@Transaction
|
@Transaction
|
||||||
@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")
|
||||||
|
fun getChargesByBatteryId(id: Int): Flow<List<Charge>>
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.sockenklaus.batterytracker.ui
|
package com.sockenklaus.batterytracker.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -29,6 +30,7 @@ object Routes {
|
|||||||
const val BATTERY_DETAILS = "Battery Details"
|
const val BATTERY_DETAILS = "Battery Details"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
|
||||||
@Composable
|
@Composable
|
||||||
fun BatteryTracker() {
|
fun BatteryTracker() {
|
||||||
MaterialTheme {
|
MaterialTheme {
|
||||||
@@ -39,13 +41,15 @@ fun BatteryTracker() {
|
|||||||
scaffoldState = state.scaffoldState,
|
scaffoldState = state.scaffoldState,
|
||||||
|
|
||||||
topBar = {
|
topBar = {
|
||||||
when(state.currentScreen){
|
when {
|
||||||
|
state.currentScreen.startsWith(Routes.BATTERY_DETAILS) -> {
|
||||||
|
|
||||||
Routes.BATTERY_DETAILS -> DetailsTopAppBar(
|
DetailsTopAppBar(
|
||||||
navController = state.navController,
|
navController = state.navController,
|
||||||
drawerState = state.scaffoldState.drawerState,
|
drawerState = state.scaffoldState.drawerState,
|
||||||
appTitle = state.currentScreen
|
appTitle = state.currentScreen
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
else -> MainTopAppBar(
|
else -> MainTopAppBar(
|
||||||
drawerState = state.scaffoldState.drawerState,
|
drawerState = state.scaffoldState.drawerState,
|
||||||
@@ -100,9 +104,10 @@ fun BatteryTracker() {
|
|||||||
route = "${Routes.BATTERY_DETAILS}/{batteryId}",
|
route = "${Routes.BATTERY_DETAILS}/{batteryId}",
|
||||||
arguments = listOf(navArgument("batteryId"){ type = NavType.IntType })
|
arguments = listOf(navArgument("batteryId"){ type = NavType.IntType })
|
||||||
) { navBackStackEntry ->
|
) { navBackStackEntry ->
|
||||||
state.currentScreen = Routes.BATTERY_DETAILS
|
val id = navBackStackEntry.arguments?.getInt("batteryId")
|
||||||
|
state.currentScreen = Routes.BATTERY_DETAILS + ": " + state.getBatteryName(id = id)
|
||||||
BatteryDetails(
|
BatteryDetails(
|
||||||
batteryId = navBackStackEntry.arguments?.getInt("batteryId"),
|
batteryId = id,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,54 @@ package com.sockenklaus.batterytracker.ui.composables
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
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.*
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
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.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.sockenklaus.batterytracker.room.entities.Charge
|
||||||
import com.sockenklaus.batterytracker.ui.AppBarTitle
|
import com.sockenklaus.batterytracker.ui.AppBarTitle
|
||||||
import com.sockenklaus.batterytracker.ui.Routes
|
import com.sockenklaus.batterytracker.ui.Routes
|
||||||
|
import com.sockenklaus.batterytracker.ui.models.BatteryDetailsViewModel
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.format.FormatStyle
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BatteryDetails(
|
fun BatteryDetails(
|
||||||
batteryId: Int? = null
|
batteryId: Int? = null
|
||||||
){
|
){
|
||||||
|
val model: BatteryDetailsViewModel = viewModel()
|
||||||
|
val battery by model.battery.observeAsState()
|
||||||
|
val charges: List<Charge> by model.charges.observeAsState(emptyList())
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
){
|
){
|
||||||
Text(batteryId.toString())
|
|
||||||
|
val outputFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.GERMANY)
|
||||||
|
|
||||||
|
LazyColumn(
|
||||||
|
state = LazyListState()
|
||||||
|
) {
|
||||||
|
items(charges){ charge ->
|
||||||
|
ListItem(
|
||||||
|
text = { Text("Charge: " + charge.charge.toString() + " Ah") },
|
||||||
|
secondaryText = { Text("Date: " + charge.date.format(outputFormat)) }
|
||||||
|
|
||||||
|
)
|
||||||
|
Divider(Modifier.padding(horizontal = 16.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.sockenklaus.batterytracker.ui.models
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import androidx.lifecycle.asLiveData
|
||||||
|
import com.sockenklaus.batterytracker.room.BatteryTrackerDB
|
||||||
|
import com.sockenklaus.batterytracker.room.entities.Battery
|
||||||
|
import com.sockenklaus.batterytracker.room.entities.Charge
|
||||||
|
|
||||||
|
class BatteryDetailsViewModel(
|
||||||
|
application: Application,
|
||||||
|
state: SavedStateHandle
|
||||||
|
) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
private val db = BatteryTrackerDB.getInstance(application)
|
||||||
|
|
||||||
|
val battery: LiveData<Battery> = if(state.get<Int?>("batteryId") !== null) {
|
||||||
|
db.batteryDao().getBatteryById(state["batteryId"]!!).asLiveData()
|
||||||
|
} else {
|
||||||
|
MutableLiveData()
|
||||||
|
}
|
||||||
|
|
||||||
|
val charges: LiveData<List<Charge>> = if(state.get<Int?>("batteryId") !== null){
|
||||||
|
db.chargeDao().getChargesByBatteryId(state["batteryId"]!!).asLiveData()
|
||||||
|
} else {
|
||||||
|
MutableLiveData()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
val batteryAndCharges = batteriesAndCharges?.find{ it.battery.id == batteryId }
|
val batteryAndCharges = batteriesAndCharges?.find{ it.battery.id == batteryId }
|
||||||
|
|
||||||
if((batteryAndCharges != null) && batteryAndCharges.charges.isNotEmpty()){
|
if((batteryAndCharges != null) && batteryAndCharges.charges.isNotEmpty()){
|
||||||
return batteryAndCharges.charges.map { it.charge }.min()
|
return batteryAndCharges.charges.minOfOrNull { it.charge }
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
val batteryAndCharges = batteriesAndCharges?.find { it.battery.id == batteryId }
|
val batteryAndCharges = batteriesAndCharges?.find { it.battery.id == batteryId }
|
||||||
|
|
||||||
if((batteryAndCharges != null) && batteryAndCharges.charges.isNotEmpty()) {
|
if((batteryAndCharges != null) && batteryAndCharges.charges.isNotEmpty()) {
|
||||||
return batteryAndCharges.charges.map { it.charge }.max()
|
return batteryAndCharges.charges.maxOfOrNull { it.charge }
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package com.sockenklaus.batterytracker.ui.models
|
|||||||
|
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import com.sockenklaus.batterytracker.room.BatteryTrackerDB
|
||||||
|
import com.sockenklaus.batterytracker.room.entities.Battery
|
||||||
import com.sockenklaus.batterytracker.ui.Routes
|
import com.sockenklaus.batterytracker.ui.Routes
|
||||||
|
|
||||||
class MainViewModel : ViewModel() {
|
class MainViewModel : ViewModel() {
|
||||||
@@ -19,4 +22,20 @@ class MainViewModel : ViewModel() {
|
|||||||
navController = rememberNavController()
|
navController = rememberNavController()
|
||||||
scaffoldState = rememberScaffoldState()
|
scaffoldState = rememberScaffoldState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun getBatteryName(
|
||||||
|
id: Int?
|
||||||
|
) : String {
|
||||||
|
val db = BatteryTrackerDB.getInstance(LocalContext.current)
|
||||||
|
val battery = id?.let { db.batteryDao().getBatteryById(it).collectAsState(initial = Battery(name="")) }
|
||||||
|
|
||||||
|
var name = ""
|
||||||
|
|
||||||
|
if (battery != null){
|
||||||
|
name = battery.value.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,8 @@ ext {
|
|||||||
}
|
}
|
||||||
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '7.2.1' apply false
|
id 'com.android.application' version '7.3.1' apply false
|
||||||
id 'com.android.library' version '7.2.1' apply false
|
id 'com.android.library' version '7.3.1' apply false
|
||||||
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
|
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
|
||||||
id 'org.jetbrains.kotlin.kapt' version '1.7.0' apply false
|
id 'org.jetbrains.kotlin.kapt' version '1.7.0' apply false
|
||||||
}
|
}
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Sun Jul 10 23:29:55 CEST 2022
|
#Sun Jul 10 23:29:55 CEST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
Reference in New Issue
Block a user