diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 79600dd18a..d8307d1687 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -603,12 +603,14 @@ class Account( suspend fun updateZapAmounts( amountSet: List, + onchainAmountSet: List, selectedZapType: LnZapEvent.ZapType, nip47Update: Nip47WalletConnect.Nip47URINorm?, ) { var changed = false if (settings.changeZapAmounts(amountSet)) changed = true + if (settings.changeOnchainZapAmounts(onchainAmountSet)) changed = true if (settings.changeDefaultZapType(selectedZapType)) changed = true if (settings.changeZapPaymentRequest(nip47Update)) changed = true diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt index 07ae07b865..6d80a12bc5 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt @@ -267,6 +267,15 @@ class AccountSettings( return false } + fun changeOnchainZapAmounts(newAmounts: List): Boolean { + if (syncedSettings.zaps.onchainZapAmountChoices.value != newAmounts) { + syncedSettings.zaps.onchainZapAmountChoices.tryEmit(newAmounts.toImmutableList()) + saveAccountSettings() + return true + } + return false + } + fun changeReactionTypes(newTypes: List): Boolean { if (syncedSettings.reactions.reactionChoices.value != newTypes) { syncedSettings.reactions.reactionChoices.tryEmit(newTypes.toImmutableList()) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt index ca5b08b360..c8fa71e767 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt @@ -40,6 +40,7 @@ class AccountSyncedSettings( val zaps = AccountZapPreferences( MutableStateFlow(internalSettings.zaps.zapAmountChoices.toImmutableList()), + MutableStateFlow(internalSettings.zaps.onchainZapAmountChoices.toImmutableList()), MutableStateFlow(internalSettings.zaps.defaultZapType), ) val languages = @@ -69,6 +70,7 @@ class AccountSyncedSettings( zaps = AccountZapPreferencesInternal( zaps.zapAmountChoices.value, + zaps.onchainZapAmountChoices.value, zaps.defaultZapType.value, ), languages = @@ -107,6 +109,11 @@ class AccountSyncedSettings( zaps.zapAmountChoices.tryEmit(newZapChoices) } + val newOnchainZapChoices = syncedSettingsInternal.zaps.onchainZapAmountChoices.toImmutableList() + if (!equalImmutableLists(zaps.onchainZapAmountChoices.value, newOnchainZapChoices)) { + zaps.onchainZapAmountChoices.tryEmit(newOnchainZapChoices) + } + if (zaps.defaultZapType.value != syncedSettingsInternal.zaps.defaultZapType) { zaps.defaultZapType.tryEmit(syncedSettingsInternal.zaps.defaultZapType) } @@ -175,6 +182,7 @@ class AccountVideoPlayerPreferences( @Stable class AccountZapPreferences( var zapAmountChoices: MutableStateFlow>, + var onchainZapAmountChoices: MutableStateFlow>, val defaultZapType: MutableStateFlow, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt index 29ebf1bbc4..c411336809 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt @@ -38,6 +38,7 @@ val DefaultReactions = ) val DefaultZapAmounts = listOf(100L, 500L, 1000L) +val DefaultOnchainZapAmounts = listOf(10_000L, 50_000L, 250_000L) val DefaultReportWarningThreshold = 5 @Serializable @@ -153,6 +154,7 @@ class AccountReactionPreferencesInternal( @Serializable class AccountZapPreferencesInternal( var zapAmountChoices: List = DefaultZapAmounts, + var onchainZapAmountChoices: List = DefaultOnchainZapAmounts, val defaultZapType: LnZapEvent.ZapType = LnZapEvent.ZapType.PUBLIC, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index 77f49a84af..e24844d6fa 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -136,6 +136,7 @@ import com.vitorpamplona.amethyst.ui.navigation.routes.routeReplyTo import com.vitorpamplona.amethyst.ui.note.types.EditState import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.header.PaymentTargetsDialog +import com.vitorpamplona.amethyst.ui.screen.loggedIn.wallet.OnchainZapSendDialog import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import com.vitorpamplona.amethyst.ui.theme.ButtonBorder @@ -172,6 +173,7 @@ import com.vitorpamplona.amethyst.ui.theme.reactionBox import com.vitorpamplona.amethyst.ui.theme.ripple24dp import com.vitorpamplona.amethyst.ui.theme.selectedReactionBoxModifier import com.vitorpamplona.quartz.experimental.nipA3.PaymentTargetsEvent +import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable @@ -1121,6 +1123,11 @@ private fun likeClick( } } +@Immutable +private data class OnchainZapRequest( + val amountSats: Long?, +) + @Composable @OptIn(ExperimentalFoundationApi::class, ExperimentalUuidApi::class) fun ZapReaction( @@ -1135,6 +1142,9 @@ fun ZapReaction( ) { var wantsToZap by remember { mutableStateOf(false) } var wantsToSetCustomZap by remember { mutableStateOf(false) } + // null = closed; OnchainZapRequest(amount=null) = open with no prefill; + // OnchainZapRequest(amount=N) = open prefilled to N sats. + var onchainZapRequest by remember { mutableStateOf(null) } val context = LocalContext.current val scope = rememberCoroutineScope() @@ -1207,6 +1217,10 @@ fun ZapReaction( nav.nav(Route.UpdateZapAmount()) } }, + onOnchainAmount = { amount -> + wantsToZap = false + onchainZapRequest = OnchainZapRequest(amount) + }, onError = { _, message, user -> scope.launch { zappingProgress = 0f @@ -1230,6 +1244,16 @@ fun ZapReaction( ) } + onchainZapRequest?.let { request -> + OnchainZapSendDialog( + accountViewModel = accountViewModel, + onDismiss = { onchainZapRequest = null }, + recipientPubKey = baseNote.author?.pubkeyHex, + zappedEvent = baseNote.toEventHint(), + prefillAmountSats = request.amountSats, + ) + } + if (wantsToSetCustomZap) { ZapCustomDialog( onZapStarts = { zapStartingTime = TimeUtils.now() }, @@ -1834,12 +1858,29 @@ fun ZapAmountChoicePopup( onError: (title: String, text: String, user: User?) -> Unit, onProgress: (percent: Float) -> Unit, onPayViaIntent: (ImmutableList) -> Unit, + onOnchainAmount: ((Long?) -> Unit)? = null, ) { val zapAmountChoices by accountViewModel.account.settings.syncedSettings.zaps.zapAmountChoices .collectAsStateWithLifecycle() + val onchainZapAmountChoices by + accountViewModel.account.settings.syncedSettings.zaps.onchainZapAmountChoices + .collectAsStateWithLifecycle() - ZapAmountChoicePopup(baseNote, zapAmountChoices, accountViewModel, popupYOffset, onZapStarts, onDismiss, onChangeAmount, onError, onProgress, onPayViaIntent) + ZapAmountChoicePopup( + baseNote = baseNote, + zapAmountChoices = zapAmountChoices, + accountViewModel = accountViewModel, + popupYOffset = popupYOffset, + onZapStarts = onZapStarts, + onDismiss = onDismiss, + onChangeAmount = onChangeAmount, + onError = onError, + onProgress = onProgress, + onPayViaIntent = onPayViaIntent, + onchainZapAmountChoices = if (onOnchainAmount != null) onchainZapAmountChoices else persistentListOf(), + onOnchainAmount = onOnchainAmount ?: {}, + ) } @Composable @@ -1854,9 +1895,11 @@ fun ZapAmountChoicePopup( onError: (title: String, text: String, user: User?) -> Unit, onProgress: (percent: Float) -> Unit, onPayViaIntent: (ImmutableList) -> Unit, + onchainZapAmountChoices: ImmutableList = persistentListOf(), + onOnchainAmount: (Long?) -> Unit = {}, ) { val visibilityState = rememberVisibilityState(onDismiss) - ZapAmountChoicePopup(baseNote, zapAmountChoices, accountViewModel, popupYOffset, visibilityState, onZapStarts, onChangeAmount, onError, onProgress, onPayViaIntent) + ZapAmountChoicePopup(baseNote, zapAmountChoices, onchainZapAmountChoices, accountViewModel, popupYOffset, visibilityState, onZapStarts, onChangeAmount, onOnchainAmount, onError, onProgress, onPayViaIntent) } @OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class) @@ -1864,11 +1907,13 @@ fun ZapAmountChoicePopup( fun ZapAmountChoicePopup( baseNote: Note, zapAmountChoices: ImmutableList, + onchainZapAmountChoices: ImmutableList, accountViewModel: AccountViewModel, popupYOffset: Dp, visibilityState: MutableTransitionState, onZapStarts: () -> Unit, onChangeAmount: () -> Unit, + onOnchainAmount: (Long?) -> Unit, onError: (title: String, text: String, user: User?) -> Unit, onProgress: (percent: Float) -> Unit, onPayViaIntent: (ImmutableList) -> Unit, @@ -1889,6 +1934,7 @@ fun ZapAmountChoicePopup( ) { ZapAmountChoicePopupContent( zapAmountChoices = zapAmountChoices, + onchainZapAmountChoices = onchainZapAmountChoices, onZap = { amountInSats -> onZapStarts() accountViewModel.zap( @@ -1905,6 +1951,10 @@ fun ZapAmountChoicePopup( visibilityState.targetState = false }, onChangeAmount = onChangeAmount, + onOnchainAmount = { amount -> + onOnchainAmount(amount) + visibilityState.targetState = false + }, ) } } @@ -1916,6 +1966,8 @@ fun ZapAmountChoicePopupContent( zapAmountChoices: ImmutableList, onZap: (Long) -> Unit, onChangeAmount: () -> Unit, + onchainZapAmountChoices: ImmutableList = persistentListOf(), + onOnchainAmount: (Long?) -> Unit = {}, ) { Box(HalfPadding, contentAlignment = Center) { ElevatedCard( @@ -1923,33 +1975,66 @@ fun ZapAmountChoicePopupContent( elevation = CardDefaults.elevatedCardElevation(defaultElevation = 8.dp), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant), ) { - FlowRow( - modifier = Modifier.padding(horizontal = 5.dp, vertical = 5.dp), - horizontalArrangement = Arrangement.Center, - verticalArrangement = Arrangement.Center, - itemVerticalAlignment = CenterVertically, - ) { - zapAmountChoices.forEach { amountInSats -> - ZapAmountChip( - amountInSats = amountInSats, - onClick = { onZap(amountInSats) }, - onLongClick = onChangeAmount, - ) - } - ClickableBox( - modifier = - Modifier - .padding(horizontal = 4.dp, vertical = 6.dp) - .size(32.dp) - .padding(7.dp), - onClick = onChangeAmount, + Column { + FlowRow( + modifier = Modifier.padding(horizontal = 5.dp, vertical = 5.dp), + horizontalArrangement = Arrangement.Center, + verticalArrangement = Arrangement.Center, + itemVerticalAlignment = CenterVertically, ) { - Icon( - symbol = MaterialSymbols.Tune, - contentDescription = stringRes(R.string.quick_zap_amounts), - modifier = Size18Modifier, - tint = MaterialTheme.colorScheme.placeholderText, - ) + zapAmountChoices.forEach { amountInSats -> + ZapAmountChip( + amountInSats = amountInSats, + onClick = { onZap(amountInSats) }, + onLongClick = onChangeAmount, + ) + } + ClickableBox( + modifier = + Modifier + .padding(horizontal = 4.dp, vertical = 6.dp) + .size(32.dp) + .padding(7.dp), + onClick = onChangeAmount, + ) { + Icon( + symbol = MaterialSymbols.Tune, + contentDescription = stringRes(R.string.quick_zap_amounts), + modifier = Size18Modifier, + tint = MaterialTheme.colorScheme.placeholderText, + ) + } + } + if (onchainZapAmountChoices.isNotEmpty()) { + FlowRow( + modifier = Modifier.padding(horizontal = 5.dp, vertical = 5.dp), + horizontalArrangement = Arrangement.Center, + verticalArrangement = Arrangement.Center, + itemVerticalAlignment = CenterVertically, + ) { + onchainZapAmountChoices.forEach { amountInSats -> + OnchainZapAmountChip( + amountInSats = amountInSats, + onClick = { onOnchainAmount(amountInSats) }, + onLongClick = onChangeAmount, + ) + } + ClickableBox( + modifier = + Modifier + .padding(horizontal = 4.dp, vertical = 6.dp) + .size(32.dp) + .padding(7.dp), + onClick = { onOnchainAmount(null) }, + ) { + Icon( + symbol = MaterialSymbols.Tune, + contentDescription = stringRes(R.string.quick_zap_amounts_onchain), + modifier = Size18Modifier, + tint = MaterialTheme.colorScheme.placeholderText, + ) + } + } } } } @@ -1992,14 +2077,52 @@ private fun ZapAmountChip( } } +@OptIn(ExperimentalFoundationApi::class) +@Composable +private fun OnchainZapAmountChip( + amountInSats: Long, + onClick: () -> Unit, + onLongClick: () -> Unit, +) { + Surface( + shape = ButtonBorder, + color = BitcoinOrange, + modifier = Modifier.padding(horizontal = 4.dp, vertical = 6.dp), + ) { + Row( + modifier = + Modifier + .combinedClickable(onClick = onClick, onLongClick = onLongClick) + .padding(horizontal = 12.dp, vertical = 6.dp), + verticalAlignment = CenterVertically, + ) { + Icon( + symbol = MaterialSymbols.CurrencyBitcoin, + contentDescription = null, + modifier = Size18Modifier, + tint = Color.White, + ) + Spacer(Modifier.width(2.dp)) + Text( + text = showAmount(amountInSats.toBigDecimal().setScale(1)), + color = Color.White, + fontWeight = FontWeight.SemiBold, + textAlign = TextAlign.Center, + ) + } + } +} + @Preview @Composable fun ZapAmountChoicePopupPreview() { ThemeComparisonColumn { ZapAmountChoicePopupContent( zapAmountChoices = persistentListOf(50L, 100L, 500L, 1_000L, 5_000L, 10_000L, 100_000L), + onchainZapAmountChoices = persistentListOf(10_000L, 50_000L, 250_000L), onZap = {}, onChangeAmount = {}, + onOnchainAmount = {}, ) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt index 571be707fb..d4e5b3c5a0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountDialog.kt @@ -306,7 +306,96 @@ fun UpdateZapAmountContent( ) } - // ── Section 2: Zap Privacy ──────────────────────────────────────────── + // ── Section 2: Quick On-chain Zap Amounts ───────────────────────────── + + Text( + text = stringRes(R.string.quick_zap_amounts_onchain), + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.titleSmall, + modifier = SettingsCategorySpacingModifier, + ) + Text( + text = stringRes(R.string.quick_zap_amounts_onchain_explainer), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.placeholderText, + modifier = Modifier.padding(bottom = 6.dp), + ) + + FlowRow( + modifier = + Modifier + .fillMaxWidth() + .animateContentSize(animationSpec = spring(stiffness = Spring.StiffnessMediumLow)), + horizontalArrangement = Arrangement.spacedBy(6.dp), + verticalArrangement = Arrangement.spacedBy(6.dp), + ) { + postViewModel.onchainAmountSet.forEach { amountInSats -> + InputChip( + selected = false, + onClick = { postViewModel.removeOnchainAmount(amountInSats) }, + label = { + Text( + text = "₿ ${showAmount(amountInSats.toBigDecimal().setScale(1))}", + ) + }, + trailingIcon = { + Icon( + symbol = MaterialSymbols.Close, + contentDescription = stringRes(R.string.remove), + modifier = Modifier.size(InputChipDefaults.AvatarSize), + ) + }, + colors = + InputChipDefaults.inputChipColors( + containerColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.12f), + labelColor = MaterialTheme.colorScheme.primary, + trailingIconColor = MaterialTheme.colorScheme.primary, + ), + ) + } + } + + Spacer(modifier = Modifier.height(6.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + OutlinedTextField( + label = { Text(text = stringRes(R.string.new_amount_in_sats_onchain)) }, + value = postViewModel.nextOnchainAmount, + onValueChange = { postViewModel.nextOnchainAmount = it }, + keyboardOptions = + KeyboardOptions.Default.copy( + capitalization = KeyboardCapitalization.None, + keyboardType = KeyboardType.Number, + ), + placeholder = { + Text( + text = "10000, 50000, 250000", + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + trailingIcon = { + IconButton( + onClick = postViewModel::addOnchainAmount, + shape = ButtonBorder, + enabled = postViewModel.nextOnchainAmount.text.isNotBlank(), + ) { + Icon( + symbol = MaterialSymbols.AddCircle, + contentDescription = stringRes(R.string.add), + modifier = Size20Modifier, + ) + } + }, + singleLine = true, + modifier = Modifier.weight(1f), + ) + } + + // ── Section 3: Zap Privacy ──────────────────────────────────────────── Text( text = stringRes(R.string.zap_privacy_section), diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountViewModel.kt index 8d50017d9a..963e6c2864 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateZapAmountViewModel.kt @@ -41,6 +41,8 @@ class UpdateZapAmountViewModel : ViewModel() { var nextAmount by mutableStateOf(TextFieldValue("")) var amountSet by mutableStateOf(listOf()) + var nextOnchainAmount by mutableStateOf(TextFieldValue("")) + var onchainAmountSet by mutableStateOf(listOf()) var walletConnectRelay by mutableStateOf(TextFieldValue("")) var walletConnectPubkey by mutableStateOf(TextFieldValue("")) var walletConnectSecret by mutableStateOf(TextFieldValue("")) @@ -59,6 +61,7 @@ class UpdateZapAmountViewModel : ViewModel() { fun load() { this.amountSet = accountViewModel.account.settings.syncedSettings.zaps.zapAmountChoices.value + this.onchainAmountSet = accountViewModel.account.settings.syncedSettings.zaps.onchainZapAmountChoices.value this.selectedZapType = accountViewModel.account.settings.syncedSettings.zaps.defaultZapType.value val nip47 = accountViewModel.account.settings.defaultZapPaymentRequest() @@ -83,6 +86,19 @@ class UpdateZapAmountViewModel : ViewModel() { amountSet = amountSet - amount } + fun addOnchainAmount() { + val newValue = nextOnchainAmount.text.trim().toLongOrNull() + if (newValue != null) { + onchainAmountSet = onchainAmountSet + newValue + } + + nextOnchainAmount = TextFieldValue("") + } + + fun removeOnchainAmount(amount: Long) { + onchainAmountSet = onchainAmountSet - amount + } + fun sendPost() { accountViewModel.launchSigner { sendPostSuspend() @@ -116,13 +132,15 @@ class UpdateZapAmountViewModel : ViewModel() { null } - accountViewModel.account.updateZapAmounts(amountSet, selectedZapType, nip47Update) + accountViewModel.account.updateZapAmounts(amountSet, onchainAmountSet, selectedZapType, nip47Update) nextAmount = TextFieldValue("") + nextOnchainAmount = TextFieldValue("") } fun cancel() { nextAmount = TextFieldValue("") + nextOnchainAmount = TextFieldValue("") } fun hasChanged(): Boolean { @@ -130,6 +148,7 @@ class UpdateZapAmountViewModel : ViewModel() { return ( selectedZapType != accountViewModel.account.settings.syncedSettings.zaps.defaultZapType.value || amountSet != accountViewModel.account.settings.syncedSettings.zaps.zapAmountChoices.value || + onchainAmountSet != accountViewModel.account.settings.syncedSettings.zaps.onchainZapAmountChoices.value || walletConnectPubkey.text != (defaultUri?.pubKeyHex ?: "") || walletConnectRelay.text != (defaultUri?.relayUri?.url ?: "") || walletConnectSecret.text != (defaultUri?.secret ?: "") diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index b695b85191..af93b2af10 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -1236,9 +1236,10 @@ class AccountViewModel( fun updateZapAmounts( amountSet: List, + onchainAmountSet: List, selectedZapType: LnZapEvent.ZapType, nip47Update: Nip47WalletConnect.Nip47URINorm?, - ) = launchSigner { account.updateZapAmounts(amountSet, selectedZapType, nip47Update) } + ) = launchSigner { account.updateZapAmounts(amountSet, onchainAmountSet, selectedZapType, nip47Update) } fun toggleDontTranslateFrom(languageCode: String) = launchSigner { account.toggleDontTranslateFrom(languageCode) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/wallet/OnchainZapSendDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/wallet/OnchainZapSendDialog.kt index f0738c3956..85e4782e2f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/wallet/OnchainZapSendDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/wallet/OnchainZapSendDialog.kt @@ -127,6 +127,7 @@ fun OnchainZapSendDialog( onDismiss: () -> Unit, recipientPubKey: HexKey? = null, zappedEvent: EventHintBundle? = null, + prefillAmountSats: Long? = null, ) { val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val scope = rememberCoroutineScope() @@ -141,7 +142,7 @@ fun OnchainZapSendDialog( var searchInput by remember { mutableStateOf("") } var selectedUser by remember { mutableStateOf(null) } - var amountInput by remember { mutableStateOf("") } + var amountInput by remember { mutableStateOf(prefillAmountSats?.toString().orEmpty()) } var comment by remember { mutableStateOf("") } var feeTier by remember { mutableStateOf(FeeTier.NORMAL) } var fees by remember { mutableStateOf(null) } @@ -155,10 +156,8 @@ fun OnchainZapSendDialog( runCatching { withContext(Dispatchers.IO) { backend.feeEstimates() } }.getOrNull() } - val presetAmounts = - remember(accountViewModel) { - accountViewModel.zapAmountChoices() - } + val presetAmounts by accountViewModel.account.settings.syncedSettings.zaps.onchainZapAmountChoices + .collectAsStateWithLifecycle() // Mirror the dropdown's NIP-05 / Namecoin (.bit) resolution so Send can // enable as soon as the typed name resolves, without forcing the user to diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index 1bc3b6a9db..b66a7902a7 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -821,6 +821,9 @@ Advanced: enter connection details manually Quick Zap Amounts Shown when pressing the zap button. Tap an amount to remove it. If you leave it empty, it will open the dialog to insert an amount every time. + Quick On-chain Zap Amounts + On-chain zaps pay miner fees, so amounts are usually larger than Lightning. Tap an amount to remove it. + New on-chain amount in sats Zap Privacy Controls how your identity is shown when you send a zap. Connect Wallet