feat: on-chain handoff from the custom-zap dialog
Adds a "Send on-chain instead" link button at the bottom of ZapCustomDialog. Tapping it opens OnchainZapSendDialog with the entered amount and message prefilled, the note as zappedEvent, and the same split-detection / dust-preview / fee-tier picker that the Reactions zap chip uses. This also fixes the participant zap path in nests audio rooms (ParticipantHostActionsSheet long-press → "Zap") since that menu item opens ZapCustomDialog under the hood — fixing the custom dialog covers both entry points transitively. OnchainZapSendDialog gains a `prefillComment: String = ""` parameter so the message field carries over from the LN dialog. Poll-note zaps (FilteredZapAmountChoicePopup) intentionally stay Lightning-only — the poll_option vote is encoded in the kind:9734 zap request and counted via kind:9735 receipts; kind:8333 on-chain receipts have no poll_option analog and the count infrastructure doesn't index them. This is a protocol design constraint, not a UI oversight. Coverage audit summary — every user-facing zap initiation point now has on-chain support except the poll-voting path: - ZapReaction (reactions row) ✅ - ZapAmountChoicePopup (popup chips) ✅ - ZapCustomDialog (custom amount + message) ✅ (this commit) - ReusableZapButton (Zap the Devs + DVM buttons) ✅ - NestActionBar (audio room) ✅ - ParticipantHostActionsSheet (audio room participant) ✅ (transitive) - ChatMessageCompose / live-activity headers (use ZapReaction) ✅ - FilteredZapAmountChoicePopup (poll votes) ⚠️ LN-only by protocol
This commit is contained in:
@@ -48,6 +48,7 @@ import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SuggestionChip
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -81,6 +82,7 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
|
||||
import com.vitorpamplona.amethyst.ui.note.buttons.CloseButton
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.wallet.OnchainZapSendDialog
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
||||
@@ -89,6 +91,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.ZeroPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -157,6 +160,11 @@ fun ZapCustomDialog(
|
||||
|
||||
val presetAmounts = remember(accountViewModel) { accountViewModel.zapAmountChoices() }
|
||||
|
||||
// True while the on-chain hand-off sheet is open. Dismissing the on-chain
|
||||
// sheet closes the whole zap flow — the user has already committed to a
|
||||
// payment method, no "go back to Lightning" is offered here.
|
||||
var sendOnchain by remember { mutableStateOf(false) }
|
||||
|
||||
Dialog(
|
||||
onDismissRequest = { onClose() },
|
||||
properties =
|
||||
@@ -326,9 +334,38 @@ fun ZapCustomDialog(
|
||||
)
|
||||
onClose()
|
||||
}
|
||||
|
||||
// Hand off to the on-chain dialog with the entered amount +
|
||||
// message prefilled. Disabled while the amount is empty so the
|
||||
// user can't open a sheet that immediately gates on its own
|
||||
// empty field.
|
||||
TextButton(
|
||||
onClick = { sendOnchain = true },
|
||||
enabled = postViewModel.canSend() && !baseNote.isDraft(),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 4.dp),
|
||||
) {
|
||||
Text(text = stringRes(id = R.string.send_onchain_instead))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sendOnchain) {
|
||||
OnchainZapSendDialog(
|
||||
accountViewModel = accountViewModel,
|
||||
onDismiss = {
|
||||
sendOnchain = false
|
||||
onClose()
|
||||
},
|
||||
recipientPubKey = baseNote.author?.pubkeyHex,
|
||||
zappedEvent = baseNote.toEventHint<Event>(),
|
||||
prefillAmountSats = postViewModel.value(),
|
||||
prefillComment = postViewModel.customMessage.text,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
+2
-1
@@ -137,6 +137,7 @@ fun OnchainZapSendDialog(
|
||||
recipientPubKey: HexKey? = null,
|
||||
zappedEvent: EventHintBundle<out Event>? = null,
|
||||
prefillAmountSats: Long? = null,
|
||||
prefillComment: String = "",
|
||||
) {
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
val scope = rememberCoroutineScope()
|
||||
@@ -152,7 +153,7 @@ fun OnchainZapSendDialog(
|
||||
var searchInput by remember { mutableStateOf("") }
|
||||
var selectedUser by remember { mutableStateOf<User?>(null) }
|
||||
var amountInput by remember { mutableStateOf(prefillAmountSats?.toString().orEmpty()) }
|
||||
var comment by remember { mutableStateOf("") }
|
||||
var comment by remember { mutableStateOf(prefillComment) }
|
||||
var feeTier by remember { mutableStateOf(FeeTier.NORMAL) }
|
||||
var fees by remember { mutableStateOf<FeeEstimates?>(null) }
|
||||
|
||||
|
||||
@@ -824,6 +824,7 @@
|
||||
<string name="quick_zap_amounts_onchain">Quick On-chain Zap Amounts</string>
|
||||
<string name="quick_zap_amounts_onchain_explainer">On-chain zaps pay miner fees, so amounts are usually larger than Lightning. Tap an amount to remove it.</string>
|
||||
<string name="new_amount_in_sats_onchain">New on-chain amount in sats</string>
|
||||
<string name="send_onchain_instead">Send on-chain instead</string>
|
||||
<string name="zap_privacy_section">Zap Privacy</string>
|
||||
<string name="zap_type_section_explainer">Controls how your identity is shown when you send a zap.</string>
|
||||
<string name="wallet_connect_connect_app">Connect Wallet</string>
|
||||
|
||||
Reference in New Issue
Block a user