tooot/src/components/Timelines/Timeline/Shared/Attachment.tsx

173 lines
5.1 KiB
TypeScript
Raw Normal View History

2020-12-25 21:09:43 +01:00
import React, { useCallback, useMemo, useState } from 'react'
2020-12-03 01:28:56 +01:00
import { Pressable, StyleSheet, Text, View } from 'react-native'
2020-12-13 14:04:25 +01:00
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
2020-10-30 20:03:44 +01:00
2020-12-25 18:20:09 +01:00
import AttachmentImage from '@root/components/Timelines/Timeline/Shared/Attachment/Image'
import AttachmentVideo from '@root/components/Timelines/Timeline/Shared/Attachment/Video'
import { IImageInfo } from 'react-native-image-zoom-viewer/built/image-viewer.type'
import { useNavigation } from '@react-navigation/native'
import AttachmentUnsupported from './Attachment/Unsupported'
2020-12-25 21:09:43 +01:00
import AttachmentAudio from './Attachment/Audio'
import { Feather } from '@expo/vector-icons'
2020-12-26 14:40:10 +01:00
import layoutAnimation from '@root/utils/styles/layoutAnimation'
2020-10-30 20:03:44 +01:00
2020-10-31 21:04:46 +01:00
export interface Props {
2020-12-03 01:28:56 +01:00
status: Pick<Mastodon.Status, 'media_attachments' | 'sensitive'>
2020-12-25 18:20:09 +01:00
contentWidth: number
2020-10-31 21:04:46 +01:00
}
2020-12-25 18:20:09 +01:00
const TimelineAttachment: React.FC<Props> = ({ status, contentWidth }) => {
const { theme } = useTheme()
2020-12-03 01:28:56 +01:00
2020-12-25 18:20:09 +01:00
const [sensitiveShown, setSensitiveShown] = useState(status.sensitive)
2020-12-03 01:28:56 +01:00
const onPressBlurView = useCallback(() => {
2020-12-26 14:40:10 +01:00
layoutAnimation()
2020-12-03 01:28:56 +01:00
setSensitiveShown(false)
}, [])
2020-12-25 18:20:09 +01:00
let imageUrls: (IImageInfo & {
preview_url: Mastodon.AttachmentImage['preview_url']
remote_url?: Mastodon.AttachmentImage['remote_url']
imageIndex: number
})[] = []
const navigation = useNavigation()
const navigateToImagesViewer = (imageIndex: number) =>
navigation.navigate('Screen-Shared-ImagesViewer', {
imageUrls,
imageIndex
})
const attachments = useMemo(
() =>
status.media_attachments.map((attachment, index) => {
switch (attachment.type) {
case 'image':
imageUrls.push({
url: attachment.url,
width: attachment.meta?.original?.width,
height: attachment.meta?.original?.height,
preview_url: attachment.preview_url,
remote_url: attachment.remote_url,
imageIndex: index
})
return (
<AttachmentImage
key={index}
sensitiveShown={sensitiveShown}
image={attachment}
imageIndex={index}
navigateToImagesViewer={navigateToImagesViewer}
/>
)
case 'video':
return (
<AttachmentVideo
key={index}
sensitiveShown={sensitiveShown}
video={attachment}
width={contentWidth}
height={(contentWidth / 16) * 9}
/>
)
case 'gifv':
return (
<AttachmentVideo
key={index}
sensitiveShown={sensitiveShown}
video={attachment}
width={contentWidth}
height={(contentWidth / 16) * 9}
/>
)
case 'audio':
2020-12-25 21:09:43 +01:00
return (
<AttachmentAudio
key={index}
sensitiveShown={sensitiveShown}
audio={attachment}
/>
)
2020-12-25 18:20:09 +01:00
default:
return <AttachmentUnsupported key={index} attachment={attachment} />
}
}),
[sensitiveShown]
)
2020-10-30 20:03:44 +01:00
return (
2020-12-28 16:54:19 +01:00
<View style={styles.base}>
2020-12-25 18:20:09 +01:00
{attachments}
2020-12-25 21:09:43 +01:00
{status.sensitive &&
(sensitiveShown ? (
<Pressable style={styles.sensitiveBlur}>
<Pressable
onPress={onPressBlurView}
style={[
styles.sensitiveBlurButton,
{ backgroundColor: theme.backgroundOverlay }
]}
>
<Text
style={[styles.sensitiveText, { color: theme.primaryOverlay }]}
>
</Text>
</Pressable>
</Pressable>
) : (
2020-12-25 18:20:09 +01:00
<Pressable
style={[
styles.sensitiveBlurButton,
2020-12-25 21:09:43 +01:00
{
backgroundColor: theme.backgroundOverlay,
position: 'absolute',
top: StyleConstants.Spacing.S,
left: StyleConstants.Spacing.S
}
2020-12-25 18:20:09 +01:00
]}
2020-12-25 21:09:43 +01:00
onPress={() => setSensitiveShown(!sensitiveShown)}
2020-12-25 18:20:09 +01:00
>
2020-12-25 21:09:43 +01:00
<Feather
name='eye-off'
size={StyleConstants.Font.Size.L}
color={theme.primaryOverlay}
/>
2020-12-03 01:28:56 +01:00
</Pressable>
2020-12-25 21:09:43 +01:00
))}
2020-10-30 20:03:44 +01:00
</View>
)
}
2020-12-03 01:28:56 +01:00
const styles = StyleSheet.create({
2020-12-25 18:20:09 +01:00
base: {
marginTop: StyleConstants.Spacing.S,
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
2020-12-28 16:54:19 +01:00
justifyContent: 'center',
2020-12-25 18:20:09 +01:00
alignContent: 'stretch'
},
2020-12-28 16:54:19 +01:00
container: {
flexBasis: '50%',
aspectRatio: 16 / 9
},
2020-12-25 18:20:09 +01:00
sensitiveBlur: {
2020-12-03 01:28:56 +01:00
position: 'absolute',
width: '100%',
2020-12-25 18:20:09 +01:00
height: '100%',
2020-12-03 01:28:56 +01:00
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
2020-12-25 18:20:09 +01:00
sensitiveBlurButton: {
padding: StyleConstants.Spacing.S,
borderRadius: 6
},
2020-12-03 01:28:56 +01:00
sensitiveText: {
fontSize: StyleConstants.Font.Size.M
}
})
export default React.memo(TimelineAttachment, () => true)