diff --git a/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/BalanceScreenContent.kt b/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/BalanceScreenContent.kt index fed38939d..a3efa7b35 100644 --- a/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/BalanceScreenContent.kt +++ b/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/BalanceScreenContent.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewWrapper import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.flipcash.app.balance.internal.components.BalanceHeader import com.flipcash.app.core.AppRoute @@ -28,6 +29,7 @@ import com.flipcash.app.core.tokens.TokenPurpose import com.flipcash.app.theme.FlipcashPreview import com.flipcash.app.tokens.ui.SelectTokenViewModel import com.flipcash.app.core.ui.rememberTokenBalanceRowStyling +import com.flipcash.app.theme.FlipcashThemeWrapper import com.flipcash.app.tokens.ui.TokenList import com.flipcash.features.balance.R import com.getcode.opencode.compose.ExchangeStub @@ -60,32 +62,39 @@ private fun BalanceScreenContent( ) { Column { val tokens = remember(tokenState.tokens) { tokenState.tokens } + val isEmpty = tokens.orEmpty().isEmpty() + + val headerContent: @Composable () -> Unit = { + BalanceHeader( + modifier = Modifier + .fillMaxWidth(), + balance = tokenState.totalBalance, + appreciation = tokenState.aggregateAppreciation, + ) { + dispatchEvent(BalanceViewModel.Event.OpenCurrencySelection) + } + + Spacer(modifier = Modifier.padding(CodeTheme.dimens.grid.x2)) + } TokenList( modifier = Modifier.weight(1f), itemModifier = { Modifier.animateItem(fadeInSpec = null) }, styling = rememberTokenBalanceRowStyling(), - header = { - BalanceHeader( - modifier = Modifier - .fillMaxWidth(), - balance = tokenState.totalBalance, - appreciation = tokenState.aggregateAppreciation, - ) { - dispatchEvent(BalanceViewModel.Event.OpenCurrencySelection) - } - - Spacer(modifier = Modifier.padding(CodeTheme.dimens.grid.x2)) - }, + // When empty, the header is rendered inside the empty state (pinned + // to the top) so the prompt can be centered against the full + // viewport. As a separate leading list item it would offset the + // empty state down by the header's height. + header = if (isEmpty) null else headerContent, emptyState = { - Box( - modifier = Modifier - .fillParentMaxSize() - .padding(bottom = CodeTheme.dimens.grid.x20), - contentAlignment = Alignment.Center - ) { + Box(modifier = Modifier.fillParentMaxSize()) { + Column(modifier = Modifier.align(Alignment.TopCenter)) { + headerContent() + } + Column( modifier = Modifier + .align(Alignment.Center) .fillMaxWidth() .padding(horizontal = CodeTheme.dimens.inset), verticalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x2), @@ -129,7 +138,7 @@ private fun BalanceScreenContent( } }, pinFooter = true, - footer = if (tokenState.discoveryEnabled) { + footer = if (tokenState.totalBalance?.nativeAmount?.hasDisplayableValue == true) { { CodeButton( modifier = Modifier @@ -137,12 +146,22 @@ private fun BalanceScreenContent( .padding(horizontal = CodeTheme.dimens.inset) .padding(bottom = CodeTheme.dimens.grid.x3) .navigationBarsPadding(), - text = stringResource(R.string.action_discoverCurrencies), + text = if (addMoneyUx) { + stringResource(R.string.action_addMoney) + } else { + stringResource(R.string.action_discoverCurrencies) + }, buttonState = ButtonState.Filled10, onClick = { - dispatchEvent( - BalanceViewModel.Event.OpenScreen(AppRoute.Token.Discovery) - ) + if (addMoneyUx) { + dispatchEvent( + BalanceViewModel.Event.PresentDepositOptions + ) + } else { + dispatchEvent( + BalanceViewModel.Event.OpenScreen(AppRoute.Token.Discovery) + ) + } } ) } @@ -163,27 +182,27 @@ private val cadUsdRate = Rate(fx = 1.371881, currency = CurrencyCode.CAD) private val usdCadRate = Rate(fx = 1.0 / 1.371881, currency = CurrencyCode.CAD) @Preview +@PreviewWrapper(FlipcashThemeWrapper::class) @Composable private fun Preview_BalanceScreen_Empty() { - FlipcashPreview { - CompositionLocalProvider( - LocalExchange provides ExchangeStub( - providedRates = mapOf( - CurrencyCode.CAD to cadUsdRate, - CurrencyCode.USD to usdCadRate - ), - context = LocalContext.current + CompositionLocalProvider( + LocalExchange provides ExchangeStub( + providedRates = mapOf( + CurrencyCode.CAD to cadUsdRate, + CurrencyCode.USD to usdCadRate ), - ) { - Box(modifier = Modifier.background(CodeTheme.colors.background)) { - BalanceScreenContent( - tokenState = SelectTokenViewModel.State( - purpose = TokenPurpose.Balance, - tokens = emptyList() - ), - dispatchEvent = {} - ) - } + context = LocalContext.current + ), + ) { + Box(modifier = Modifier.background(CodeTheme.colors.background)) { + BalanceScreenContent( + addMoneyUx = true, + tokenState = SelectTokenViewModel.State( + purpose = TokenPurpose.Balance, + tokens = emptyList() + ), + dispatchEvent = {} + ) } } } \ No newline at end of file diff --git a/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenList.kt b/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenList.kt index 90fe9ab50..c6f6a1039 100644 --- a/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenList.kt +++ b/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenList.kt @@ -81,16 +81,16 @@ fun TokenList( .sheetResignmentBehavior(listState), state = listState ) { + header?.let { content -> + item(contentType = "header") { + content() + } + } if (tokens != null && tokens.isEmpty() && emptyState != null) { item(contentType = "empty_state") { emptyState() } } else { - header?.let { content -> - item(contentType = "header") { - content() - } - } items( items = filteredTokens.orEmpty(), key = { item -> item.token.address.base58() },