Skip to content

Commit 697199d

Browse files
committed
chore(balance): always show header; update empty state to be properly centered
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 0ef9efe commit 697199d

2 files changed

Lines changed: 65 additions & 46 deletions

File tree

apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/BalanceScreenContent.kt

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ import androidx.compose.ui.platform.LocalContext
2121
import androidx.compose.ui.res.stringResource
2222
import androidx.compose.ui.text.style.TextAlign
2323
import androidx.compose.ui.tooling.preview.Preview
24+
import androidx.compose.ui.tooling.preview.PreviewWrapper
2425
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2526
import com.flipcash.app.balance.internal.components.BalanceHeader
2627
import com.flipcash.app.core.AppRoute
2728
import com.flipcash.app.core.tokens.TokenPurpose
2829
import com.flipcash.app.theme.FlipcashPreview
2930
import com.flipcash.app.tokens.ui.SelectTokenViewModel
3031
import com.flipcash.app.core.ui.rememberTokenBalanceRowStyling
32+
import com.flipcash.app.theme.FlipcashThemeWrapper
3133
import com.flipcash.app.tokens.ui.TokenList
3234
import com.flipcash.features.balance.R
3335
import com.getcode.opencode.compose.ExchangeStub
@@ -60,32 +62,39 @@ private fun BalanceScreenContent(
6062
) {
6163
Column {
6264
val tokens = remember(tokenState.tokens) { tokenState.tokens }
65+
val isEmpty = tokens.orEmpty().isEmpty()
66+
67+
val headerContent: @Composable () -> Unit = {
68+
BalanceHeader(
69+
modifier = Modifier
70+
.fillMaxWidth(),
71+
balance = tokenState.totalBalance,
72+
appreciation = tokenState.aggregateAppreciation,
73+
) {
74+
dispatchEvent(BalanceViewModel.Event.OpenCurrencySelection)
75+
}
76+
77+
Spacer(modifier = Modifier.padding(CodeTheme.dimens.grid.x2))
78+
}
6379

6480
TokenList(
6581
modifier = Modifier.weight(1f),
6682
itemModifier = { Modifier.animateItem(fadeInSpec = null) },
6783
styling = rememberTokenBalanceRowStyling(),
68-
header = {
69-
BalanceHeader(
70-
modifier = Modifier
71-
.fillMaxWidth(),
72-
balance = tokenState.totalBalance,
73-
appreciation = tokenState.aggregateAppreciation,
74-
) {
75-
dispatchEvent(BalanceViewModel.Event.OpenCurrencySelection)
76-
}
77-
78-
Spacer(modifier = Modifier.padding(CodeTheme.dimens.grid.x2))
79-
},
84+
// When empty, the header is rendered inside the empty state (pinned
85+
// to the top) so the prompt can be centered against the full
86+
// viewport. As a separate leading list item it would offset the
87+
// empty state down by the header's height.
88+
header = if (isEmpty) null else headerContent,
8089
emptyState = {
81-
Box(
82-
modifier = Modifier
83-
.fillParentMaxSize()
84-
.padding(bottom = CodeTheme.dimens.grid.x20),
85-
contentAlignment = Alignment.Center
86-
) {
90+
Box(modifier = Modifier.fillParentMaxSize()) {
91+
Column(modifier = Modifier.align(Alignment.TopCenter)) {
92+
headerContent()
93+
}
94+
8795
Column(
8896
modifier = Modifier
97+
.align(Alignment.Center)
8998
.fillMaxWidth()
9099
.padding(horizontal = CodeTheme.dimens.inset),
91100
verticalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x2),
@@ -129,20 +138,30 @@ private fun BalanceScreenContent(
129138
}
130139
},
131140
pinFooter = true,
132-
footer = if (tokenState.discoveryEnabled) {
141+
footer = if (tokenState.totalBalance?.nativeAmount?.hasDisplayableValue == true) {
133142
{
134143
CodeButton(
135144
modifier = Modifier
136145
.fillMaxWidth()
137146
.padding(horizontal = CodeTheme.dimens.inset)
138147
.padding(bottom = CodeTheme.dimens.grid.x3)
139148
.navigationBarsPadding(),
140-
text = stringResource(R.string.action_discoverCurrencies),
149+
text = if (addMoneyUx) {
150+
stringResource(R.string.action_addMoney)
151+
} else {
152+
stringResource(R.string.action_discoverCurrencies)
153+
},
141154
buttonState = ButtonState.Filled10,
142155
onClick = {
143-
dispatchEvent(
144-
BalanceViewModel.Event.OpenScreen(AppRoute.Token.Discovery)
145-
)
156+
if (addMoneyUx) {
157+
dispatchEvent(
158+
BalanceViewModel.Event.PresentDepositOptions
159+
)
160+
} else {
161+
dispatchEvent(
162+
BalanceViewModel.Event.OpenScreen(AppRoute.Token.Discovery)
163+
)
164+
}
146165
}
147166
)
148167
}
@@ -163,27 +182,27 @@ private val cadUsdRate = Rate(fx = 1.371881, currency = CurrencyCode.CAD)
163182
private val usdCadRate = Rate(fx = 1.0 / 1.371881, currency = CurrencyCode.CAD)
164183

165184
@Preview
185+
@PreviewWrapper(FlipcashThemeWrapper::class)
166186
@Composable
167187
private fun Preview_BalanceScreen_Empty() {
168-
FlipcashPreview {
169-
CompositionLocalProvider(
170-
LocalExchange provides ExchangeStub(
171-
providedRates = mapOf(
172-
CurrencyCode.CAD to cadUsdRate,
173-
CurrencyCode.USD to usdCadRate
174-
),
175-
context = LocalContext.current
188+
CompositionLocalProvider(
189+
LocalExchange provides ExchangeStub(
190+
providedRates = mapOf(
191+
CurrencyCode.CAD to cadUsdRate,
192+
CurrencyCode.USD to usdCadRate
176193
),
177-
) {
178-
Box(modifier = Modifier.background(CodeTheme.colors.background)) {
179-
BalanceScreenContent(
180-
tokenState = SelectTokenViewModel.State(
181-
purpose = TokenPurpose.Balance,
182-
tokens = emptyList()
183-
),
184-
dispatchEvent = {}
185-
)
186-
}
194+
context = LocalContext.current
195+
),
196+
) {
197+
Box(modifier = Modifier.background(CodeTheme.colors.background)) {
198+
BalanceScreenContent(
199+
addMoneyUx = true,
200+
tokenState = SelectTokenViewModel.State(
201+
purpose = TokenPurpose.Balance,
202+
tokens = emptyList()
203+
),
204+
dispatchEvent = {}
205+
)
187206
}
188207
}
189208
}

apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenList.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,16 @@ fun TokenList(
8181
.sheetResignmentBehavior(listState),
8282
state = listState
8383
) {
84+
header?.let { content ->
85+
item(contentType = "header") {
86+
content()
87+
}
88+
}
8489
if (tokens != null && tokens.isEmpty() && emptyState != null) {
8590
item(contentType = "empty_state") {
8691
emptyState()
8792
}
8893
} else {
89-
header?.let { content ->
90-
item(contentType = "header") {
91-
content()
92-
}
93-
}
9494
items(
9595
items = filteredTokens.orEmpty(),
9696
key = { item -> item.token.address.base58() },

0 commit comments

Comments
 (0)