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

257 lines
7.2 KiB
TypeScript
Raw Normal View History

2020-12-30 00:56:25 +01:00
import { Feather } from '@expo/vector-icons'
import Button from '@components/Button'
import { useNavigation } from '@react-navigation/native'
import { ComposeContext } from '@screens/Shared/Compose'
import addAttachment from '@screens/Shared/Compose/addAttachment'
import { ExtendedAttachment } from '@screens/Shared/Compose/utils/types'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useContext, useMemo } from 'react'
2020-12-06 21:42:19 +01:00
import {
FlatList,
Image,
Pressable,
StyleSheet,
Text,
View
} from 'react-native'
2020-12-30 00:56:25 +01:00
import { Chase } from 'react-native-animated-spinkit'
import layoutAnimation from '@root/utils/styles/layoutAnimation'
2020-12-30 14:33:33 +01:00
import haptics from '@root/components/haptics'
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-30 00:56:25 +01:00
const sensitiveOnPress = useCallback(
() =>
composeDispatch({
type: 'attachments/sensitive',
payload: { sensitive: !composeState.attachments.sensitive }
}),
[composeState.attachments.sensitive]
)
2020-12-06 21:42:19 +01:00
const renderAttachment = useCallback(
2020-12-30 00:56:25 +01:00
({ item, index }: { item: ExtendedAttachment; index: number }) => {
let calculatedWidth: number
if (item.local) {
calculatedWidth =
(item.local.width / item.local.height) * DEFAULT_HEIGHT
} else {
if (item.remote) {
if (item.remote.meta.original.aspect) {
calculatedWidth = item.remote.meta.original.aspect * DEFAULT_HEIGHT
} else if (
item.remote.meta.original.width &&
item.remote.meta.original.height
) {
calculatedWidth =
(item.remote.meta.original.width /
item.remote.meta.original.height) *
DEFAULT_HEIGHT
} else {
calculatedWidth = DEFAULT_HEIGHT
}
} else {
calculatedWidth = DEFAULT_HEIGHT
}
}
2020-12-06 12:52:29 +01:00
return (
2020-12-30 00:56:25 +01:00
<View
key={index}
style={[styles.container, { width: calculatedWidth }]}
>
2020-12-06 12:52:29 +01:00
<Image
2020-12-30 00:56:25 +01:00
style={styles.image}
2020-12-06 12:52:29 +01:00
source={{
2020-12-30 00:56:25 +01:00
uri: item.local?.local_thumbnail || item.remote?.preview_url
2020-12-06 12:52:29 +01:00
}}
/>
2020-12-30 00:56:25 +01:00
{item.remote?.meta?.original?.duration && (
2020-12-06 21:42:19 +01:00
<Text
style={[
styles.duration,
{
color: theme.background,
backgroundColor: theme.backgroundOverlay
}
]}
>
2020-12-30 00:56:25 +01:00
{item.remote.meta.original.duration}
2020-12-06 21:42:19 +01:00
</Text>
)}
2020-12-30 00:56:25 +01:00
{item.uploading ? (
<View
style={[
styles.uploading,
{ backgroundColor: theme.backgroundOverlay }
]}
2020-12-06 21:42:19 +01:00
>
2020-12-30 00:56:25 +01:00
<Chase
size={StyleConstants.Font.Size.L * 2}
color={theme.primaryOverlay}
/>
</View>
) : (
<>
2020-12-26 23:05:17 +01:00
<Button
type='icon'
2020-12-30 00:56:25 +01:00
content='x'
2020-12-26 23:05:17 +01:00
spacing='M'
round
overlay
2020-12-30 00:56:25 +01:00
style={styles.delete}
onPress={() => {
layoutAnimation()
composeDispatch({
type: 'attachment/delete',
payload: item.remote!.id
})
2020-12-30 14:33:33 +01:00
haptics('Success')
2020-12-06 21:42:19 +01:00
}}
/>
2020-12-30 00:56:25 +01:00
<Button
type='icon'
content='edit'
spacing='M'
round
overlay
style={styles.edit}
onPress={() =>
navigation.navigate('Screen-Shared-Compose-EditAttachment', {
index
})
}
/>
</>
2020-12-06 21:42:19 +01:00
)}
2020-12-30 00:56:25 +01:00
</View>
)
},
[]
)
2020-12-06 21:42:19 +01:00
2020-12-30 00:56:25 +01:00
const listFooter = useMemo(
() => (
2020-12-07 00:23:26 +01:00
<Pressable
2020-12-30 00:56:25 +01:00
style={[
styles.container,
{
width: DEFAULT_HEIGHT,
backgroundColor: theme.backgroundOverlay
}
]}
onPress={async () => await addAttachment({ composeDispatch })}
2020-12-07 00:23:26 +01:00
>
2020-12-30 00:56:25 +01:00
<Button
type='icon'
content='upload-cloud'
spacing='M'
round
overlay
onPress={async () => await addAttachment({ composeDispatch })}
style={{
position: 'absolute',
top:
(DEFAULT_HEIGHT -
StyleConstants.Spacing.M * 2 -
StyleConstants.Font.Size.M) /
2,
left:
(DEFAULT_HEIGHT -
StyleConstants.Spacing.M * 2 -
StyleConstants.Font.Size.M) /
2
}}
/>
</Pressable>
),
[]
)
return (
<View style={styles.base}>
<Pressable style={styles.sensitive} onPress={sensitiveOnPress}>
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>
2020-12-30 00:56:25 +01:00
<FlatList
horizontal
keyExtractor={item => item.local!.uri || item.remote!.url}
data={composeState.attachments.uploads}
renderItem={renderAttachment}
ListFooterComponent={
composeState.attachments.uploads.length < 4 ? listFooter : null
}
showsHorizontalScrollIndicator={false}
keyboardShouldPersistTaps='handled'
/>
</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: {
...StyleConstants.FontStyle.M,
2020-12-07 00:23:26 +01:00
marginLeft: StyleConstants.Spacing.S
},
2020-12-30 00:56:25 +01:00
container: {
height: DEFAULT_HEIGHT,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.Global.PagePadding
},
2020-12-30 00:56:25 +01:00
image: {
width: '100%',
height: '100%'
},
2020-12-06 21:42:19 +01:00
duration: {
position: 'absolute',
2020-12-30 00:56:25 +01:00
bottom: StyleConstants.Spacing.S,
left: StyleConstants.Spacing.S,
...StyleConstants.FontStyle.S,
2020-12-06 21:42:19 +01:00
paddingLeft: StyleConstants.Spacing.S,
paddingRight: StyleConstants.Spacing.S,
paddingTop: StyleConstants.Spacing.XS,
paddingBottom: StyleConstants.Spacing.XS
},
2020-12-30 00:56:25 +01:00
uploading: {
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center'
},
2020-12-26 23:05:17 +01:00
delete: {
position: 'absolute',
2020-12-30 00:56:25 +01:00
top: StyleConstants.Spacing.S,
2020-12-26 23:05:17 +01:00
right: StyleConstants.Spacing.S
},
2020-12-06 12:52:29 +01:00
edit: {
2020-12-26 23:05:17 +01:00
position: 'absolute',
2020-12-30 00:56:25 +01:00
bottom: StyleConstants.Spacing.S,
2020-12-06 12:52:29 +01:00
right: StyleConstants.Spacing.S
}
})
2020-12-30 00:56:25 +01:00
export default React.memo(ComposeAttachments, () => true)