diff --git a/app/src/main/java/to/bitkit/ui/ContentView.kt b/app/src/main/java/to/bitkit/ui/ContentView.kt index 96188dbf9..118d73a2e 100644 --- a/app/src/main/java/to/bitkit/ui/ContentView.kt +++ b/app/src/main/java/to/bitkit/ui/ContentView.kt @@ -89,7 +89,6 @@ import to.bitkit.ui.screens.transfer.TransferIntroScreen import to.bitkit.ui.screens.transfer.external.ExternalAmountScreen import to.bitkit.ui.screens.transfer.external.ExternalConfirmScreen import to.bitkit.ui.screens.transfer.external.ExternalConnectionScreen -import to.bitkit.ui.screens.transfer.external.ExternalFeeCustomScreen import to.bitkit.ui.screens.transfer.external.ExternalNodeViewModel import to.bitkit.ui.screens.transfer.external.ExternalSuccessScreen import to.bitkit.ui.screens.transfer.external.LnurlChannelScreen @@ -735,7 +734,6 @@ private fun RootNavHost( walletViewModel.refreshState() navController.navigate(Routes.ExternalSuccess) }, - onNetworkFeeClick = { navController.navigate(Routes.ExternalFeeCustom) }, onBackClick = { navController.popBackStack() }, ) } @@ -752,15 +750,6 @@ private fun RootNavHost( onContinue = { navController.popBackStack(inclusive = true) }, ) } - composableWithDefaultTransitions { - val parentEntry = remember(it) { navController.getBackStackEntry(Routes.ExternalNav) } - val viewModel = hiltViewModel(parentEntry) - - ExternalFeeCustomScreen( - viewModel = viewModel, - onBack = { navController.popBackStack() }, - ) - } } } } @@ -1913,9 +1902,6 @@ sealed interface Routes { @Serializable data object ExternalSuccess : Routes - @Serializable - data object ExternalFeeCustom : Routes - @Serializable data class LnurlChannel(val uri: String, val callback: String, val k1: String) : Routes diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt index 9fd0426b5..4e64dd7a6 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt @@ -1,47 +1,36 @@ package to.bitkit.ui.screens.transfer.external -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import to.bitkit.R -import to.bitkit.ui.components.Caption13Up import to.bitkit.ui.components.Display import to.bitkit.ui.components.FeeInfo -import to.bitkit.ui.components.MoneySSB import to.bitkit.ui.components.SwipeToConfirm import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.DrawerNavIcon import to.bitkit.ui.scaffold.ScreenColumn import to.bitkit.ui.screens.transfer.external.ExternalNodeContract.SideEffect -import to.bitkit.ui.shared.modifiers.clickableAlpha import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import to.bitkit.ui.utils.withAccent @@ -50,7 +39,6 @@ import to.bitkit.ui.utils.withAccent fun ExternalConfirmScreen( viewModel: ExternalNodeViewModel, onConfirm: () -> Unit, - onNetworkFeeClick: () -> Unit, onBackClick: () -> Unit, ) { val uiState by viewModel.uiState.collectAsState() @@ -67,7 +55,6 @@ fun ExternalConfirmScreen( Content( uiState = uiState, onConfirm = viewModel::onConfirm, - onNetworkFeeClick = onNetworkFeeClick, onBackClick = onBackClick, ) } @@ -76,7 +63,6 @@ fun ExternalConfirmScreen( private fun Content( uiState: ExternalNodeContract.UiState, onConfirm: () -> Unit = {}, - onNetworkFeeClick: () -> Unit = {}, onBackClick: () -> Unit = {}, ) { ScreenColumn { @@ -103,32 +89,10 @@ private fun Content( horizontalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.height(IntrinsicSize.Min) ) { - Column( - modifier = Modifier - .fillMaxHeight() - .weight(1f) - .padding(top = 16.dp) - .clickableAlpha(onClick = onNetworkFeeClick) - .testTag("SetCustomFee") - ) { - Caption13Up( - text = stringResource(R.string.lightning__spending_confirm__network_fee), - color = Colors.White64, - ) - Spacer(modifier = Modifier.height(8.dp)) - - AnimatedVisibility(visible = networkFee > 0L, enter = fadeIn(), exit = fadeOut()) { - Row(verticalAlignment = Alignment.CenterVertically) { - MoneySSB(sats = networkFee) - Spacer(modifier = Modifier.width(4.dp)) - Icon( - painterResource(R.drawable.ic_pencil_simple), - contentDescription = null, - modifier = Modifier.size(16.dp) - ) - } - } - } + FeeInfo( + label = stringResource(R.string.lightning__spending_confirm__network_fee), + amount = networkFee, + ) FeeInfo( label = stringResource(R.string.lightning__spending_confirm__lsp_fee), amount = serviceFee, diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalFeeCustomScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalFeeCustomScreen.kt deleted file mode 100644 index f2cd73f25..000000000 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalFeeCustomScreen.kt +++ /dev/null @@ -1,187 +0,0 @@ -package to.bitkit.ui.screens.transfer.external - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.testTag -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import kotlinx.coroutines.launch -import to.bitkit.R -import to.bitkit.models.BITCOIN_SYMBOL -import to.bitkit.models.Toast -import to.bitkit.ui.components.BodyM -import to.bitkit.ui.components.Caption13Up -import to.bitkit.ui.components.Display -import to.bitkit.ui.components.FillHeight -import to.bitkit.ui.components.KEY_DELETE -import to.bitkit.ui.components.LargeRow -import to.bitkit.ui.components.NumberPad -import to.bitkit.ui.components.NumberPadType -import to.bitkit.ui.components.PrimaryButton -import to.bitkit.ui.components.VerticalSpacer -import to.bitkit.ui.currencyViewModel -import to.bitkit.ui.scaffold.AppTopBar -import to.bitkit.ui.scaffold.DrawerNavIcon -import to.bitkit.ui.scaffold.ScreenColumn -import to.bitkit.ui.shared.toast.ToastEventBus -import to.bitkit.ui.theme.AppThemeSurface -import to.bitkit.ui.theme.Colors -import to.bitkit.ui.utils.withAccent - -@Composable -fun ExternalFeeCustomScreen( - viewModel: ExternalNodeViewModel, - onBack: () -> Unit, -) { - val uiState by viewModel.uiState.collectAsState() - val currency = currencyViewModel ?: return - val scope = rememberCoroutineScope() - - val context = LocalContext.current - - var input by remember { - mutableStateOf(uiState.customFeeRate?.toString() ?: "") - } - - LaunchedEffect(input) { - val feeRate = input.toUIntOrNull() ?: 0u - viewModel.onCustomFeeRateChange(feeRate) - } - - val totalFeeText = remember(uiState.networkFee) { - if (uiState.networkFee == 0L) { - "" - } else { - currency.convert(uiState.networkFee) - ?.let { - context.getString(R.string.wallet__send_fee_total_fiat) - .replace("{feeSats}", "${uiState.networkFee}") - .replace("{fiatSymbol}", it.symbol) - .replace("{fiatFormatted}", it.formatted) - } ?: context.getString(R.string.wallet__send_fee_total).replace("{feeSats}", "${uiState.networkFee}") - } - } - - Content( - input = input, - totalFeeText = totalFeeText, - onKeyPress = { key -> - when (key) { - KEY_DELETE -> input = if (input.isNotEmpty()) input.dropLast(1) else "" - else -> if (input.length < 3) input = (input + key).trimStart('0') - } - }, - onContinue = { - val feeRate = input.toUIntOrNull() ?: 0u - if (feeRate == 0u) { - scope.launch { - ToastEventBus.send( - type = Toast.ToastType.INFO, - title = context.getString(R.string.wallet__min_possible_fee_rate), - description = context.getString(R.string.wallet__min_possible_fee_rate_msg), - ) - } - return@Content - } - onBack() - }, - onBack = onBack, - ) -} - -@Composable -private fun Content( - input: String, - totalFeeText: String, - onKeyPress: (String) -> Unit = {}, - onContinue: () -> Unit = {}, - onBack: () -> Unit = {}, -) { - val feeRate = input.toUIntOrNull() ?: 0u - val isValid = feeRate != 0u - - ScreenColumn { - AppTopBar( - titleText = stringResource(R.string.lightning__external__nav_title), - onBackClick = onBack, - actions = { DrawerNavIcon() }, - ) - Column( - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxSize() - ) { - VerticalSpacer(16.dp) - Display(stringResource(R.string.lightning__transfer__custom_fee).withAccent(accentColor = Colors.Purple)) - - FillHeight() - - Column { - Caption13Up(stringResource(R.string.common__sat_vbyte), color = Colors.White64) - - VerticalSpacer(16.dp) - LargeRow( - prefix = null, - text = input.ifEmpty { "0" }, - symbol = BITCOIN_SYMBOL, - showSymbol = true, - ) - VerticalSpacer(8.dp) - - Column( - modifier = Modifier.height(22.dp) - ) { - if (isValid) { - AnimatedVisibility(visible = totalFeeText.isNotEmpty(), enter = fadeIn(), exit = fadeOut()) { - BodyM(totalFeeText, color = Colors.White64) - } - } - } - } - - FillHeight() - - NumberPad( - onPress = onKeyPress, - type = NumberPadType.SIMPLE, - modifier = Modifier - .height(350.dp) - .testTag("FeeCustomNumberPad") - ) - - PrimaryButton( - onClick = onContinue, - text = stringResource(R.string.common__continue), - modifier = Modifier.testTag("FeeCustomContinue") - ) - VerticalSpacer(16.dp) - } - } -} - -@Preview(showSystemUi = true) -@Composable -private fun Preview() { - AppThemeSurface { - Content( - input = "5", - totalFeeText = "₿ 256 for this transaction ($0.25)" - ) - } -} diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt index efd087df3..c501c193b 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt @@ -21,7 +21,6 @@ import to.bitkit.ext.WatchResult import to.bitkit.ext.of import to.bitkit.ext.watchUntil import to.bitkit.models.Toast -import to.bitkit.models.TransactionSpeed import to.bitkit.models.TransferType import to.bitkit.models.formatToModernDisplay import to.bitkit.repositories.LightningRepo @@ -118,34 +117,13 @@ class ExternalNodeViewModel @Inject constructor( fun onAmountContinue() { viewModelScope.launch { val speed = settingsStore.data.first().defaultTransactionSpeed - val defaultSatsPerVbyte = lightningRepo.getFeeRateForSpeed(speed).getOrThrow().toUInt() - _uiState.update { - it.copy( - customFeeRate = defaultSatsPerVbyte, - networkFee = 0L, - ) - } - updateNetworkFee() - } - } - - fun onCustomFeeRateChange(feeRate: UInt) { - _uiState.update { it.copy(customFeeRate = feeRate) } - updateNetworkFee() - } - - private fun updateNetworkFee() { - viewModelScope.launch { val amountSats = _uiState.value.amount.sats - val customFeeRate = _uiState.value.customFeeRate - if (amountSats <= 0 || customFeeRate == 0u) { + if (amountSats <= 0) { _uiState.update { it.copy(networkFee = 0L) } return@launch } - val speed = customFeeRate?.let { TransactionSpeed.Custom(it) } - val fee = lightningRepo.calculateTotalFee( amountSats = amountSats.toULong(), speed = speed, @@ -219,7 +197,6 @@ interface ExternalNodeContract { val peer: PeerDetails? = null, val amount: Amount = Amount(), val networkFee: Long = 0, - val customFeeRate: UInt? = null, ) { data class Amount( val sats: Long = 0, diff --git a/docs/e2e-test-ids.md b/docs/e2e-test-ids.md index fa0ed0182..03888b9cb 100644 --- a/docs/e2e-test-ids.md +++ b/docs/e2e-test-ids.md @@ -634,7 +634,7 @@ Legend: | Send | ✅ | | SendAmountNumberPad | ✅ | | SendSuccess | ✅ | -| SetCustomFee | ✅ | +| SetCustomFee | 🚫 | | SpendingAdvanced | ✅ | | SpendingAdvancedContinue | ✅ | | SpendingAdvancedDefault | ✅ |