diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c4b58cd..b4f997d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -73,7 +73,7 @@ jobs: - run: | echo "Run, Build Application" - ./gradlew build + ./gradlew assembleDebug test lint - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/.idea/.name b/.idea/.name index 922e93e..11201ac 100644 --- a/.idea/.name +++ b/.idea/.name @@ -1 +1 @@ -Recurring Expense Tracker \ No newline at end of file +RecurringExpenseTracker \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 90d87fd..04fdbfb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,7 +15,7 @@ android { minSdk = 24 targetSdk = 34 versionCode = 1 - versionName = "1.0" + versionName = "0.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -23,13 +23,30 @@ android { } } + signingConfigs { + create("release") { + storeFile = file("keystore/android_keystore.jks") + storePassword = System.getenv("SIGNING_STORE_PASSWORD") + keyAlias = System.getenv("SIGNING_KEY_ALIAS") + keyPassword = System.getenv("SIGNING_KEY_PASSWORD") + } + } + buildTypes { - release { + named("release") { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro", ) + applicationVariants.all { + outputs.forEach { output -> + if (output is com.android.build.gradle.internal.api.BaseVariantOutputImpl) { + output.outputFileName = "${rootProject.name}_$versionName.apk" + } + } + } + signingConfig = signingConfigs.getByName("release") } } compileOptions { diff --git a/app/src/main/java/de/dbauer/expensetracker/Extensions.kt b/app/src/main/java/de/dbauer/expensetracker/Extensions.kt index 40ccaa8..5d8ae5c 100644 --- a/app/src/main/java/de/dbauer/expensetracker/Extensions.kt +++ b/app/src/main/java/de/dbauer/expensetracker/Extensions.kt @@ -1,7 +1,16 @@ package de.dbauer.expensetracker -fun Float.toValueString(): String { - return "%.2f".format(this) +import java.text.NumberFormat + +fun Float.toCurrencyString(): String { + return NumberFormat.getCurrencyInstance().format(this) +} + +fun Float.toLocalString(): String { + return NumberFormat.getInstance().let { + it.minimumFractionDigits = 2 + it.format(this) + } } fun String.toFloatIgnoreSeparator(): Float { diff --git a/app/src/main/java/de/dbauer/expensetracker/MainActivity.kt b/app/src/main/java/de/dbauer/expensetracker/MainActivity.kt index e6138b6..0f5f8c2 100644 --- a/app/src/main/java/de/dbauer/expensetracker/MainActivity.kt +++ b/app/src/main/java/de/dbauer/expensetracker/MainActivity.kt @@ -234,19 +234,19 @@ private fun MainActivityContentPreview() { id = 0, name = "Netflix", description = "My Netflix description", - priceValue = 9.99f, + price = 9.99f, ), RecurringExpenseData( id = 1, name = "Disney Plus", description = "My Disney Plus description", - priceValue = 5f, + price = 5f, ), RecurringExpenseData( id = 2, name = "Amazon Prime", description = "My Disney Plus description", - priceValue = 7.95f, + price = 7.95f, ), ), onRecurringExpenseAdded = {}, diff --git a/app/src/main/java/de/dbauer/expensetracker/data/RecurringExpenseData.kt b/app/src/main/java/de/dbauer/expensetracker/data/RecurringExpenseData.kt index 9be8d07..b264c91 100644 --- a/app/src/main/java/de/dbauer/expensetracker/data/RecurringExpenseData.kt +++ b/app/src/main/java/de/dbauer/expensetracker/data/RecurringExpenseData.kt @@ -1,12 +1,8 @@ package de.dbauer.expensetracker.data -import de.dbauer.expensetracker.toValueString - data class RecurringExpenseData( val id: Int, val name: String, val description: String, - val priceValue: Float, -) { - val priceString = "${priceValue.toValueString()} €" // TODO: Make currency dynamic -} + val price: Float, +) diff --git a/app/src/main/java/de/dbauer/expensetracker/ui/EditRecurringExpense.kt b/app/src/main/java/de/dbauer/expensetracker/ui/EditRecurringExpense.kt index f68a550..ac17480 100644 --- a/app/src/main/java/de/dbauer/expensetracker/ui/EditRecurringExpense.kt +++ b/app/src/main/java/de/dbauer/expensetracker/ui/EditRecurringExpense.kt @@ -47,7 +47,7 @@ import androidx.compose.ui.unit.dp import de.dbauer.expensetracker.R import de.dbauer.expensetracker.data.RecurringExpenseData import de.dbauer.expensetracker.toFloatIgnoreSeparator -import de.dbauer.expensetracker.toValueString +import de.dbauer.expensetracker.toLocalString import de.dbauer.expensetracker.ui.theme.ExpenseTrackerTheme @OptIn(ExperimentalMaterial3Api::class) @@ -104,7 +104,7 @@ private fun EditRecurringExpenseInternal( mutableStateOf(TextFieldValue(currentData?.description ?: "")) } var priceState by rememberSaveable(stateSaver = TextFieldValue.Saver) { - mutableStateOf(TextFieldValue(currentData?.priceValue?.toValueString() ?: "")) + mutableStateOf(TextFieldValue(currentData?.price?.toLocalString() ?: "")) } val priceInputError = rememberSaveable { @@ -166,7 +166,7 @@ private fun EditRecurringExpenseInternal( CustomTextField( value = priceState, onValueChange = { priceState = it }, - placeholder = stringResource(R.string.edit_expense_price_placeholder), + placeholder = 0f.toLocalString(), keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Decimal, @@ -320,7 +320,7 @@ private fun onConfirmClicked( id = currentData?.id ?: 0, name = name, description = description, - priceValue = price.toFloatIgnoreSeparator(), + price = price.toFloatIgnoreSeparator(), ), ) } diff --git a/app/src/main/java/de/dbauer/expensetracker/ui/RecurringExpenseOverview.kt b/app/src/main/java/de/dbauer/expensetracker/ui/RecurringExpenseOverview.kt index a5a19f0..6a6e793 100644 --- a/app/src/main/java/de/dbauer/expensetracker/ui/RecurringExpenseOverview.kt +++ b/app/src/main/java/de/dbauer/expensetracker/ui/RecurringExpenseOverview.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import de.dbauer.expensetracker.R import de.dbauer.expensetracker.data.RecurringExpenseData +import de.dbauer.expensetracker.toCurrencyString import de.dbauer.expensetracker.ui.theme.ExpenseTrackerTheme import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -151,7 +152,7 @@ private fun RecurringExpense( } } Text( - text = recurringExpenseData.priceString, + text = recurringExpenseData.price.toCurrencyString(), style = MaterialTheme.typography.headlineSmall, ) } @@ -173,7 +174,7 @@ private fun RecurringExpenseOverviewPreview() { id = 0, name = "Netflix", description = "My Netflix description", - priceValue = 9.99f, + price = 9.99f, ), RecurringExpenseData( id = 1, @@ -181,13 +182,13 @@ private fun RecurringExpenseOverviewPreview() { description = "My Disney Plus very very very very very " + "very very very very long description", - priceValue = 5f, + price = 5f, ), RecurringExpenseData( id = 2, name = "Amazon Prime with a long name", description = "", - priceValue = 7.95f, + price = 7.95f, ), ), onItemClicked = {}, diff --git a/app/src/main/java/de/dbauer/expensetracker/viewmodel/MainActivityViewModel.kt b/app/src/main/java/de/dbauer/expensetracker/viewmodel/MainActivityViewModel.kt index 1e79f6d..39cccb3 100644 --- a/app/src/main/java/de/dbauer/expensetracker/viewmodel/MainActivityViewModel.kt +++ b/app/src/main/java/de/dbauer/expensetracker/viewmodel/MainActivityViewModel.kt @@ -8,7 +8,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import de.dbauer.expensetracker.data.RecurringExpenseData -import de.dbauer.expensetracker.toValueString +import de.dbauer.expensetracker.toCurrencyString import de.dbauer.expensetracker.viewmodel.database.ExpenseRepository import de.dbauer.expensetracker.viewmodel.database.RecurringExpense import kotlinx.collections.immutable.ImmutableList @@ -42,7 +42,7 @@ class MainActivityViewModel( id = it.id, name = it.name!!, description = it.description!!, - priceValue = it.price!!, + price = it.price!!, ), ) } @@ -58,7 +58,7 @@ class MainActivityViewModel( id = 0, name = recurringExpense.name, description = recurringExpense.description, - price = recurringExpense.priceValue, + price = recurringExpense.price, ), ) } @@ -71,7 +71,7 @@ class MainActivityViewModel( id = recurringExpense.id, name = recurringExpense.name, description = recurringExpense.description, - price = recurringExpense.priceValue, + price = recurringExpense.price, ), ) } @@ -84,7 +84,7 @@ class MainActivityViewModel( id = recurringExpense.id, name = recurringExpense.name, description = recurringExpense.description, - price = recurringExpense.priceValue, + price = recurringExpense.price, ), ) } @@ -93,11 +93,11 @@ class MainActivityViewModel( private fun updateExpenseSummary() { var price = 0f _recurringExpenseData.forEach { - price += it.priceValue + price += it.price } - _weeklyExpense = "${(price / 30f).toValueString()} €" // TODO: Make currency dynamic - _monthlyExpense = "${price.toValueString()} €" // TODO: Make currency dynamic - _yearlyExpense = "${(price * 12).toValueString()} €" // TODO: Make currency dynamic + _weeklyExpense = (price / 30f).toCurrencyString() + _monthlyExpense = price.toCurrencyString() + _yearlyExpense = (price * 12).toCurrencyString() } companion object { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 60d3315..1483648 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,5 +22,4 @@ Name e.g. Netflix Price - 0,00 \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 0a12163..402a303 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,6 +13,5 @@ dependencyResolutionManagement { } } -rootProject.name = "Recurring Expense Tracker" +rootProject.name = "RecurringExpenseTracker" include(":app") - \ No newline at end of file