mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2024-09-29 16:30:49 +00:00
Migrates from PAY to NOTIFY as per https://github.com/nostr-protocol/nips/pull/901
This commit is contained in:
parent
5356d869fd
commit
e2aaa8efe0
@ -152,9 +152,7 @@ class Account(
|
||||
|
||||
data class PaymentRequest(
|
||||
val relayUrl: String,
|
||||
val lnInvoice: String?,
|
||||
val description: String?,
|
||||
val otherOptionsUrl: String?
|
||||
val description: String
|
||||
)
|
||||
var transientPaymentRequestDismissals: Set<PaymentRequest> = emptySet()
|
||||
val transientPaymentRequests: MutableStateFlow<Set<PaymentRequest>> = MutableStateFlow(emptySet())
|
||||
|
@ -245,11 +245,11 @@ object NostrAccountDataSource : NostrDataSource("AccountData") {
|
||||
}
|
||||
}
|
||||
|
||||
override fun pay(relay: Relay, lnInvoice: String?, description: String?, otherOptionsUrl: String?) {
|
||||
super.pay(relay, lnInvoice, description, otherOptionsUrl)
|
||||
override fun notify(relay: Relay, description: String) {
|
||||
super.notify(relay, description)
|
||||
|
||||
if (this::account.isInitialized) {
|
||||
account.addPaymentRequestIfNew(Account.PaymentRequest(relay.url, lnInvoice, description, otherOptionsUrl))
|
||||
account.addPaymentRequestIfNew(Account.PaymentRequest(relay.url, description))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,13 +77,11 @@ abstract class NostrDataSource(val debugName: String) {
|
||||
auth(relay, challenge)
|
||||
}
|
||||
|
||||
override fun onPaymentRequired(
|
||||
override fun onNotify(
|
||||
relay: Relay,
|
||||
lnInvoice: String?,
|
||||
description: String?,
|
||||
otherOptionsUrl: String?
|
||||
description: String
|
||||
) {
|
||||
pay(relay, lnInvoice, description, otherOptionsUrl)
|
||||
notify(relay, description)
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,5 +197,5 @@ abstract class NostrDataSource(val debugName: String) {
|
||||
|
||||
abstract fun updateChannelFilters()
|
||||
open fun auth(relay: Relay, challenge: String) = Unit
|
||||
open fun pay(relay: Relay, lnInvoice: String?, description: String?, otherOptionsUrl: String?) = Unit
|
||||
open fun notify(relay: Relay, description: String) = Unit
|
||||
}
|
||||
|
@ -177,11 +177,11 @@ object Client : RelayPool.Listener {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPaymentRequired(relay: Relay, lnInvoice: String?, description: String?, otherOptionsUrl: String?) {
|
||||
override fun onNotify(relay: Relay, description: String) {
|
||||
// Releases the Web thread for the new payload.
|
||||
// May need to add a processing queue if processing new events become too costly.
|
||||
GlobalScope.launch(Dispatchers.Default) {
|
||||
listeners.forEach { it.onPaymentRequired(relay, lnInvoice, description, otherOptionsUrl) }
|
||||
listeners.forEach { it.onNotify(relay, description) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,6 +224,6 @@ object Client : RelayPool.Listener {
|
||||
|
||||
open fun onAuth(relay: Relay, challenge: String) = Unit
|
||||
|
||||
open fun onPaymentRequired(relay: Relay, lnInvoice: String?, description: String?, otherOptionsUrl: String?) = Unit
|
||||
open fun onNotify(relay: Relay, description: String) = Unit
|
||||
}
|
||||
}
|
||||
|
@ -244,9 +244,9 @@ class Relay(
|
||||
// Log.w("Relay", "Relay$url, ${msg[1].asString}")
|
||||
it.onAuth(this@Relay, msgArray[1].asText())
|
||||
}
|
||||
"PAY" -> listeners.forEach {
|
||||
"NOTIFY" -> listeners.forEach {
|
||||
// Log.w("Relay", "Relay$url, ${msg[1].asString}")
|
||||
it.onPaymentRequired(this@Relay, msgArray[1].asText(), msgArray[2].asText(), msgArray[3].asText())
|
||||
it.onNotify(this@Relay, msgArray[1].asText())
|
||||
}
|
||||
else -> listeners.forEach {
|
||||
Log.w("Relay", "Unsupported message: $newMessage")
|
||||
@ -326,27 +326,23 @@ class Relay(
|
||||
eventUploadCounterInBytes += event.bytesUsedInMemory()
|
||||
} else {
|
||||
if (write) {
|
||||
val event = """["EVENT",${signedEvent.toJson()}]"""
|
||||
if (isConnected()) {
|
||||
if (isReady) {
|
||||
val event = """["EVENT",${signedEvent.toJson()}]"""
|
||||
socket?.send(event)
|
||||
eventUploadCounterInBytes += event.bytesUsedInMemory()
|
||||
}
|
||||
} else {
|
||||
// waits 60 seconds to reconnect after disconnected.
|
||||
if (TimeUtils.now() > closingTimeInSeconds + RECONNECTING_IN_SECONDS) {
|
||||
// sends all filters after connection is successful.
|
||||
connectAndRun {
|
||||
checkNotInMainThread()
|
||||
// sends all filters after connection is successful.
|
||||
connectAndRun {
|
||||
checkNotInMainThread()
|
||||
|
||||
val event = """["EVENT",${signedEvent.toJson()}]"""
|
||||
socket?.send(event)
|
||||
eventUploadCounterInBytes += event.bytesUsedInMemory()
|
||||
socket?.send(event)
|
||||
eventUploadCounterInBytes += event.bytesUsedInMemory()
|
||||
|
||||
// Sends everything.
|
||||
Client.allSubscriptions().forEach {
|
||||
sendFilter(requestId = it)
|
||||
}
|
||||
// Sends everything.
|
||||
Client.allSubscriptions().forEach {
|
||||
sendFilter(requestId = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,6 +397,6 @@ class Relay(
|
||||
/**
|
||||
* Relay sent an invoice
|
||||
*/
|
||||
fun onPaymentRequired(relay: Relay, lnInvoice: String?, description: String?, otherOptionsUrl: String?)
|
||||
fun onNotify(relay: Relay, description: String)
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ object RelayPool : Relay.Listener {
|
||||
|
||||
fun onAuth(relay: Relay, challenge: String)
|
||||
|
||||
fun onPaymentRequired(relay: Relay, lnInvoice: String?, description: String?, otherOptionsUrl: String?)
|
||||
fun onNotify(relay: Relay, description: String)
|
||||
}
|
||||
|
||||
override fun onEvent(relay: Relay, subscriptionId: String, event: Event) {
|
||||
@ -140,8 +140,8 @@ object RelayPool : Relay.Listener {
|
||||
listeners.forEach { it.onAuth(relay, challenge) }
|
||||
}
|
||||
|
||||
override fun onPaymentRequired(relay: Relay, lnInvoice: String?, description: String?, otherOptionsUrl: String?) {
|
||||
listeners.forEach { it.onPaymentRequired(relay, lnInvoice, description, otherOptionsUrl) }
|
||||
override fun onNotify(relay: Relay, description: String) {
|
||||
listeners.forEach { it.onNotify(relay, description) }
|
||||
}
|
||||
|
||||
private fun updateStatus() {
|
||||
|
@ -0,0 +1,74 @@
|
||||
package com.vitorpamplona.amethyst.ui.actions
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size16dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.quartz.events.EmptyTagList
|
||||
|
||||
@Composable
|
||||
fun NotifyRequestDialog(
|
||||
title: String,
|
||||
textContent: String,
|
||||
buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text(title)
|
||||
},
|
||||
text = {
|
||||
val defaultBackground = MaterialTheme.colorScheme.background
|
||||
val background = remember {
|
||||
mutableStateOf(defaultBackground)
|
||||
}
|
||||
|
||||
TranslatableRichTextViewer(
|
||||
textContent,
|
||||
canPreview = true,
|
||||
Modifier.fillMaxWidth(),
|
||||
EmptyTagList,
|
||||
background,
|
||||
accountViewModel,
|
||||
nav
|
||||
)
|
||||
},
|
||||
confirmButton = {
|
||||
Button(onClick = onDismiss, colors = buttonColors, contentPadding = PaddingValues(horizontal = Size16dp)) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Done,
|
||||
contentDescription = null
|
||||
)
|
||||
Spacer(StdHorzSpacer)
|
||||
Text(stringResource(R.string.error_dialog_button_ok))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
package com.vitorpamplona.amethyst.ui.actions
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.OpenInNew
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ui.components.InvoicePreview
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadValueFromInvoice
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size16dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||
|
||||
@Composable
|
||||
fun PayRequestDialog(
|
||||
title: String,
|
||||
textContent: String,
|
||||
lnInvoice: String?,
|
||||
textContent2: String,
|
||||
otherOptions: String?,
|
||||
buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val uri = LocalUriHandler.current
|
||||
|
||||
val uriOpener: @Composable (() -> Unit) = otherOptions?.let {
|
||||
{
|
||||
Button(
|
||||
onClick = {
|
||||
runCatching {
|
||||
uri.openUri(it)
|
||||
}
|
||||
},
|
||||
colors = buttonColors,
|
||||
contentPadding = PaddingValues(horizontal = Size16dp)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.OpenInNew,
|
||||
contentDescription = null
|
||||
)
|
||||
Spacer(StdHorzSpacer)
|
||||
Text(stringResource(R.string.other_options))
|
||||
}
|
||||
}
|
||||
}
|
||||
} ?: {
|
||||
Row() {}
|
||||
}
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text(title)
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
Text(textContent)
|
||||
Spacer(modifier = StdVertSpacer)
|
||||
if (lnInvoice != null) {
|
||||
LoadValueFromInvoice(lnbcWord = lnInvoice) { invoiceAmount ->
|
||||
Crossfade(targetState = invoiceAmount, label = "PayRequestDialog") {
|
||||
if (it != null) {
|
||||
InvoicePreview(it.invoice, it.amount)
|
||||
} else {
|
||||
Text(
|
||||
text = lnInvoice,
|
||||
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = StdVertSpacer)
|
||||
Text(textContent2)
|
||||
}
|
||||
},
|
||||
confirmButton = uriOpener,
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
onDismiss()
|
||||
}
|
||||
) {
|
||||
Text(text = stringResource(R.string.dismiss))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@ -56,7 +56,7 @@ import androidx.navigation.compose.rememberNavController
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.BooleanType
|
||||
import com.vitorpamplona.amethyst.ui.actions.InformationDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.PayRequestDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.NotifyRequestDialog
|
||||
import com.vitorpamplona.amethyst.ui.buttons.ChannelFabColumn
|
||||
import com.vitorpamplona.amethyst.ui.buttons.NewCommunityNoteButton
|
||||
import com.vitorpamplona.amethyst.ui.buttons.NewImageButton
|
||||
@ -136,7 +136,7 @@ fun MainScreen(
|
||||
}
|
||||
|
||||
DisplayErrorMessages(accountViewModel)
|
||||
DisplayPayMessages(accountViewModel)
|
||||
DisplayNotifyMessages(accountViewModel, nav)
|
||||
|
||||
val navPopBack = remember(navController) {
|
||||
{
|
||||
@ -421,18 +421,15 @@ private fun DisplayErrorMessages(accountViewModel: AccountViewModel) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DisplayPayMessages(accountViewModel: AccountViewModel) {
|
||||
private fun DisplayNotifyMessages(accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
||||
val openDialogMsg = accountViewModel.account.transientPaymentRequests.collectAsStateWithLifecycle(null)
|
||||
|
||||
openDialogMsg.value?.firstOrNull()?.let { request ->
|
||||
PayRequestDialog(
|
||||
stringResource(id = R.string.payment_required_title, request.relayUrl.removePrefix("wss://").removeSuffix("/")),
|
||||
request.description?.let {
|
||||
stringResource(id = R.string.payment_required_explain, it)
|
||||
} ?: stringResource(id = R.string.payment_required_explain_null_description),
|
||||
request.lnInvoice,
|
||||
stringResource(id = R.string.payment_required_explain2),
|
||||
request.otherOptionsUrl
|
||||
NotifyRequestDialog(
|
||||
title = stringResource(id = R.string.payment_required_title, request.relayUrl.removePrefix("wss://").removeSuffix("/")),
|
||||
textContent = request.description,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav
|
||||
) {
|
||||
accountViewModel.dismissPaymentRequest(request)
|
||||
}
|
||||
|
@ -662,10 +662,5 @@
|
||||
After installing, select the app you want to use in the Settings.
|
||||
</string>
|
||||
|
||||
<string name="payment_required_title">Payment Required for %1$s</string>
|
||||
<string name="payment_required_explain">Relay has requested a payment of the invoice below for the %1$s.</string>
|
||||
<string name="payment_required_explain_null_description">Relay has requested a payment of the invoice below</string>
|
||||
<string name="payment_required_explain2">If you do not intend to use this relay anymore, please remove it from your relay list</string>
|
||||
<string name="dismiss">Dismiss</string>
|
||||
<string name="other_options">See other options</string>
|
||||
<string name="payment_required_title">Message from %1$s</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user