diff --git a/src/screens/Search/SearchResults.tsx b/src/screens/Search/SearchResults.tsx index bbf08cfd26..4543e085bd 100644 --- a/src/screens/Search/SearchResults.tsx +++ b/src/screens/Search/SearchResults.tsx @@ -1,9 +1,7 @@ import {memo, useCallback, useMemo, useState} from 'react' import {ActivityIndicator, View} from 'react-native' import {type AppBskyFeedDefs} from '@atproto/api' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' -import {Trans} from '@lingui/react/macro' +import {Trans, useLingui} from '@lingui/react/macro' import {urls} from '#/lib/constants' import {usePostViewTracking} from '#/lib/hooks/usePostViewTracking' @@ -27,6 +25,7 @@ import {InlineLinkText} from '#/components/Link' import {ListFooter} from '#/components/Lists' import {SearchError} from '#/components/SearchError' import {Text} from '#/components/Typography' +import type * as bsky from '#/types/bsky' let SearchResults = ({ query, @@ -43,14 +42,14 @@ let SearchResults = ({ headerHeight: number initialPage?: number }): React.ReactNode => { - const {_} = useLingui() + const {t: l} = useLingui() const sections = useMemo(() => { if (!queryWithParams) return [] const noParams = queryWithParams === query return [ { - title: _(msg`Top`), + title: l`Top`, component: ( ), }, noParams && { - title: _(msg`Feeds`), + title: l`Feeds`, component: ( ), @@ -85,7 +84,10 @@ let SearchResults = ({ title: string component: React.ReactNode }[] - }, [_, query, queryWithParams, activeTab]) + }, [l, query, queryWithParams, activeTab]) + + // There may be fewer tabs after changing the search options. + const selectedPage = initialPage > sections.length - 1 ? 0 : initialPage return ( section.title)} {...props} /> )} - initialPage={initialPage}> + initialPage={selectedPage}> {sections.map((section, i) => ( {section.component} ))} @@ -161,15 +163,15 @@ function EmptyState({ function NoResultsText({query}: {query: string}) { const t = useTheme() - const {_} = useLingui() + const {t: l} = useLingui() return ( <> - No results found for " + No results found for “ {query} - ". + ”. {'\n\n'} @@ -177,12 +179,10 @@ function NoResultsText({query}: {query: string}) { Try a different search term, or{' '} read about how to use search filters @@ -214,7 +214,7 @@ let SearchScreenPostResults = ({ sort?: 'top' | 'latest' active: boolean }): React.ReactNode => { - const {_} = useLingui() + const {t: l} = useLingui() const {currentAccount, hasSession} = useSession() const [isPTR, setIsPTR] = useState(false) const trackPostView = usePostViewTracking('SearchResults') @@ -242,7 +242,7 @@ let SearchScreenPostResults = ({ }, [setIsPTR, refetch]) const onEndReached = useCallback(() => { if (isFetching || !hasNextPage || error) return - fetchNextPage() + void fetchNextPage() }, [isFetching, error, hasNextPage, fetchNextPage]) const posts = useMemo(() => { @@ -289,19 +289,15 @@ let SearchScreenPostResults = ({ if (!hasSession) { return ( - + - + Sign in or create an account @@ -319,9 +315,7 @@ let SearchScreenPostResults = ({ return error ? ( ) : ( @@ -331,18 +325,20 @@ let SearchScreenPostResults = ({ {posts.length ? ( { + renderItem={({item}: {item: SearchResultSlice}) => { if (item.type === 'post') { return } else { return null } }} - keyExtractor={item => item.key} + keyExtractor={(item: SearchResultSlice) => item.key} refreshing={isPTR} - onRefresh={onPullToRefresh} + onRefresh={() => { + void onPullToRefresh() + }} onEndReached={onEndReached} - onItemSeen={item => { + onItemSeen={(item: SearchResultSlice) => { if (item.type === 'post') { trackPostView(item.post) } @@ -374,7 +370,7 @@ let SearchScreenUserResults = ({ query: string active: boolean }): React.ReactNode => { - const {_} = useLingui() + const {t: l} = useLingui() const {hasSession} = useSession() const [isPTR, setIsPTR] = useState(false) @@ -400,7 +396,7 @@ let SearchScreenUserResults = ({ const onEndReached = useCallback(() => { if (!hasSession) return if (isFetching || !hasNextPage || error) return - fetchNextPage() + void fetchNextPage() }, [isFetching, error, hasNextPage, fetchNextPage, hasSession]) const profiles = useMemo(() => { @@ -410,9 +406,7 @@ let SearchScreenUserResults = ({ if (error) { return ( ) @@ -423,10 +417,12 @@ let SearchScreenUserResults = ({ {profiles.length ? ( } - keyExtractor={item => item.did} + renderItem={({item}: {item: bsky.profile.AnyProfileView}) => ( + + )} + keyExtractor={(item: bsky.profile.AnyProfileView) => item.did} refreshing={isPTR} - onRefresh={onPullToRefresh} + onRefresh={() => void onPullToRefresh()} onEndReached={onEndReached} desktopFixedHeight ListFooterComponent={ @@ -465,7 +461,7 @@ let SearchScreenFeedsResults = ({ {results.length ? ( ( + renderItem={({item}: {item: AppBskyFeedDefs.GeneratorView}) => ( )} - keyExtractor={item => item.uri} + keyExtractor={(item: AppBskyFeedDefs.GeneratorView) => item.uri} desktopFixedHeight ListFooterComponent={} /> diff --git a/src/screens/Search/Shell.tsx b/src/screens/Search/Shell.tsx index 9baffb11a4..4314f52f18 100644 --- a/src/screens/Search/Shell.tsx +++ b/src/screens/Search/Shell.tsx @@ -12,9 +12,7 @@ import { View, type ViewStyle, } from 'react-native' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' -import {Trans} from '@lingui/react/macro' +import {Trans, useLingui} from '@lingui/react/macro' import {useFocusEffect, useNavigation, useRoute} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' @@ -49,6 +47,23 @@ import {SearchLanguageDropdown} from './components/SearchLanguageDropdown' import {Explore} from './Explore' import {SearchResults} from './SearchResults' +type TabParam = 'user' | 'profile' | 'feed' | 'latest' + +// Map tab parameter to tab index +function getTabIndex(tabParam?: TabParam) { + switch (tabParam) { + case 'feed': + return 3 // Feeds tab + case 'user': + case 'profile': + return 2 // People tab + case 'latest': + return 1 // Latest tab + default: + return 0 // Top tab + } +} + export function SearchScreenShell({ queryParam, testID, @@ -69,11 +84,15 @@ export function SearchScreenShell({ const navigation = useNavigation() const route = useRoute() const textInput = useRef(null) - const {_} = useLingui() + const {t: l} = useLingui() const setMinimalShellMode = useSetMinimalShellMode() const {currentAccount} = useSession() const queryClient = useQueryClient() + // Get tab parameter from route params + const tabParam = (route.params as {q?: string; tab?: TabParam})?.tab + const [activeTab, setActiveTab] = useState(() => getTabIndex(tabParam)) + // Query terms const [searchText, setSearchText] = useState(queryParam) const {data: autocompleteData, isFetching: isAutocompleteFetching} = @@ -96,7 +115,7 @@ export function SearchScreenShell({ }) const updateSearchHistory = useCallback( - async (item: string) => { + (item: string) => { if (!item) return const newSearchHistory = [ item, @@ -108,7 +127,7 @@ export function SearchScreenShell({ ) const updateProfileHistory = useCallback( - async (item: bsky.profile.AnyProfileView) => { + (item: bsky.profile.AnyProfileView) => { const newAccountHistory = [ item.did, ...accountHistory.filter(p => p !== item.did), @@ -119,13 +138,13 @@ export function SearchScreenShell({ ) const deleteSearchHistoryItem = useCallback( - async (item: string) => { + (item: string) => { setTermHistory(termHistory.filter(search => search !== item)) }, [termHistory, setTermHistory], ) const deleteProfileHistoryItem = useCallback( - async (item: bsky.profile.AnyProfileView) => { + (item: bsky.profile.AnyProfileView) => { setAccountHistory(accountHistory.filter(p => p !== item.did)) }, [accountHistory, setAccountHistory], @@ -162,7 +181,7 @@ export function SearchScreenShell({ textInput.current?.focus() }, []) - const onChangeText = useCallback(async (text: string) => { + const onChangeText = useCallback((text: string) => { scrollToTopWeb() setSearchText(text) }, []) @@ -277,7 +296,7 @@ export function SearchScreenShell({ }, [setShowAutocomplete]) const focusSearchInput = useCallback( - (tab?: 'user' | 'profile' | 'feed') => { + (tab?: TabParam) => { textInput.current?.focus() // If a tab is specified, set the tab parameter @@ -350,15 +369,14 @@ export function SearchScreenShell({ onClearText={onPressClearQuery} onSubmitEditing={onSubmit} placeholder={ - inputPlaceholder ?? - _(msg`Search for posts, users, or feeds`) + inputPlaceholder ?? l`Search for posts, users, or feeds` } hitSlop={{...HITSLOP_20, top: 0}} /> {showAutocomplete && (