Manage Currencies
This commit is contained in:
+24
-117
@@ -7,14 +7,8 @@ import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.helcel.cowspent.R
|
||||
import net.helcel.cowspent.android.helper.showToast
|
||||
import net.helcel.cowspent.model.DBBill
|
||||
import net.helcel.cowspent.model.DBCurrency
|
||||
import net.helcel.cowspent.model.ProjectType
|
||||
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
||||
import net.helcel.cowspent.theme.ThemeUtils
|
||||
@@ -25,7 +19,6 @@ class ManageCurrenciesActivity : AppCompatActivity() {
|
||||
|
||||
internal val viewModel: ManageCurrenciesViewModel by viewModels()
|
||||
private var db: CowspentSQLiteOpenHelper? = null
|
||||
private var selectedProjectID: Long = -1
|
||||
|
||||
private val editMainCurrencyCallBack: ICallback = object : ICallback {
|
||||
override fun onFinish() {}
|
||||
@@ -47,131 +40,45 @@ class ManageCurrenciesActivity : AppCompatActivity() {
|
||||
enableEdgeToEdge()
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
intent.extras?.let {
|
||||
selectedProjectID = it.getLong(EXTRA_PROJECT_ID)
|
||||
}
|
||||
val selectedProjectID = intent.getLongExtra(EXTRA_PROJECT_ID, -1L)
|
||||
if (selectedProjectID == -1L) {
|
||||
Log.e(TAG, "Missing project id")
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
db = CowspentSQLiteOpenHelper.getInstance(this)
|
||||
|
||||
lifecycleScope.launch {
|
||||
val project = withContext(Dispatchers.IO) { db!!.getProject(selectedProjectID) }
|
||||
viewModel.mainCurrencyName = project?.currencyName?.let { if (it == "null") "" else it } ?: ""
|
||||
updateCurrenciesList()
|
||||
viewModel.projectId = selectedProjectID
|
||||
viewModel.loadCurrencies()
|
||||
|
||||
setContent {
|
||||
ThemeUtils.CowspentTheme {
|
||||
ManageCurrenciesScreen(
|
||||
viewModel = viewModel,
|
||||
onBack = { finish() },
|
||||
onSaveMain = { saveMainCurrency() },
|
||||
onAdd = { addOrUpdateCurrency() },
|
||||
onDelete = { deleteCurrency(it) },
|
||||
onEdit = { startEditing(it) },
|
||||
onCancelEdit = { cancelEditing() }
|
||||
)
|
||||
}
|
||||
db = CowspentSQLiteOpenHelper.getInstance(this)
|
||||
|
||||
setContent {
|
||||
ThemeUtils.CowspentTheme {
|
||||
ManageCurrenciesScreen(
|
||||
viewModel = viewModel,
|
||||
onBack = { finish() },
|
||||
onSaveMain = { saveMainCurrency() },
|
||||
onAdd = { viewModel.addCurrency() },
|
||||
onDelete = { viewModel.deleteCurrency(it.id) },
|
||||
onEdit = { viewModel.startEditing(it) },
|
||||
onCancelEdit = { viewModel.cancelEditing() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveMainCurrency() {
|
||||
val newMainCurrencyName = viewModel.mainCurrencyName
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db!!.updateProject(
|
||||
projId = selectedProjectID,
|
||||
newCurrencyName = newMainCurrencyName
|
||||
)
|
||||
val project = db!!.getProject(selectedProjectID)
|
||||
if (project != null) {
|
||||
db!!.syncIfRemote(project)
|
||||
if (project.type == ProjectType.COSPEND) {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!db!!.cowspentServerSyncHelper
|
||||
.editRemoteProject(
|
||||
projId = selectedProjectID,
|
||||
newName = project.name,
|
||||
newMainCurrencyName = newMainCurrencyName,
|
||||
callback = editMainCurrencyCallBack
|
||||
)
|
||||
) {
|
||||
showToast(this@ManageCurrenciesActivity, getString(R.string.remote_project_operation_no_network), Toast.LENGTH_LONG)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withContext(Dispatchers.Main) {
|
||||
showToast(this@ManageCurrenciesActivity, getString(R.string.currency_saved_success), Toast.LENGTH_LONG)
|
||||
}
|
||||
}
|
||||
val project = db?.getProject(viewModel.projectId)
|
||||
if (project != null) {
|
||||
if (project.type == ProjectType.COSPEND) {
|
||||
if (!db!!.cowspentServerSyncHelper.isSyncPossible) {
|
||||
showToast(this, getString(R.string.remote_project_operation_no_network), Toast.LENGTH_LONG)
|
||||
}
|
||||
} else {
|
||||
showToast(this, getString(R.string.currency_saved_success), Toast.LENGTH_LONG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addOrUpdateCurrency() {
|
||||
val uiRate = try { viewModel.newCurrencyRate.toDouble() } catch (_: Exception) { 0.0 }
|
||||
val exchangeRate = if (uiRate != 0.0) 1.0 / uiRate else 0.0
|
||||
val currencyName = viewModel.newCurrencyName
|
||||
val editingId = viewModel.editingCurrencyId
|
||||
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
if (editingId != null) {
|
||||
db!!.updateCurrency(editingId, currencyName, exchangeRate)
|
||||
val currency = db!!.getCurrency(editingId)
|
||||
if (currency != null) {
|
||||
db!!.setCurrencyStateSync(editingId, DBBill.STATE_EDITED)
|
||||
}
|
||||
} else {
|
||||
val newCurrency = DBCurrency(
|
||||
0, 0, selectedProjectID,
|
||||
currencyName, exchangeRate, DBBill.STATE_ADDED
|
||||
)
|
||||
db!!.addCurrencyAndSync(newCurrency)
|
||||
}
|
||||
}
|
||||
cancelEditing()
|
||||
updateCurrenciesList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startEditing(currency: DBCurrency) {
|
||||
viewModel.editingCurrencyId = currency.id
|
||||
viewModel.newCurrencyName = currency.name ?: ""
|
||||
val uiRate = if (currency.exchangeRate != 0.0) 1.0 / currency.exchangeRate else 0.0
|
||||
viewModel.newCurrencyRate = uiRate.toString()
|
||||
}
|
||||
|
||||
private fun cancelEditing() {
|
||||
viewModel.editingCurrencyId = null
|
||||
viewModel.newCurrencyName = ""
|
||||
viewModel.newCurrencyRate = ""
|
||||
}
|
||||
|
||||
private fun deleteCurrency(currency: DBCurrency) {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db!!.setCurrencyStateSync(currency.id, DBBill.STATE_DELETED)
|
||||
}
|
||||
updateCurrenciesList()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateCurrenciesList() {
|
||||
val currenciesDB = withContext(Dispatchers.IO) {
|
||||
val list = db!!.getCurrenciesOfProjectWithState(selectedProjectID, DBBill.STATE_ADDED).toMutableList()
|
||||
list.addAll(db!!.getCurrenciesOfProjectWithState(selectedProjectID, DBBill.STATE_EDITED))
|
||||
list.addAll(db!!.getCurrenciesOfProjectWithState(selectedProjectID, DBBill.STATE_OK))
|
||||
list
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
viewModel.currencies = currenciesDB
|
||||
}
|
||||
viewModel.saveMainCurrency(editMainCurrencyCallBack)
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.helcel.cowspent.android.currencies
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -351,9 +352,10 @@ fun CurrencyRowPreview() {
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun ManageCurrenciesScreenPreview() {
|
||||
val application = LocalContext.current.applicationContext as Application
|
||||
MaterialTheme {
|
||||
ManageCurrenciesScreen(
|
||||
viewModel = ManageCurrenciesViewModel().apply {
|
||||
viewModel = ManageCurrenciesViewModel(application).apply {
|
||||
mainCurrencyName = "EUR"
|
||||
currencies = listOf(
|
||||
DBCurrency(1, 0, 0, "USD", 1.1, 0),
|
||||
|
||||
+111
-2
@@ -1,14 +1,24 @@
|
||||
package net.helcel.cowspent.android.currencies
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.helcel.cowspent.android.helper.DialogState
|
||||
import net.helcel.cowspent.model.DBBill
|
||||
import net.helcel.cowspent.model.DBCurrency
|
||||
import net.helcel.cowspent.model.ProjectType
|
||||
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
||||
import net.helcel.cowspent.util.ICallback
|
||||
|
||||
class ManageCurrenciesViewModel : ViewModel() {
|
||||
class ManageCurrenciesViewModel(application: Application) : AndroidViewModel(application) {
|
||||
var projectId: Long = -1
|
||||
var mainCurrencyName by mutableStateOf("")
|
||||
var newCurrencyName by mutableStateOf("")
|
||||
var newCurrencyRate by mutableStateOf("")
|
||||
@@ -19,6 +29,105 @@ class ManageCurrenciesViewModel : ViewModel() {
|
||||
|
||||
var dialogState by mutableStateOf<DialogState?>(null)
|
||||
|
||||
private val db = CowspentSQLiteOpenHelper.getInstance(application)
|
||||
|
||||
fun loadCurrencies() {
|
||||
if (projectId == -1L) return
|
||||
viewModelScope.launch {
|
||||
val project = withContext(Dispatchers.IO) { db.getProject(projectId) }
|
||||
mainCurrencyName = project?.currencyName?.let { if (it == "null") "" else it } ?: ""
|
||||
updateCurrenciesList()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateCurrenciesList() {
|
||||
val currenciesDB = withContext(Dispatchers.IO) {
|
||||
val list = db.getCurrenciesOfProjectWithState(projectId, DBBill.STATE_ADDED).toMutableList()
|
||||
list.addAll(db.getCurrenciesOfProjectWithState(projectId, DBBill.STATE_EDITED))
|
||||
list.addAll(db.getCurrenciesOfProjectWithState(projectId, DBBill.STATE_OK))
|
||||
list
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
currencies = currenciesDB
|
||||
}
|
||||
}
|
||||
|
||||
fun saveMainCurrency(callback: ICallback) {
|
||||
val newMainCurrencyName = mainCurrencyName
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db.updateProject(
|
||||
projId = projectId,
|
||||
newCurrencyName = newMainCurrencyName
|
||||
)
|
||||
val project = db.getProject(projectId)
|
||||
if (project != null) {
|
||||
db.syncIfRemote(project)
|
||||
if (project.type == ProjectType.COSPEND) {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!db.cowspentServerSyncHelper
|
||||
.editRemoteProject(
|
||||
projId = projectId,
|
||||
newName = project.name,
|
||||
newMainCurrencyName = newMainCurrencyName,
|
||||
callback = callback
|
||||
)
|
||||
) {
|
||||
// Handled by activity showing toast
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addCurrency() {
|
||||
val uiRate = try { newCurrencyRate.toDouble() } catch (_: Exception) { 0.0 }
|
||||
val exchangeRate = if (uiRate != 0.0) 1.0 / uiRate else 0.0
|
||||
val currencyName = newCurrencyName
|
||||
val editingId = editingCurrencyId
|
||||
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
if (editingId != null) {
|
||||
db.updateCurrency(editingId, currencyName, exchangeRate)
|
||||
db.setCurrencyStateSync(editingId, DBBill.STATE_EDITED)
|
||||
} else {
|
||||
val newCurrency = DBCurrency(
|
||||
0, 0, projectId,
|
||||
currencyName, exchangeRate, DBBill.STATE_ADDED
|
||||
)
|
||||
db.addCurrencyAndSync(newCurrency)
|
||||
}
|
||||
}
|
||||
cancelEditing()
|
||||
updateCurrenciesList()
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteCurrency(currencyId: Long) {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db.setCurrencyStateSync(currencyId, DBBill.STATE_DELETED)
|
||||
}
|
||||
updateCurrenciesList()
|
||||
}
|
||||
}
|
||||
|
||||
fun startEditing(currency: DBCurrency) {
|
||||
editingCurrencyId = currency.id
|
||||
newCurrencyName = currency.name ?: ""
|
||||
val uiRate = if (currency.exchangeRate != 0.0) 1.0 / currency.exchangeRate else 0.0
|
||||
newCurrencyRate = uiRate.toString()
|
||||
}
|
||||
|
||||
fun cancelEditing() {
|
||||
editingCurrencyId = null
|
||||
newCurrencyName = ""
|
||||
newCurrencyRate = ""
|
||||
}
|
||||
|
||||
fun showDialog(
|
||||
title: String? = null,
|
||||
message: String? = null,
|
||||
|
||||
Reference in New Issue
Block a user