Added option to set if TransactionsList should be shown in zebra stripes or not

This commit is contained in:
dankito 2024-09-05 03:01:38 +02:00
parent d1687e894b
commit 89bc373476
8 changed files with 89 additions and 20 deletions

View File

@ -40,6 +40,10 @@ fun App() {
// we want to place the FAB half size into the BottomBar so we have to add some top padding to it // we want to place the FAB half size into the BottomBar so we have to add some top padding to it
val fabPositionAdjustment = 44.dp // FabSpacing = 16.dp + FAB height (= 56.dp) / 2 val fabPositionAdjustment = 44.dp // FabSpacing = 16.dp + FAB height (= 56.dp) / 2
val uiState = DI.uiState
val uiSettings = DI.uiSettings
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
coroutineScope.launch { coroutineScope.launch {
@ -56,13 +60,13 @@ fun App() {
FloatingActionButton( FloatingActionButton(
shape = CircleShape, shape = CircleShape,
modifier = Modifier.offset(x = 4.dp, y = fabPositionAdjustment), modifier = Modifier.offset(x = 4.dp, y = fabPositionAdjustment),
onClick = { DI.uiState.showAddAccountDialog.value = true } onClick = { uiState.showAddAccountDialog.value = true }
) { ) {
Icon(Icons.Filled.Add, contentDescription = "Add a bank account") Icon(Icons.Filled.Add, contentDescription = "Add a bank account")
} }
}, },
snackbarHost = { snackbarHostState -> snackbarHost = { snackbarHostState ->
StateHandler(DI.uiState, snackbarHostState) StateHandler(uiState, snackbarHostState)
SnackbarHost( SnackbarHost(
hostState = snackbarHostState hostState = snackbarHostState
@ -83,7 +87,7 @@ fun App() {
} }
) { scaffoldPadding -> ) { scaffoldPadding ->
Column(Modifier.fillMaxSize().padding(scaffoldPadding), horizontalAlignment = Alignment.CenterHorizontally) { Column(Modifier.fillMaxSize().padding(scaffoldPadding), horizontalAlignment = Alignment.CenterHorizontally) {
TransactionsList(DI.uiState) TransactionsList(uiState, uiSettings)
} }
} }
} }

View File

@ -1,10 +1,7 @@
package net.codinux.banking.ui.appskeleton package net.codinux.banking.ui.appskeleton
import androidx.compose.foundation.Image import androidx.compose.foundation.*
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.verticalScroll
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.automirrored.filled.Send import androidx.compose.material.icons.automirrored.filled.Send
@ -21,9 +18,9 @@ import bankmeister.composeapp.generated.resources.Res
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.codinux.banking.ui.composables.BanksList import net.codinux.banking.ui.composables.BanksList
import net.codinux.banking.ui.composables.NavigationMenuItem import net.codinux.banking.ui.composables.NavigationMenuItem
import net.codinux.banking.ui.composables.settings.UiSettings
import net.codinux.banking.ui.config.Colors import net.codinux.banking.ui.config.Colors
import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.config.DI
import net.codinux.banking.ui.model.BankAccountFilter
import org.jetbrains.compose.resources.imageResource import org.jetbrains.compose.resources.imageResource
private val uiState = DI.uiState private val uiState = DI.uiState
@ -48,7 +45,7 @@ private val itemModifier = Modifier.height(ItemHeight).widthIn(min = 350.dp)
private val iconSize = 24.dp private val iconSize = 24.dp
private val VerticalSpacing = 12.dp private val VerticalSpacing = 8.dp
@Composable @Composable
@ -118,14 +115,16 @@ fun SideMenu(appContent: @Composable () -> Unit) {
if (accounts.isNotEmpty()) { if (accounts.isNotEmpty()) {
Divider(color = Colors.DrawerDivider) Divider(color = Colors.DrawerDivider)
Spacer(Modifier.height(VerticalSpacing)) Column(Modifier.padding(16.dp)) {
UiSettings(Modifier.fillMaxWidth().padding(bottom = VerticalSpacing))
NavigationMenuItem(itemModifier, "Daten exportieren", textColor, horizontalPadding = ItemHorizontalPadding, icon = { Icon(Icons.AutoMirrored.Filled.Send, "Konto hinzufügen", Modifier.size(iconSize)) }) { NavigationMenuItem(itemModifier, "Daten exportieren", textColor, horizontalPadding = ItemHorizontalPadding, icon = { Icon(Icons.AutoMirrored.Filled.Send, "Konto hinzufügen", Modifier.size(iconSize)) }) {
coroutineScope.launch { coroutineScope.launch {
drawerState.close() drawerState.close()
}
uiState.showExportScreen.value = true
} }
uiState.showExportScreen.value = true
} }
} }
} }

View File

@ -0,0 +1,22 @@
package net.codinux.banking.ui.composables.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import net.codinux.banking.ui.config.DI
import net.codinux.banking.ui.forms.BooleanOption
@Composable
fun UiSettings(modifier: Modifier) {
val uiSettings = DI.uiSettings
val zebraStripes by uiSettings.zebraStripes.collectAsState()
Column(modifier) {
BooleanOption("Zebra Stripes", zebraStripes) { uiSettings.zebraStripes.value = it }
}
}

View File

@ -20,6 +20,7 @@ import net.codinux.banking.ui.config.Colors
import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.config.DI
import net.codinux.banking.ui.forms.RoundedCornersCard import net.codinux.banking.ui.forms.RoundedCornersCard
import net.codinux.banking.ui.model.AccountTransactionViewModel import net.codinux.banking.ui.model.AccountTransactionViewModel
import net.codinux.banking.ui.settings.UiSettings
private val calculator = DI.calculator private val calculator = DI.calculator
@ -29,13 +30,17 @@ private val formatUtil = DI.formatUtil
fun GroupedTransactionsListItems( fun GroupedTransactionsListItems(
modifier: Modifier, modifier: Modifier,
transactionsToDisplay: List<AccountTransactionViewModel>, transactionsToDisplay: List<AccountTransactionViewModel>,
userAccountsId: Map<Long, UserAccountEntity> userAccountsId: Map<Long, UserAccountEntity>,
uiSettings: UiSettings
) { ) {
val groupedByMonth by remember(transactionsToDisplay) { val groupedByMonth by remember(transactionsToDisplay) {
derivedStateOf { transactionsToDisplay.groupBy { LocalDate(it.valueDate.year, it.valueDate.monthNumber, 1) } } derivedStateOf { transactionsToDisplay.groupBy { LocalDate(it.valueDate.year, it.valueDate.monthNumber, 1) } }
} }
val zebraStripes by uiSettings.zebraStripes.collectAsState()
LazyColumn(modifier) { LazyColumn(modifier) {
items(groupedByMonth.keys.sortedDescending()) { month -> items(groupedByMonth.keys.sortedDescending()) { month ->
Column(Modifier.fillMaxWidth()) { Column(Modifier.fillMaxWidth()) {
@ -54,7 +59,7 @@ fun GroupedTransactionsListItems(
RoundedCornersCard { RoundedCornersCard {
Column(Modifier.background(Color.White)) { // LazyColumn inside LazyColumn is not allowed Column(Modifier.background(Color.White)) { // LazyColumn inside LazyColumn is not allowed
monthTransactions.forEachIndexed { index, transaction -> monthTransactions.forEachIndexed { index, transaction ->
val backgroundColor = if (index % 2 == 1) Colors.Zinc100_50 else Color.Transparent val backgroundColor = if (zebraStripes && index % 2 == 1) Colors.Zinc100_50 else Color.Transparent
TransactionListItem(userAccountsId[transaction.userAccountId], transaction, backgroundColor) TransactionListItem(userAccountsId[transaction.userAccountId], transaction, backgroundColor)
if (index < monthTransactions.size - 1) { if (index < monthTransactions.size - 1) {

View File

@ -10,6 +10,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import net.codinux.banking.ui.config.Colors import net.codinux.banking.ui.config.Colors
import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.config.DI
import net.codinux.banking.ui.settings.UiSettings
import net.codinux.banking.ui.state.UiState import net.codinux.banking.ui.state.UiState
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
@ -20,7 +21,7 @@ private val calculator = DI.calculator
private val formatUtil = DI.formatUtil private val formatUtil = DI.formatUtil
@Composable @Composable
fun TransactionsList(uiState: UiState) { fun TransactionsList(uiState: UiState, uiSettings: UiSettings) {
val userAccounts by uiState.userAccounts.collectAsState() val userAccounts by uiState.userAccounts.collectAsState()
val userAccountsId by remember(userAccounts) { val userAccountsId by remember(userAccounts) {
derivedStateOf { userAccounts.associateBy { it.id } } derivedStateOf { userAccounts.associateBy { it.id } }
@ -46,7 +47,7 @@ fun TransactionsList(uiState: UiState) {
Text(formatUtil.formatAmount(balance, "EUR"), color = formatUtil.getColorForAmount(balance)) Text(formatUtil.formatAmount(balance, "EUR"), color = formatUtil.getColorForAmount(balance))
} }
GroupedTransactionsListItems(transactionsListModifier, transactionsToDisplay, userAccountsId) GroupedTransactionsListItems(transactionsListModifier, transactionsToDisplay, userAccountsId, uiSettings)
} }
} }
@ -54,6 +55,6 @@ fun TransactionsList(uiState: UiState) {
@Composable @Composable
fun TransactionsListPreview() { fun TransactionsListPreview() {
MaterialTheme { MaterialTheme {
TransactionsList(UiState()) TransactionsList(UiState(), UiSettings())
} }
} }

View File

@ -7,12 +7,15 @@ import net.codinux.banking.dataaccess.SqliteBankingRepository
import net.codinux.banking.ui.Platform import net.codinux.banking.ui.Platform
import net.codinux.banking.ui.getPlatform import net.codinux.banking.ui.getPlatform
import net.codinux.banking.ui.service.* import net.codinux.banking.ui.service.*
import net.codinux.banking.ui.settings.UiSettings
import net.codinux.banking.ui.state.UiState import net.codinux.banking.ui.state.UiState
object DI { object DI {
val uiState = UiState() val uiState = UiState()
val uiSettings = UiSettings()
val platform: Platform = getPlatform() val platform: Platform = getPlatform()

View File

@ -0,0 +1,25 @@
package net.codinux.banking.ui.forms
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Switch
import androidx.compose.material.SwitchDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import net.codinux.banking.ui.config.Colors
@Composable
fun BooleanOption(label: String, isChecked: Boolean, enabled: Boolean = true, checkChanged: (Boolean) -> Unit) {
Row(verticalAlignment = Alignment.CenterVertically) {
Switch(checked = isChecked, onCheckedChange = checkChanged, enabled = enabled, colors = SwitchDefaults.colors(checkedThumbColor = Colors.CodinuxSecondaryColor))
Text(label, Modifier.fillMaxWidth().clickable { checkChanged(!!!isChecked) }.padding(start = 6.dp))
}
}

View File

@ -0,0 +1,10 @@
package net.codinux.banking.ui.settings
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
class UiSettings : ViewModel() {
val zebraStripes = MutableStateFlow(true)
}