From 5241a6dfa79cedd1e0cdd54f3fb3e59b078f2d8d Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 13 Jan 2026 11:27:45 -0500 Subject: [PATCH] Fixes missing cache after AI PR for the desktop app Removes dependency on the Cache from User. Updates interface methods to match. --- .../amethyst/model/LocalCache.kt | 8 +++-- .../com/vitorpamplona/amethyst/model/User.kt | 3 -- .../reqCommand/user/UserObservers.kt | 5 +++- .../amethyst/commons/model/User.kt | 29 ++++--------------- .../commons/model/cache/ICacheProvider.kt | 3 +- 5 files changed, 18 insertions(+), 30 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index beac2ade5..34224a4b1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -324,7 +324,7 @@ object LocalCache : ILocalCache, ICacheProvider { return users.get(key) } - override fun countUsers(predicate: (String, Any) -> Boolean): Int { + override fun countUsers(predicate: (String, User) -> Boolean): Int { var count = 0 users.forEach { key, user -> if (predicate(key, user)) count++ @@ -531,9 +531,13 @@ object LocalCache : ILocalCache, ICacheProvider { // avoids processing empty contact lists. if (event.createdAt > (user.latestContactList?.createdAt ?: 0) && !event.tags.isEmpty() && (wasVerified || justVerify(event))) { - user.updateContactList(event) + val needsToUpdateFollowers = user.updateContactList(event) // Log.d("CL", "Consumed contact list ${user.toNostrUri()} ${event.relays()?.size}") + needsToUpdateFollowers.forEach { + getUserIfExists(it)?.flowSet?.followers?.invalidateData() + } + updateObservables(event) return true diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/User.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/User.kt index bfa68c725..860631c0c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/User.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/User.kt @@ -21,9 +21,6 @@ package com.vitorpamplona.amethyst.model // Re-export from commons for backwards compatibility -typealias UserDependencies = com.vitorpamplona.amethyst.commons.model.UserDependencies typealias User = com.vitorpamplona.amethyst.commons.model.User -typealias UserFlowSet = com.vitorpamplona.amethyst.commons.model.UserFlowSet typealias RelayInfo = com.vitorpamplona.amethyst.commons.model.RelayInfo -typealias UserBundledRefresherFlow = com.vitorpamplona.amethyst.commons.model.UserBundledRefresherFlow typealias UserState = com.vitorpamplona.amethyst.commons.model.UserState diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/user/UserObservers.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/user/UserObservers.kt index d2d2b59da..7e0496b7c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/user/UserObservers.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/user/UserObservers.kt @@ -36,6 +36,7 @@ import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl +import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser import com.vitorpamplona.quartz.nip51Lists.bookmarkList.BookmarkListEvent import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent import kotlinx.collections.immutable.ImmutableList @@ -392,7 +393,9 @@ fun observeUserFollowerCount( .followers.stateFlow .sample(200) .mapLatest { userState -> - userState.user.transientFollowerCount() + LocalCache.countUsers { _, user -> + user.latestContactList?.isTaggedUser(user.pubkeyHex) ?: false + } }.distinctUntilChanged() .flowOn(Dispatchers.IO) } diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt index 287992db5..558cf168c 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt @@ -22,11 +22,11 @@ package com.vitorpamplona.amethyst.commons.model import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable -import com.vitorpamplona.amethyst.commons.model.cache.ICacheProvider import com.vitorpamplona.amethyst.commons.model.nip56Reports.UserReportCache import com.vitorpamplona.amethyst.commons.model.trustedAssertions.UserCardsCache import com.vitorpamplona.amethyst.commons.util.toShortDisplay import com.vitorpamplona.quartz.lightning.Lud06 +import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.toImmutableListOfLists import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata @@ -51,7 +51,6 @@ class User( val pubkeyHex: String, val nip65RelayListNote: Note, val dmRelayListNote: Note, - private val cacheProvider: ICacheProvider? = null, ) { private var reports: UserReportCache? = null private var cards: UserCardsCache? = null @@ -120,8 +119,8 @@ class User( fun profilePicture(): String? = info?.picture - fun updateContactList(event: ContactListEvent) { - if (event.id == latestContactList?.id) return + fun updateContactList(event: ContactListEvent): Set { + if (event.id == latestContactList?.id) return emptySet() val oldContactListEvent = latestContactList latestContactList = event @@ -129,20 +128,9 @@ class User( // Update following of the current user flowSet?.follows?.invalidateData() - // Update Followers of the past user list - // Update Followers of the new contact list - (oldContactListEvent)?.unverifiedFollowKeySet()?.forEach { - (cacheProvider?.getUserIfExists(it) as? User) - ?.flowSet - ?.followers - ?.invalidateData() - } - (latestContactList)?.unverifiedFollowKeySet()?.forEach { - (cacheProvider?.getUserIfExists(it) as? User) - ?.flowSet - ?.followers - ?.invalidateData() - } + val affectedUsers = event.verifiedFollowKeySet() + (oldContactListEvent?.verifiedFollowKeySet() ?: emptySet()) + + return affectedUsers } fun addZap( @@ -217,11 +205,6 @@ class User( fun transientFollowCount(): Int? = latestContactList?.unverifiedFollowKeySet()?.size - fun transientFollowerCount(): Int = - cacheProvider?.countUsers { _, it -> - (it as? User)?.latestContactList?.isTaggedUser(pubkeyHex) ?: false - } ?: 0 - fun reportsOrNull(): UserReportCache? = reports fun reports(): UserReportCache = reports ?: UserReportCache().also { reports = it } diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/cache/ICacheProvider.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/cache/ICacheProvider.kt index 7d1f32f98..16d8fae4e 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/cache/ICacheProvider.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/cache/ICacheProvider.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.amethyst.commons.model.cache +import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.quartz.nip01Core.core.HexKey /** @@ -60,7 +61,7 @@ interface ICacheProvider { * @param predicate Filter function for counting users * @return Count of users matching the predicate */ - fun countUsers(predicate: (String, Any) -> Boolean): Int + fun countUsers(predicate: (String, User) -> Boolean): Int /** * Gets a Note if it exists in cache.