tooot/src/components/Timeline/Shared/Card.tsx

162 lines
5.0 KiB
TypeScript
Raw Normal View History

2022-11-12 17:52:50 +01:00
import ComponentAccount from '@components/Account'
2021-01-16 00:00:31 +01:00
import GracefullyImage from '@components/GracefullyImage'
2021-01-01 16:48:16 +01:00
import openLink from '@components/openLink'
import CustomText from '@components/Text'
2021-03-21 23:06:53 +01:00
import { useNavigation } from '@react-navigation/native'
2023-01-03 23:57:23 +01:00
import { StackNavigationProp } from '@react-navigation/stack'
import { urlMatcher } from '@utils/helpers/urlMatcher'
import { TabLocalStackParamList } from '@utils/navigation/navigators'
2022-11-12 17:52:50 +01:00
import { useAccountQuery } from '@utils/queryHooks/account'
import { useStatusQuery } from '@utils/queryHooks/status'
2020-12-13 14:04:25 +01:00
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
2022-12-03 20:47:11 +01:00
import React, { useContext, useEffect, useState } from 'react'
2022-12-31 00:07:28 +01:00
import { Pressable, View } from 'react-native'
2022-11-12 17:52:50 +01:00
import TimelineDefault from '../Default'
2022-12-03 20:47:11 +01:00
import StatusContext from './Context'
2020-10-29 14:52:28 +01:00
2022-12-03 20:47:11 +01:00
const TimelineCard: React.FC = () => {
const { status, spoilerHidden, disableDetails } = useContext(StatusContext)
if (!status || !status.card) return null
2020-10-31 21:04:46 +01:00
2022-04-30 21:47:17 +02:00
const { colors } = useTheme()
2023-01-03 23:57:23 +01:00
const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
2020-11-28 17:07:30 +01:00
2022-11-12 17:52:50 +01:00
const [loading, setLoading] = useState(false)
2023-01-03 23:57:23 +01:00
const match = urlMatcher(status.card.url)
2022-11-12 17:52:50 +01:00
const [foundStatus, setFoundStatus] = useState<Mastodon.Status>()
const [foundAccount, setFoundAccount] = useState<Mastodon.Account>()
const statusQuery = useStatusQuery({
2023-01-03 23:57:23 +01:00
status: match?.status ? { ...match.status, uri: status.card.url } : undefined,
2023-01-09 19:18:48 +01:00
options: { enabled: false, retry: false }
2022-11-12 17:52:50 +01:00
})
useEffect(() => {
2023-01-03 23:57:23 +01:00
if (match?.status) {
2022-11-12 17:52:50 +01:00
setLoading(true)
2023-01-03 23:57:23 +01:00
statusQuery
.refetch()
.then(res => {
res.data && setFoundStatus(res.data)
setLoading(false)
})
.catch(() => setLoading(false))
2022-11-12 17:52:50 +01:00
}
}, [])
const accountQuery = useAccountQuery({
2023-01-03 23:57:23 +01:00
account: match?.account ? { ...match?.account, url: status.card.url } : undefined,
2023-01-09 19:18:48 +01:00
options: { enabled: false, retry: false }
2022-11-12 17:52:50 +01:00
})
useEffect(() => {
2023-01-03 23:57:23 +01:00
if (match?.account) {
2022-11-12 17:52:50 +01:00
setLoading(true)
2023-01-03 23:57:23 +01:00
accountQuery
.refetch()
.then(res => {
res.data && setFoundAccount(res.data)
setLoading(false)
})
.catch(() => setLoading(false))
2022-11-12 17:52:50 +01:00
}
}, [])
2023-01-12 20:28:43 +01:00
if (loading) {
return null
}
2023-01-14 15:26:11 +01:00
if (status.media_attachments.length) {
return null
}
2023-01-12 20:28:43 +01:00
if ((!status.card?.image || !status.card.title) && !status.card?.description) {
return null
}
2022-11-12 17:52:50 +01:00
const cardContent = () => {
2023-01-03 23:57:23 +01:00
if (match?.status && foundStatus) {
2022-11-29 23:44:11 +01:00
return <TimelineDefault item={foundStatus} disableDetails disableOnPress />
2022-11-12 17:52:50 +01:00
}
2023-01-03 23:57:23 +01:00
if (match?.account && foundAccount) {
2022-11-29 23:44:11 +01:00
return <ComponentAccount account={foundAccount} />
2022-11-12 17:52:50 +01:00
}
return (
<>
2022-12-03 20:47:11 +01:00
{status.card?.image ? (
2022-11-12 17:52:50 +01:00
<GracefullyImage
2023-02-08 01:10:59 +01:00
sources={{ default: { uri: status.card.image }, blurhash: status.card.blurhash }}
2022-11-12 17:52:50 +01:00
style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }}
imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }}
2023-01-29 17:28:49 +01:00
dim
2022-11-12 17:52:50 +01:00
/>
) : null}
<View style={{ flex: 1, padding: StyleConstants.Spacing.S }}>
2022-12-17 23:31:46 +01:00
{status.card?.title.length ? (
<CustomText
fontStyle='S'
numberOfLines={2}
style={{
marginBottom: StyleConstants.Spacing.XS,
color: colors.primaryDefault
}}
fontWeight='Bold'
testID='title'
>
{status.card.title}
</CustomText>
) : null}
{status.card?.description.length ? (
2022-11-12 17:52:50 +01:00
<CustomText
fontStyle='S'
numberOfLines={1}
style={{
marginBottom: StyleConstants.Spacing.XS,
color: colors.primaryDefault
}}
testID='description'
>
2022-12-03 20:47:11 +01:00
{status.card.description}
2022-11-12 17:52:50 +01:00
</CustomText>
) : null}
2022-12-17 23:31:46 +01:00
{status.card?.url.length ? (
<CustomText fontStyle='S' numberOfLines={1} style={{ color: colors.secondary }}>
{status.card.url}
</CustomText>
) : null}
2022-11-12 17:52:50 +01:00
</View>
</>
)
}
2022-12-03 20:47:11 +01:00
if (spoilerHidden || disableDetails) return null
2022-04-30 21:47:17 +02:00
return (
<Pressable
accessible
accessibilityRole='link'
style={{
flex: 1,
flexDirection: 'row',
marginTop: StyleConstants.Spacing.M,
2022-12-31 00:07:28 +01:00
borderWidth: 1,
2022-11-12 17:52:50 +01:00
borderRadius: StyleConstants.Spacing.S,
overflow: 'hidden',
borderColor: colors.border
}}
2023-01-03 23:57:23 +01:00
onPress={async () => {
if (match?.status && foundStatus) {
navigation.push('Tab-Shared-Toot', { toot: foundStatus })
return
}
if (match?.account && foundAccount) {
navigation.push('Tab-Shared-Account', { account: foundAccount })
return
}
status.card?.url && (await openLink(status.card.url, navigation))
}}
2022-12-03 20:47:11 +01:00
children={cardContent()}
2022-11-12 17:52:50 +01:00
/>
2022-04-30 21:47:17 +02:00
)
2022-12-03 20:47:11 +01:00
}
2020-10-29 14:52:28 +01:00
2021-02-27 16:33:54 +01:00
export default TimelineCard