fix: actually fetch ChannelCreateEvent (kind 40) and widen the relay set

filterMissingChannelsById had an inverted isEmpty() check that emitted
zero filters, so kind 40 was never requested from any relay. Channels
discovered from kind 42 messages stayed as empty stubs unless the
creator also happened to publish a kind 41 metadata update findable on
the same relay — which is why most cards in the Public Chats feed
loaded with no name or picture.

Fix:
- Drop the inverted condition; mapOfSet guarantees non-empty values, so
  emit a RelayBasedFilter for every (relay, channelIds) entry.
- Widen the relay set per channel to include the user's search and
  indexer relay lists. Falls back to DefaultSearchRelayList /
  DefaultIndexerRelayList when those lists are empty.
- Plumb the Account through ChannelFinderQueryState so the assembler
  can read the search/indexer flows. Mirrors EventFinderQueryState.
This commit is contained in:
Claude
2026-05-21 21:35:27 +00:00
parent ee0b658401
commit 3f91cb1689
3 changed files with 26 additions and 21 deletions
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.commons.model.Channel
import com.vitorpamplona.amethyst.commons.relayClient.composeSubscriptionManagers.ComposeSubscriptionManager
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.mixChatsLive.ChannelMetadataAndLiveActivityWatcherSubAssembler
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.nip28PublicChats.ChannelLoaderSubAssembler
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
@@ -31,6 +32,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
@Stable
class ChannelFinderQueryState(
val channel: Channel,
val account: Account,
)
@Stable
@@ -24,24 +24,26 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.vitorpamplona.amethyst.commons.model.Channel
import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.LifecycleAwareKeyDataSourceSubscription
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@Composable
fun ChannelFinderFilterAssemblerSubscription(
channel: Channel,
accountViewModel: AccountViewModel,
) = ChannelFinderFilterAssemblerSubscription(channel, accountViewModel.dataSources().channelFinder)
) = ChannelFinderFilterAssemblerSubscription(channel, accountViewModel.account, accountViewModel.dataSources().channelFinder)
@Composable
fun ChannelFinderFilterAssemblerSubscription(
channel: Channel,
account: Account,
dataSource: ChannelFinderFilterAssemblyGroup,
) {
// different screens get different states
// even if they are tracking the same tag.
val state =
remember(channel) {
ChannelFinderQueryState(channel)
remember(channel, account) {
ChannelFinderQueryState(channel, account)
}
LifecycleAwareKeyDataSourceSubscription(state, dataSource)
@@ -20,6 +20,8 @@
*/
package com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.nip28PublicChats
import com.vitorpamplona.amethyst.commons.defaults.DefaultIndexerRelayList
import com.vitorpamplona.amethyst.commons.defaults.DefaultSearchRelayList
import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChannel
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.ChannelFinderQueryState
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
@@ -34,29 +36,28 @@ fun filterMissingChannelsById(keys: List<ChannelFinderQueryState>): List<RelayBa
mapOfSet {
keys.forEach { key ->
if (key.channel is PublicChatChannel && key.channel.event == null) {
key.channel.relays().forEach {
val searchRelays =
key.account.searchRelayList.flow.value
.ifEmpty { DefaultSearchRelayList }
val indexerRelays =
key.account.indexerRelayList.flow.value
.ifEmpty { DefaultIndexerRelayList }
(key.channel.relays() + searchRelays + indexerRelays).forEach {
add(it, key.channel.idHex)
}
} else {
null
}
}
}
if (relayPerChannel.isEmpty()) return emptyList()
return relayPerChannel.mapNotNull {
if (it.value.isEmpty()) {
RelayBasedFilter(
relay = it.key,
filter =
Filter(
kinds = filterMissingPublicChannelsByIdKinds,
ids = it.value.sorted(),
),
)
} else {
null
}
return relayPerChannel.map { (relay, channelIds) ->
RelayBasedFilter(
relay = relay,
filter =
Filter(
kinds = filterMissingPublicChannelsByIdKinds,
ids = channelIds.sorted(),
),
)
}
}