mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-10 13:47:49 +01:00
Improves caching of encrypted DMs:
- Migrates caching of decrypted value outside of the Event class - Removes encrypted parts of NIP-17 from the cache - Removes old NIP-04 messages from the cache - Avoids deleting new NIP-17 plain text chats from memory
This commit is contained in:
@@ -2290,14 +2290,16 @@ class Account(
|
||||
val mine = signedEvents.wraps.filter { (it.recipientPubKey() == signer.pubKey) }
|
||||
|
||||
mine.forEach { giftWrap ->
|
||||
giftWrap.cachedGift(signer) { gift ->
|
||||
giftWrap.unwrap(signer) { gift ->
|
||||
if (gift is SealedGossipEvent) {
|
||||
gift.cachedGossip(signer) { gossip -> LocalCache.justConsume(gossip, null) }
|
||||
} else {
|
||||
LocalCache.justConsume(gift, null)
|
||||
gift.unseal(signer) { gossip ->
|
||||
LocalCache.justConsume(gossip, null)
|
||||
}
|
||||
}
|
||||
|
||||
LocalCache.justConsume(gift, null)
|
||||
}
|
||||
|
||||
LocalCache.consume(giftWrap, null)
|
||||
}
|
||||
|
||||
@@ -2842,7 +2844,7 @@ class Account(
|
||||
) {
|
||||
if (!isWriteable()) return
|
||||
|
||||
return event.cachedGift(signer, onReady)
|
||||
return event.unwrap(signer, onReady)
|
||||
}
|
||||
|
||||
fun unseal(
|
||||
@@ -2851,7 +2853,7 @@ class Account(
|
||||
) {
|
||||
if (!isWriteable()) return
|
||||
|
||||
return event.cachedGossip(signer, onReady)
|
||||
return event.unseal(signer, onReady)
|
||||
}
|
||||
|
||||
fun cachedDecryptContent(note: Note): String? = cachedDecryptContent(note.event)
|
||||
|
||||
@@ -22,7 +22,9 @@ package com.vitorpamplona.amethyst.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Stable
|
||||
@@ -75,7 +77,7 @@ class Chatroom {
|
||||
fun senderIntersects(keySet: Set<HexKey>): Boolean = authors.any { it.pubkeyHex in keySet }
|
||||
|
||||
fun pruneMessagesToTheLatestOnly(): Set<Note> {
|
||||
val sorted = roomMessages.sortedWith(compareBy({ it.createdAt() }, { it.idHex })).reversed()
|
||||
val sorted = roomMessages.sortedWith(DefaultFeedOrder)
|
||||
|
||||
val toKeep =
|
||||
if ((sorted.firstOrNull()?.createdAt() ?: 0) > TimeUtils.oneWeekAgo()) {
|
||||
@@ -84,7 +86,7 @@ class Chatroom {
|
||||
} else {
|
||||
// Old messages, keep the last one.
|
||||
sorted.take(1).toSet()
|
||||
} + sorted.filter { it.liveSet?.isInUse() ?: false }
|
||||
} + sorted.filter { it.liveSet?.isInUse() ?: false } + sorted.filter { it.event !is PrivateDmEvent }
|
||||
|
||||
val toRemove = roomMessages.minus(toKeep)
|
||||
roomMessages = toKeep
|
||||
|
||||
@@ -299,10 +299,18 @@ object NostrAccountDataSource : AmethystNostrDataSource("AccountData") {
|
||||
override fun consume(
|
||||
event: Event,
|
||||
relay: Relay,
|
||||
) {
|
||||
if (LocalCache.justVerify(event)) {
|
||||
consumeAlreadyVerified(event, relay)
|
||||
}
|
||||
}
|
||||
|
||||
fun consumeAlreadyVerified(
|
||||
event: Event,
|
||||
relay: Relay,
|
||||
) {
|
||||
checkNotInMainThread()
|
||||
|
||||
if (LocalCache.justVerify(event)) {
|
||||
when (event) {
|
||||
is PrivateOutboxRelayListEvent -> {
|
||||
val note = LocalCache.getAddressableNoteIfExists(event.addressTag())
|
||||
@@ -339,14 +347,22 @@ object NostrAccountDataSource : AmethystNostrDataSource("AccountData") {
|
||||
val noteEvent = note?.event as? GiftWrapEvent
|
||||
if (noteEvent != null) {
|
||||
if (relay.brief !in note.relays) {
|
||||
noteEvent.cachedGift(account.signer) {
|
||||
LocalCache.justConsume(noteEvent, relay)
|
||||
|
||||
noteEvent.innerEventId?.let {
|
||||
(LocalCache.getNoteIfExists(it)?.event as? Event)?.let {
|
||||
this.consumeAlreadyVerified(it, relay)
|
||||
}
|
||||
} ?: run {
|
||||
event.unwrap(account.signer) {
|
||||
this.consume(it, relay)
|
||||
noteEvent.innerEventId = it.id
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// new event
|
||||
event.cachedGift(account.signer) {
|
||||
event.unwrap(account.signer) {
|
||||
LocalCache.justConsume(event, relay)
|
||||
this.consume(it, relay)
|
||||
}
|
||||
@@ -359,15 +375,22 @@ object NostrAccountDataSource : AmethystNostrDataSource("AccountData") {
|
||||
val noteEvent = note?.event as? SealedGossipEvent
|
||||
if (noteEvent != null) {
|
||||
if (relay.brief !in note.relays) {
|
||||
// adds the relay to seal and inner chat
|
||||
noteEvent.cachedGossip(account.signer) {
|
||||
LocalCache.consume(noteEvent, relay)
|
||||
LocalCache.justConsume(noteEvent, relay)
|
||||
|
||||
noteEvent.innerEventId?.let {
|
||||
(LocalCache.getNoteIfExists(it)?.event as? Event)?.let {
|
||||
LocalCache.justConsume(it, relay)
|
||||
}
|
||||
} ?: run {
|
||||
event.unseal(account.signer) {
|
||||
LocalCache.justConsume(it, relay)
|
||||
noteEvent.innerEventId = it.id
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// new event
|
||||
event.cachedGossip(account.signer) {
|
||||
event.unseal(account.signer) {
|
||||
LocalCache.justConsume(event, relay)
|
||||
LocalCache.justConsume(it, relay)
|
||||
}
|
||||
@@ -393,7 +416,6 @@ object NostrAccountDataSource : AmethystNostrDataSource("AccountData") {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun markAsSeenOnRelay(
|
||||
eventId: String,
|
||||
@@ -409,16 +431,30 @@ object NostrAccountDataSource : AmethystNostrDataSource("AccountData") {
|
||||
}
|
||||
|
||||
private fun markInnerAsSeenOnRelay(
|
||||
noteEvent: EventInterface,
|
||||
newNoteEvent: EventInterface,
|
||||
relay: Relay,
|
||||
) {
|
||||
LocalCache.getNoteIfExists(noteEvent.id())?.addRelay(relay)
|
||||
markInnerAsSeenOnRelay(newNoteEvent.id(), relay)
|
||||
}
|
||||
|
||||
private fun markInnerAsSeenOnRelay(
|
||||
eventId: HexKey,
|
||||
relay: Relay,
|
||||
) {
|
||||
val note = LocalCache.getNoteIfExists(eventId)
|
||||
|
||||
if (note != null) {
|
||||
note.addRelay(relay)
|
||||
|
||||
val noteEvent = note.event
|
||||
if (noteEvent is GiftWrapEvent) {
|
||||
noteEvent.cachedGift(account.signer) { gift -> markInnerAsSeenOnRelay(gift, relay) }
|
||||
noteEvent.innerEventId?.let {
|
||||
markInnerAsSeenOnRelay(it, relay)
|
||||
}
|
||||
} else if (noteEvent is SealedGossipEvent) {
|
||||
noteEvent.cachedGossip(account.signer) { rumor ->
|
||||
markInnerAsSeenOnRelay(rumor, relay)
|
||||
noteEvent.innerEventId?.let {
|
||||
markInnerAsSeenOnRelay(it, relay)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,8 @@ class EventNotificationConsumer(
|
||||
pushWrappedEvent: GiftWrapEvent,
|
||||
account: Account,
|
||||
) {
|
||||
pushWrappedEvent.cachedGift(account.signer) { notificationEvent ->
|
||||
// no need to cache
|
||||
pushWrappedEvent.unwrap(account.signer) { notificationEvent ->
|
||||
val consumed = LocalCache.hasConsumed(notificationEvent)
|
||||
val verified = LocalCache.justVerify(notificationEvent)
|
||||
Log.d("EventNotificationConsumer", "New Notification ${notificationEvent.kind} ${notificationEvent.id} Arrived for ${account.userProfile().toBestDisplayName()} consumed= $consumed && verified= $verified")
|
||||
@@ -111,15 +112,19 @@ class EventNotificationConsumer(
|
||||
|
||||
when (event) {
|
||||
is GiftWrapEvent -> {
|
||||
event.cachedGift(account.signer) { unwrapAndConsume(it, account, onReady) }
|
||||
event.unwrap(account.signer) {
|
||||
unwrapAndConsume(it, account, onReady)
|
||||
LocalCache.justConsume(event, null)
|
||||
}
|
||||
}
|
||||
is SealedGossipEvent -> {
|
||||
event.cachedGossip(account.signer) {
|
||||
event.unseal(account.signer) {
|
||||
if (!LocalCache.hasConsumed(it)) {
|
||||
// this is not verifiable
|
||||
LocalCache.justConsume(it, null)
|
||||
onReady(it)
|
||||
}
|
||||
LocalCache.justConsume(event, null)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
||||
@@ -1364,7 +1364,18 @@ class AccountViewModel(
|
||||
) {
|
||||
when (event) {
|
||||
is GiftWrapEvent -> {
|
||||
event.cachedGift(account.signer) {
|
||||
event.innerEventId?.let {
|
||||
val existingNote = LocalCache.getNoteIfExists(it)
|
||||
if (existingNote != null) {
|
||||
unwrapIfNeeded(existingNote.event, onReady)
|
||||
} else {
|
||||
event.unwrap(account.signer) {
|
||||
LocalCache.verifyAndConsume(it, null)
|
||||
unwrapIfNeeded(it, onReady)
|
||||
}
|
||||
}
|
||||
} ?: run {
|
||||
event.unwrap(account.signer) {
|
||||
val existingNote = LocalCache.getNoteIfExists(it.id)
|
||||
if (existingNote != null) {
|
||||
unwrapIfNeeded(existingNote.event, onReady)
|
||||
@@ -1374,8 +1385,21 @@ class AccountViewModel(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is SealedGossipEvent -> {
|
||||
event.cachedGossip(account.signer) {
|
||||
event.innerEventId?.let {
|
||||
val existingNote = LocalCache.getNoteIfExists(it)
|
||||
if (existingNote != null) {
|
||||
unwrapIfNeeded(existingNote.event, onReady)
|
||||
} else {
|
||||
event.unseal(account.signer) {
|
||||
// this is not verifiable
|
||||
LocalCache.justConsume(it, null)
|
||||
unwrapIfNeeded(it, onReady)
|
||||
}
|
||||
}
|
||||
} ?: run {
|
||||
event.unseal(account.signer) {
|
||||
val existingNote = LocalCache.getNoteIfExists(it.id)
|
||||
if (existingNote != null) {
|
||||
unwrapIfNeeded(existingNote.event, onReady)
|
||||
@@ -1386,6 +1410,7 @@ class AccountViewModel(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
event?.id()?.let {
|
||||
LocalCache.getNoteIfExists(it)?.let {
|
||||
|
||||
@@ -43,10 +43,15 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.navigation.Route
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.events.ChannelCreateEvent
|
||||
import com.vitorpamplona.quartz.events.ChannelMessageEvent
|
||||
import com.vitorpamplona.quartz.events.ChannelMetadataEvent
|
||||
import com.vitorpamplona.quartz.events.ChatroomKeyable
|
||||
import com.vitorpamplona.quartz.events.EventInterface
|
||||
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
||||
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
|
||||
import com.vitorpamplona.quartz.events.LiveActivitiesEvent
|
||||
import com.vitorpamplona.quartz.events.SealedGossipEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -104,7 +109,7 @@ fun LoadRedirectScreen(
|
||||
val event = note.event
|
||||
|
||||
if (event != null) {
|
||||
withContext(Dispatchers.IO) { redirect(event, note, accountViewModel, nav) }
|
||||
withContext(Dispatchers.IO) { redirect(event, accountViewModel, nav) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,35 +123,60 @@ fun LoadRedirectScreen(
|
||||
}
|
||||
|
||||
fun redirect(
|
||||
event: EventInterface,
|
||||
note: Note,
|
||||
eventId: HexKey,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val channelHex = note.channelHex()
|
||||
LocalCache.getNoteIfExists(eventId)?.event?.let {
|
||||
redirect(it, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
|
||||
fun redirect(
|
||||
event: EventInterface,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val channelHex =
|
||||
if (
|
||||
event is ChannelMessageEvent ||
|
||||
event is ChannelMetadataEvent ||
|
||||
event is ChannelCreateEvent ||
|
||||
event is LiveActivitiesChatMessageEvent ||
|
||||
event is LiveActivitiesEvent
|
||||
) {
|
||||
(event as? ChannelMessageEvent)?.channel()
|
||||
?: (event as? ChannelMetadataEvent)?.channel()
|
||||
?: (event as? ChannelCreateEvent)?.id
|
||||
?: (event as? LiveActivitiesChatMessageEvent)?.activity()?.toTag()
|
||||
?: (event as? LiveActivitiesEvent)?.address()?.toTag()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
if (event is GiftWrapEvent) {
|
||||
accountViewModel.unwrap(event) { redirect(it, note, accountViewModel, nav) }
|
||||
} else if (event is SealedGossipEvent) {
|
||||
accountViewModel.unseal(event) { redirect(it, note, accountViewModel, nav) }
|
||||
} else {
|
||||
if (event == null) {
|
||||
// stay here, loading
|
||||
} else if (event is ChannelCreateEvent) {
|
||||
nav("Channel/${note.idHex}")
|
||||
} else if (event is ChatroomKeyable) {
|
||||
note.author?.let {
|
||||
val withKey =
|
||||
(event as ChatroomKeyable).chatroomKey(accountViewModel.userProfile().pubkeyHex)
|
||||
|
||||
accountViewModel.userProfile().createChatroom(withKey)
|
||||
|
||||
nav("Room/${withKey.hashCode()}")
|
||||
event.innerEventId?.let {
|
||||
redirect(it, accountViewModel, nav)
|
||||
} ?: run {
|
||||
accountViewModel.unwrap(event) { redirect(it, accountViewModel, nav) }
|
||||
}
|
||||
} else if (event is SealedGossipEvent) {
|
||||
event.innerEventId?.let {
|
||||
redirect(it, accountViewModel, nav)
|
||||
} ?: run {
|
||||
accountViewModel.unseal(event) { redirect(it, accountViewModel, nav) }
|
||||
}
|
||||
} else {
|
||||
if (event is ChannelCreateEvent) {
|
||||
nav("Channel/${event.id()}")
|
||||
} else if (event is ChatroomKeyable) {
|
||||
val withKey = event.chatroomKey(accountViewModel.userProfile().pubkeyHex)
|
||||
accountViewModel.userProfile().createChatroom(withKey)
|
||||
nav("Room/${withKey.hashCode()}")
|
||||
} else if (channelHex != null) {
|
||||
nav("Channel/$channelHex")
|
||||
} else {
|
||||
nav("Note/${note.idHex}")
|
||||
nav("Note/${event.id()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.events
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.crypto.KeyPair
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.signers.NostrSignerInternal
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
||||
import com.vitorpamplona.quartz.utils.pointerSizeInBytes
|
||||
|
||||
@Immutable
|
||||
@@ -37,11 +39,11 @@ class GiftWrapEvent(
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
@Transient private var cachedInnerEvent: Map<HexKey, Event?> = mapOf()
|
||||
@Transient var innerEventId: HexKey? = null
|
||||
|
||||
override fun countMemory(): Long =
|
||||
super.countMemory() +
|
||||
32 + (cachedInnerEvent.values.sumOf { pointerSizeInBytes + (it?.countMemory() ?: 0) }) // rough calculation
|
||||
pointerSizeInBytes + (innerEventId?.bytesUsedInMemory() ?: 0)
|
||||
|
||||
fun copyNoContent(): GiftWrapEvent {
|
||||
val copy =
|
||||
@@ -54,48 +56,38 @@ class GiftWrapEvent(
|
||||
sig,
|
||||
)
|
||||
|
||||
copy.cachedInnerEvent = cachedInnerEvent
|
||||
copy.innerEventId = innerEventId
|
||||
|
||||
return copy
|
||||
}
|
||||
|
||||
override fun isContentEncoded() = true
|
||||
|
||||
fun preCachedGift(signer: NostrSigner): Event? = cachedInnerEvent[signer.pubKey]
|
||||
|
||||
fun addToCache(
|
||||
pubKey: HexKey,
|
||||
gift: Event,
|
||||
) {
|
||||
cachedInnerEvent = cachedInnerEvent + Pair(pubKey, gift)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
message = "Heavy caching was removed from this class due to high memory use. Cache it separatedly",
|
||||
replaceWith = ReplaceWith("unwrap"),
|
||||
)
|
||||
fun cachedGift(
|
||||
signer: NostrSigner,
|
||||
onReady: (Event) -> Unit,
|
||||
) {
|
||||
cachedInnerEvent[signer.pubKey]?.let {
|
||||
onReady(it)
|
||||
return
|
||||
}
|
||||
unwrap(signer) { gift ->
|
||||
if (gift is WrappedEvent) {
|
||||
gift.host = HostStub(this.id, this.pubKey, this.kind)
|
||||
}
|
||||
addToCache(signer.pubKey, gift)
|
||||
) = unwrap(signer, onReady)
|
||||
|
||||
onReady(gift)
|
||||
}
|
||||
}
|
||||
|
||||
private fun unwrap(
|
||||
fun unwrap(
|
||||
signer: NostrSigner,
|
||||
onReady: (Event) -> Unit,
|
||||
) {
|
||||
try {
|
||||
plainContent(signer) { onReady(fromJson(it)) }
|
||||
plainContent(signer) { giftStr ->
|
||||
val gift = fromJson(giftStr)
|
||||
if (gift is WrappedEvent) {
|
||||
gift.host = HostStub(this.id, this.pubKey, this.kind)
|
||||
}
|
||||
innerEventId = gift.id
|
||||
|
||||
onReady(gift)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// Log.e("UnwrapError", "Couldn't Decrypt the content", e)
|
||||
Log.w("GiftWrapEvent", "Couldn't Decrypt the content", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
||||
import com.vitorpamplona.quartz.utils.pointerSizeInBytes
|
||||
|
||||
@Immutable
|
||||
@@ -38,11 +39,11 @@ class SealedGossipEvent(
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : WrappedEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
@Transient private var cachedInnerEvent: Map<HexKey, Event?> = mapOf()
|
||||
@Transient var innerEventId: HexKey? = null
|
||||
|
||||
override fun countMemory(): Long =
|
||||
super.countMemory() +
|
||||
pointerSizeInBytes + cachedInnerEvent.values.sumOf { pointerSizeInBytes + (it?.countMemory() ?: 0) }
|
||||
pointerSizeInBytes + (innerEventId?.bytesUsedInMemory() ?: 0)
|
||||
|
||||
fun copyNoContent(): SealedGossipEvent {
|
||||
val copy =
|
||||
@@ -55,51 +56,38 @@ class SealedGossipEvent(
|
||||
sig,
|
||||
)
|
||||
|
||||
copy.cachedInnerEvent = cachedInnerEvent
|
||||
copy.host = host
|
||||
copy.innerEventId = innerEventId
|
||||
|
||||
return copy
|
||||
}
|
||||
|
||||
override fun isContentEncoded() = true
|
||||
|
||||
fun preCachedGossip(signer: NostrSigner): Event? = cachedInnerEvent[signer.pubKey]
|
||||
|
||||
fun addToCache(
|
||||
pubKey: HexKey,
|
||||
gift: Event,
|
||||
) {
|
||||
cachedInnerEvent = cachedInnerEvent + Pair(pubKey, gift)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
message = "Heavy caching was removed from this class due to high memory use. Cache it separatedly",
|
||||
replaceWith = ReplaceWith("unseal"),
|
||||
)
|
||||
fun cachedGossip(
|
||||
signer: NostrSigner,
|
||||
onReady: (Event) -> Unit,
|
||||
) {
|
||||
cachedInnerEvent[signer.pubKey]?.let {
|
||||
onReady(it)
|
||||
return
|
||||
}
|
||||
) = unseal(signer, onReady)
|
||||
|
||||
unseal(signer) { gossip ->
|
||||
val event = gossip.mergeWith(this)
|
||||
if (event is WrappedEvent) {
|
||||
event.host = host ?: HostStub(this.id, this.pubKey, this.kind)
|
||||
}
|
||||
addToCache(signer.pubKey, event)
|
||||
|
||||
onReady(event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun unseal(
|
||||
fun unseal(
|
||||
signer: NostrSigner,
|
||||
onReady: (Gossip) -> Unit,
|
||||
onReady: (Event) -> Unit,
|
||||
) {
|
||||
try {
|
||||
plainContent(signer) {
|
||||
try {
|
||||
onReady(Gossip.fromJson(it))
|
||||
val gossip = Gossip.fromJson(it)
|
||||
val event = gossip.mergeWith(this)
|
||||
if (event is WrappedEvent) {
|
||||
event.host = host ?: HostStub(this.id, this.pubKey, this.kind)
|
||||
}
|
||||
innerEventId = event.id
|
||||
|
||||
onReady(event)
|
||||
} catch (e: Exception) {
|
||||
Log.w("GossipEvent", "Fail to decrypt or parse Gossip", e)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user