import analytics from '@components/analytics' import Button from '@components/Button' import haptics from '@components/haptics' import Icon from '@components/Icon' import { useActionSheet } from '@expo/react-native-action-sheet' import { useNavigation } from '@react-navigation/native' import { StyleConstants } from '@utils/styles/constants' import layoutAnimation from '@utils/styles/layoutAnimation' import { useTheme } from '@utils/styles/ThemeManager' import React, { RefObject, useCallback, useContext, useEffect, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' import { FlatList, Image, Pressable, StyleSheet, Text, View } from 'react-native' import { Circle } from 'react-native-animated-spinkit' import ComposeContext from '../../utils/createContext' import { ExtendedAttachment } from '../../utils/types' import addAttachment from './addAttachment' export interface Props { accessibleRefAttachments: RefObject } const DEFAULT_HEIGHT = 200 const ComposeAttachments: React.FC = ({ accessibleRefAttachments }) => { const { showActionSheetWithOptions } = useActionSheet() const { composeState, composeDispatch } = useContext(ComposeContext) const { t } = useTranslation('screenCompose') const { colors, mode } = useTheme() const navigation = useNavigation() const flatListRef = useRef(null) const sensitiveOnPress = useCallback(() => { analytics('compose_attachment_sensitive_press', { current: composeState.attachments.sensitive }) composeDispatch({ type: 'attachments/sensitive', payload: { sensitive: !composeState.attachments.sensitive } }) }, [composeState.attachments.sensitive]) 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 ) } else { return DEFAULT_HEIGHT } } else { return DEFAULT_HEIGHT } } }, []) 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]) let prevOffsets = useRef() useEffect(() => { if ( snapToOffsets.length > (prevOffsets.current ? prevOffsets.current.length : 0) ) { flatListRef.current?.scrollToOffset({ offset: snapToOffsets[snapToOffsets.length - 2] + snapToOffsets[snapToOffsets.length - 1] }) } prevOffsets.current = snapToOffsets }, [snapToOffsets, prevOffsets.current]) const renderAttachment = useCallback( ({ item, index }: { item: ExtendedAttachment; index: number }) => { return ( {item.remote?.meta?.original?.duration ? ( {item.remote.meta.original.duration} ) : null} {item.uploading ? ( ) : (