tooot/src/screens/Tabs/Shared/Search.tsx

231 lines
6.8 KiB
TypeScript
Raw Normal View History

2021-01-19 01:13:45 +01:00
import ComponentAccount from '@components/Account'
import ComponentHashtag from '@components/Hashtag'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
2021-02-08 23:47:20 +01:00
import TimelineDefault from '@components/Timeline/Default'
2021-08-29 15:25:38 +02:00
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
2021-01-11 21:36:57 +01:00
import { useSearchQuery } from '@utils/queryHooks/search'
2021-01-01 16:48:16 +01:00
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
2021-03-14 00:47:55 +01:00
import React, { useCallback, useMemo } from 'react'
2021-01-19 01:13:45 +01:00
import { Trans, useTranslation } from 'react-i18next'
2020-12-19 01:57:57 +01:00
import {
KeyboardAvoidingView,
2021-01-14 00:43:35 +01:00
Platform,
2020-12-19 01:57:57 +01:00
SectionList,
StyleSheet,
View
} from 'react-native'
2021-02-08 23:47:20 +01:00
import { Circle } from 'react-native-animated-spinkit'
2020-11-24 00:18:47 +01:00
2021-12-18 19:59:38 +01:00
const TabSharedSearch: React.FC<
TabSharedStackScreenProps<'Tab-Shared-Search'>
> = ({
2021-03-14 00:47:55 +01:00
route: {
params: { text }
}
}) => {
2021-03-28 23:31:10 +02:00
const { t } = useTranslation('screenTabs')
2022-02-12 14:51:01 +01:00
const { colors } = useTheme()
2020-12-19 01:57:57 +01:00
2021-01-19 01:13:45 +01:00
const mapKeyToTranslations = {
2021-03-28 23:31:10 +02:00
accounts: t('shared.search.sections.accounts'),
hashtags: t('shared.search.sections.hashtags'),
statuses: t('shared.search.sections.statuses')
2021-01-19 01:13:45 +01:00
}
2021-12-18 19:59:38 +01:00
const { status, data } = useSearchQuery<
{
title: string
translation: string
data: any[]
}[]
>({
2021-03-14 00:47:55 +01:00
term: text,
options: {
enabled: text !== undefined,
select: data =>
2020-12-19 01:57:57 +01:00
Object.keys(data as Mastodon.Results)
2020-12-18 19:02:18 +01:00
.map(key => ({
title: key,
// @ts-ignore
2021-01-19 01:13:45 +01:00
translation: mapKeyToTranslations[key],
// @ts-ignore
2020-12-18 19:02:18 +01:00
data: data[key]
}))
.sort((a, b) => {
if (!a.data.length) {
return 1
} else if (!b.data.length) {
return -1
} else {
return 0
}
})
2020-12-19 01:57:57 +01:00
}
2021-03-14 00:47:55 +01:00
})
2020-12-18 19:02:18 +01:00
2021-01-19 01:13:45 +01:00
const listEmpty = useMemo(() => {
return (
<View
style={{
marginVertical: StyleConstants.Spacing.Global.PagePadding,
alignItems: 'center'
}}
>
2021-01-04 18:29:02 +01:00
<View>
{status === 'loading' ? (
<View style={{ flex: 1, alignItems: 'center' }}>
2021-02-08 23:47:20 +01:00
<Circle
2021-01-04 18:29:02 +01:00
size={StyleConstants.Font.Size.M * 1.25}
2022-02-12 14:51:01 +01:00
color={colors.secondary}
2021-01-04 18:29:02 +01:00
/>
</View>
) : (
<>
<CustomText
fontStyle='S'
style={{
marginBottom: StyleConstants.Spacing.L,
color: colors.primaryDefault
}}
2021-01-04 18:29:02 +01:00
>
2021-01-19 01:13:45 +01:00
<Trans
2021-03-28 23:31:10 +02:00
i18nKey='screenTabs:shared.search.empty.general'
components={{
2022-05-10 23:19:26 +02:00
bold: <CustomText fontWeight='Bold' />
}}
2021-01-19 01:13:45 +01:00
/>
</CustomText>
<CustomText
2022-02-12 14:51:01 +01:00
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
2021-03-28 23:31:10 +02:00
{t('shared.search.empty.advanced.header')}
</CustomText>
<CustomText
2022-02-12 14:51:01 +01:00
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<CustomText style={{ color: colors.secondary }}>
2022-02-12 14:51:01 +01:00
@username@domain
</CustomText>
2021-01-04 18:29:02 +01:00
{' '}
2021-03-28 23:31:10 +02:00
{t('shared.search.empty.advanced.example.account')}
</CustomText>
<CustomText
2022-02-12 14:51:01 +01:00
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<CustomText style={{ color: colors.secondary }}>
#example
</CustomText>
2021-01-19 01:13:45 +01:00
{' '}
2021-03-28 23:31:10 +02:00
{t('shared.search.empty.advanced.example.hashtag')}
</CustomText>
<CustomText
2022-02-12 14:51:01 +01:00
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
2021-01-19 01:13:45 +01:00
{' '}
2021-03-28 23:31:10 +02:00
{t('shared.search.empty.advanced.example.statusLink')}
</CustomText>
<CustomText
2022-02-12 14:51:01 +01:00
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
2021-01-19 01:13:45 +01:00
{' '}
2021-03-28 23:31:10 +02:00
{t('shared.search.empty.advanced.example.accountLink')}
</CustomText>
2021-01-04 18:29:02 +01:00
</>
)}
</View>
</View>
2021-01-19 01:13:45 +01:00
)
}, [status])
2020-12-19 01:57:57 +01:00
const sectionHeader = useCallback(
2021-01-19 01:13:45 +01:00
({ section: { translation } }) => (
2020-12-19 01:57:57 +01:00
<View
style={{
padding: StyleConstants.Spacing.M,
backgroundColor: colors.backgroundDefault
}}
2020-12-19 01:57:57 +01:00
>
<CustomText
fontStyle='M'
style={{
textAlign: 'center',
color: colors.primaryDefault
}}
2022-05-10 23:19:26 +02:00
fontWeight='Bold'
>
2021-01-19 01:13:45 +01:00
{translation}
</CustomText>
2020-12-19 01:57:57 +01:00
</View>
),
[]
)
const sectionFooter = useCallback(
2021-01-19 01:13:45 +01:00
({ section: { data, translation } }) =>
2020-12-19 01:57:57 +01:00
!data.length ? (
<View
style={{
padding: StyleConstants.Spacing.S,
backgroundColor: colors.backgroundDefault
}}
2020-12-19 01:57:57 +01:00
>
<CustomText
fontStyle='S'
style={{ textAlign: 'center', color: colors.secondary }}
>
2021-01-19 01:13:45 +01:00
<Trans
i18nKey='screenTabs:shared.search.notFound'
2021-03-14 00:47:55 +01:00
values={{ searchTerm: text, type: translation }}
components={{
2022-05-10 23:19:26 +02:00
bold: <CustomText fontWeight='Bold' />
}}
2021-01-19 01:13:45 +01:00
/>
</CustomText>
2020-12-19 01:57:57 +01:00
</View>
) : null,
2021-03-14 00:47:55 +01:00
[text]
2020-12-19 01:57:57 +01:00
)
2021-01-19 01:13:45 +01:00
const listItem = useCallback(({ item, section }) => {
2020-12-19 01:57:57 +01:00
switch (section.title) {
case 'accounts':
2021-01-24 02:25:43 +01:00
return <ComponentAccount account={item} origin='search' />
2020-12-19 01:57:57 +01:00
case 'hashtags':
2021-01-24 02:25:43 +01:00
return <ComponentHashtag hashtag={item} origin='search' />
2020-12-19 01:57:57 +01:00
case 'statuses':
2021-01-24 02:25:43 +01:00
return <TimelineDefault item={item} disableDetails origin='search' />
2020-12-19 01:57:57 +01:00
default:
return null
}
}, [])
2020-12-18 19:02:18 +01:00
return (
2021-01-14 00:43:35 +01:00
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={{ flex: 1 }}
>
2021-01-04 18:29:02 +01:00
<SectionList
style={{ minHeight: '100%' }}
2021-01-04 18:29:02 +01:00
renderItem={listItem}
stickySectionHeadersEnabled
2021-03-14 00:47:55 +01:00
sections={data || []}
2021-01-04 18:29:02 +01:00
ListEmptyComponent={listEmpty}
keyboardShouldPersistTaps='always'
renderSectionHeader={sectionHeader}
renderSectionFooter={sectionFooter}
keyExtractor={(item, index) => item + index}
SectionSeparatorComponent={ComponentSeparator}
ItemSeparatorComponent={ComponentSeparator}
/>
</KeyboardAvoidingView>
2020-12-18 19:02:18 +01:00
)
2020-11-24 00:18:47 +01:00
}
2020-12-18 19:02:18 +01:00
const styles = StyleSheet.create({
emptyAdvanced: {
marginBottom: StyleConstants.Spacing.S
}
})
2021-01-30 01:29:15 +01:00
export default TabSharedSearch