UNPKG

react-native-media-viewing

Version:

React Native modal component for viewing images and video as a sliding gallery

87 lines (86 loc) 4.46 kB
/** * Copyright (c) JOB TODAY S.A. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import React, { useCallback, useRef, useEffect } from "react"; import { Animated, Dimensions, StyleSheet, View, VirtualizedList, Modal, } from "react-native"; import MediaItem from "./components/MediaItem/MediaItem"; import MediaDefaultHeader from "./components/MediaDefaultHeader"; import StatusBarManager from "./components/StatusBarManager"; import useAnimatedComponents from "./hooks/useAnimatedComponents"; import useImageIndexChange from "./hooks/useImageIndexChange"; import useRequestClose from "./hooks/useRequestClose"; const DEFAULT_ANIMATION_TYPE = "fade"; const DEFAULT_BG_COLOR = "#000"; const DEFAULT_DELAY_LONG_PRESS = 800; const SCREEN = Dimensions.get("screen"); const SCREEN_WIDTH = SCREEN.width; function MediaViewing({ media, keyExtractor, imageIndex, visible, onRequestClose, onLongPress = () => { }, onImageIndexChange, animationType = DEFAULT_ANIMATION_TYPE, backgroundColor = DEFAULT_BG_COLOR, presentationStyle, swipeToCloseEnabled, doubleTapToZoomEnabled, delayLongPress = DEFAULT_DELAY_LONG_PRESS, HeaderComponent, FooterComponent, }) { const imageList = useRef(null); const [opacity, onRequestCloseEnhanced] = useRequestClose(onRequestClose); const [currentImageIndex, onScroll] = useImageIndexChange(imageIndex, SCREEN); const [headerTransform, footerTransform, toggleBarsVisible] = useAnimatedComponents(); useEffect(() => { if (onImageIndexChange) { onImageIndexChange(currentImageIndex); } }, [currentImageIndex]); const onZoom = useCallback((isScaled) => { var _a, _b; // @ts-ignore (_b = (_a = imageList) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.setNativeProps({ scrollEnabled: !isScaled }); toggleBarsVisible(!isScaled); }, [imageList]); if (!visible) { return null; } return (<Modal transparent={presentationStyle === "overFullScreen"} visible={visible} presentationStyle={presentationStyle} animationType={animationType} onRequestClose={onRequestCloseEnhanced} supportedOrientations={["portrait"]} hardwareAccelerated> <StatusBarManager presentationStyle={presentationStyle}/> <View style={[styles.container, { opacity, backgroundColor }]}> <Animated.View style={[styles.header, { transform: headerTransform }]}> {typeof HeaderComponent !== "undefined" ? (React.createElement(HeaderComponent, { imageIndex: currentImageIndex, })) : (<MediaDefaultHeader onRequestClose={onRequestCloseEnhanced}/>)} </Animated.View> <VirtualizedList ref={imageList} data={media} horizontal pagingEnabled windowSize={2} initialNumToRender={1} maxToRenderPerBatch={1} showsHorizontalScrollIndicator={false} showsVerticalScrollIndicator={false} initialScrollIndex={imageIndex} getItem={(_, index) => media[index]} getItemCount={() => media.length} getItemLayout={(_, index) => ({ length: SCREEN_WIDTH, offset: SCREEN_WIDTH * index, index, })} renderItem={({ item: mediaSrc }) => (<MediaItem onZoom={onZoom} mediaSrc={mediaSrc} onRequestClose={onRequestCloseEnhanced} onLongPress={onLongPress} delayLongPress={delayLongPress} swipeToCloseEnabled={swipeToCloseEnabled} doubleTapToZoomEnabled={doubleTapToZoomEnabled}/>)} onMomentumScrollEnd={onScroll} //@ts-ignore keyExtractor={(mediaSrc, index) => keyExtractor ? keyExtractor(mediaSrc, index) : typeof mediaSrc === "number" ? `${mediaSrc}` : mediaSrc.uri}/> {typeof FooterComponent !== "undefined" && (<Animated.View style={[styles.footer, { transform: footerTransform }]}> {React.createElement(FooterComponent, { imageIndex: currentImageIndex, })} </Animated.View>)} </View> </Modal>); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#000", }, header: { position: "absolute", width: "100%", zIndex: 1, top: 0, }, footer: { position: "absolute", width: "100%", zIndex: 1, bottom: 0, }, }); const EnhancedMediaViewing = (props) => (<MediaViewing key={props.imageIndex} {...props}/>); export default EnhancedMediaViewing;