From b2b7cba352177e1c409883d437e8b815b08d0519 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 30 Nov 2023 16:24:53 -0500 Subject: [PATCH] Loads basic information for all the accounts in the app. --- .../amethyst/LocalPreferences.kt | 27 ++++++++++++++++--- .../vitorpamplona/amethyst/ServiceManager.kt | 9 +++++++ .../service/NostrAccountDataSource.kt | 19 +++++++++++-- .../EventNotificationConsumer.kt | 2 +- 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index e4478d737..05192db76 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -35,6 +35,8 @@ import com.vitorpamplona.quartz.signers.NostrSignerExternal import com.vitorpamplona.quartz.signers.NostrSignerInternal import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import java.io.File import java.util.Locale @@ -99,6 +101,7 @@ object LocalPreferences { private var _currentAccount: String? = null private var _savedAccounts: List? = null + private var _cachedAccounts: MutableMap = mutableMapOf() suspend fun currentAccount(): String? { if (_currentAccount == null) { @@ -286,9 +289,9 @@ object LocalPreferences { } suspend fun loadCurrentAccountFromEncryptedStorage(): Account? { - val acc = loadCurrentAccountFromEncryptedStorage(currentAccount()) - acc?.registerObservers() - return acc + return currentAccount()?.let { + loadCurrentAccountFromEncryptedStorage(it) + } } suspend fun migrateOldSharedSettings(): Settings? { @@ -376,7 +379,23 @@ object LocalPreferences { } } - suspend fun loadCurrentAccountFromEncryptedStorage(npub: String?): Account? = withContext(Dispatchers.IO) { + val mutex = Mutex() + suspend fun loadCurrentAccountFromEncryptedStorage(npub: String): Account? = withContext(Dispatchers.IO) { + mutex.withLock { + if (_cachedAccounts.containsKey(npub)) { + return@withContext _cachedAccounts.get(npub) + } + + val account = innerLoadCurrentAccountFromEncryptedStorage(npub) + account?.registerObservers() + + _cachedAccounts.put(npub, account) + + return@withContext account + } + } + + suspend fun innerLoadCurrentAccountFromEncryptedStorage(npub: String?): Account? = withContext(Dispatchers.IO) { checkNotInMainThread() return@withContext with(encryptedPreferences(npub)) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt index 53f01f4b4..239e46ad1 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt @@ -28,7 +28,9 @@ import com.vitorpamplona.amethyst.service.NostrThreadDataSource import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource import com.vitorpamplona.amethyst.service.NostrVideoDataSource import com.vitorpamplona.amethyst.service.relays.Client +import com.vitorpamplona.quartz.encoders.bechToBytes import com.vitorpamplona.quartz.encoders.decodePublicKeyAsHexOrNull +import com.vitorpamplona.quartz.encoders.toHexKey import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay @@ -78,6 +80,13 @@ class ServiceManager { // start services NostrAccountDataSource.account = myAccount + NostrAccountDataSource.otherAccounts = LocalPreferences.allSavedAccounts().mapNotNull { + try { + it.npub.bechToBytes().toHexKey() + } catch (e: Exception) { + null + } + } NostrHomeDataSource.account = myAccount NostrChatroomListDataSource.account = myAccount NostrVideoDataSource.account = myAccount 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 26afd3b18..881367e45 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt @@ -10,6 +10,7 @@ import com.vitorpamplona.amethyst.service.relays.EOSETime import com.vitorpamplona.amethyst.service.relays.JsonFilter import com.vitorpamplona.amethyst.service.relays.Relay import com.vitorpamplona.amethyst.service.relays.TypedFilter +import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent import com.vitorpamplona.quartz.events.BadgeAwardEvent import com.vitorpamplona.quartz.events.BadgeProfilesEvent @@ -38,6 +39,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils // TODO: Migrate this to a property of AccountVi object NostrAccountDataSource : NostrDataSource("AccountData") { lateinit var account: Account + var otherAccounts = listOf() val latestEOSEs = EOSEAccount() val hasLoadedTheBasics = mutableMapOf() @@ -75,6 +77,18 @@ object NostrAccountDataSource : NostrDataSource("AccountData") { ) } + fun createOtherAccountsBaseFilter(): TypedFilter? { + if (otherAccounts.isEmpty()) return null + return TypedFilter( + types = COMMON_FEED_TYPES, + filter = JsonFilter( + kinds = listOf(MetadataEvent.kind, ContactListEvent.kind, AdvertisedRelayListEvent.kind, MuteListEvent.kind, PeopleListEvent.kind), + authors = otherAccounts.filter { it != account.userProfile().pubkeyHex }, + limit = 100 + ) + ) + } + fun createAccountAcceptedAwardsFilter(): TypedFilter { return TypedFilter( types = COMMON_FEED_TYPES, @@ -218,7 +232,7 @@ object NostrAccountDataSource : NostrDataSource("AccountData") { override fun updateChannelFilters() { return if (hasLoadedTheBasics[account.userProfile()] != null) { // gets everthing about the user logged in - accountChannel.typedFilters = listOf( + accountChannel.typedFilters = listOfNotNull( createAccountMetadataFilter(), createAccountContactListFilter(), createAccountRelayListFilter(), @@ -227,7 +241,8 @@ object NostrAccountDataSource : NostrDataSource("AccountData") { createAccountReportsFilter(), createAccountAcceptedAwardsFilter(), createAccountBookmarkListFilter(), - createAccountLastPostsListFilter() + createAccountLastPostsListFilter(), + createOtherAccountsBaseFilter() ).ifEmpty { null } } else { // just the basics. diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/EventNotificationConsumer.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/EventNotificationConsumer.kt index bc915fa10..52be47216 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/EventNotificationConsumer.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/EventNotificationConsumer.kt @@ -116,7 +116,7 @@ class EventNotificationConsumer(private val applicationContext: Context) { // old event being re-broadcast if (event.createdAt < TimeUtils.fiveMinutesAgo()) return - if (acc != null && acc.userProfile().pubkeyHex == event.verifiedRecipientPubKey()) { + if (acc.userProfile().pubkeyHex == event.verifiedRecipientPubKey()) { val followingKeySet = acc.followingKeySet() val knownChatrooms = acc.userProfile().privateChatrooms.keys.filter {