diff --git a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index c2c21bb24..f71ef1439 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -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>() {}.type ) ?: listOf(500L, 1000L, 5000L) + val defaultZapType = gson.fromJson( + getString(PrefKeys.DEFAULT_ZAPTYPE, "PUBLIC"), + object : TypeToken() {}.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, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index df4c61fb7..0aa093724 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -43,6 +43,7 @@ class Account( var languagePreferences: Map = mapOf(), var translateTo: String = Locale.getDefault().language, var zapAmountChoices: List = 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) { zapAmountChoices = newAmounts live.invalidateData() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 140a30849..640318b2f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -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 diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/Event.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/Event.kt index 6d857328c..f5924fcd5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/Event.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/Event.kt @@ -19,7 +19,7 @@ open class Event( @SerializedName("created_at") val createdAt: Long, val kind: Int, val tags: List>, - val content: String, + var content: String, val sig: HexKey ) : EventInterface { override fun id(): HexKey = id diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoiceRequest.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoiceRequest.kt index 06e38c773..a5c417728 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoiceRequest.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/InvoiceRequest.kt @@ -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, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt index 537649905..5148c0632 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt @@ -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, 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(), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt index 26e83cf91..28ffb025f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt @@ -250,7 +250,7 @@ fun ZapVote( zappingProgress = it } }, - zapType = LnZapEvent.ZapType.PUBLIC + zapType = account.defaultZapType ) } } else { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index 27234a2b9..f334df087 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -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() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt index 6239a0abb..7ea074c96 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt @@ -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() ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 504fcfae0..5c0125fb8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -287,6 +287,9 @@ "Looking for Event %1$s" Add a public message + Add a private message + Add an invoice message + Thank you for all your work! Create and Add