Files
iNaturalistReactNative/src/components/ObsDetailsDefaultMode/ObsMedia.js
2025-12-22 18:26:38 -08:00

100 lines
2.4 KiB
JavaScript

// @flow
import MediaViewerModal from "components/MediaViewer/MediaViewerModal";
import { ActivityIndicator, Carousel, CarouselDots } from "components/SharedComponents";
import { View } from "components/styledComponents";
import type { Node } from "react";
import React, { useCallback, useMemo, useState } from "react";
import PhotoContainer from "./PhotoContainer";
import SoundContainer from "./SoundContainer";
type Props = {
loading: boolean,
photos: {
id?: number,
url: string,
localFilePath?: string,
attribution?: string,
licenseCode?: string
}[],
sounds?: {
file_url: string
}[]
}
const ObsMedia = ( {
loading,
photos = [],
sounds = [],
}: Props ): Node => {
const [index, setIndex] = useState( 0 );
const [mediaViewerVisible, setMediaViewerVisible] = useState( false );
const items = useMemo( ( ) => ( [...photos, ...sounds] ), [photos, sounds] );
const CarouselSlide = useCallback(
( { item } ) => ( item.file_url
? (
<SoundContainer
sizeClass="h-72 w-screen"
sound={item}
isVisible={items.indexOf( item ) === index}
/>
)
: (
<PhotoContainer photo={item} onPress={() => setMediaViewerVisible( true )} />
) ),
[setMediaViewerVisible, items, index],
);
const currentPhotoUrl = index >= photos.length
? undefined
: photos[index]?.url;
const loadingIndicator = (
<View className="h-[288px] w-full items-center justify-center">
<ActivityIndicator
className="absolute"
/>
</View>
);
const renderPhone = ( ) => (
<>
{loading
? loadingIndicator
: (
<Carousel
testID="photo-scroll"
data={items}
renderItem={CarouselSlide}
onSlideScroll={setIndex}
/>
)}
{items.length > 1 && (
<View
className="flex absolute bottom-0 w-full justify-evenly items-center p-[15px]"
>
<CarouselDots length={items.length} index={index} />
</View>
)}
</>
);
return (
<View className="relative">
{renderPhone( )}
<MediaViewerModal
showModal={mediaViewerVisible}
onClose={( ) => setMediaViewerVisible( false )}
uri={currentPhotoUrl}
photos={photos}
sounds={sounds}
/>
</View>
);
};
export default ObsMedia;