mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
feat(search): give the desktop spotlight its people picker
Typing `from:` or `to:` in the spotlight opened nothing — the field was constructed without `people`, `displayName` or `onPeopleQuery`, so the picker had no rows to offer and a key had to be pasted in as a raw npub. It now builds the same UserSearchEngine the full search screen does, with the same DesktopRelayUserSearchDelegate behind it: cache hits first, then whatever the account's search relays answer with. The built-in `people` list is used rather than the `peoplePicker` slot, because that path is the keyboard-walkable one — arrows walk the rows and Enter takes the highlighted one, which is what a spotlight is driven by. `displayName` also gives finished key chips a name instead of a short npub. The input row switches from centre to top alignment. The picker opens below the field inside the same column, so centring would drag the leading search icon halfway down it; with no picker up the two are the same height and the resting layout is unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017yKjw2WqwZpSzsqcYZMnkV
This commit is contained in:
+30
-1
@@ -62,13 +62,22 @@ import androidx.compose.ui.window.Dialog
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.search.QuerySerializer
|
||||
import com.vitorpamplona.amethyst.commons.search.UserSearchEngine
|
||||
import com.vitorpamplona.amethyst.commons.ui.search.SearchFieldState
|
||||
import com.vitorpamplona.amethyst.commons.ui.search.TokenizedSearchField
|
||||
import com.vitorpamplona.amethyst.commons.ui.search.rememberChipNames
|
||||
import com.vitorpamplona.amethyst.commons.ui.search.rememberPersonCandidates
|
||||
import com.vitorpamplona.amethyst.desktop.SearchHistoryStore
|
||||
import com.vitorpamplona.amethyst.desktop.cache.DesktopLocalCache
|
||||
import com.vitorpamplona.amethyst.desktop.network.DesktopRelayConnectionManager
|
||||
import com.vitorpamplona.amethyst.desktop.search.DesktopRelayUserSearchDelegate
|
||||
import com.vitorpamplona.amethyst.desktop.ui.relay.LocalRelayCategories
|
||||
import com.vitorpamplona.amethyst.desktop.ui.theme.hoverHighlight
|
||||
|
||||
@Composable
|
||||
fun SearchSpotlight(
|
||||
localCache: DesktopLocalCache,
|
||||
relayManager: DesktopRelayConnectionManager,
|
||||
onSelectProfile: (String) -> Unit,
|
||||
onSelectNote: (String) -> Unit,
|
||||
onSelectHashtag: (String) -> Unit,
|
||||
@@ -79,6 +88,19 @@ fun SearchSpotlight(
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val fieldState = remember { SearchFieldState() }
|
||||
|
||||
// The people a half-written `from:`/`to:` token offers, and the names their finished
|
||||
// chips draw. Same engine the full search screen uses: cache hits first, then whatever
|
||||
// the account's search relays answer with.
|
||||
val searchRelays by LocalRelayCategories.current.searchRelays.collectAsState()
|
||||
val userSearch =
|
||||
remember(relayManager, localCache) {
|
||||
UserSearchEngine(localCache, scope).apply {
|
||||
relayDelegate = DesktopRelayUserSearchDelegate(relayManager, localCache, { searchRelays }, scope)
|
||||
}
|
||||
}
|
||||
val personCandidates = rememberPersonCandidates(userSearch)
|
||||
val chipNames = rememberChipNames(userSearch)
|
||||
|
||||
val history by SearchHistoryStore.history.collectAsState()
|
||||
val savedSearches by SearchHistoryStore.savedSearches.collectAsState()
|
||||
|
||||
@@ -130,7 +152,11 @@ fun SearchSpotlight(
|
||||
) {
|
||||
// Search input
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
// Top, not centre: the picker opens *below* the field inside the
|
||||
// same column, and centring would drag the leading icon halfway
|
||||
// down it. With no picker up the two are the same height, so the
|
||||
// resting layout is unchanged.
|
||||
verticalAlignment = Alignment.Top,
|
||||
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
||||
) {
|
||||
Icon(
|
||||
@@ -148,6 +174,9 @@ fun SearchSpotlight(
|
||||
modifier = Modifier.weight(1f),
|
||||
fieldModifier = Modifier.focusRequester(focusRequester),
|
||||
placeholder = "Search notes, profiles, hashtags...",
|
||||
people = personCandidates,
|
||||
displayName = chipNames,
|
||||
onPeopleQuery = { userSearch.search(it) },
|
||||
textStyle = MaterialTheme.typography.bodyLarge,
|
||||
onSubmit = { onOpenFullSearch(fieldState.text) },
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user