Merge branch 'mary-ext-feat/better-autocomplete-view' into main
commit
2f6c34d18d
|
@ -42,9 +42,13 @@ import {useSetDrawerOpen} from '#/state/shell'
|
|||
import {useAnalytics} from '#/lib/analytics/analytics'
|
||||
import {MagnifyingGlassIcon} from '#/lib/icons'
|
||||
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 {isWeb} from '#/platform/detection'
|
||||
import {isNative, isWeb} from '#/platform/detection'
|
||||
import {listenSoftReset} from '#/state/events'
|
||||
import {s} from '#/lib/styles'
|
||||
|
||||
|
@ -509,6 +513,11 @@ export function SearchScreen(
|
|||
onPressCancelSearch()
|
||||
}, [onPressCancelSearch])
|
||||
|
||||
const queryMaybeHandle = React.useMemo(() => {
|
||||
const match = MATCH_HANDLE.exec(query)
|
||||
return match && match[1]
|
||||
}, [query])
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
setMinimalShellMode(false)
|
||||
|
@ -615,18 +624,31 @@ export function SearchScreen(
|
|||
dataSet={{stableGutters: '1'}}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
keyboardDismissMode="on-drag">
|
||||
{searchResults.length ? (
|
||||
searchResults.map((item, i) => (
|
||||
<SearchResultCard
|
||||
<SearchLinkCard
|
||||
label={_(msg`Search for "${query}"`)}
|
||||
onPress={isNative ? onSubmit : undefined}
|
||||
to={
|
||||
isNative
|
||||
? undefined
|
||||
: `/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}
|
||||
profile={item}
|
||||
moderation={moderateProfile(item, moderationOpts)}
|
||||
style={i === 0 ? {borderTopWidth: 0} : {}}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<EmptyState message={_(msg`No results found for ${query}`)} />
|
||||
)}
|
||||
))}
|
||||
|
||||
<View style={{height: 200}} />
|
||||
</ScrollView>
|
||||
|
|
|
@ -29,13 +29,63 @@ import {UserAvatar} from '#/view/com/util/UserAvatar'
|
|||
import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
|
||||
import {useModerationOpts} from '#/state/queries/preferences'
|
||||
|
||||
export function SearchResultCard({
|
||||
profile,
|
||||
export const MATCH_HANDLE =
|
||||
/@?([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))/
|
||||
|
||||
export function SearchLinkCard({
|
||||
label,
|
||||
to,
|
||||
onPress,
|
||||
style,
|
||||
}: {
|
||||
label: string
|
||||
to?: string
|
||||
onPress?: () => void
|
||||
style?: ViewStyle
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
|
||||
const inner = (
|
||||
<View
|
||||
style={[pal.border, {paddingVertical: 16, paddingHorizontal: 12}, style]}>
|
||||
<Text type="md" style={[pal.text]}>
|
||||
{label}
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
|
||||
if (onPress) {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={onPress}
|
||||
accessibilityLabel={label}
|
||||
accessibilityHint="">
|
||||
{inner}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
}: {
|
||||
profile: AppBskyActorDefs.ProfileViewBasic
|
||||
style: ViewStyle
|
||||
moderation: ProfileModeration
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
|
@ -50,9 +100,7 @@ export function SearchResultCard({
|
|||
<View
|
||||
style={[
|
||||
pal.border,
|
||||
style,
|
||||
{
|
||||
borderTopWidth: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
|
@ -147,6 +195,11 @@ export function DesktopSearch() {
|
|||
navigation.dispatch(StackActions.push('Search', {q: query}))
|
||||
}, [query, navigation, setSearchResults])
|
||||
|
||||
const queryMaybeHandle = React.useMemo(() => {
|
||||
const match = MATCH_HANDLE.exec(query)
|
||||
return match && match[1]
|
||||
}, [query])
|
||||
|
||||
return (
|
||||
<View style={[styles.container, pal.view]}>
|
||||
<View
|
||||
|
@ -198,22 +251,26 @@ export function DesktopSearch() {
|
|||
</View>
|
||||
) : (
|
||||
<>
|
||||
{searchResults.length ? (
|
||||
searchResults.map((item, i) => (
|
||||
<SearchResultCard
|
||||
<SearchLinkCard
|
||||
label={_(msg`Search for "${query}"`)}
|
||||
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}
|
||||
profile={item}
|
||||
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>
|
||||
|
|
Loading…
Reference in New Issue