diff options
Diffstat (limited to 'src/view/shell')
-rw-r--r-- | src/view/shell/Drawer.tsx | 5 | ||||
-rw-r--r-- | src/view/shell/desktop/Search.tsx | 99 | ||||
-rw-r--r-- | src/view/shell/index.tsx | 2 | ||||
-rw-r--r-- | src/view/shell/index.web.tsx | 2 |
4 files changed, 86 insertions, 22 deletions
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx index 6f748755a..c30874c2f 100644 --- a/src/view/shell/Drawer.tsx +++ b/src/view/shell/Drawer.tsx @@ -53,6 +53,8 @@ import {useInviteCodesQuery} from '#/state/queries/invites' import {NavSignupCard} from '#/view/shell/NavSignupCard' import {TextLink} from '../com/util/Link' +import {useTheme as useAlfTheme} from '#/alf' + let DrawerProfileCard = ({ account, onPressProfile, @@ -106,6 +108,7 @@ export {DrawerProfileCard} let DrawerContent = ({}: {}): React.ReactNode => { const theme = useTheme() + const t = useAlfTheme() const pal = usePalette('default') const {_} = useLingui() const setDrawerOpen = useSetDrawerOpen() @@ -208,7 +211,7 @@ let DrawerContent = ({}: {}): React.ReactNode => { testID="drawer" style={[ styles.view, - theme.colorScheme === 'light' ? pal.view : styles.viewDarkMode, + theme.colorScheme === 'light' ? pal.view : t.atoms.bg_contrast_25, ]}> <SafeAreaView style={s.flex1}> <ScrollView style={styles.main}> diff --git a/src/view/shell/desktop/Search.tsx b/src/view/shell/desktop/Search.tsx index df49da55b..4a9483733 100644 --- a/src/view/shell/desktop/Search.tsx +++ b/src/view/shell/desktop/Search.tsx @@ -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 - 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> - )} + <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)} + /> + ))} </> )} </View> diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index 51c03ae3d..5320aebfc 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -28,6 +28,7 @@ import {isAndroid} from 'platform/detection' import {useSession} from '#/state/session' import {useCloseAnyActiveElement} from '#/state/util' import * as notifications from 'lib/notifications/notifications' +import {Outlet as PortalOutlet} from '#/components/Portal' function ShellInner() { const isDrawerOpen = useIsDrawerOpen() @@ -94,6 +95,7 @@ function ShellInner() { </View> <Composer winHeight={winDim.height} /> <ModalsContainer /> + <PortalOutlet /> <Lightbox /> </> ) diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx index 20bc0dff1..1ada883c9 100644 --- a/src/view/shell/index.web.tsx +++ b/src/view/shell/index.web.tsx @@ -15,6 +15,7 @@ import {useAuxClick} from 'lib/hooks/useAuxClick' import {t} from '@lingui/macro' import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' import {useCloseAllActiveElements} from '#/state/util' +import {Outlet as PortalOutlet} from '#/components/Portal' function ShellInner() { const isDrawerOpen = useIsDrawerOpen() @@ -41,6 +42,7 @@ function ShellInner() { </View> <Composer winHeight={0} /> <ModalsContainer /> + <PortalOutlet /> <Lightbox /> {!isDesktop && isDrawerOpen && ( <TouchableOpacity |