2021-01-24 02:25:43 +01:00
|
|
|
import analytics from '@components/analytics'
|
2020-12-30 00:56:25 +01:00
|
|
|
import Button from '@components/Button'
|
2021-01-01 17:52:14 +01:00
|
|
|
import haptics from '@components/haptics'
|
2021-01-03 02:00:26 +01:00
|
|
|
import Icon from '@components/Icon'
|
2021-01-13 01:03:46 +01:00
|
|
|
import { useActionSheet } from '@expo/react-native-action-sheet'
|
2020-12-30 00:56:25 +01:00
|
|
|
import { useNavigation } from '@react-navigation/native'
|
|
|
|
import { StyleConstants } from '@utils/styles/constants'
|
2021-01-01 17:52:14 +01:00
|
|
|
import layoutAnimation from '@utils/styles/layoutAnimation'
|
2020-12-30 00:56:25 +01:00
|
|
|
import { useTheme } from '@utils/styles/ThemeManager'
|
2021-01-01 16:48:16 +01:00
|
|
|
import React, {
|
2021-04-09 21:43:12 +02:00
|
|
|
RefObject,
|
2021-01-01 16:48:16 +01:00
|
|
|
useCallback,
|
|
|
|
useContext,
|
|
|
|
useEffect,
|
|
|
|
useMemo,
|
|
|
|
useRef
|
|
|
|
} from 'react'
|
2021-01-19 01:13:45 +01:00
|
|
|
import { useTranslation } from 'react-i18next'
|
2021-03-19 21:44:52 +01:00
|
|
|
import {
|
|
|
|
FlatList,
|
|
|
|
Image,
|
|
|
|
Pressable,
|
|
|
|
StyleSheet,
|
|
|
|
Text,
|
|
|
|
View
|
|
|
|
} from 'react-native'
|
2021-02-08 23:47:20 +01:00
|
|
|
import { Circle } from 'react-native-animated-spinkit'
|
2021-01-19 01:13:45 +01:00
|
|
|
import ComposeContext from '../../utils/createContext'
|
|
|
|
import { ExtendedAttachment } from '../../utils/types'
|
2021-01-01 17:52:14 +01:00
|
|
|
import addAttachment from './addAttachment'
|
2020-12-06 12:52:29 +01:00
|
|
|
|
2021-04-09 21:43:12 +02:00
|
|
|
export interface Props {
|
|
|
|
accessibleRefAttachments: RefObject<View>
|
|
|
|
}
|
|
|
|
|
2020-12-06 12:52:29 +01:00
|
|
|
const DEFAULT_HEIGHT = 200
|
2020-11-19 22:45:26 +01:00
|
|
|
|
2021-04-09 21:43:12 +02:00
|
|
|
const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
|
2021-01-13 01:03:46 +01:00
|
|
|
const { showActionSheetWithOptions } = useActionSheet()
|
2020-12-11 00:29:22 +01:00
|
|
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
2021-03-28 23:31:10 +02:00
|
|
|
const { t } = useTranslation('screenCompose')
|
2022-02-12 14:51:01 +01:00
|
|
|
const { colors, mode } = useTheme()
|
2021-08-29 15:25:38 +02:00
|
|
|
const navigation = useNavigation<any>()
|
2020-12-06 12:52:29 +01:00
|
|
|
|
2021-01-01 16:48:16 +01:00
|
|
|
const flatListRef = useRef<FlatList>(null)
|
|
|
|
|
2021-01-24 02:25:43 +01:00
|
|
|
const sensitiveOnPress = useCallback(() => {
|
|
|
|
analytics('compose_attachment_sensitive_press', {
|
|
|
|
current: composeState.attachments.sensitive
|
|
|
|
})
|
|
|
|
composeDispatch({
|
|
|
|
type: 'attachments/sensitive',
|
|
|
|
payload: { sensitive: !composeState.attachments.sensitive }
|
|
|
|
})
|
|
|
|
}, [composeState.attachments.sensitive])
|
2020-12-30 00:56:25 +01:00
|
|
|
|
2021-01-01 16:48:16 +01:00
|
|
|
const calculateWidth = useCallback(item => {
|
|
|
|
if (item.local) {
|
|
|
|
return (item.local.width / item.local.height) * DEFAULT_HEIGHT
|
|
|
|
} else {
|
|
|
|
if (item.remote) {
|
|
|
|
if (item.remote.meta.original.aspect) {
|
|
|
|
return item.remote.meta.original.aspect * DEFAULT_HEIGHT
|
|
|
|
} else if (
|
|
|
|
item.remote.meta.original.width &&
|
|
|
|
item.remote.meta.original.height
|
|
|
|
) {
|
|
|
|
return (
|
|
|
|
(item.remote.meta.original.width /
|
|
|
|
item.remote.meta.original.height) *
|
|
|
|
DEFAULT_HEIGHT
|
|
|
|
)
|
2020-12-30 00:56:25 +01:00
|
|
|
} else {
|
2021-01-01 16:48:16 +01:00
|
|
|
return DEFAULT_HEIGHT
|
2020-12-30 00:56:25 +01:00
|
|
|
}
|
2021-01-01 16:48:16 +01:00
|
|
|
} else {
|
|
|
|
return DEFAULT_HEIGHT
|
2020-12-30 00:56:25 +01:00
|
|
|
}
|
2021-01-01 16:48:16 +01:00
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
const snapToOffsets = useMemo(() => {
|
|
|
|
const attachmentsOffsets = composeState.attachments.uploads.map(
|
|
|
|
(_, index) => {
|
|
|
|
let currentOffset = 0
|
|
|
|
Array.from(Array(index).keys()).map(
|
|
|
|
i =>
|
|
|
|
(currentOffset =
|
|
|
|
currentOffset +
|
|
|
|
calculateWidth(composeState.attachments.uploads[i]) +
|
|
|
|
StyleConstants.Spacing.Global.PagePadding)
|
|
|
|
)
|
|
|
|
return currentOffset
|
|
|
|
}
|
|
|
|
)
|
|
|
|
return attachmentsOffsets.length < 4
|
|
|
|
? [
|
|
|
|
...attachmentsOffsets,
|
|
|
|
attachmentsOffsets.reduce((a, b) => a + b, 0) +
|
|
|
|
DEFAULT_HEIGHT +
|
|
|
|
StyleConstants.Spacing.Global.PagePadding
|
|
|
|
]
|
|
|
|
: attachmentsOffsets
|
|
|
|
}, [composeState.attachments.uploads.length])
|
2021-02-11 01:33:31 +01:00
|
|
|
let prevOffsets = useRef<number[]>()
|
2021-01-01 16:48:16 +01:00
|
|
|
useEffect(() => {
|
|
|
|
if (
|
|
|
|
snapToOffsets.length >
|
2021-03-02 01:17:06 +01:00
|
|
|
(prevOffsets.current ? prevOffsets.current.length : 0)
|
2021-01-01 16:48:16 +01:00
|
|
|
) {
|
|
|
|
flatListRef.current?.scrollToOffset({
|
|
|
|
offset:
|
|
|
|
snapToOffsets[snapToOffsets.length - 2] +
|
|
|
|
snapToOffsets[snapToOffsets.length - 1]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
prevOffsets.current = snapToOffsets
|
2021-02-11 01:33:31 +01:00
|
|
|
}, [snapToOffsets, prevOffsets.current])
|
2021-01-01 16:48:16 +01:00
|
|
|
|
|
|
|
const renderAttachment = useCallback(
|
|
|
|
({ item, index }: { item: ExtendedAttachment; index: number }) => {
|
2020-12-06 12:52:29 +01:00
|
|
|
return (
|
2020-12-30 00:56:25 +01:00
|
|
|
<View
|
|
|
|
key={index}
|
2021-01-01 16:48:16 +01:00
|
|
|
style={[styles.container, { width: calculateWidth(item) }]}
|
2020-12-30 00:56:25 +01:00
|
|
|
>
|
2021-03-19 21:44:52 +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
|
|
|
}}
|
|
|
|
/>
|
2021-06-11 23:07:41 +02:00
|
|
|
{item.remote?.meta?.original?.duration ? (
|
2020-12-06 21:42:19 +01:00
|
|
|
<Text
|
|
|
|
style={[
|
|
|
|
styles.duration,
|
|
|
|
{
|
2022-02-12 14:51:01 +01:00
|
|
|
color: colors.backgroundDefault,
|
|
|
|
backgroundColor: colors.backgroundOverlayInvert
|
2020-12-06 21:42:19 +01:00
|
|
|
}
|
|
|
|
]}
|
|
|
|
>
|
2020-12-30 00:56:25 +01:00
|
|
|
{item.remote.meta.original.duration}
|
2020-12-06 21:42:19 +01:00
|
|
|
</Text>
|
2021-06-11 23:07:41 +02:00
|
|
|
) : null}
|
2020-12-30 00:56:25 +01:00
|
|
|
{item.uploading ? (
|
|
|
|
<View
|
|
|
|
style={[
|
|
|
|
styles.uploading,
|
2022-02-12 14:51:01 +01:00
|
|
|
{ backgroundColor: colors.backgroundOverlayInvert }
|
2020-12-30 00:56:25 +01:00
|
|
|
]}
|
2020-12-06 21:42:19 +01:00
|
|
|
>
|
2021-02-08 23:47:20 +01:00
|
|
|
<Circle
|
|
|
|
size={StyleConstants.Font.Size.L}
|
2022-02-12 14:51:01 +01:00
|
|
|
color={colors.primaryOverlay}
|
2020-12-30 00:56:25 +01:00
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
) : (
|
2021-01-04 14:55:34 +01:00
|
|
|
<View style={styles.actions}>
|
2020-12-26 23:05:17 +01:00
|
|
|
<Button
|
2021-04-09 21:43:12 +02:00
|
|
|
accessibilityLabel={t(
|
|
|
|
'content.root.footer.attachments.remove.accessibilityLabel',
|
|
|
|
{ attachment: index + 1 }
|
|
|
|
)}
|
2020-12-26 23:05:17 +01:00
|
|
|
type='icon'
|
2021-01-03 02:00:26 +01:00
|
|
|
content='X'
|
2020-12-26 23:05:17 +01:00
|
|
|
spacing='M'
|
|
|
|
round
|
|
|
|
overlay
|
2020-12-30 00:56:25 +01:00
|
|
|
onPress={() => {
|
2021-01-24 02:25:43 +01:00
|
|
|
analytics('compose_attachment_delete')
|
2020-12-30 00:56:25 +01:00
|
|
|
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
|
2021-04-09 21:43:12 +02:00
|
|
|
accessibilityLabel={t(
|
|
|
|
'content.root.footer.attachments.edit.accessibilityLabel',
|
|
|
|
{ attachment: index + 1 }
|
|
|
|
)}
|
2020-12-30 00:56:25 +01:00
|
|
|
type='icon'
|
2021-01-03 02:00:26 +01:00
|
|
|
content='Edit'
|
2020-12-30 00:56:25 +01:00
|
|
|
spacing='M'
|
|
|
|
round
|
|
|
|
overlay
|
2021-01-24 02:25:43 +01:00
|
|
|
onPress={() => {
|
|
|
|
analytics('compose_attachment_edit')
|
2021-01-30 01:29:15 +01:00
|
|
|
navigation.navigate('Screen-Compose-EditAttachment', {
|
2020-12-30 00:56:25 +01:00
|
|
|
index
|
|
|
|
})
|
2021-01-24 02:25:43 +01:00
|
|
|
}}
|
2020-12-30 00:56:25 +01:00
|
|
|
/>
|
2021-01-04 14:55:34 +01:00
|
|
|
</View>
|
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
|
2021-04-09 21:43:12 +02:00
|
|
|
accessible
|
|
|
|
accessibilityLabel={t(
|
|
|
|
'content.root.footer.attachments.upload.accessibilityLabel'
|
|
|
|
)}
|
2020-12-30 00:56:25 +01:00
|
|
|
style={[
|
|
|
|
styles.container,
|
|
|
|
{
|
|
|
|
width: DEFAULT_HEIGHT,
|
2022-02-12 14:51:01 +01:00
|
|
|
backgroundColor: colors.backgroundOverlayInvert
|
2020-12-30 00:56:25 +01:00
|
|
|
}
|
|
|
|
]}
|
2021-01-24 02:25:43 +01:00
|
|
|
onPress={async () => {
|
|
|
|
analytics('compose_attachment_add_container_press')
|
2021-01-13 01:03:46 +01:00
|
|
|
await addAttachment({ composeDispatch, showActionSheetWithOptions })
|
2021-01-24 02:25:43 +01:00
|
|
|
}}
|
2020-12-07 00:23:26 +01:00
|
|
|
>
|
2020-12-30 00:56:25 +01:00
|
|
|
<Button
|
|
|
|
type='icon'
|
2021-01-03 02:00:26 +01:00
|
|
|
content='UploadCloud'
|
2020-12-30 00:56:25 +01:00
|
|
|
spacing='M'
|
|
|
|
round
|
|
|
|
overlay
|
2021-01-24 02:25:43 +01:00
|
|
|
onPress={async () => {
|
|
|
|
analytics('compose_attachment_add_button_press')
|
2021-01-13 01:03:46 +01:00
|
|
|
await addAttachment({ composeDispatch, showActionSheetWithOptions })
|
2021-01-24 02:25:43 +01:00
|
|
|
}}
|
2020-12-30 00:56:25 +01:00
|
|
|
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 (
|
2021-04-09 21:43:12 +02:00
|
|
|
<View style={styles.base} ref={accessibleRefAttachments} accessible>
|
2020-12-30 00:56:25 +01:00
|
|
|
<Pressable style={styles.sensitive} onPress={sensitiveOnPress}>
|
2021-01-03 02:00:26 +01:00
|
|
|
<Icon
|
|
|
|
name={composeState.attachments.sensitive ? 'CheckCircle' : 'Circle'}
|
2020-12-07 00:23:26 +01:00
|
|
|
size={StyleConstants.Font.Size.L}
|
2022-02-12 14:51:01 +01:00
|
|
|
color={colors.primaryDefault}
|
2020-12-07 00:23:26 +01:00
|
|
|
/>
|
2022-02-12 14:51:01 +01:00
|
|
|
<Text style={[styles.sensitiveText, { color: colors.primaryDefault }]}>
|
2021-01-19 01:13:45 +01:00
|
|
|
{t('content.root.footer.attachments.sensitive')}
|
2020-12-07 00:23:26 +01:00
|
|
|
</Text>
|
|
|
|
</Pressable>
|
2020-12-30 00:56:25 +01:00
|
|
|
<FlatList
|
|
|
|
horizontal
|
2021-01-01 16:48:16 +01:00
|
|
|
ref={flatListRef}
|
|
|
|
decelerationRate={0}
|
|
|
|
pagingEnabled={false}
|
|
|
|
snapToAlignment='center'
|
2020-12-30 00:56:25 +01:00
|
|
|
renderItem={renderAttachment}
|
2021-01-01 16:48:16 +01:00
|
|
|
snapToOffsets={snapToOffsets}
|
2021-03-18 23:32:31 +01:00
|
|
|
keyboardShouldPersistTaps='always'
|
2021-01-01 16:48:16 +01:00
|
|
|
showsHorizontalScrollIndicator={false}
|
|
|
|
data={composeState.attachments.uploads}
|
2021-02-07 00:39:11 +01:00
|
|
|
keyExtractor={item =>
|
2021-02-11 01:33:31 +01:00
|
|
|
item.local?.uri || item.remote?.url || Math.random().toString()
|
2021-02-07 00:39:11 +01:00
|
|
|
}
|
2020-12-30 00:56:25 +01:00
|
|
|
ListFooterComponent={
|
|
|
|
composeState.attachments.uploads.length < 4 ? listFooter : null
|
|
|
|
}
|
|
|
|
/>
|
2020-11-19 22:45:26 +01:00
|
|
|
</View>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
base: {
|
|
|
|
flex: 1,
|
2020-12-05 01:55:53 +01:00
|
|
|
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: {
|
2020-12-29 00:21:05 +01:00
|
|
|
...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,
|
2020-12-05 01:55:53 +01:00
|
|
|
marginLeft: StyleConstants.Spacing.Global.PagePadding,
|
|
|
|
marginTop: StyleConstants.Spacing.Global.PagePadding,
|
|
|
|
marginBottom: StyleConstants.Spacing.Global.PagePadding
|
2020-11-19 22:45:26 +01:00
|
|
|
},
|
2020-12-30 00:56:25 +01:00
|
|
|
image: {
|
|
|
|
width: '100%',
|
|
|
|
height: '100%'
|
|
|
|
},
|
2020-12-06 21:42:19 +01:00
|
|
|
duration: {
|
2020-11-19 22:45:26 +01:00
|
|
|
position: 'absolute',
|
2020-12-30 00:56:25 +01:00
|
|
|
bottom: StyleConstants.Spacing.S,
|
|
|
|
left: StyleConstants.Spacing.S,
|
2020-12-29 00:21:05 +01:00
|
|
|
...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-11-19 22:45:26 +01:00
|
|
|
},
|
2020-12-30 00:56:25 +01:00
|
|
|
uploading: {
|
|
|
|
...StyleSheet.absoluteFillObject,
|
|
|
|
justifyContent: 'center',
|
|
|
|
alignItems: 'center'
|
|
|
|
},
|
2021-01-04 14:55:34 +01:00
|
|
|
actions: {
|
|
|
|
...StyleSheet.absoluteFillObject,
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
alignContent: 'flex-end',
|
|
|
|
alignItems: 'flex-end',
|
|
|
|
padding: StyleConstants.Spacing.S
|
2020-11-19 22:45:26 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-12-30 00:56:25 +01:00
|
|
|
export default React.memo(ComposeAttachments, () => true)
|