mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at no-pointer-events 180 lines 4.9 kB view raw
1/** 2 * Copyright (c) JOB TODAY S.A. and its affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 * 7 */ 8// Original code copied and simplified from the link below as the codebase is currently not maintained: 9// https://github.com/jobtoday/react-native-image-viewing 10 11import React, {ComponentType, useCallback, useMemo, useState} from 'react' 12import {StyleSheet, View, Platform} from 'react-native' 13 14import ImageItem from './components/ImageItem/ImageItem' 15import ImageDefaultHeader from './components/ImageDefaultHeader' 16 17import {ImageSource} from './@types' 18import Animated, {useAnimatedStyle, withSpring} from 'react-native-reanimated' 19import {Edge, SafeAreaView} from 'react-native-safe-area-context' 20import PagerView from 'react-native-pager-view' 21 22type Props = { 23 images: ImageSource[] 24 initialImageIndex: number 25 visible: boolean 26 onRequestClose: () => void 27 backgroundColor?: string 28 HeaderComponent?: ComponentType<{imageIndex: number}> 29 FooterComponent?: ComponentType<{imageIndex: number}> 30} 31 32const DEFAULT_BG_COLOR = '#000' 33 34function ImageViewing({ 35 images, 36 initialImageIndex, 37 visible, 38 onRequestClose, 39 backgroundColor = DEFAULT_BG_COLOR, 40 HeaderComponent, 41 FooterComponent, 42}: Props) { 43 const [isScaled, setIsScaled] = useState(false) 44 const [isDragging, setIsDragging] = useState(false) 45 const [imageIndex, setImageIndex] = useState(initialImageIndex) 46 const [showControls, setShowControls] = useState(true) 47 48 const animatedHeaderStyle = useAnimatedStyle(() => ({ 49 pointerEvents: showControls ? 'auto' : 'none', 50 opacity: withClampedSpring(showControls ? 1 : 0), 51 transform: [ 52 { 53 translateY: withClampedSpring(showControls ? 0 : -30), 54 }, 55 ], 56 })) 57 const animatedFooterStyle = useAnimatedStyle(() => ({ 58 pointerEvents: showControls ? 'auto' : 'none', 59 opacity: withClampedSpring(showControls ? 1 : 0), 60 transform: [ 61 { 62 translateY: withClampedSpring(showControls ? 0 : 30), 63 }, 64 ], 65 })) 66 67 const onTap = useCallback(() => { 68 setShowControls(show => !show) 69 }, []) 70 71 const onZoom = useCallback((nextIsScaled: boolean) => { 72 setIsScaled(nextIsScaled) 73 if (nextIsScaled) { 74 setShowControls(false) 75 } 76 }, []) 77 78 const edges = useMemo(() => { 79 if (Platform.OS === 'android') { 80 return ['top', 'bottom', 'left', 'right'] satisfies Edge[] 81 } 82 return ['left', 'right'] satisfies Edge[] // iOS, so no top/bottom safe area 83 }, []) 84 85 if (!visible) { 86 return null 87 } 88 89 return ( 90 <SafeAreaView 91 style={styles.screen} 92 edges={edges} 93 aria-modal 94 accessibilityViewIsModal> 95 <View style={[styles.container, {backgroundColor}]}> 96 <Animated.View style={[styles.header, animatedHeaderStyle]}> 97 {typeof HeaderComponent !== 'undefined' ? ( 98 React.createElement(HeaderComponent, { 99 imageIndex, 100 }) 101 ) : ( 102 <ImageDefaultHeader onRequestClose={onRequestClose} /> 103 )} 104 </Animated.View> 105 <PagerView 106 scrollEnabled={!isScaled} 107 initialPage={initialImageIndex} 108 onPageSelected={e => { 109 setImageIndex(e.nativeEvent.position) 110 setIsScaled(false) 111 }} 112 onPageScrollStateChanged={e => { 113 setIsDragging(e.nativeEvent.pageScrollState !== 'idle') 114 }} 115 overdrag={true} 116 style={styles.pager}> 117 {images.map(imageSrc => ( 118 <View key={imageSrc.uri}> 119 <ImageItem 120 onTap={onTap} 121 onZoom={onZoom} 122 imageSrc={imageSrc} 123 onRequestClose={onRequestClose} 124 isScrollViewBeingDragged={isDragging} 125 /> 126 </View> 127 ))} 128 </PagerView> 129 {typeof FooterComponent !== 'undefined' && ( 130 <Animated.View style={[styles.footer, animatedFooterStyle]}> 131 {React.createElement(FooterComponent, { 132 imageIndex, 133 })} 134 </Animated.View> 135 )} 136 </View> 137 </SafeAreaView> 138 ) 139} 140 141const styles = StyleSheet.create({ 142 screen: { 143 position: 'absolute', 144 top: 0, 145 left: 0, 146 bottom: 0, 147 right: 0, 148 }, 149 container: { 150 flex: 1, 151 backgroundColor: '#000', 152 }, 153 pager: { 154 flex: 1, 155 }, 156 header: { 157 position: 'absolute', 158 width: '100%', 159 zIndex: 1, 160 top: 0, 161 pointerEvents: 'box-none', 162 }, 163 footer: { 164 position: 'absolute', 165 width: '100%', 166 zIndex: 1, 167 bottom: 0, 168 }, 169}) 170 171const EnhancedImageViewing = (props: Props) => ( 172 <ImageViewing key={props.initialImageIndex} {...props} /> 173) 174 175function withClampedSpring(value: any) { 176 'worklet' 177 return withSpring(value, {overshootClamping: true, stiffness: 300}) 178} 179 180export default EnhancedImageViewing