Merge pull request #372 from believethehype/privatezaps
Update for Custom Zaps
This commit is contained in:
@@ -11,6 +11,7 @@ import com.vitorpamplona.amethyst.model.toByteArray
|
||||
import com.vitorpamplona.amethyst.service.model.ContactListEvent
|
||||
import com.vitorpamplona.amethyst.service.model.Event
|
||||
import com.vitorpamplona.amethyst.service.model.Event.Companion.getRefinedEvent
|
||||
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
||||
import com.vitorpamplona.amethyst.ui.note.Nip47URI
|
||||
import fr.acinq.secp256k1.Hex
|
||||
import nostr.postr.Persona
|
||||
@@ -42,6 +43,7 @@ private object PrefKeys {
|
||||
const val LANGUAGE_PREFS = "languagePreferences"
|
||||
const val TRANSLATE_TO = "translateTo"
|
||||
const val ZAP_AMOUNTS = "zapAmounts"
|
||||
const val DEFAULT_ZAPTYPE = "defaultZapType"
|
||||
const val ZAP_PAYMENT_REQUEST_SERVER = "zapPaymentServer"
|
||||
const val LATEST_CONTACT_LIST = "latestContactList"
|
||||
const val HIDE_DELETE_REQUEST_DIALOG = "hide_delete_request_dialog"
|
||||
@@ -191,6 +193,7 @@ object LocalPreferences {
|
||||
putString(PrefKeys.LANGUAGE_PREFS, gson.toJson(account.languagePreferences))
|
||||
putString(PrefKeys.TRANSLATE_TO, account.translateTo)
|
||||
putString(PrefKeys.ZAP_AMOUNTS, gson.toJson(account.zapAmountChoices))
|
||||
putString(PrefKeys.DEFAULT_ZAPTYPE, gson.toJson(account.defaultZapType))
|
||||
putString(PrefKeys.ZAP_PAYMENT_REQUEST_SERVER, gson.toJson(account.zapPaymentRequest))
|
||||
putString(PrefKeys.LATEST_CONTACT_LIST, Event.gson.toJson(account.backupContactList))
|
||||
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, account.hideDeleteRequestDialog)
|
||||
@@ -217,6 +220,11 @@ object LocalPreferences {
|
||||
object : TypeToken<List<Long>>() {}.type
|
||||
) ?: listOf(500L, 1000L, 5000L)
|
||||
|
||||
val defaultZapType = gson.fromJson(
|
||||
getString(PrefKeys.DEFAULT_ZAPTYPE, "PUBLIC"),
|
||||
object : TypeToken<LnZapEvent.ZapType>() {}.type
|
||||
) ?: LnZapEvent.ZapType.PUBLIC
|
||||
|
||||
val zapPaymentRequestServer = try {
|
||||
getString(PrefKeys.ZAP_PAYMENT_REQUEST_SERVER, null)?.let {
|
||||
gson.fromJson(it, Nip47URI::class.java)
|
||||
@@ -260,6 +268,7 @@ object LocalPreferences {
|
||||
languagePreferences,
|
||||
translateTo,
|
||||
zapAmountChoices,
|
||||
defaultZapType,
|
||||
zapPaymentRequestServer,
|
||||
hideDeleteRequestDialog,
|
||||
hideBlockAlertDialog,
|
||||
|
||||
@@ -43,6 +43,7 @@ class Account(
|
||||
var languagePreferences: Map<String, String> = mapOf(),
|
||||
var translateTo: String = Locale.getDefault().language,
|
||||
var zapAmountChoices: List<Long> = listOf(500L, 1000L, 5000L),
|
||||
var defaultZapType: LnZapEvent.ZapType = LnZapEvent.ZapType.PUBLIC,
|
||||
var zapPaymentRequest: Nip47URI? = null,
|
||||
var hideDeleteRequestDialog: Boolean = false,
|
||||
var hideBlockAlertDialog: Boolean = false,
|
||||
@@ -625,6 +626,12 @@ class Account(
|
||||
saveable.invalidateData()
|
||||
}
|
||||
|
||||
fun changeDefaultZapType(zapType: LnZapEvent.ZapType) {
|
||||
defaultZapType = zapType
|
||||
live.invalidateData()
|
||||
saveable.invalidateData()
|
||||
}
|
||||
|
||||
fun changeZapAmounts(newAmounts: List<Long>) {
|
||||
zapAmountChoices = newAmounts
|
||||
live.invalidateData()
|
||||
|
||||
@@ -594,17 +594,6 @@ object LocalCache {
|
||||
|
||||
fun consume(event: LnZapEvent) {
|
||||
val note = getOrCreateNote(event.id)
|
||||
|
||||
var decryptedContent = LnZapRequestEvent.checkForPrivateZap(event.zapRequest!!, account.loggedIn.privKey!!)
|
||||
if (decryptedContent != null) {
|
||||
Log.e(
|
||||
"DC",
|
||||
"Decrypted Content from Anon Tag: Sender: {${decryptedContent.pubKey}}, Message: {${decryptedContent.content}} "
|
||||
|
||||
// TODO Update Notification with this Sender and Message
|
||||
)
|
||||
}
|
||||
|
||||
// Already processed this event.
|
||||
if (note.event != null) return
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ open class Event(
|
||||
@SerializedName("created_at") val createdAt: Long,
|
||||
val kind: Int,
|
||||
val tags: List<List<String>>,
|
||||
val content: String,
|
||||
var content: String,
|
||||
val sig: HexKey
|
||||
) : EventInterface {
|
||||
override fun id(): HexKey = id
|
||||
|
||||
@@ -37,7 +37,6 @@ import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver
|
||||
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
@@ -136,7 +135,7 @@ fun InvoiceRequest(
|
||||
Button(
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 10.dp),
|
||||
onClick = {
|
||||
val zapRequest = account.createZapRequestFor(toUserPubKeyHex, message, LnZapEvent.ZapType.PUBLIC)
|
||||
val zapRequest = account.createZapRequestFor(toUserPubKeyHex, message, account.defaultZapType)
|
||||
|
||||
LightningAddressResolver().lnAddressInvoice(
|
||||
lud16,
|
||||
|
||||
@@ -36,8 +36,13 @@ import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.NostrAccountDataSource
|
||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
||||
import com.vitorpamplona.amethyst.service.model.Event
|
||||
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
||||
import com.vitorpamplona.amethyst.service.model.LnZapRequestEvent
|
||||
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||
import com.vitorpamplona.amethyst.ui.screen.MultiSetCard
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
@@ -135,7 +140,16 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
||||
)
|
||||
}
|
||||
|
||||
AuthorGallery(multiSetCard.zapEvents.keys, navController, account)
|
||||
for (i in multiSetCard.zapEvents) {
|
||||
var decryptedContent = (i.value.event as LnZapEvent).zapRequest?.let {
|
||||
LnZapRequestEvent.checkForPrivateZap(it, NostrAccountDataSource.account.loggedIn.privKey!!)
|
||||
}
|
||||
if (decryptedContent != null) {
|
||||
(i.key.event as Event).content = decryptedContent.content
|
||||
i.key.author = LocalCache.getOrCreateUser(decryptedContent.pubKey)
|
||||
}
|
||||
}
|
||||
AuthorGallery(multiSetCard.zapEvents.keys, navController, account, accountViewModel, "zap")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +170,7 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
||||
)
|
||||
}
|
||||
|
||||
AuthorGallery(multiSetCard.boostEvents, navController, account)
|
||||
AuthorGallery(multiSetCard.boostEvents, navController, account, accountViewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +191,7 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
||||
)
|
||||
}
|
||||
|
||||
AuthorGallery(multiSetCard.likeEvents, navController, account)
|
||||
AuthorGallery(multiSetCard.likeEvents, navController, account, accountViewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +225,9 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
||||
fun AuthorGallery(
|
||||
authorNotes: Collection<Note>,
|
||||
navController: NavController,
|
||||
account: Account
|
||||
account: Account,
|
||||
accountViewModel: AccountViewModel,
|
||||
kind: String = "nonzap"
|
||||
) {
|
||||
val accountState by account.userProfile().live().follows.observeAsState()
|
||||
val accountUser = accountState?.user ?: return
|
||||
@@ -219,12 +235,39 @@ fun AuthorGallery(
|
||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||
FlowRow() {
|
||||
authorNotes.forEach {
|
||||
FastNoteAuthorPicture(
|
||||
note = it,
|
||||
navController = navController,
|
||||
userAccount = accountUser,
|
||||
size = 35.dp
|
||||
)
|
||||
if (it.event?.content() != "" && kind == "zap") {
|
||||
Row(Modifier.fillMaxWidth()) {
|
||||
FastNoteAuthorPicture(
|
||||
note = it,
|
||||
navController = navController,
|
||||
userAccount = accountUser,
|
||||
size = 35.dp
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Row() {
|
||||
FastNoteAuthorPicture(
|
||||
note = it,
|
||||
navController = navController,
|
||||
userAccount = accountUser,
|
||||
size = 35.dp
|
||||
)
|
||||
}
|
||||
}
|
||||
if (it.event?.content() != "" && kind == "zap") {
|
||||
Row(Modifier.fillMaxWidth()) {
|
||||
it.event?.let {
|
||||
TranslatableRichTextViewer(
|
||||
content = it.content(),
|
||||
canPreview = true,
|
||||
tags = null,
|
||||
backgroundColor = MaterialTheme.colors.background,
|
||||
accountViewModel = accountViewModel,
|
||||
navController = navController
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,7 +288,6 @@ fun FastNoteAuthorPicture(
|
||||
val user = userState?.user ?: return
|
||||
|
||||
val showFollowingMark = userAccount.isFollowingCached(user) || user === userAccount
|
||||
|
||||
UserPicture(
|
||||
userHex = user.pubkeyHex,
|
||||
userPicture = user.profilePicture(),
|
||||
|
||||
@@ -250,7 +250,7 @@ fun ZapVote(
|
||||
zappingProgress = it
|
||||
}
|
||||
},
|
||||
zapType = LnZapEvent.ZapType.PUBLIC
|
||||
zapType = account.defaultZapType
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -55,7 +55,6 @@ import coil.request.CachePolicy
|
||||
import coil.request.ImageRequest
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPostView
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
@@ -365,7 +364,7 @@ fun ZapReaction(
|
||||
zappingProgress = it
|
||||
}
|
||||
},
|
||||
zapType = LnZapEvent.ZapType.PUBLIC
|
||||
zapType = account.defaultZapType
|
||||
)
|
||||
}
|
||||
} else if (account.zapAmountChoices.size > 1) {
|
||||
@@ -562,7 +561,7 @@ fun ZapAmountChoicePopup(
|
||||
context,
|
||||
onError,
|
||||
onProgress,
|
||||
LnZapEvent.ZapType.PUBLIC
|
||||
account.defaultZapType
|
||||
)
|
||||
onDismiss()
|
||||
}
|
||||
@@ -588,7 +587,7 @@ fun ZapAmountChoicePopup(
|
||||
context,
|
||||
onError,
|
||||
onProgress,
|
||||
LnZapEvent.ZapType.PUBLIC
|
||||
account.defaultZapType
|
||||
)
|
||||
onDismiss()
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import kotlinx.coroutines.launch
|
||||
|
||||
class ZapOptionstViewModel : ViewModel() {
|
||||
private var account: Account? = null
|
||||
|
||||
var customAmount by mutableStateOf(TextFieldValue("21"))
|
||||
var customMessage by mutableStateOf(TextFieldValue(""))
|
||||
|
||||
@@ -73,7 +74,7 @@ fun ZapCustomDialog(onClose: () -> Unit, account: Account, accountViewModel: Acc
|
||||
)
|
||||
|
||||
val zapOptions = zapTypes.map { it.second }
|
||||
var selectedZapType by remember { mutableStateOf(zapTypes[0]) }
|
||||
var selectedZapType by remember { mutableStateOf(account.defaultZapType) }
|
||||
|
||||
Dialog(
|
||||
onDismissRequest = { onClose() },
|
||||
@@ -116,7 +117,7 @@ fun ZapCustomDialog(onClose: () -> Unit, account: Account, accountViewModel: Acc
|
||||
zappingProgress = it
|
||||
}
|
||||
},
|
||||
zapType = selectedZapType.first
|
||||
zapType = selectedZapType
|
||||
)
|
||||
}
|
||||
onClose()
|
||||
@@ -163,7 +164,15 @@ fun ZapCustomDialog(onClose: () -> Unit, account: Account, accountViewModel: Acc
|
||||
) {
|
||||
OutlinedTextField(
|
||||
// stringResource(R.string.new_amount_in_sats
|
||||
label = { Text(text = stringResource(id = R.string.custom_zaps_add_a_message)) },
|
||||
label = {
|
||||
if (selectedZapType == LnZapEvent.ZapType.PUBLIC || selectedZapType == LnZapEvent.ZapType.ANONYMOUS) {
|
||||
Text(text = stringResource(id = R.string.custom_zaps_add_a_message))
|
||||
} else if (selectedZapType == LnZapEvent.ZapType.PRIVATE) {
|
||||
Text(text = stringResource(id = R.string.custom_zaps_add_a_message_private))
|
||||
} else if (selectedZapType == LnZapEvent.ZapType.NONZAP) {
|
||||
Text(text = stringResource(id = R.string.custom_zaps_add_a_message_nonzap))
|
||||
}
|
||||
},
|
||||
value = postViewModel.customMessage,
|
||||
onValueChange = {
|
||||
postViewModel.customMessage = it
|
||||
@@ -186,10 +195,11 @@ fun ZapCustomDialog(onClose: () -> Unit, account: Account, accountViewModel: Acc
|
||||
}
|
||||
TextSpinner(
|
||||
label = "Zap Type",
|
||||
placeholder = "Public",
|
||||
placeholder = zapTypes.filter { it.first == account.defaultZapType }.first().second,
|
||||
options = zapOptions,
|
||||
onSelect = {
|
||||
selectedZapType = zapTypes[it]
|
||||
selectedZapType = zapTypes[it].first
|
||||
account.changeDefaultZapType(selectedZapType)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
@@ -287,6 +287,9 @@
|
||||
<string name="looking_for_event">"Looking for Event %1$s"</string>
|
||||
|
||||
<string name="custom_zaps_add_a_message">Add a public message</string>
|
||||
<string name="custom_zaps_add_a_message_private">Add a private message</string>
|
||||
<string name="custom_zaps_add_a_message_nonzap">Add an invoice message</string>
|
||||
|
||||
<string name="custom_zaps_add_a_message_example">Thank you for all your work!</string>
|
||||
|
||||
<string name="lightning_create_and_add_invoice">Create and Add</string>
|
||||
|
||||
Reference in New Issue
Block a user