Improving the performance and UI of Zap notification messages.
This commit is contained in:
@@ -691,11 +691,22 @@ class Account(
|
|||||||
}
|
}
|
||||||
|
|
||||||
event.plainContent(loggedIn.privKey!!, pubkeyToUse.toByteArray())
|
event.plainContent(loggedIn.privKey!!, pubkeyToUse.toByteArray())
|
||||||
|
} else if (event is LnZapRequestEvent && loggedIn.privKey != null) {
|
||||||
|
LnZapRequestEvent.checkForPrivateZap(event, loggedIn.privKey!!)?.content()
|
||||||
} else {
|
} else {
|
||||||
event?.content()
|
event?.content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun decryptZapContentAuthor(note: Note): Event? {
|
||||||
|
val event = note.event
|
||||||
|
return if (event is LnZapRequestEvent && loggedIn.privKey != null) {
|
||||||
|
LnZapRequestEvent.checkForPrivateZap(event, loggedIn.privKey!!)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun addDontTranslateFrom(languageCode: String) {
|
fun addDontTranslateFrom(languageCode: String) {
|
||||||
dontTranslateFrom = dontTranslateFrom.plus(languageCode)
|
dontTranslateFrom = dontTranslateFrom.plus(languageCode)
|
||||||
liveLanguages.invalidateData()
|
liveLanguages.invalidateData()
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ open class Event(
|
|||||||
@SerializedName("created_at") val createdAt: Long,
|
@SerializedName("created_at") val createdAt: Long,
|
||||||
val kind: Int,
|
val kind: Int,
|
||||||
val tags: List<List<String>>,
|
val tags: List<List<String>>,
|
||||||
var content: String,
|
val content: String,
|
||||||
val sig: HexKey
|
val sig: HexKey
|
||||||
) : EventInterface {
|
) : EventInterface {
|
||||||
override fun id(): HexKey = id
|
override fun id(): HexKey = id
|
||||||
|
|||||||
@@ -149,9 +149,9 @@ class LnZapRequestEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun checkForPrivateZap(zaprequest: Event, loggedInUserPrivKey: ByteArray): Event? {
|
fun checkForPrivateZap(zaprequest: Event, loggedInUserPrivKey: ByteArray): Event? {
|
||||||
val anonTag = zaprequest.tags.firstOrNull { t -> t.count() >= 2 && t[0] == "anon" }
|
val anonTag = zaprequest.tags.firstOrNull { t -> t.size >= 2 && t[0] == "anon" }
|
||||||
if (anonTag != null && anonTag.size > 1) {
|
if (anonTag != null) {
|
||||||
val encnote = anonTag?.elementAt(1)
|
val encnote = anonTag[1]
|
||||||
if (encnote != null && encnote != "") {
|
if (encnote != null && encnote != "") {
|
||||||
try {
|
try {
|
||||||
val note = decryptPrivateZapMessage(encnote, loggedInUserPrivKey, zaprequest.pubKey.toByteArray())
|
val note = decryptPrivateZapMessage(encnote, loggedInUserPrivKey, zaprequest.pubKey.toByteArray())
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.combinedClickable
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
@@ -36,10 +37,7 @@ import com.vitorpamplona.amethyst.model.Account
|
|||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
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.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.LnZapRequestEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
||||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||||
@@ -86,9 +84,11 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
|||||||
.combinedClickable(
|
.combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent is ChannelMessageEvent) {
|
if (noteEvent is ChannelMessageEvent) {
|
||||||
note.channel()?.let {
|
note
|
||||||
navController.navigate("Channel/${it.idHex}")
|
.channel()
|
||||||
}
|
?.let {
|
||||||
|
navController.navigate("Channel/${it.idHex}")
|
||||||
|
}
|
||||||
} else if (noteEvent is PrivateDmEvent) {
|
} else if (noteEvent is PrivateDmEvent) {
|
||||||
val replyAuthorBase =
|
val replyAuthorBase =
|
||||||
(note.event as? PrivateDmEvent)
|
(note.event as? PrivateDmEvent)
|
||||||
@@ -140,16 +140,7 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in multiSetCard.zapEvents) {
|
AuthorGalleryZaps(multiSetCard.zapEvents, navController, account, accountViewModel)
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,12 +213,11 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AuthorGallery(
|
fun AuthorGalleryZaps(
|
||||||
authorNotes: Collection<Note>,
|
authorNotes: Map<Note, Note>,
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
account: Account,
|
account: Account,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel
|
||||||
kind: String = "nonzap"
|
|
||||||
) {
|
) {
|
||||||
val accountState by account.userProfile().live().follows.observeAsState()
|
val accountState by account.userProfile().live().follows.observeAsState()
|
||||||
val accountUser = accountState?.user ?: return
|
val accountUser = accountState?.user ?: return
|
||||||
@@ -235,38 +225,92 @@ fun AuthorGallery(
|
|||||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
FlowRow() {
|
FlowRow() {
|
||||||
authorNotes.forEach {
|
authorNotes.forEach {
|
||||||
if (it.event?.content() != "" && kind == "zap") {
|
AuthorPictureAndComment(it.key, it.value, navController, accountUser, accountViewModel)
|
||||||
Row(Modifier.fillMaxWidth()) {
|
}
|
||||||
FastNoteAuthorPicture(
|
}
|
||||||
note = it,
|
}
|
||||||
navController = navController,
|
}
|
||||||
userAccount = accountUser,
|
|
||||||
size = 35.dp
|
@Composable
|
||||||
)
|
private fun AuthorPictureAndComment(
|
||||||
}
|
zapRequest: Note,
|
||||||
} else {
|
zapEvent: Note,
|
||||||
Row() {
|
navController: NavController,
|
||||||
FastNoteAuthorPicture(
|
accountUser: User,
|
||||||
note = it,
|
accountViewModel: AccountViewModel
|
||||||
navController = navController,
|
) {
|
||||||
userAccount = accountUser,
|
var content by remember { mutableStateOf<Pair<User, String?>>(Pair(zapRequest.author!!, null)) }
|
||||||
size = 35.dp
|
|
||||||
)
|
LaunchedEffect(key1 = zapRequest.idHex) {
|
||||||
}
|
(zapRequest.event as? LnZapRequestEvent)?.let {
|
||||||
|
val decryptedContent = accountViewModel.decryptZap(zapRequest)
|
||||||
|
if (decryptedContent != null) {
|
||||||
|
val author = LocalCache.getOrCreateUser(decryptedContent.pubKey)
|
||||||
|
content = Pair(author, decryptedContent.content)
|
||||||
|
} else {
|
||||||
|
if (!zapRequest.event?.content().isNullOrBlank()) {
|
||||||
|
content = Pair(zapRequest.author!!, zapRequest.event?.content())
|
||||||
}
|
}
|
||||||
if (it.event?.content() != "" && kind == "zap") {
|
}
|
||||||
Row(Modifier.fillMaxWidth()) {
|
}
|
||||||
it.event?.let {
|
}
|
||||||
TranslatableRichTextViewer(
|
|
||||||
content = it.content(),
|
AuthorPictureAndComment(content.first, content.second, navController, accountUser, accountViewModel)
|
||||||
canPreview = true,
|
}
|
||||||
tags = null,
|
|
||||||
backgroundColor = MaterialTheme.colors.background,
|
@Composable
|
||||||
accountViewModel = accountViewModel,
|
private fun AuthorPictureAndComment(
|
||||||
navController = navController
|
author: User,
|
||||||
)
|
comment: String?,
|
||||||
}
|
navController: NavController,
|
||||||
}
|
accountUser: User,
|
||||||
|
accountViewModel: AccountViewModel
|
||||||
|
) {
|
||||||
|
val modifier = if (!comment.isNullOrBlank()) {
|
||||||
|
Modifier.fillMaxWidth()
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
FastNoteAuthorPicture(
|
||||||
|
author = author,
|
||||||
|
navController = navController,
|
||||||
|
userAccount = accountUser,
|
||||||
|
size = 35.dp
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!comment.isNullOrBlank()) {
|
||||||
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
|
TranslatableRichTextViewer(
|
||||||
|
content = comment,
|
||||||
|
canPreview = false,
|
||||||
|
tags = null,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
backgroundColor = MaterialTheme.colors.background,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AuthorGallery(
|
||||||
|
authorNotes: Collection<Note>,
|
||||||
|
navController: NavController,
|
||||||
|
account: Account,
|
||||||
|
accountViewModel: AccountViewModel
|
||||||
|
) {
|
||||||
|
val accountState by account.userProfile().live().follows.observeAsState()
|
||||||
|
val accountUser = accountState?.user ?: return
|
||||||
|
|
||||||
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
|
FlowRow() {
|
||||||
|
authorNotes.forEach {
|
||||||
|
val author = it.author
|
||||||
|
if (author != null) {
|
||||||
|
AuthorPictureAndComment(author, null, navController, accountUser, accountViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,15 +319,12 @@ fun AuthorGallery(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FastNoteAuthorPicture(
|
fun FastNoteAuthorPicture(
|
||||||
note: Note,
|
author: User,
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
userAccount: User,
|
userAccount: User,
|
||||||
size: Dp,
|
size: Dp,
|
||||||
pictureModifier: Modifier = Modifier
|
pictureModifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
// can't be null if here
|
|
||||||
val author = note.author ?: return
|
|
||||||
|
|
||||||
val userState by author.live().metadata.observeAsState()
|
val userState by author.live().metadata.observeAsState()
|
||||||
val user = userState?.user ?: return
|
val user = userState?.user ?: return
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.vitorpamplona.amethyst.model.AccountState
|
|||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver
|
import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver
|
||||||
|
import com.vitorpamplona.amethyst.service.model.Event
|
||||||
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.PayInvoiceErrorResponse
|
import com.vitorpamplona.amethyst.service.model.PayInvoiceErrorResponse
|
||||||
import com.vitorpamplona.amethyst.service.model.ReportEvent
|
import com.vitorpamplona.amethyst.service.model.ReportEvent
|
||||||
@@ -164,6 +165,10 @@ class AccountViewModel(private val account: Account) : ViewModel() {
|
|||||||
return account.decryptContent(note)
|
return account.decryptContent(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun decryptZap(note: Note): Event? {
|
||||||
|
return account.decryptZapContentAuthor(note)
|
||||||
|
}
|
||||||
|
|
||||||
fun hide(user: User) {
|
fun hide(user: User) {
|
||||||
account.hideUser(user.pubkeyHex)
|
account.hideUser(user.pubkeyHex)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user