diff --git a/src/screens/Tabs/Local.tsx b/src/screens/Tabs/Local.tsx index 7f885001..93bba91d 100644 --- a/src/screens/Tabs/Local.tsx +++ b/src/screens/Tabs/Local.tsx @@ -86,12 +86,7 @@ const TabLocal = React.memo( accessibilityLabel={t('common.search.accessibilityLabel')} accessibilityHint={t('common.search.accessibilityHint')} content='Search' - onPress={() => - navigation.navigate('Tab-Local', { - screen: 'Tab-Shared-Search', - params: { text: undefined } - }) - } + onPress={() => navigation.navigate('Tab-Local', { screen: 'Tab-Shared-Search' })} /> ) }} diff --git a/src/screens/Tabs/Public.tsx b/src/screens/Tabs/Public.tsx index 65fbbd04..8865623e 100644 --- a/src/screens/Tabs/Public.tsx +++ b/src/screens/Tabs/Public.tsx @@ -50,12 +50,7 @@ const TabPublic = React.memo( accessibilityLabel={t('common.search.accessibilityLabel')} accessibilityHint={t('common.search.accessibilityHint')} content='Search' - onPress={() => - navigation.navigate('Tab-Public', { - screen: 'Tab-Shared-Search', - params: { text: undefined } - }) - } + onPress={() => navigation.navigate('Tab-Public', { screen: 'Tab-Shared-Search' })} /> ) }), diff --git a/src/screens/Tabs/Shared/Search/Empty.tsx b/src/screens/Tabs/Shared/Search/Empty.tsx new file mode 100644 index 00000000..34b61b01 --- /dev/null +++ b/src/screens/Tabs/Shared/Search/Empty.tsx @@ -0,0 +1,114 @@ +import ComponentHashtag from '@components/Hashtag' +import ComponentSeparator from '@components/Separator' +import CustomText from '@components/Text' +import { useTrendsQuery } from '@utils/queryHooks/trends' +import { StyleConstants } from '@utils/styles/constants' +import { useTheme } from '@utils/styles/ThemeManager' +import React from 'react' +import { Trans, useTranslation } from 'react-i18next' +import { StyleSheet, TextInput, View } from 'react-native' +import { Circle } from 'react-native-animated-spinkit' + +export interface Props { + isLoading: boolean + inputRef: React.RefObject + setSearchTerm: React.Dispatch> +} + +const SearchEmpty: React.FC = ({ isLoading, inputRef, setSearchTerm }) => { + const { colors } = useTheme() + const { t } = useTranslation('screenTabs') + + const trendsTags = useTrendsQuery({ type: 'tags' }) + + return ( + + {isLoading ? ( + + + + ) : ( + <> + + + + }} + /> + + + {t('shared.search.empty.advanced.header')} + + + @username@domain + {' '} + {t('shared.search.empty.advanced.example.account')} + + + #example + {' '} + {t('shared.search.empty.advanced.example.hashtag')} + + + URL + {' '} + {t('shared.search.empty.advanced.example.statusLink')} + + + URL + {' '} + {t('shared.search.empty.advanced.example.accountLink')} + + + + + {t('shared.search.empty.trending.tags')} + + + {trendsTags.data?.map((tag, index) => { + const hashtag = tag as Mastodon.Tag + return ( + + {index !== 0 ? : null} + { + inputRef.current?.setNativeProps({ text: `#${hashtag.name}` }) + setSearchTerm(`#${hashtag.name}`) + }} + /> + + ) + })} + + + )} + + ) +} + +const styles = StyleSheet.create({ + emptyAdvanced: { + marginBottom: StyleConstants.Spacing.S + } +}) + +export default SearchEmpty diff --git a/src/screens/Tabs/Shared/Search.tsx b/src/screens/Tabs/Shared/Search/index.tsx similarity index 54% rename from src/screens/Tabs/Shared/Search.tsx rename to src/screens/Tabs/Shared/Search/index.tsx index ba7fa0d0..2eee2d01 100644 --- a/src/screens/Tabs/Shared/Search.tsx +++ b/src/screens/Tabs/Shared/Search/index.tsx @@ -6,31 +6,22 @@ import CustomText from '@components/Text' import TimelineDefault from '@components/Timeline/Default' import { TabSharedStackScreenProps } from '@utils/navigation/navigators' import { useSearchQuery } from '@utils/queryHooks/search' -import { useTrendsQuery } from '@utils/queryHooks/trends' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import { debounce } from 'lodash' -import React, { useEffect } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' -import { - KeyboardAvoidingView, - Platform, - SectionList, - StyleSheet, - TextInput, - View -} from 'react-native' -import { Circle } from 'react-native-animated-spinkit' +import { KeyboardAvoidingView, Platform, SectionList, TextInput, View } from 'react-native' +import SearchEmpty from './Empty' const TabSharedSearch: React.FC> = ({ - navigation, - route: { - params: { text } - } + navigation }) => { const { t } = useTranslation('screenTabs') const { colors, mode } = useTheme() + const inputRef = useRef(null) + const [searchTerm, setSearchTerm] = useState('') useEffect(() => { navigation.setOptions({ ...(Platform.OS === 'ios' @@ -56,6 +47,7 @@ const TabSharedSearch: React.FC> defaultValue={t('shared.search.header.prefix')} /> > paddingLeft: StyleConstants.Spacing.XS }} autoFocus - value={text} - onChangeText={debounce((text: string) => navigation.setParams({ text }), 1000, { - trailing: true - })} + onChangeText={debounce( + text => { + setSearchTerm(text) + refetch() + }, + 1000, + { trailing: true } + )} autoCapitalize='none' autoCorrect={false} clearButtonMode='always' keyboardType='web-search' - onSubmitEditing={({ nativeEvent: { text } }) => navigation.setParams({ text })} placeholder={t('shared.search.header.placeholder')} placeholderTextColor={colors.secondary} returnKeyType='search' @@ -82,25 +77,23 @@ const TabSharedSearch: React.FC> ) } }) - }, [text, mode]) - - const trendsTags = useTrendsQuery({ type: 'tags' }) + }, [mode]) const mapKeyToTranslations = { accounts: t('shared.search.sections.accounts'), hashtags: t('shared.search.sections.hashtags'), statuses: t('shared.search.sections.statuses') } - const { status, data } = useSearchQuery< + const { isLoading, data, refetch } = useSearchQuery< { title: string translation: string data: any[] }[] >({ - term: text, + term: searchTerm, options: { - enabled: text !== undefined, + enabled: !!searchTerm.length, select: data => Object.keys(data as Mastodon.Results) .map(key => ({ @@ -110,6 +103,7 @@ const TabSharedSearch: React.FC> // @ts-ignore data: data[key] })) + .filter(d => d.data.length) .sort((a, b) => { if (!a.data.length) { return 1 @@ -122,88 +116,6 @@ const TabSharedSearch: React.FC> } }) - const listEmpty = () => { - return ( - - {status === 'loading' ? ( - - - - ) : ( - <> - - - - }} - /> - - - {t('shared.search.empty.advanced.header')} - - - @username@domain - {' '} - {t('shared.search.empty.advanced.example.account')} - - - #example - {' '} - {t('shared.search.empty.advanced.example.hashtag')} - - - URL - {' '} - {t('shared.search.empty.advanced.example.statusLink')} - - - URL - {' '} - {t('shared.search.empty.advanced.example.accountLink')} - - - - - {t('shared.search.empty.trending.tags')} - - - {trendsTags.data?.map((tag, index) => { - const hashtag = tag as Mastodon.Tag - return ( - - {index !== 0 ? : null} - navigation.setParams({ text: `#${hashtag.name}` })} - /> - - ) - })} - - - )} - - ) - } - return ( > > { switch (section.title) { case 'accounts': @@ -224,8 +137,9 @@ const TabSharedSearch: React.FC> } }} stickySectionHeadersEnabled - sections={data || []} - ListEmptyComponent={listEmpty()} + ListEmptyComponent={ + + } keyboardShouldPersistTaps='always' renderSectionHeader={({ section: { translation } }) => ( > }} @@ -274,10 +188,4 @@ const TabSharedSearch: React.FC> ) } -const styles = StyleSheet.create({ - emptyAdvanced: { - marginBottom: StyleConstants.Spacing.S - } -}) - export default TabSharedSearch diff --git a/src/utils/navigation/navigators.ts b/src/utils/navigation/navigators.ts index 2560bf75..8c7f70ee 100644 --- a/src/utils/navigation/navigators.ts +++ b/src/utils/navigation/navigators.ts @@ -104,7 +104,7 @@ export type TabSharedStackParamList = { 'Tab-Shared-History': { id: Mastodon.Status['id'] } - 'Tab-Shared-Search': { text: string | undefined } + 'Tab-Shared-Search': undefined 'Tab-Shared-Toot': { toot: Mastodon.Status rootQueryKey?: QueryKeyTimeline