From eff0a30a392dff890fa5b02a70edd0d1d4a6e0ae Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 22:57:49 +0000 Subject: [PATCH] perf: skip chat warmup + activity preview for Buzz forum rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forum channels store their posts as threads (a separate store), not in the chat notes the activity preview reads — so a forum row was opening a kind-9 chat warmup subscription that returns nothing and could never render a last-message preview, facepile, or unread badge. Add a `showActivityPreview` flag (default true) to BuzzImportRow that gates the warmup, the notes-flow collection, and the preview/facepile/unread reads. The forum section passes false, so a forum row skips the useless subscription and shows a member-count summary instead. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01FHnm6G9YytnLfs1ycYfK89 --- .../ui/screen/loggedIn/buzz/BuzzImportRow.kt | 59 +++++++++++++------ .../relayGroup/RelayGroupChannelListScreen.kt | 3 + 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/buzz/BuzzImportRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/buzz/BuzzImportRow.kt index 83faebeeff..06486b8b0d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/buzz/BuzzImportRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/buzz/BuzzImportRow.kt @@ -87,6 +87,12 @@ private const val CARD_WARMUP_LIMIT = 10 * per-channel actions — Pin/Unpin and Add-to-my-list — so the row stays clean. * * Reused by the relay group-list screen where Buzz membership discovery is folded in. + * + * [showActivityPreview] gates the chat-activity machinery — the recent-message warmup, the + * last-message preview, the recent-posters facepile and the unread badge. Enable it for **chat** + * channels (whose content lives in [RelayGroupChannel.notes]); leave it off for **forum** channels, + * whose posts are threads (a separate store), so the row doesn't open a kind-9 chat subscription that + * would return nothing and drives a member-count summary instead. */ @Composable fun BuzzImportRow( @@ -97,6 +103,7 @@ fun BuzzImportRow( onOpen: (() -> Unit)? = null, isStarred: Boolean = false, onToggleStar: (() -> Unit)? = null, + showActivityPreview: Boolean = true, ) { val account = accountViewModel.account val baseChannel = remember(groupId) { LocalCache.getOrCreateRelayGroupChannel(groupId) } @@ -104,32 +111,46 @@ fun BuzzImportRow( // Warm a first screen's worth of recent messages while this card is visible (content only — the // directory subscription already streams metadata), so the preview + facepile fill in ahead of a // tap instead of staying blank until the channel is opened. Bounded to visible rows by the - // LazyColumn and released as they scroll off. - RelayGroupCardWarmupSubscription( - baseChannel, - accountViewModel.dataSources().relayGroupCardWarmup, - accountViewModel, - contentOnly = true, - contentLimit = CARD_WARMUP_LIMIT, - ) + // LazyColumn and released as they scroll off. Skipped for forum channels (no chat to warm). + if (showActivityPreview) { + RelayGroupCardWarmupSubscription( + baseChannel, + accountViewModel.dataSources().relayGroupCardWarmup, + accountViewModel, + contentOnly = true, + contentLimit = CARD_WARMUP_LIMIT, + ) + } val channelState by observeChannel(baseChannel, accountViewModel) val channel = channelState?.channel as? RelayGroupChannel ?: baseChannel - // The channel's own notes flow drives the preview/facepile so they update the moment a message - // folds in, independent of the metadata-scoped [observeChannel] above. - val notesState by channel - .flow() - .notes.stateFlow - .collectAsStateWithLifecycle() val name = channel.toBestDisplayName() val memberCount = channel.memberCount() val isPrivate = channel.isPrivate() - val lastNote = remember(notesState) { channel.newestTimelineNote(account) } - val faceAuthors = remember(notesState) { channel.recentAuthorHexes(account, FACEPILE_MAX) } - val unread by - remember(groupId) { relayGroupChannelUnreadCountFlow(account, groupId) } - .collectAsStateWithLifecycle(0) + + // The channel's own notes flow drives the preview/facepile so they update the moment a message + // folds in, independent of the metadata-scoped [observeChannel] above. Only collected for chat + // channels; a forum row shows a member-count summary with no facepile/unread. + val lastNote: Note? + val faceAuthors: List + val unread: Int + if (showActivityPreview) { + val notesState by channel + .flow() + .notes.stateFlow + .collectAsStateWithLifecycle() + lastNote = remember(notesState) { channel.newestTimelineNote(account) } + faceAuthors = remember(notesState) { channel.recentAuthorHexes(account, FACEPILE_MAX) } + unread = + remember(groupId) { relayGroupChannelUnreadCountFlow(account, groupId) } + .collectAsStateWithLifecycle(0) + .value + } else { + lastNote = null + faceAuthors = emptyList() + unread = 0 + } val hasUnread = unread > 0 val content = diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/RelayGroupChannelListScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/RelayGroupChannelListScreen.kt index c762bc06be..e57252f94c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/RelayGroupChannelListScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/RelayGroupChannelListScreen.kt @@ -413,6 +413,9 @@ fun RelayGroupChannelListScreen( onOpen = { nav.nav(Route.RelayGroupThreads(groupId.id, relay.url)) }, isStarred = groupId.id in starred, onToggleStar = { BuzzChannelStars.toggle(groupId.id) }, + // Forum posts live in a separate thread store, not the chat notes the + // activity preview reads — so don't warm a kind-9 sub that returns nothing. + showActivityPreview = false, ) } }