Skip to content

Commit c47a1f9

Browse files
authored
Merge pull request #264 from synonymdev/refactor/state-handling-improvement
SpendingAmountScreen state handling improvement
2 parents 43b52b6 + 308b644 commit c47a1f9

File tree

4 files changed

+249
-112
lines changed

4 files changed

+249
-112
lines changed

app/src/main/java/to/bitkit/ui/ContentView.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import kotlinx.coroutines.launch
3232
import kotlinx.serialization.Serializable
3333
import to.bitkit.models.NewTransactionSheetDetails
3434
import to.bitkit.models.NodeLifecycleState
35+
import to.bitkit.models.Toast
3536
import to.bitkit.models.WidgetType
3637
import to.bitkit.ui.components.AuthCheckScreen
3738
import to.bitkit.ui.components.BottomSheetType
@@ -494,6 +495,14 @@ private fun RootNavHost(
494495
onBackClick = { navController.popBackStack() },
495496
onCloseClick = { navController.navigateToHome() },
496497
onOrderCreated = { navController.navigate(Routes.SpendingConfirm) },
498+
toastException = { appViewModel.toast(it) },
499+
toast = { title, description ->
500+
appViewModel.toast(
501+
type = Toast.ToastType.ERROR,
502+
title = title,
503+
description = description
504+
)
505+
},
497506
)
498507
}
499508
composableWithDefaultTransitions<Routes.SpendingConfirm> {

app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt

Lines changed: 79 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -12,57 +12,84 @@ import androidx.compose.material3.HorizontalDivider
1212
import androidx.compose.runtime.Composable
1313
import androidx.compose.runtime.LaunchedEffect
1414
import androidx.compose.runtime.getValue
15-
import androidx.compose.runtime.mutableLongStateOf
16-
import androidx.compose.runtime.mutableStateOf
17-
import androidx.compose.runtime.remember
18-
import androidx.compose.runtime.rememberCoroutineScope
19-
import androidx.compose.runtime.saveable.rememberSaveable
20-
import androidx.compose.runtime.setValue
2115
import androidx.compose.ui.Alignment
2216
import androidx.compose.ui.Modifier
23-
import androidx.compose.ui.platform.LocalContext
2417
import androidx.compose.ui.res.stringResource
18+
import androidx.compose.ui.tooling.preview.Preview
2519
import androidx.compose.ui.unit.dp
2620
import androidx.lifecycle.compose.collectAsStateWithLifecycle
27-
import kotlinx.coroutines.launch
2821
import to.bitkit.R
29-
import to.bitkit.models.Toast
30-
import to.bitkit.ui.LocalBalances
3122
import to.bitkit.ui.LocalCurrencies
32-
import to.bitkit.ui.appViewModel
33-
import to.bitkit.ui.blocktankViewModel
3423
import to.bitkit.ui.components.AmountInput
3524
import to.bitkit.ui.components.Display
25+
import to.bitkit.ui.components.FillHeight
26+
import to.bitkit.ui.components.FillWidth
3627
import to.bitkit.ui.components.MoneySSB
3728
import to.bitkit.ui.components.NumberPadActionButton
3829
import to.bitkit.ui.components.PrimaryButton
3930
import to.bitkit.ui.components.Text13Up
4031
import to.bitkit.ui.components.UnitButton
32+
import to.bitkit.ui.components.VerticalSpacer
4133
import to.bitkit.ui.scaffold.AppTopBar
4234
import to.bitkit.ui.scaffold.CloseNavIcon
4335
import to.bitkit.ui.scaffold.ScreenColumn
36+
import to.bitkit.ui.theme.AppThemeSurface
4437
import to.bitkit.ui.theme.Colors
4538
import to.bitkit.ui.utils.withAccent
46-
import to.bitkit.utils.Logger
39+
import to.bitkit.viewmodels.CurrencyUiState
40+
import to.bitkit.viewmodels.TransferEffect
41+
import to.bitkit.viewmodels.TransferToSpendingUiState
4742
import to.bitkit.viewmodels.TransferViewModel
48-
import kotlin.math.max
49-
import kotlin.math.min
50-
import kotlin.math.roundToLong
5143

5244
@Composable
5345
fun SpendingAmountScreen(
5446
viewModel: TransferViewModel,
5547
onBackClick: () -> Unit = {},
5648
onCloseClick: () -> Unit = {},
5749
onOrderCreated: () -> Unit = {},
50+
toastException: (Throwable) -> Unit,
51+
toast: (title: String, description: String) -> Unit,
5852
) {
59-
val scope = rememberCoroutineScope()
60-
val app = appViewModel ?: return
61-
val blocktank = blocktankViewModel ?: return
6253
val currencies = LocalCurrencies.current
63-
val resources = LocalContext.current.resources
64-
val transferValues by viewModel.transferValues.collectAsStateWithLifecycle()
54+
val uiState by viewModel.spendingUiState.collectAsStateWithLifecycle()
6555

56+
LaunchedEffect(Unit) {
57+
viewModel.updateLimits(retry = true)
58+
}
59+
60+
LaunchedEffect(Unit) {
61+
viewModel.transferEffects.collect { effect ->
62+
when (effect) {
63+
TransferEffect.OnOrderCreated -> onOrderCreated()
64+
is TransferEffect.ToastError -> toast(effect.title, effect.description)
65+
is TransferEffect.ToastException -> toastException(effect.e)
66+
}
67+
}
68+
}
69+
70+
Content(
71+
uiState = uiState,
72+
currencies = currencies,
73+
onBackClick = onBackClick,
74+
onCloseClick = onCloseClick,
75+
onClickQuarter = viewModel::onClickQuarter,
76+
onClickMaxAmount = viewModel::onClickMaxAmount,
77+
onConfirmAmount = viewModel::onConfirmAmount,
78+
onAmountChanged = viewModel::onAmountChanged
79+
)
80+
}
81+
82+
@Composable
83+
private fun Content(
84+
uiState: TransferToSpendingUiState,
85+
currencies: CurrencyUiState,
86+
onBackClick: () -> Unit,
87+
onCloseClick: () -> Unit,
88+
onClickQuarter: () -> Unit,
89+
onClickMaxAmount: () -> Unit,
90+
onConfirmAmount: () -> Unit,
91+
onAmountChanged: (Long) -> Unit,
92+
) {
6693
ScreenColumn {
6794
AppTopBar(
6895
titleText = stringResource(R.string.lightning__transfer__nav_title),
@@ -75,56 +102,20 @@ fun SpendingAmountScreen(
75102
.fillMaxSize()
76103
.imePadding()
77104
) {
78-
var satsAmount by rememberSaveable { mutableLongStateOf(0) }
79-
var overrideSats: Long? by remember { mutableStateOf(null) }
80-
var isLoading by remember { mutableStateOf(false) }
81-
82-
val availableAmount = LocalBalances.current.totalOnchainSats - 512u // default tx fee
83-
var maxLspFee by remember { mutableStateOf(0uL) }
84-
85-
val feeMaximum = max(0, availableAmount.toLong() - maxLspFee.toLong())
86-
val maximum = min(
87-
transferValues.maxClientBalance.toLong(),
88-
feeMaximum
89-
) // TODO USE MAX AVAILABLE TO TRANSFER INSTEAD OF MAX ONCHAIN BALANCE
90-
91-
// Update maxClientBalance Effect
92-
LaunchedEffect(satsAmount) {
93-
viewModel.updateTransferValues(satsAmount.toULong())
94-
Logger.debug(
95-
"satsAmount changed - maxClientBalance: ${transferValues.maxClientBalance}",
96-
context = "SpendingAmountScreen"
97-
)
98-
}
99-
100-
// Update maxLspFee Effect
101-
LaunchedEffect(availableAmount, transferValues.maxLspBalance) { // TODO MOVE TO VIEWMODEL
102-
runCatching {
103-
val estimate = blocktank.estimateOrderFee(
104-
spendingBalanceSats = availableAmount,
105-
receivingBalanceSats = transferValues.maxLspBalance,
106-
)
107-
maxLspFee = estimate.feeSat
108-
}
109-
}
110-
111-
Spacer(modifier = Modifier.height(32.dp))
105+
VerticalSpacer(32.dp)
112106
Display(
113107
text = stringResource(R.string.lightning__spending_amount__title)
114108
.withAccent(accentColor = Colors.Purple)
115109
)
116-
Spacer(modifier = Modifier.height(32.dp))
110+
VerticalSpacer(32.dp)
117111

118112
AmountInput(
119113
primaryDisplay = currencies.primaryDisplay,
120-
overrideSats = overrideSats,
121-
onSatsChange = { sats ->
122-
satsAmount = sats
123-
overrideSats = null
124-
},
114+
overrideSats = uiState.overrideSats,
115+
onSatsChange = onAmountChanged,
125116
)
126117

127-
Spacer(modifier = Modifier.weight(1f))
118+
FillHeight()
128119

129120
// Actions
130121
Row(
@@ -138,64 +129,51 @@ fun SpendingAmountScreen(
138129
color = Colors.White64,
139130
)
140131
Spacer(modifier = Modifier.height(8.dp))
141-
MoneySSB(sats = availableAmount.toLong())
132+
MoneySSB(sats = uiState.balanceAfterFee)
142133
}
143-
Spacer(modifier = Modifier.weight(1f))
134+
FillWidth()
144135
UnitButton(color = Colors.Purple)
145136
// 25% Button
146137
NumberPadActionButton(
147138
text = stringResource(R.string.lightning__spending_amount__quarter),
148139
color = Colors.Purple,
149-
onClick = {
150-
val quarter = (availableAmount.toDouble() / 4.0).roundToLong()
151-
val amount = min(quarter, maximum)
152-
overrideSats = amount
153-
},
140+
onClick = onClickQuarter,
154141
)
155142
// Max Button
156143
NumberPadActionButton(
157144
text = stringResource(R.string.common__max),
158145
color = Colors.Purple,
159-
onClick = {
160-
overrideSats = maximum
161-
},
146+
onClick = onClickMaxAmount,
162147
)
163148
}
164149
HorizontalDivider()
165-
Spacer(modifier = Modifier.height(16.dp))
150+
VerticalSpacer(16.dp)
166151

167152
PrimaryButton(
168153
text = stringResource(R.string.common__continue),
169-
onClick = {
170-
if (transferValues.maxLspBalance == 0uL) {
171-
app.toast(
172-
type = Toast.ToastType.ERROR,
173-
title = resources.getString(R.string.lightning__spending_amount__error_max__title),
174-
description = resources.getString(
175-
R.string.lightning__spending_amount__error_max__description_zero
176-
),
177-
)
178-
return@PrimaryButton
179-
}
180-
181-
isLoading = true
182-
scope.launch {
183-
try {
184-
val order = blocktank.createOrder(satsAmount.toULong())
185-
viewModel.onOrderCreated(order)
186-
onOrderCreated()
187-
} catch (e: Throwable) {
188-
app.toast(e)
189-
} finally {
190-
isLoading = false
191-
}
192-
}
193-
},
194-
enabled = !isLoading && satsAmount != 0L,
195-
isLoading = isLoading,
154+
onClick = onConfirmAmount,
155+
enabled = uiState.satsAmount != 0L && uiState.satsAmount <= uiState.maxAllowedToSend,
156+
isLoading = uiState.isLoading,
196157
)
197158

198-
Spacer(modifier = Modifier.height(16.dp))
159+
VerticalSpacer(16.dp)
199160
}
200161
}
201162
}
163+
164+
@Preview(showBackground = true)
165+
@Composable
166+
private fun Preview() {
167+
AppThemeSurface {
168+
Content(
169+
uiState = TransferToSpendingUiState(),
170+
currencies = CurrencyUiState(),
171+
onBackClick = {},
172+
onCloseClick = {},
173+
onClickQuarter = {},
174+
onClickMaxAmount = {},
175+
onConfirmAmount = {},
176+
onAmountChanged = {},
177+
)
178+
}
179+
}

app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fun SpendingConfirmScreen(
7777
onAdvancedClick = onAdvancedClick,
7878
onConfirm = onConfirm,
7979
onUseDefaultLspBalanceClick = { viewModel.onUseDefaultLspBalanceClick() },
80-
onTransferToSpendingConfirm = { order -> order },
80+
onTransferToSpendingConfirm = { order -> viewModel.onTransferToSpendingConfirm(order) },
8181
order = order,
8282
isAdvanced = isAdvanced
8383
)

0 commit comments

Comments
 (0)