Adds relay search to the search page

This commit is contained in:
Vitor Pamplona
2026-03-09 11:46:21 -04:00
parent 2387a1bb91
commit a34ba7cea8
5 changed files with 45 additions and 2 deletions
@@ -47,7 +47,6 @@ import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.HalfHalfVertPadding
import com.vitorpamplona.amethyst.ui.theme.HalfHorzPadding
import com.vitorpamplona.amethyst.ui.theme.HalfVertPadding
import com.vitorpamplona.amethyst.ui.theme.Height25Modifier
import com.vitorpamplona.amethyst.ui.theme.LargeRelayIconModifier
import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeightChatMaxWidth
@@ -63,6 +62,7 @@ fun BasicRelaySetupInfoClickableRow(
onDelete: ((BasicRelaySetupInfo) -> Unit)?,
onClick: () -> Unit,
nip11CachedRetriever: Nip11CachedRetriever,
modifier: Modifier = Modifier,
accountViewModel: AccountViewModel,
nav: INav,
) {
@@ -79,7 +79,7 @@ fun BasicRelaySetupInfoClickableRow(
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = HalfVertPadding,
modifier = modifier,
) {
val iconUrlFromRelayInfoDoc by loadRelayInfo(item.relay, nip11CachedRetriever)
@@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.model.nip11RelayInfo.Nip11CachedRetriever
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.HalfVertPadding
@Composable
fun BasicRelaySetupInfoDialog(
@@ -41,6 +42,7 @@ fun BasicRelaySetupInfoDialog(
onDelete = onDelete,
onClick = { nav.nav(Route.RelayInfo(item.relay.url)) },
nip11CachedRetriever = nip11CachedRetriever,
modifier = HalfVertPadding,
accountViewModel = accountViewModel,
nav = nav,
)
@@ -31,6 +31,7 @@ import com.vitorpamplona.amethyst.model.nip11RelayInfo.Nip11CachedRetriever
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.HalfVertPadding
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
@Composable
@@ -54,6 +55,7 @@ fun ShowRelaySuggestionList(
onClick = { onSelect(relayInfo.relay) },
onDelete = null,
nip11CachedRetriever = nip11CachedRetriever,
modifier = HalfVertPadding,
accountViewModel = accountViewModel,
nav = nav,
)
@@ -36,6 +36,7 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.SearchQueryState
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.relaySetupInfoBuilder
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinLookupException
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
import com.vitorpamplona.quartz.nip10Notes.content.findHashtags
@@ -207,6 +208,24 @@ class SearchBarViewModel(
}.flowOn(Dispatchers.IO)
.stateIn(viewModelScope, WhileSubscribed(5000), emptyList())
val relayResults =
combine(
searchValueFlow.debounce(100),
invalidations,
) { term, version ->
if (term.length > 1) {
val lower = term.lowercase()
LocalCache.relayHints.relayDB
.filter { _, relay -> relay.url.contains(lower) }
.map { relaySetupInfoBuilder(it) }
.sortedByDescending { it.relayStat.receivedBytes }
.take(20)
} else {
emptyList()
}
}.flowOn(Dispatchers.IO)
.stateIn(viewModelScope, WhileSubscribed(5000), emptyList())
override val isRefreshing = derivedStateOf { searchValue.isNotBlank() }
override fun invalidateData(ignoreIfDoing: Boolean) {
@@ -54,6 +54,7 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo
@@ -70,6 +71,7 @@ import com.vitorpamplona.amethyst.ui.note.SearchIcon
import com.vitorpamplona.amethyst.ui.note.UserCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.ChannelName
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.BasicRelaySetupInfoClickableRow
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
@@ -242,6 +244,7 @@ private fun DisplaySearchResults(
}
val hashTags by searchBarViewModel.hashtagResults.collectAsStateWithLifecycle()
val relays by searchBarViewModel.relayResults.collectAsStateWithLifecycle()
val users by searchBarViewModel.searchResultsUsers.collectAsStateWithLifecycle()
val publicChatChannels by searchBarViewModel.searchResultsPublicChatChannels.collectAsStateWithLifecycle()
val ephemeralChannels by searchBarViewModel.searchResultsEphemeralChannels.collectAsStateWithLifecycle()
@@ -265,6 +268,23 @@ private fun DisplaySearchResults(
)
}
itemsIndexed(
relays,
key = { _, item -> "relay${item.relay.url}" },
) { _, relayInfo ->
BasicRelaySetupInfoClickableRow(
item = relayInfo,
loadProfilePicture = accountViewModel.settings.showProfilePictures(),
loadRobohash = accountViewModel.settings.isNotPerformanceMode(),
onClick = { nav.nav(Route.RelayInfo(relayInfo.relay.url)) },
onDelete = null,
nip11CachedRetriever = Amethyst.instance.nip11Cache,
modifier = Modifier.padding(vertical = 5.dp, horizontal = 10.dp),
accountViewModel = accountViewModel,
nav = nav,
)
}
itemsIndexed(
users,
key = { _, item -> "u" + item.pubkeyHex },