feat(cache): cache profile metadata and follower/following counts
Profile screen now reads initial values from cache so navigating back shows data instantly instead of re-fetching everything from scratch. - Seed displayName/about/picture from User.metadataOrNull() on compose - Add followerCounts/followingCounts maps to DesktopLocalCache - Write counts on each update, read on profile open - Follower count still ticks up live (good UX) but starts from cached value - 4 new tests for profile count caching + metadata cache reads Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vendored
+25
@@ -491,6 +491,29 @@ class DesktopLocalCache : ICacheProvider {
|
||||
eventStream.emitDeletedNotes(notes)
|
||||
}
|
||||
|
||||
// ----- Profile count cache -----
|
||||
|
||||
private val followerCounts = ConcurrentHashMap<HexKey, Int>()
|
||||
private val followingCounts = ConcurrentHashMap<HexKey, Int>()
|
||||
|
||||
fun getCachedFollowerCount(pubkey: HexKey): Int = followerCounts[pubkey] ?: 0
|
||||
|
||||
fun getCachedFollowingCount(pubkey: HexKey): Int = followingCounts[pubkey] ?: 0
|
||||
|
||||
fun cacheFollowerCount(
|
||||
pubkey: HexKey,
|
||||
count: Int,
|
||||
) {
|
||||
followerCounts[pubkey] = count
|
||||
}
|
||||
|
||||
fun cacheFollowingCount(
|
||||
pubkey: HexKey,
|
||||
count: Int,
|
||||
) {
|
||||
followingCounts[pubkey] = count
|
||||
}
|
||||
|
||||
// ----- Stats -----
|
||||
|
||||
fun userCount(): Int = users.size()
|
||||
@@ -503,6 +526,8 @@ class DesktopLocalCache : ICacheProvider {
|
||||
addressableNotes.clear()
|
||||
deletedEvents.clear()
|
||||
_followedUsers.value = emptySet()
|
||||
followerCounts.clear()
|
||||
followingCounts.clear()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-9
@@ -127,12 +127,22 @@ fun UserProfileScreen(
|
||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
||||
|
||||
// User metadata
|
||||
var displayName by remember { mutableStateOf<String?>(null) }
|
||||
var about by remember { mutableStateOf<String?>(null) }
|
||||
var picture by remember { mutableStateOf<String?>(null) }
|
||||
var followersCount by remember { mutableStateOf(0) }
|
||||
var followingCount by remember { mutableStateOf(0) }
|
||||
// User metadata — seed from cache so returning to profile is instant
|
||||
val cachedUser = remember(pubKeyHex) { localCache.getUserIfExists(pubKeyHex) }
|
||||
val cachedMetadata = remember(pubKeyHex) { cachedUser?.metadataOrNull() }
|
||||
var displayName by remember { mutableStateOf(cachedMetadata?.bestName()) }
|
||||
var about by remember {
|
||||
mutableStateOf(
|
||||
cachedMetadata
|
||||
?.flow
|
||||
?.value
|
||||
?.info
|
||||
?.about,
|
||||
)
|
||||
}
|
||||
var picture by remember { mutableStateOf(cachedMetadata?.profilePicture()) }
|
||||
var followersCount by remember { mutableStateOf(localCache.getCachedFollowerCount(pubKeyHex)) }
|
||||
var followingCount by remember { mutableStateOf(localCache.getCachedFollowingCount(pubKeyHex)) }
|
||||
|
||||
// Profile editing state (only for own profile)
|
||||
val isOwnProfile = account != null && pubKeyHex == account.pubKeyHex
|
||||
@@ -279,8 +289,9 @@ fun UserProfileScreen(
|
||||
pubKeyHex = pubKeyHex,
|
||||
onEvent = { event, _, _, _ ->
|
||||
if (event is ContactListEvent) {
|
||||
// Count the number of people this user follows
|
||||
followingCount = event.verifiedFollowKeySet().size
|
||||
val count = event.verifiedFollowKeySet().size
|
||||
followingCount = count
|
||||
localCache.cacheFollowingCount(pubKeyHex, count)
|
||||
}
|
||||
},
|
||||
onEose = { _, _ -> },
|
||||
@@ -314,7 +325,9 @@ fun UserProfileScreen(
|
||||
onEvent = { event, _, _, _ ->
|
||||
// Count unique authors who follow this user
|
||||
if (followerAuthors.add(event.pubKey)) {
|
||||
followersCount = followerAuthors.size
|
||||
val count = followerAuthors.size
|
||||
followersCount = count
|
||||
localCache.cacheFollowerCount(pubKeyHex, count)
|
||||
}
|
||||
},
|
||||
onEose = { _, _ -> },
|
||||
|
||||
Reference in New Issue
Block a user