tooot/src/screens/Shared/Compose/Attachments.tsx

241 lines
7.1 KiB
TypeScript
Raw Normal View History

import React, { useCallback, useContext } from 'react'
2020-12-06 21:42:19 +01:00
import {
FlatList,
Image,
Pressable,
StyleSheet,
Text,
View
} from 'react-native'
2020-12-13 14:04:25 +01:00
import { ComposeContext } from '@screens/Shared/Compose'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
2020-12-06 12:52:29 +01:00
import { useNavigation } from '@react-navigation/native'
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder'
2020-12-13 14:04:25 +01:00
import { ButtonRound } from '@components/Button'
import addAttachments from '@screens/Shared/Compose/addAttachments'
2020-12-07 00:23:26 +01:00
import { Feather } from '@expo/vector-icons'
import { LinearGradient } from 'expo-linear-gradient'
2020-12-06 12:52:29 +01:00
const DEFAULT_HEIGHT = 200
const ComposeAttachments: React.FC = () => {
const { composeState, composeDispatch } = useContext(ComposeContext)
2020-12-06 12:52:29 +01:00
const { theme } = useTheme()
const navigation = useNavigation()
2020-12-06 21:42:19 +01:00
const renderAttachment = useCallback(
2020-12-06 12:52:29 +01:00
({
item,
index
}: {
item: Mastodon.Attachment & { local_url?: string }
index: number
}) => {
return (
<View key={index}>
<Image
style={[
styles.image,
{
2020-12-06 21:42:19 +01:00
width:
((item as Mastodon.AttachmentImage).meta?.original?.aspect ||
(item as Mastodon.AttachmentVideo).meta?.original.width! /
(item as Mastodon.AttachmentVideo).meta?.original
.height! ||
1) * DEFAULT_HEIGHT
2020-12-06 12:52:29 +01:00
}
]}
source={{
uri:
item.type === 'image'
? item.local_url || item.preview_url
: item.preview_url
}}
/>
2020-12-06 21:42:19 +01:00
{(item as Mastodon.AttachmentVideo).meta?.original?.duration && (
<Text
style={[
styles.duration,
{
color: theme.background,
backgroundColor: theme.backgroundOverlay
}
]}
>
{(item as Mastodon.AttachmentVideo).meta?.original.duration}
</Text>
)}
<ButtonRound
icon='x'
onPress={() =>
2020-12-07 12:31:40 +01:00
composeDispatch({
2020-12-06 12:52:29 +01:00
type: 'attachments',
2020-12-07 00:23:26 +01:00
payload: {
2020-12-07 12:31:40 +01:00
uploads: composeState.attachments.uploads.filter(
2020-12-07 00:23:26 +01:00
e => e.id !== item.id
)
}
2020-12-06 12:52:29 +01:00
})
2020-12-06 21:42:19 +01:00
}
styles={styles.delete}
/>
<ButtonRound
icon='edit'
onPress={() =>
2020-12-06 12:52:29 +01:00
navigation.navigate('Screen-Shared-Compose-EditAttachment', {
2020-12-06 16:06:38 +01:00
attachment: item,
2020-12-07 12:31:40 +01:00
composeDispatch
2020-12-06 12:52:29 +01:00
})
2020-12-06 21:42:19 +01:00
}
styles={styles.edit}
/>
2020-12-06 12:52:29 +01:00
</View>
)
},
[]
)
2020-12-06 21:42:19 +01:00
const listFooter = useCallback(() => {
const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient)
2020-12-06 21:42:19 +01:00
return (
<ShimmerPlaceholder
style={styles.progressContainer}
2020-12-07 12:31:40 +01:00
visible={composeState.attachmentUploadProgress === undefined}
2020-12-06 21:42:19 +01:00
width={
(composeState.attachmentUploadProgress?.aspect || 3 / 2) *
DEFAULT_HEIGHT
2020-12-06 21:42:19 +01:00
}
height={200}
>
2020-12-07 12:31:40 +01:00
{composeState.attachments.uploads.length > 0 &&
composeState.attachments.uploads[0].type === 'image' &&
composeState.attachments.uploads.length < 4 && (
2020-12-06 21:42:19 +01:00
<Pressable
style={{
width: DEFAULT_HEIGHT,
height: DEFAULT_HEIGHT,
backgroundColor: theme.border
}}
onPress={async () =>
2020-12-07 12:31:40 +01:00
await addAttachments({ composeState, composeDispatch })
2020-12-06 21:42:19 +01:00
}
>
<ButtonRound
icon='upload-cloud'
onPress={async () =>
2020-12-07 12:31:40 +01:00
await addAttachments({ composeState, composeDispatch })
2020-12-06 21:42:19 +01:00
}
styles={{
top:
(DEFAULT_HEIGHT -
StyleConstants.Spacing.Global.PagePadding) /
2,
left:
(DEFAULT_HEIGHT -
StyleConstants.Spacing.Global.PagePadding) /
2
}}
coordinate='center'
/>
</Pressable>
)}
</ShimmerPlaceholder>
)
2020-12-07 12:31:40 +01:00
}, [composeState.attachmentUploadProgress, composeState.attachments.uploads])
2020-12-06 21:42:19 +01:00
return (
<View style={styles.base}>
2020-12-07 00:23:26 +01:00
<Pressable
style={styles.sensitive}
onPress={() =>
2020-12-07 12:31:40 +01:00
composeDispatch({
2020-12-07 00:23:26 +01:00
type: 'attachments',
2020-12-07 12:31:40 +01:00
payload: { sensitive: !composeState.attachments.sensitive }
2020-12-07 00:23:26 +01:00
})
}
>
<Feather
2020-12-07 12:31:40 +01:00
name={composeState.attachments.sensitive ? 'check-circle' : 'circle'}
2020-12-07 00:23:26 +01:00
size={StyleConstants.Font.Size.L}
color={theme.primary}
/>
<Text style={[styles.sensitiveText, { color: theme.primary }]}>
</Text>
</Pressable>
<View style={styles.imageContainer}>
<FlatList
horizontal
2020-12-07 12:31:40 +01:00
extraData={composeState.attachments.uploads.length}
data={composeState.attachments.uploads}
2020-12-07 00:23:26 +01:00
renderItem={renderAttachment}
ListFooterComponent={listFooter}
showsHorizontalScrollIndicator={false}
keyboardShouldPersistTaps='handled'
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
base: {
flex: 1,
marginRight: StyleConstants.Spacing.Global.PagePadding,
2020-12-07 00:23:26 +01:00
marginTop: StyleConstants.Spacing.M
},
sensitive: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginLeft: StyleConstants.Spacing.Global.PagePadding
},
sensitiveText: {
fontSize: StyleConstants.Font.Size.M,
marginLeft: StyleConstants.Spacing.S
},
imageContainer: {
2020-12-06 12:52:29 +01:00
height: DEFAULT_HEIGHT
},
image: {
flex: 1,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.Global.PagePadding
},
2020-12-06 21:42:19 +01:00
duration: {
position: 'absolute',
2020-12-06 21:42:19 +01:00
bottom:
StyleConstants.Spacing.Global.PagePadding + StyleConstants.Spacing.S,
left: StyleConstants.Spacing.Global.PagePadding + StyleConstants.Spacing.S,
fontSize: StyleConstants.Font.Size.S,
paddingLeft: StyleConstants.Spacing.S,
paddingRight: StyleConstants.Spacing.S,
paddingTop: StyleConstants.Spacing.XS,
paddingBottom: StyleConstants.Spacing.XS
},
2020-12-06 12:52:29 +01:00
edit: {
bottom:
StyleConstants.Spacing.Global.PagePadding + StyleConstants.Spacing.S,
right: StyleConstants.Spacing.S
},
delete: {
top: StyleConstants.Spacing.Global.PagePadding + StyleConstants.Spacing.S,
right: StyleConstants.Spacing.S
},
progressContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
height: DEFAULT_HEIGHT,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.Global.PagePadding
}
})
2020-12-07 00:23:26 +01:00
export default ComposeAttachments