Merge branch 'feat/better-autocomplete-view' of https://github.com/mary-ext/fork-bsky-app into mary-ext-feat/better-autocomplete-view

zio/stable
Paul Frazee 2024-01-18 22:10:33 -08:00
commit 809c534d32
2 changed files with 86 additions and 34 deletions

View File

@ -42,7 +42,11 @@ import {useSetDrawerOpen} from '#/state/shell'
import {useAnalytics} from '#/lib/analytics/analytics' import {useAnalytics} from '#/lib/analytics/analytics'
import {MagnifyingGlassIcon} from '#/lib/icons' import {MagnifyingGlassIcon} from '#/lib/icons'
import {useModerationOpts} from '#/state/queries/preferences' import {useModerationOpts} from '#/state/queries/preferences'
import {SearchResultCard} from '#/view/shell/desktop/Search' import {
MATCH_HANDLE,
SearchLinkCard,
SearchProfileCard,
} from '#/view/shell/desktop/Search'
import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell' import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
import {isWeb} from '#/platform/detection' import {isWeb} from '#/platform/detection'
import {listenSoftReset} from '#/state/events' import {listenSoftReset} from '#/state/events'
@ -509,6 +513,11 @@ export function SearchScreen(
onPressCancelSearch() onPressCancelSearch()
}, [onPressCancelSearch]) }, [onPressCancelSearch])
const queryMaybeHandle = React.useMemo(() => {
const match = MATCH_HANDLE.exec(query)
return match && match[1]
}, [query])
useFocusEffect( useFocusEffect(
React.useCallback(() => { React.useCallback(() => {
setMinimalShellMode(false) setMinimalShellMode(false)
@ -615,18 +624,26 @@ export function SearchScreen(
dataSet={{stableGutters: '1'}} dataSet={{stableGutters: '1'}}
keyboardShouldPersistTaps="handled" keyboardShouldPersistTaps="handled"
keyboardDismissMode="on-drag"> keyboardDismissMode="on-drag">
{searchResults.length ? ( <SearchLinkCard
searchResults.map((item, i) => ( label={_(msg`Search for "${query}"`)}
<SearchResultCard to={`/search?q=${encodeURIComponent(query)}`}
style={{borderBottomWidth: 1}}
/>
{queryMaybeHandle ? (
<SearchLinkCard
label={_(msg`Go to @${queryMaybeHandle}`)}
to={`/profile/${queryMaybeHandle}`}
/>
) : null}
{searchResults.map(item => (
<SearchProfileCard
key={item.did} key={item.did}
profile={item} profile={item}
moderation={moderateProfile(item, moderationOpts)} moderation={moderateProfile(item, moderationOpts)}
style={i === 0 ? {borderTopWidth: 0} : {}}
/> />
)) ))}
) : (
<EmptyState message={_(msg`No results found for ${query}`)} />
)}
<View style={{height: 200}} /> <View style={{height: 200}} />
</ScrollView> </ScrollView>

View File

@ -29,13 +29,41 @@ import {UserAvatar} from '#/view/com/util/UserAvatar'
import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete' import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
import {useModerationOpts} from '#/state/queries/preferences' import {useModerationOpts} from '#/state/queries/preferences'
export function SearchResultCard({ export const MATCH_HANDLE =
profile, /@?([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))/
export function SearchLinkCard({
label,
to,
style, style,
}: {
label: string
to: string
style?: ViewStyle
}) {
const pal = usePalette('default')
return (
<Link href={to} asAnchor anchorNoUnderline>
<View
style={[
pal.border,
{paddingVertical: 16, paddingHorizontal: 12},
style,
]}>
<Text type="md" style={[pal.text]}>
{label}
</Text>
</View>
</Link>
)
}
export function SearchProfileCard({
profile,
moderation, moderation,
}: { }: {
profile: AppBskyActorDefs.ProfileViewBasic profile: AppBskyActorDefs.ProfileViewBasic
style: ViewStyle
moderation: ProfileModeration moderation: ProfileModeration
}) { }) {
const pal = usePalette('default') const pal = usePalette('default')
@ -50,9 +78,7 @@ export function SearchResultCard({
<View <View
style={[ style={[
pal.border, pal.border,
style,
{ {
borderTopWidth: 1,
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
gap: 12, gap: 12,
@ -147,6 +173,11 @@ export function DesktopSearch() {
navigation.dispatch(StackActions.push('Search', {q: query})) navigation.dispatch(StackActions.push('Search', {q: query}))
}, [query, navigation, setSearchResults]) }, [query, navigation, setSearchResults])
const queryMaybeHandle = React.useMemo(() => {
const match = MATCH_HANDLE.exec(query)
return match && match[1]
}, [query])
return ( return (
<View style={[styles.container, pal.view]}> <View style={[styles.container, pal.view]}>
<View <View
@ -198,22 +229,26 @@ export function DesktopSearch() {
</View> </View>
) : ( ) : (
<> <>
{searchResults.length ? ( <SearchLinkCard
searchResults.map((item, i) => ( label={_(msg`Search for "${query}"`)}
<SearchResultCard to={`/search?q=${encodeURIComponent(query)}`}
style={{borderBottomWidth: 1}}
/>
{queryMaybeHandle ? (
<SearchLinkCard
label={_(msg`Go to @${queryMaybeHandle}`)}
to={`/profile/${queryMaybeHandle}`}
/>
) : null}
{searchResults.map(item => (
<SearchProfileCard
key={item.did} key={item.did}
profile={item} profile={item}
moderation={moderateProfile(item, moderationOpts)} moderation={moderateProfile(item, moderationOpts)}
style={i === 0 ? {borderTopWidth: 0} : {}}
/> />
)) ))}
) : (
<View>
<Text style={[pal.textLight, styles.noResults]}>
<Trans>No results found for {query}</Trans>
</Text>
</View>
)}
</> </>
)} )}
</View> </View>