import React, { useState, useEffect, useRef, useMemo, useContext } from 'react'; import { View, Text, StyleSheet, Dimensions, PanResponder, ScrollView, Image, Platform, StatusBar, TouchableOpacity, Share } from 'react-native'; import Modal from 'react-native-modal'; import { Slider, Icon } from 'react-native-elements'; import Animated, { Easing } from 'react-native-reanimated'; import { State, PanGestureHandler } from 'react-native-gesture-handler'; import { getStatusBarHeight } from '../utils/StatusBarHeight'; import C from 'rn-class'; import PlayerControls from './PlayerControls'; import PlayerContents from './PlayerContents'; import PlayerHeader from './PlayerHeader'; import { getInset } from 'react-native-safe-area-view'; import Video from 'react-native-video'; import { PlayerDispatchContext, PlayerStateContext } from './PlayerReducer'; const { width, height } = Dimensions.get('window'); const statusBarHeight = getStatusBarHeight(true); const minHeight = height * 0.1; const midBound = height - height / 2.5; const upperBound = midBound + minHeight; //const destination = height - height * 0.2 //const destination = height - height*0.16 -2 - getStatusBarHeight(true); //getInset('bottom') // height > 560 // ?height * 0.75 - getInset('bottom') // :height * 0.70; const { Value, event, Extrapolate, cond, Clock, eq, set, add, sub, multiply, lessThan, clockRunning, startClock, spring, stopClock, interpolate, timing, neq, or, and, greaterThan, call } = Animated; const shadow = { alignItems: 'center', shadowColor: 'black', shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.18, shadowRadius: 2 }; const shadow2 = { alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 7 }, shadowOpacity: 0.41, shadowRadius: 9.11 //elevation: 14 }; const shadowShare = { shadowColor: '#000', shadowOffset: { width: 0, height: 7 }, shadowOpacity: 0.41, shadowRadius: 9.11, elevation: 14 }; const shadowImage = { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5 }; function runSpring(clock, value, dest) { const state = { finished: new Value(0), velocity: new Value(0), position: new Value(0), time: new Value(0) }; const config = { damping: 20, mass: 1, stiffness: 100, overshootClamping: false, restSpeedThreshold: 1, restDisplacementThreshold: 0.5, toValue: new Value(0) }; return [ cond(clockRunning(clock), 0, [ set(state.finished, 0), set(state.velocity, 0), set(state.position, value), set(config.toValue, dest), startClock(clock) ]), spring(clock, state, config), cond(state.finished, stopClock(clock)), state.position ]; } const onShare = async () => { try { const result = await Share.share({ message: '페이스북 | https://facebook.com' }); if (result.action === Share.sharedAction) { if (result.activityType) { // shared with activity type of result.activityType } else { // shared } } else if (result.action === Share.dismissedAction) { // dismissed } } catch (error) { alert(error.message); } }; export default props => { const [modalVisible, setModalVisible] = useState(null); const { y: tabY } = props.tabPosition; const destination = tabY - minHeight - statusBarHeight; const [currentPlayerValue, setCurrentPlayerValue] = useState(0); const [isPlay, setPlay] = useState(false); const { playerData } = props; const { onGestureEvent, translateY, opacity, playContainerWidth, playerContainerHeight, videoWidth, videoHeight, playerControlOpaciy, playerBoderRadius, mainPlayerContainerHeight, PlayerHeadWidth, PlayerHeadHeight, PlayerHeadOpacity } = useMemo(() => { const translationY = new Value(0); const velocityY = new Value(0); const offsetY = new Value(0); const offsetY2 = new Value(0); const gestureState = new Value(State.UNDETERMINED); const clockY = new Clock(); const finalTranslateY = add(translationY, multiply(0.2, velocityY)); /** * snapPoint 제스처가 끝날 때 위치 지정을 해주는 값 * TabBar 의 높이가 해상도와 스크린에서 그려지는 값이 틀려 TabBar 에서 * onLayout 이벤트를 이용하여 TabBar의 y 값을 가져와 처리 * destination 변수가 플레이어 축소 시 y 값 높이 */ const snapPoint = cond( lessThan(finalTranslateY, sub(offsetY, height / 4)), 0, destination ); const ty = cond( and(eq(gestureState, State.END), neq(translationY, 0)), [ set( translationY, runSpring(clockY, add(offsetY, translationY), snapPoint) ), set(offsetY, translationY), translationY ], [ cond(eq(gestureState, State.BEGAN), stopClock(clockY)), add(offsetY, translationY) ] ); const translateY = add(ty, offsetY2); // const onGestureEvent = event( // [ // { // nativeEvent: { // translationY, // velocityY, // state: gestureState // } // } // ], // { useNativeDriver: true } // ); return { translateY, onGestureEvent: event( [ { nativeEvent: { translationY, velocityY, state: gestureState } } ], { useNativeDriver: true } ), opacity: interpolate(translateY, { inputRange: [0, midBound], outputRange: [1, 0], extrapolate: Extrapolate.CLAMP }), playContainerWidth: interpolate(translateY, { inputRange: [0, midBound], outputRange: [width, width - 16], extrapolate: Extrapolate.CLAMP }), playerContainerHeight: interpolate(translateY, { inputRange: [0, midBound], outputRange: [height, 0], extrapolate: Extrapolate.CLAMP }), videoWidth: interpolate(translateY, { inputRange: [0, midBound, upperBound], outputRange: [width, width - 16, width / 4], extrapolate: Extrapolate.CLAMP }), videoHeight: interpolate(translateY, { inputRange: [0, midBound, upperBound], outputRange: [width / 1.78, minHeight * 1.3, minHeight], extrapolate: Extrapolate.CLAMP }), playerControlOpaciy: interpolate(translateY, { inputRange: [midBound, upperBound], outputRange: [0, 1], extrapolate: Extrapolate.CLAMP }), playerBoderRadius: interpolate(translateY, { inputRange: [midBound, upperBound], outputRange: [0, 15], extrapolate: Extrapolate.CLAMP }), mainPlayerContainerHeight: interpolate(translateY, { inputRange: [0, midBound, upperBound], outputRange: [height, minHeight * 1.3, minHeight], extrapolate: Extrapolate.CLAMP }), PlayerHeadWidth: interpolate(translateY, { inputRange: [0, width], outputRange: [width, 0], extrapolate: Extrapolate.CLAMP }), PlayerHeadHeight: interpolate(translateY, { inputRange: [0, 50], outputRange: [50, 0], extrapolate: Extrapolate.CLAMP }), PlayerHeadOpacity: interpolate(translateY, { inputRange: [0, minHeight], outputRange: [1, 0], extrapolate: Extrapolate.CLAMP }) }; }, []); useEffect(() => { playerDispatch({type:'currentTime', setCurrentTime: 0}); return () => { playerDispatch({type:'currentTime', setCurrentTime: 0}); }; },[playerData.soundURI]); const slideUp = () => {}; const player = useRef(null); const playerDispatch = useContext(PlayerDispatchContext); const { uri, paused, muted } = useContext(PlayerStateContext); const playerOnBuffer = (data) => { // console.log('bufffer::: ' + data) } const playerOnError = (e) => { console.log(e); } const playerOnLoad = (data) => { // console.log(data.duration) let duration=0; data.duration < 0 ? duration=1 : duration=data.duration playerDispatch({type:'paused', setPaused:false}); playerDispatch({type:'duration', setDuraton: Math.floor(duration)}); } const playerOnProgress = (data) => { // console.log(data.currentTime) playerDispatch({type:'currentTime', setCurrentTime: data.currentTime}); } const onLoadStart = () => { // console.log('onload start'); playerDispatch({type:'player', player: player}); } const playerOnEnd = () => { //console.log('end'); } const onSeek = (data) => { //console.log(data) if(data.seekTime===0 && data.currentTime===0) { playerDispatch({type:'paused', setPaused: true}); playerDispatch({type:'currentTime', setCurrentTime: 0}); } } return ( <> {/* 테스트용 Component setCurrentPlayerValue(value)} /> Time : {currentPlayerValue} { setPlay(!isPlay); }} > Click Test */} { setModalVisible(null); }} swipeDirection="left" //deviceHeight={height} deviceWidth={width} style={{ margin: 0 }} backdropColor="white" backdropOpacity={1} animationIn="slideInLeft" animationOut="slideOutLeft" > {playerData.title} {playerData.title} {playerData.content} {/* by {playerData.author.replace(/\r\n|\n|\r/gm, ' ')} */} {playerData.date} { setModalVisible(null); }} > { setModalVisible(null); }} /> {playerData.title} {playerData.duration} 공유하기, 메세지 보내기 ); }; const s = StyleSheet.create({ sharContainer: { backgroundColor: 'white', flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', borderColor: '#ddd', borderRadius: 15, flex: 1, width: width * 0.8, height: minHeight, ...shadowShare } });