From 5bb14cb1e3d1198ed18afbbe1155b678eb378d01 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 8 Aug 2023 18:24:46 -0300 Subject: [PATCH] play/pause button, currentTime equal the sound, can change the slider and reflect to the sound --- .../message/Components/Audio/Slider.tsx | 95 +++++++++++++++++-- .../message/Components/Audio/index.tsx | 26 +---- 2 files changed, 90 insertions(+), 31 deletions(-) diff --git a/app/containers/message/Components/Audio/Slider.tsx b/app/containers/message/Components/Audio/Slider.tsx index 3e80e978e..50d789141 100644 --- a/app/containers/message/Components/Audio/Slider.tsx +++ b/app/containers/message/Components/Audio/Slider.tsx @@ -1,27 +1,80 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { LayoutChangeEvent, View, TextInput } from 'react-native'; import { PanGestureHandler } from 'react-native-gesture-handler'; import Animated, { + runOnJS, useAnimatedGestureHandler, useAnimatedProps, useAnimatedStyle, useDerivedValue, useSharedValue } from 'react-native-reanimated'; +import { Sound } from 'expo-av/build/Audio/Sound'; +import { AVPlaybackStatus } from 'expo-av'; import styles from './styles'; import { useTheme } from '../../../../theme'; const AnimatedTextInput = Animated.createAnimatedComponent(TextInput); -const Slider = ({ currentTime = 0, duration = 120, thumbColor = '' }) => { - console.log('🚀 ~ file: Slider.tsx:18 ~ Slider ~ currentTime:', currentTime); +interface ISlider { + currentTime: number; + duration: number; + thumbColor: string; + sound: Sound | null; +} + +const Slider = ({ thumbColor = '', sound }: ISlider) => { + const [loaded, setLoaded] = useState(false); + const { colors } = useTheme(); + const duration = useSharedValue(0); + const currentTime = useSharedValue(0); const maxWidth = useSharedValue(1); - const x = useSharedValue(currentTime); + const x = useSharedValue(0); const current = useSharedValue('00:00'); const scale = useSharedValue(1); + const isHandlePan = useSharedValue(false); + const onEndGestureHandler = useSharedValue(false); + + const onPlaybackStatusUpdate = (status: AVPlaybackStatus) => { + console.log('🚀 ~ file: Slider.tsx:42 ~ onPlaybackStatusUpdate ~ status:', status); + if (status) { + onLoad(status); + onProgress(status); + onEnd(status); + } + }; + + useEffect(() => { + if (sound) { + sound.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate); + } + }, [onPlaybackStatusUpdate, sound]); + + const onLoad = (data: AVPlaybackStatus) => { + if (data.isLoaded && data.durationMillis) { + const durationSeconds = data.durationMillis / 1000; + duration.value = durationSeconds > 0 ? durationSeconds : 0; + setLoaded(true); + } + }; + + const onProgress = (data: AVPlaybackStatus) => { + if (data.isLoaded) { + const currentSecond = data.positionMillis / 1000; + if (currentSecond <= duration.value) { + console.log('🚀 ~ file: Slider.tsx:68 ~ onProgress ~ duration.value:', duration.value); + console.log('🚀 ~ file: Slider.tsx:70 ~ onProgress ~ currentTime.value:', currentTime.value); + currentTime.value = currentSecond; + } + } + }; + + const onEnd = (data: AVPlaybackStatus) => { + // FIX HERE + }; const styleLine = useAnimatedStyle(() => ({ width: x.value, @@ -40,6 +93,7 @@ const Slider = ({ currentTime = 0, duration = 120, thumbColor = '' }) => { const gestureHandler = useAnimatedGestureHandler({ onStart: (_, ctx: any) => { ctx.startX = x.value; + isHandlePan.value = true; }, onActive: (event, ctx: any) => { const moveInX: number = ctx.startX + event.translationX; @@ -55,18 +109,41 @@ const Slider = ({ currentTime = 0, duration = 120, thumbColor = '' }) => { }, onEnd: () => { scale.value = 1; + isHandlePan.value = false; + onEndGestureHandler.value = true; // SEND A CALLBACK TO CHANGE THE PROGRESS OF THE AUDIO } }); + const wrapper = async (time: number) => { + await sound?.setPositionAsync(Math.round(time * 1000)); + onEndGestureHandler.value = false; + }; + useDerivedValue(() => { - const cTime = (x.value * duration) / maxWidth.value; - const minutes = Math.floor(cTime / 60); - const remainingSeconds = Math.floor(cTime % 60); + if (onEndGestureHandler.value) { + runOnJS(wrapper)(currentTime.value); + } + }); + + useDerivedValue(() => { + let minutes; + let remainingSeconds; + if (isHandlePan.value) { + const cTime = (x.value * duration.value) / maxWidth.value || 0; + currentTime.value = cTime; + minutes = Math.floor(cTime / 60); + remainingSeconds = Math.floor(cTime % 60); + } else { + const xTime = (currentTime.value * maxWidth.value) / duration.value || 0; + x.value = xTime; + minutes = Math.floor(currentTime.value / 60); + remainingSeconds = Math.floor(currentTime.value % 60); + } const formattedMinutes = String(minutes).padStart(2, '0'); const formattedSeconds = String(remainingSeconds).padStart(2, '0'); current.value = `${formattedMinutes}:${formattedSeconds}`; - }, [x, maxWidth, duration]); + }, [x, maxWidth, duration, isHandlePan, currentTime]); const getCurrentTime = useAnimatedProps( () => @@ -87,7 +164,7 @@ const Slider = ({ currentTime = 0, duration = 120, thumbColor = '' }) => { - + diff --git a/app/containers/message/Components/Audio/index.tsx b/app/containers/message/Components/Audio/index.tsx index 338e10f40..5ab983a3c 100644 --- a/app/containers/message/Components/Audio/index.tsx +++ b/app/containers/message/Components/Audio/index.tsx @@ -77,7 +77,6 @@ Button.displayName = 'MessageAudioButton'; const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessageAudioProps) => { const [loading, setLoading] = useState(true); const [currentTime, setCurrentTime] = useState(0); - const [duration, setDuration] = useState(0); const [paused, setPaused] = useState(true); const [cached, setCached] = useState(false); @@ -93,8 +92,8 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage const onPlaybackStatusUpdate = (status: AVPlaybackStatus) => { if (status) { - onLoad(status); - onProgress(status); + // onLoad(status); + // onProgress(status); onEnd(status); } }; @@ -107,23 +106,6 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage return url; }; - const onLoad = (data: AVPlaybackStatus) => { - if (data.isLoaded && data.durationMillis) { - const duration = data.durationMillis / 1000; - setDuration(duration > 0 ? duration : 0); - } - }; - - const onProgress = (data: AVPlaybackStatus) => { - if (data.isLoaded) { - const currentTime = data.positionMillis / 1000; - console.log('🚀 ~ file: index.tsx:120 ~ onProgress ~ currentTime:', currentTime); - if (currentTime <= duration) { - setCurrentTime(currentTime); - } - } - }; - const onEnd = async (data: AVPlaybackStatus) => { if (data.isLoaded) { if (data.didJustFinish) { @@ -275,11 +257,11 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage ]} >