Implemented show floating action menu with options Add account and New money transfer
This commit is contained in:
parent
18ea0e35f1
commit
7275d60f82
|
@ -0,0 +1,99 @@
|
|||
package net.codinux.banking.ui.appskeleton
|
||||
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import net.codinux.banking.ui.config.DI
|
||||
import net.codinux.banking.ui.config.Style.FabMenuSpacing
|
||||
import net.codinux.banking.ui.config.Style.FabSize
|
||||
import net.codinux.banking.ui.config.Style.SmallFabSize
|
||||
import net.codinux.banking.ui.model.ShowTransferMoneyDialogData
|
||||
|
||||
|
||||
private val uiState = DI.uiState
|
||||
|
||||
@Composable
|
||||
fun FloatingActionMenu(
|
||||
showFloatingActionMenu: Boolean,
|
||||
menuItemClicked: () -> Unit
|
||||
) {
|
||||
|
||||
val fabVisibilityAnimation = animateFloatAsState(targetValue = if (showFloatingActionMenu) 1f else 0f)
|
||||
|
||||
val bottomPadding = FabSize + FabSize / 2
|
||||
|
||||
val accountsThatSupportMoneyTransfer = uiState.accountsThatSupportMoneyTransfer.collectAsState().value
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
|
||||
fun handleClick(action: () -> Unit) {
|
||||
menuItemClicked()
|
||||
|
||||
coroutineScope.launch {
|
||||
delay(50)
|
||||
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fabVisibilityAnimation.value > 0) {
|
||||
Box(Modifier.fillMaxSize().padding(bottom = bottomPadding, end = 12.dp), contentAlignment = Alignment.BottomEnd) {
|
||||
Column(Modifier, horizontalAlignment = Alignment.End) {
|
||||
FloatingActionMenuItem("Überweisung", "Neue Überweisung", enabled = accountsThatSupportMoneyTransfer.isNotEmpty()) {
|
||||
handleClick {
|
||||
uiState.showTransferMoneyDialogData.value = ShowTransferMoneyDialogData()
|
||||
}
|
||||
}
|
||||
|
||||
FloatingActionMenuItem("Konto", "Neues Konto hinzufügen") {
|
||||
handleClick {
|
||||
uiState.showAddAccountDialog.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FloatingActionMenuItem(
|
||||
label: String,
|
||||
contentDescription: String,
|
||||
enabled: Boolean = true,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(bottom = FabMenuSpacing).clickable(enabled) { onClick() }) {
|
||||
Text(label, fontSize = 16.sp, color = contentColorFor(MaterialTheme.colors.secondary).copy(if (enabled) 1f else ContentAlpha.disabled), modifier = Modifier.padding(end = 8.dp).background(MaterialTheme.colors.secondary).shadow(20.dp).padding(horizontal = 20.dp, vertical = 4.dp)) // the same background color as the FAB
|
||||
|
||||
FloatingActionButton(
|
||||
shape = CircleShape,
|
||||
elevation = FloatingActionButtonDefaults.elevation(defaultElevation = 20.dp),
|
||||
modifier = Modifier.padding(end = (FabSize - SmallFabSize) / 2).size(SmallFabSize),
|
||||
onClick = {
|
||||
if (enabled) {
|
||||
onClick()
|
||||
}
|
||||
}
|
||||
) {
|
||||
Icon(Icons.Filled.Add, contentDescription = contentDescription, tint = LocalContentColor.current.copy(if (enabled) LocalContentAlpha.current else ContentAlpha.disabled))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,7 +56,9 @@ private val VerticalSpacing = 8.dp
|
|||
fun SideMenuContent() {
|
||||
val drawerState = uiState.drawerState.collectAsState().value
|
||||
|
||||
val accounts = uiState.banks.collectAsState().value
|
||||
val accounts = uiState.accounts.collectAsState().value
|
||||
|
||||
val accountsThatSupportMoneyTransfer = uiState.accountsThatSupportMoneyTransfer.collectAsState().value
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
|
@ -97,7 +99,7 @@ fun SideMenuContent() {
|
|||
}
|
||||
}
|
||||
|
||||
if (accounts.isNotEmpty()) {
|
||||
if (accountsThatSupportMoneyTransfer.isNotEmpty()) {
|
||||
Spacer(Modifier.height(VerticalSpacing))
|
||||
|
||||
NavigationMenuItem(itemModifier, "Neue Überweisung", textColor, horizontalPadding = ItemHorizontalPadding,
|
||||
|
|
|
@ -19,6 +19,15 @@ object Style {
|
|||
val ListItemHeaderWeight = FontWeight.Medium // couldn't believe it, the FontWeights look different on Desktop and Android
|
||||
|
||||
|
||||
val FabSize = 56.dp
|
||||
|
||||
val SmallFabSize = 46.dp
|
||||
|
||||
val FabSpacing = 16.dp
|
||||
|
||||
val FabMenuSpacing = FabSpacing / 2
|
||||
|
||||
|
||||
val DividerThickness = 1.dp
|
||||
|
||||
}
|
|
@ -42,8 +42,7 @@ fun TransferMoneyDialog(
|
|||
val accountsToBank = banks.sortedBy { it.displayIndex }
|
||||
.flatMap { bank -> bank.accountsSorted.map { it to bank } }.toMap()
|
||||
|
||||
val accountsSupportingTransferringMoney = banks.flatMap { it.accounts }
|
||||
.filter { it.supportsMoneyTransfer }
|
||||
val accountsSupportingTransferringMoney = uiState.accountsThatSupportMoneyTransfer.collectAsState().value
|
||||
|
||||
if (accountsSupportingTransferringMoney.isEmpty()) {
|
||||
uiState.applicationErrorOccurred(ErroneousAction.TransferMoney, "Keines Ihrer Konten unterstützt das Überweisen von Geld")
|
||||
|
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.shape.CircleShape
|
|||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
@ -30,6 +31,8 @@ fun MainScreen() {
|
|||
val fabPositionAdjustment = if (isMobile) 44.dp // FabSpacing = 16.dp + FAB height (= 56.dp) / 2
|
||||
else (-10).dp
|
||||
|
||||
var showFloatingActionMenu by remember { mutableStateOf(false) }
|
||||
|
||||
val desktopDrawerWidth = 350.dp
|
||||
|
||||
val uiState = DI.uiState
|
||||
|
@ -51,9 +54,13 @@ fun MainScreen() {
|
|||
FloatingActionButton(
|
||||
shape = CircleShape,
|
||||
modifier = Modifier.offset(x = 4.dp, y = fabPositionAdjustment),
|
||||
onClick = { uiState.showAddAccountDialog.value = true }
|
||||
onClick = { showFloatingActionMenu = !showFloatingActionMenu }
|
||||
) {
|
||||
Icon(Icons.Filled.Add, contentDescription = "Add a bank account")
|
||||
if (showFloatingActionMenu) {
|
||||
Icon(Icons.Filled.Close, contentDescription = "Menü zum Hinzufügen eines Kontos, für eine neue Überweisung, ... verstecken")
|
||||
} else {
|
||||
Icon(Icons.Filled.Add, contentDescription = "Zeigt ein Menü zum Hinzufügen eines Kontos, für eine neue Überweisung, ... an")
|
||||
}
|
||||
}
|
||||
},
|
||||
drawerContent = { if (isMobile) SideMenuContent() else null },
|
||||
|
@ -85,6 +92,9 @@ fun MainScreen() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
FloatingActionMenu(showFloatingActionMenu) { showFloatingActionMenu = false }
|
||||
|
||||
if (showFilterBar.value) {
|
||||
FilterBar()
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package net.codinux.banking.ui.state
|
|||
import androidx.compose.material.DrawerState
|
||||
import androidx.compose.material.DrawerValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
import net.codinux.banking.client.model.tan.EnterTanResult
|
||||
import net.codinux.banking.client.model.tan.TanChallenge
|
||||
import net.codinux.banking.persistence.entities.HoldingEntity
|
||||
|
@ -25,6 +25,18 @@ class UiState : ViewModel() {
|
|||
|
||||
val banks = MutableStateFlow<List<BankAccessEntity>>(emptyList())
|
||||
|
||||
val accounts = banks.map { it.flatMap { it.accounts } }.stateIn(
|
||||
scope = this.viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = emptyList()
|
||||
)
|
||||
|
||||
val accountsThatSupportMoneyTransfer = accounts.map { it.filter { it.supportsMoneyTransfer } }.stateIn(
|
||||
scope = this.viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = emptyList()
|
||||
)
|
||||
|
||||
val transactions = MutableStateFlow<List<AccountTransactionViewModel>>(emptyList())
|
||||
|
||||
val holdings = MutableStateFlow<List<HoldingEntity>>(emptyList())
|
||||
|
|
Loading…
Reference in New Issue