diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt index 5575a4285..0d7e96fc6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt @@ -6,6 +6,7 @@ import androidx.activity.result.ActivityResultLauncher import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.quartz.encoders.HexKey +import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.EventInterface import com.vitorpamplona.quartz.events.LnZapRequestEvent @@ -82,6 +83,20 @@ object AmberUtils { } } + fun decryptGossip(event: Event) { + if (IntentUtils.eventCache.get(event.id) == null) { + IntentUtils.eventCache.put(event.id, event) + } + isActivityRunning = true + openAmber( + event.content, + SignerType.NIP44_DECRYPT, + IntentUtils.decryptGossipResultLauncher, + event.pubKey, + event.id + ) + } + fun encrypt(decryptedContent: String, pubKey: HexKey, signerType: SignerType = SignerType.NIP04_ENCRYPT) { isActivityRunning = true openAmber( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt index c2694cf37..675e44df3 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt @@ -2,12 +2,17 @@ package com.vitorpamplona.amethyst.service import android.app.Activity import android.content.Intent +import android.util.LruCache import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.ServiceManager +import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.ui.MainActivity +import com.vitorpamplona.quartz.events.Event +import com.vitorpamplona.quartz.events.GiftWrapEvent +import com.vitorpamplona.quartz.events.SealedGossipEvent import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -15,6 +20,45 @@ import kotlinx.coroutines.launch object IntentUtils { lateinit var activityResultLauncher: ActivityResultLauncher + lateinit var decryptGossipResultLauncher: ActivityResultLauncher + val eventCache = LruCache(100) + + @OptIn(DelicateCoroutinesApi::class) + fun consume(event: Event) { + if (LocalCache.justVerify(event)) { + if (event is GiftWrapEvent) { + GlobalScope.launch(Dispatchers.IO) { + val decryptedContent = AmberUtils.cachedDecryptedContent[event.id] ?: "" + if (decryptedContent.isNotBlank()) { + event.cachedGift( + NostrAccountDataSource.account.keyPair.pubKey, + decryptedContent + )?.let { + consume(it) + } + } else { + AmberUtils.decryptGossip(event) + } + } + } + + if (event is SealedGossipEvent) { + GlobalScope.launch(Dispatchers.IO) { + val decryptedContent = AmberUtils.cachedDecryptedContent[event.id] ?: "" + if (decryptedContent.isNotBlank()) { + event.cachedGossip(NostrAccountDataSource.account.keyPair.pubKey, decryptedContent)?.let { + LocalCache.justConsume(it, null) + } + } else { + AmberUtils.decryptGossip(event) + } + } + // Don't store sealed gossips to avoid rebroadcasting by mistake. + } else { + LocalCache.justConsume(event, null) + } + } + } @OptIn(DelicateCoroutinesApi::class) fun start(activity: MainActivity) { @@ -29,15 +73,41 @@ object IntentUtils { Toast.LENGTH_SHORT ).show() } - AmberUtils.isActivityRunning = false - return@registerForActivityResult + } else { + val event = it.data?.getStringExtra("signature") ?: "" + AmberUtils.content = event + val id = it.data?.getStringExtra("id") ?: "" + if (id.isNotBlank()) { + AmberUtils.cachedDecryptedContent[id] = event + } } + AmberUtils.isActivityRunning = false + ServiceManager.shouldPauseService = true + } - val event = it.data?.getStringExtra("signature") ?: "" - AmberUtils.content = event - val id = it.data?.getStringExtra("id") ?: "" - if (id.isNotBlank()) { - AmberUtils.cachedDecryptedContent[id] = event + decryptGossipResultLauncher = activity.registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { + if (it.resultCode != Activity.RESULT_OK) { + GlobalScope.launch(Dispatchers.Main) { + Toast.makeText( + Amethyst.instance, + "Sign request rejected", + Toast.LENGTH_SHORT + ).show() + } + } else { + val decryptedContent = it.data?.getStringExtra("signature") ?: "" + val id = it.data?.getStringExtra("id") ?: "" + if (id.isNotBlank()) { + val event = eventCache.get(id) + if (event != null) { + GlobalScope.launch(Dispatchers.IO) { + AmberUtils.cachedDecryptedContent[event.id] = decryptedContent + consume(event) + } + } + } } AmberUtils.isActivityRunning = false ServiceManager.shouldPauseService = true diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt index 7b94661a1..01a7fe054 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt @@ -160,13 +160,13 @@ object NostrAccountDataSource : NostrDataSource("AccountData") { } } else if (account.loginWithAmber) { GlobalScope.launch(Dispatchers.IO) { - AmberUtils.content = "" - AmberUtils.decrypt(event.content, event.pubKey, event.id, SignerType.NIP44_DECRYPT) val decryptedContent = AmberUtils.cachedDecryptedContent[event.id] ?: "" if (decryptedContent.isNotBlank()) { event.cachedGift(account.keyPair.pubKey, decryptedContent)?.let { consume(it, relay) } + } else { + AmberUtils.decryptGossip(event) } } } @@ -180,18 +180,13 @@ object NostrAccountDataSource : NostrDataSource("AccountData") { } } else if (account.loginWithAmber) { GlobalScope.launch(Dispatchers.IO) { - AmberUtils.content = "" - AmberUtils.decrypt( - event.content, - event.pubKey, - event.id, - SignerType.NIP44_DECRYPT - ) val decryptedContent = AmberUtils.cachedDecryptedContent[event.id] ?: "" if (decryptedContent.isNotBlank()) { event.cachedGossip(account.keyPair.pubKey, decryptedContent)?.let { LocalCache.justConsume(it, relay) } + } else { + AmberUtils.decryptGossip(event) } } }