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

204 lines
5.9 KiB
TypeScript
Raw Normal View History

import React, { Dispatch, useCallback } from 'react'
2020-12-06 21:42:19 +01:00
import {
FlatList,
Image,
Pressable,
StyleSheet,
Text,
View
} from 'react-native'
2020-11-21 13:19:05 +01:00
import { PostAction, PostState } from '../Compose'
import { StyleConstants } from 'src/utils/styles/constants'
2020-12-06 12:52:29 +01:00
import { useTheme } from 'src/utils/styles/ThemeManager'
import { useNavigation } from '@react-navigation/native'
import ShimmerPlaceholder from 'react-native-shimmer-placeholder'
2020-12-06 21:42:19 +01:00
import { ButtonRound } from 'src/components/Button'
import addAttachments from './addAttachments'
2020-12-06 12:52:29 +01:00
const DEFAULT_HEIGHT = 200
export interface Props {
postState: PostState
postDispatch: Dispatch<PostAction>
}
2020-12-03 22:03:06 +01:00
const ComposeAttachments: React.FC<Props> = ({ postState, postDispatch }) => {
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-06 12:52:29 +01:00
postDispatch({
type: 'attachments',
payload: postState.attachments.filter(e => e.id !== item.id)
})
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,
postDispatch
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(() => {
return (
<ShimmerPlaceholder
style={styles.progressContainer}
visible={postState.attachmentUploadProgress === undefined}
width={
(postState.attachmentUploadProgress?.aspect || 3 / 2) * DEFAULT_HEIGHT
}
height={200}
>
{postState.attachments.length > 0 &&
postState.attachments[0].type === 'image' &&
postState.attachments.length < 4 && (
<Pressable
style={{
width: DEFAULT_HEIGHT,
height: DEFAULT_HEIGHT,
backgroundColor: theme.border
}}
onPress={async () =>
await addAttachments({ postState, postDispatch })
}
>
<ButtonRound
icon='upload-cloud'
onPress={async () =>
await addAttachments({ postState, postDispatch })
}
styles={{
top:
(DEFAULT_HEIGHT -
StyleConstants.Spacing.Global.PagePadding) /
2,
left:
(DEFAULT_HEIGHT -
StyleConstants.Spacing.Global.PagePadding) /
2
}}
coordinate='center'
/>
</Pressable>
)}
</ShimmerPlaceholder>
)
}, [postState.attachmentUploadProgress])
return (
<View style={styles.base}>
<FlatList
horizontal
2020-12-06 21:42:19 +01:00
extraData={postState.attachmentUploadProgress}
data={postState.attachments}
2020-12-06 21:42:19 +01:00
renderItem={renderAttachment}
ListFooterComponent={listFooter}
2020-12-06 12:52:29 +01:00
showsHorizontalScrollIndicator={false}
2020-12-06 22:32:36 +01:00
keyboardShouldPersistTaps='handled'
/>
</View>
)
}
const styles = StyleSheet.create({
base: {
flex: 1,
flexDirection: 'row',
marginRight: StyleConstants.Spacing.Global.PagePadding,
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-06 21:42:19 +01:00
export default React.memo(ComposeAttachments, () => true)