import Button from '@components/Button' import haptics from '@components/haptics' import Icon from '@components/Icon' import CustomText from '@components/Text' import { useActionSheet } from '@expo/react-native-action-sheet' import { useNavigation } from '@react-navigation/native' import { getInstanceConfigurationStatusMaxAttachments } from '@utils/slices/instancesSlice' 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, Pressable, StyleSheet, View } from 'react-native' import { Circle } from 'react-native-animated-spinkit' import FastImage from 'react-native-fast-image' import { useSelector } from 'react-redux' import ComposeContext from '../../utils/createContext' import { ExtendedAttachment } from '../../utils/types' import chooseAndUploadAttachment 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 } = useTheme() const navigation = useNavigation() const maxAttachments = useSelector(getInstanceConfigurationStatusMaxAttachments, () => true) const flatListRef = useRef(null) const sensitiveOnPress = useCallback( () => composeDispatch({ type: 'attachments/sensitive', payload: { sensitive: !composeState.attachments.sensitive } }), [composeState.attachments.sensitive] ) const calculateWidth = useCallback((item: ExtendedAttachment) => { if (item.local) { return ((item.local.width || 100) / (item.local.height || 100)) * 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 ? ( ) : (