diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt index 65743c61d..83275d591 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt @@ -12,6 +12,7 @@ import coil.disk.DiskCache import coil.util.DebugLogger import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.service.AmberUtils import com.vitorpamplona.amethyst.service.HttpClient import com.vitorpamplona.amethyst.service.NostrAccountDataSource import com.vitorpamplona.amethyst.service.NostrChannelDataSource @@ -41,6 +42,7 @@ object ServiceManager { fun start(account: Account, context: Context) { this.account = account + AmberUtils.account = account start(context) } 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 3e93e153d..3f41b52bf 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -108,31 +108,43 @@ class Account( live.combineWith(getBlockListNote().live().metadata) { localLive, liveMuteListEvent -> val blockList = liveMuteListEvent?.note?.event as? PeopleListEvent if (loginWithAmber) { - if (blockList?.decryptedContent == null) { - GlobalScope.launch(Dispatchers.IO) { - val content = blockList?.content ?: "" - if (content.isEmpty()) return@launch - AmberUtils.content = "" - AmberUtils.decrypt( - content, - keyPair.pubKey.toHexKey(), - blockList?.id() ?: "" - ) - blockList?.decryptedContent = AmberUtils.content - live.invalidateData() - AmberUtils.content = "" - } + val id = blockList?.id + if (id != null) { + if (AmberUtils.cachedDecryptedContent[blockList.id] == null) { + GlobalScope.launch(Dispatchers.IO) { + val content = blockList.content + if (content.isEmpty()) return@launch + AmberUtils.content = "" + AmberUtils.decryptBlockList( + content, + keyPair.pubKey.toHexKey(), + blockList.id() + ) + blockList.decryptedContent = AmberUtils.cachedDecryptedContent[blockList.id] + live.invalidateData() + } + LiveHiddenUsers( + hiddenUsers = persistentSetOf(), + spammers = localLive?.account?.transientHiddenUsers + ?: persistentSetOf(), + showSensitiveContent = showSensitiveContent + ) + } else { + blockList.decryptedContent = AmberUtils.cachedDecryptedContent[blockList.id] + val liveBlockedUsers = blockList.publicAndPrivateUsers(blockList.decryptedContent ?: "") + LiveHiddenUsers( + hiddenUsers = liveBlockedUsers, + spammers = localLive?.account?.transientHiddenUsers + ?: persistentSetOf(), + showSensitiveContent = showSensitiveContent + ) + } + } else { LiveHiddenUsers( hiddenUsers = persistentSetOf(), - spammers = localLive?.account?.transientHiddenUsers ?: persistentSetOf(), - showSensitiveContent = showSensitiveContent - ) - } else { - val liveBlockedUsers = blockList.publicAndPrivateUsers(blockList.decryptedContent ?: "") - LiveHiddenUsers( - hiddenUsers = liveBlockedUsers, - spammers = localLive?.account?.transientHiddenUsers ?: persistentSetOf(), + spammers = localLive?.account?.transientHiddenUsers + ?: persistentSetOf(), showSensitiveContent = showSensitiveContent ) } @@ -2167,8 +2179,8 @@ class Account( fun hideUser(pubkeyHex: String) { val blockList = migrateHiddenUsersIfNeeded(getBlockList()) if (loginWithAmber) { - val content = blockList?.content ?: "" - val encryptedContent = if (content.isBlank()) { + val id = blockList?.id + val encryptedContent = if (id == null) { val privateTags = listOf(listOf("p", pubkeyHex)) val msg = Event.mapper.writeValueAsString(privateTags) @@ -2177,12 +2189,15 @@ class Account( if (AmberUtils.content.isBlank()) return AmberUtils.content } else { - AmberUtils.content = "" - AmberUtils.decrypt(content, keyPair.pubKey.toHexKey(), blockList?.id ?: "") - if (AmberUtils.content.isBlank()) return - val decryptedContent = AmberUtils.content - AmberUtils.content = "" - val privateTags = blockList?.privateTagsOrEmpty(decryptedContent)?.plus(element = listOf("p", pubkeyHex)) + var decryptedContent = AmberUtils.cachedDecryptedContent[id] + if (decryptedContent == null) { + AmberUtils.content = "" + AmberUtils.decrypt(blockList.content, keyPair.pubKey.toHexKey(), blockList.id) + if (AmberUtils.content.isBlank()) return + decryptedContent = AmberUtils.content + } + + val privateTags = blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", pubkeyHex)) val msg = Event.mapper.writeValueAsString(privateTags) AmberUtils.content = "" AmberUtils.encrypt(msg, keyPair.pubKey.toHexKey()) @@ -2251,7 +2266,7 @@ class Account( if (blockList != null) { if (loginWithAmber) { - val content = blockList.content ?: "" + val content = blockList.content val encryptedContent = if (content.isBlank()) { val privateTags = listOf(listOf("p", pubkeyHex)) val msg = Event.mapper.writeValueAsString(privateTags) @@ -2261,10 +2276,13 @@ class Account( if (AmberUtils.content.isBlank()) return AmberUtils.content } else { - AmberUtils.content = "" - AmberUtils.decrypt(content, keyPair.pubKey.toHexKey(), blockList.id) - if (AmberUtils.content.isBlank()) return - val decryptedContent = AmberUtils.content + var decryptedContent = AmberUtils.cachedDecryptedContent[blockList.id] + if (decryptedContent == null) { + AmberUtils.content = "" + AmberUtils.decrypt(blockList.content, keyPair.pubKey.toHexKey(), blockList.id) + if (AmberUtils.content.isBlank()) return + decryptedContent = AmberUtils.content + } AmberUtils.content = "" val privateTags = blockList.privateTagsOrEmpty(decryptedContent).minus(element = listOf("p", pubkeyHex)) val msg = Event.mapper.writeValueAsString(privateTags) @@ -2551,8 +2569,16 @@ class Account( val event = note.event return when (event) { is PrivateDmEvent -> { - AmberUtils.decrypt(event.content, event.talkingWith(userProfile().pubkeyHex), event.id) - AmberUtils.cachedDecryptedContent[event.id] + if (AmberUtils.cachedDecryptedContent[event.id] == null) { + AmberUtils.decrypt( + event.content, + event.talkingWith(userProfile().pubkeyHex), + event.id + ) + AmberUtils.cachedDecryptedContent[event.id] + } else { + AmberUtils.cachedDecryptedContent[event.id] + } } is LnZapRequestEvent -> { decryptZapContentAuthor(note)?.content() 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 5ae4d2d99..aa9d2d42f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt @@ -4,6 +4,7 @@ import android.content.Intent import android.net.Uri import androidx.activity.result.ActivityResultLauncher import com.vitorpamplona.amethyst.ServiceManager +import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.events.Event @@ -14,6 +15,7 @@ object AmberUtils { var content: String = "" var isActivityRunning: Boolean = false val cachedDecryptedContent = mutableMapOf() + lateinit var account: Account fun openAmber( data: String, @@ -67,6 +69,17 @@ object AmberUtils { ) } + fun decryptBlockList(encryptedContent: String, pubKey: HexKey, id: String, signerType: SignerType = SignerType.NIP04_DECRYPT) { + isActivityRunning = true + openAmber( + encryptedContent, + signerType, + IntentUtils.blockListResultLauncher, + pubKey, + id + ) + } + fun decrypt(encryptedContent: String, pubKey: HexKey, id: String, signerType: SignerType = SignerType.NIP04_DECRYPT) { if (content.isBlank()) { isActivityRunning = true 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 675e44df3..5962943b2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt @@ -21,6 +21,7 @@ import kotlinx.coroutines.launch object IntentUtils { lateinit var activityResultLauncher: ActivityResultLauncher lateinit var decryptGossipResultLauncher: ActivityResultLauncher + lateinit var blockListResultLauncher: ActivityResultLauncher val eventCache = LruCache(100) @OptIn(DelicateCoroutinesApi::class) @@ -85,6 +86,29 @@ object IntentUtils { ServiceManager.shouldPauseService = true } + blockListResultLauncher = 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()) { + AmberUtils.cachedDecryptedContent[id] = decryptedContent + AmberUtils.account.live.invalidateData() + } + } + AmberUtils.isActivityRunning = false + ServiceManager.shouldPauseService = true + } + decryptGossipResultLauncher = activity.registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) {