fix: show Concord channels on Messages as soon as the control plane folds

A Concord control-plane fold is what first reveals a community's channels and
makes ConcordCommunitySession.state non-null, without which
ChatroomListKnownFeedFilter emits nothing at all for that community. None of it
flows through LocalCache.newEventBundles, so the additive feed path could not
see it: a folded channel only reached the Messages tab if a message for it
happened to arrive afterwards.

Cold boot therefore showed a subset of a community's channels, or omitted a
quiet community entirely, until some unrelated invalidation fired. Measured on
device: the Concord hub reported 3 communities / 17 channels folded in memory
while Messages rendered 3 rows and omitted one community completely.

AccountFeedContentStates already forces a rebuild for the Marmot, NIP-29,
geohash, view-mode and pin flows for exactly this reason; Concord was the one
missing collector. Add it, sampled the same way Account.kt samples this flow to
drive refreshConcordChannelIndex.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vitor Pamplona
2026-07-21 13:21:35 -04:00
parent a960ceb6a8
commit f67d242f7a

View File

@@ -77,7 +77,9 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.webBookmarks.dal.WebBookmar
import com.vitorpamplona.amethyst.ui.screen.loggedIn.workouts.dal.WorkoutFeedFilter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
class AccountFeedContentStates(
@@ -201,6 +203,26 @@ class AccountFeedContentStates(
}
}
// A Concord control-plane fold is what first reveals a community's channels (and what makes
// ConcordCommunitySession.state non-null, without which ChatroomListKnownFeedFilter emits
// nothing at all for that community). None of it flows through LocalCache.newEventBundles,
// so the additive path can't see it: a folded channel reaches the Messages tab only if a
// message for it happens to arrive afterwards. Cold boot therefore shows a *subset* of a
// community's channels, or omits a quiet community entirely, until some unrelated
// invalidation fires. Rebuild on every structural change instead. `revision` bumps only on
// fold/membership/rekey (never a plain message), and sample() coalesces the burst of folds
// that lands as each control plane catches up — the same pairing Account.kt uses to drive
// refreshConcordChannelIndex off this flow.
scope.launch(Dispatchers.IO) {
@OptIn(FlowPreview::class)
account.concordSessions.revision
.drop(1)
.sample(500)
.collect {
dmKnown.invalidateData()
}
}
// Same for the Concord view mode (inline channels vs one row per community).
scope.launch(Dispatchers.IO) {
account.settings.concordViewMode