diff --git a/app/containers/message/Components/Audio/Slider.tsx b/app/containers/message/Components/Audio/Slider.tsx
new file mode 100644
index 000000000..3e80e978e
--- /dev/null
+++ b/app/containers/message/Components/Audio/Slider.tsx
@@ -0,0 +1,98 @@
+import React from 'react';
+import { LayoutChangeEvent, View, TextInput } from 'react-native';
+import { PanGestureHandler } from 'react-native-gesture-handler';
+import Animated, {
+ useAnimatedGestureHandler,
+ useAnimatedProps,
+ useAnimatedStyle,
+ useDerivedValue,
+ useSharedValue
+} from 'react-native-reanimated';
+
+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);
+ const { colors } = useTheme();
+
+ const maxWidth = useSharedValue(1);
+ const x = useSharedValue(currentTime);
+ const current = useSharedValue('00:00');
+ const scale = useSharedValue(1);
+
+ const styleLine = useAnimatedStyle(() => ({
+ width: x.value,
+ zIndex: 2
+ }));
+
+ const styleThumb = useAnimatedStyle(() => ({
+ transform: [{ translateX: x.value }, { scale: scale.value }]
+ }));
+
+ const onLayout = (event: LayoutChangeEvent) => {
+ const { width } = event.nativeEvent.layout;
+ maxWidth.value = width - 12;
+ };
+
+ const gestureHandler = useAnimatedGestureHandler({
+ onStart: (_, ctx: any) => {
+ ctx.startX = x.value;
+ },
+ onActive: (event, ctx: any) => {
+ const moveInX: number = ctx.startX + event.translationX;
+ if (moveInX < 0) {
+ x.value = 0;
+ } else if (moveInX > maxWidth.value) {
+ x.value = maxWidth.value;
+ } else {
+ x.value = moveInX;
+ }
+
+ scale.value = 1.3;
+ },
+ onEnd: () => {
+ scale.value = 1;
+ // SEND A CALLBACK TO CHANGE THE PROGRESS OF THE AUDIO
+ }
+ });
+
+ useDerivedValue(() => {
+ const cTime = (x.value * duration) / maxWidth.value;
+ const minutes = Math.floor(cTime / 60);
+ const remainingSeconds = Math.floor(cTime % 60);
+ const formattedMinutes = String(minutes).padStart(2, '0');
+ const formattedSeconds = String(remainingSeconds).padStart(2, '0');
+ current.value = `${formattedMinutes}:${formattedSeconds}`;
+ }, [x, maxWidth, duration]);
+
+ const getCurrentTime = useAnimatedProps(
+ () =>
+ ({
+ text: current.value
+ } as any),
+ [current]
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default Slider;
diff --git a/app/containers/message/Components/Audio/index.tsx b/app/containers/message/Components/Audio/index.tsx
index f7e6d2691..338e10f40 100644
--- a/app/containers/message/Components/Audio/index.tsx
+++ b/app/containers/message/Components/Audio/index.tsx
@@ -1,17 +1,13 @@
import React, { useContext, useEffect, useRef, useState } from 'react';
-import { StyleProp, StyleSheet, Text, TextStyle, View, useWindowDimensions } from 'react-native';
+import { StyleProp, TextStyle, View } from 'react-native';
import { Audio, AVPlaybackStatus, InterruptionModeAndroid, InterruptionModeIOS } from 'expo-av';
-import Slider from '@react-native-community/slider';
-import moment from 'moment';
import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake';
import { Sound } from 'expo-av/build/Audio/Sound';
import Touchable from '../../Touchable';
import Markdown from '../../../markdown';
import { CustomIcon } from '../../../CustomIcon';
-import sharedStyles from '../../../../views/Styles';
import { themes } from '../../../../lib/constants';
-import { isAndroid, isIOS } from '../../../../lib/methods/helpers';
import MessageContext from '../../Context';
import ActivityIndicator from '../../../ActivityIndicator';
import { TGetCustomEmoji } from '../../../../definitions/IEmoji';
@@ -21,6 +17,8 @@ import { downloadMediaFile, getMediaCache } from '../../../../lib/methods/handle
import EventEmitter from '../../../../lib/methods/helpers/events';
import { PAUSE_AUDIO } from '../../constants';
import { fetchAutoDownloadEnabled } from '../../../../lib/methods/autoDownloadPreference';
+import styles from './styles';
+import Slider from './Slider';
interface IButton {
loading: boolean;
@@ -48,36 +46,6 @@ const mode = {
interruptionModeAndroid: InterruptionModeAndroid.DoNotMix
};
-const styles = StyleSheet.create({
- audioContainer: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- height: 56,
- borderWidth: 1,
- borderRadius: 4,
- marginBottom: 6
- },
- playPauseButton: {
- marginHorizontal: 10,
- alignItems: 'center',
- backgroundColor: 'transparent'
- },
- audioLoading: {
- marginHorizontal: 8
- },
- slider: {
- flex: 1
- },
- duration: {
- marginHorizontal: 12,
- fontSize: 14,
- ...sharedStyles.textRegular
- }
-});
-
-const formatTime = (seconds: number) => moment.utc(seconds * 1000).format('mm:ss');
-
const BUTTON_HIT_SLOP = { top: 12, right: 12, bottom: 12, left: 12 };
const Button = React.memo(({ loading, paused, onPress, disabled, cached }: IButton) => {
@@ -114,7 +82,6 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
const [cached, setCached] = useState(false);
const { baseUrl, user } = useContext(MessageContext);
- const { scale } = useWindowDimensions();
const { theme } = useTheme();
const sound = useRef(null);
@@ -150,6 +117,7 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
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);
}
@@ -171,8 +139,6 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
}
};
- const getDuration = () => formatTime(currentTime || duration);
-
const togglePlayPause = () => {
setPaused(!paused);
playPause(!paused);
@@ -240,15 +206,6 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
handleDownload();
};
- const onValueChange = async (value: number) => {
- try {
- setCurrentTime(value);
- await sound.current?.setPositionAsync(value * 1000);
- } catch {
- // Do nothing
- }
- };
-
useEffect(() => {
sound.current = new Audio.Sound();
sound.current?.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate);
@@ -296,9 +253,9 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
}
let thumbColor;
- if (isAndroid && isReply) {
+ if (isReply) {
thumbColor = themes[theme].tintDisabled;
- } else if (isAndroid) {
+ } else {
thumbColor = themes[theme].tintColor;
}
@@ -318,19 +275,8 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
]}
>
- {getDuration()}
-
+
+
>
);
diff --git a/app/containers/message/Components/Audio/styles.ts b/app/containers/message/Components/Audio/styles.ts
new file mode 100644
index 000000000..ef59931b9
--- /dev/null
+++ b/app/containers/message/Components/Audio/styles.ts
@@ -0,0 +1,60 @@
+import { StyleSheet } from 'react-native';
+
+import sharedStyles from '../../../../views/Styles';
+
+const styles = StyleSheet.create({
+ audioContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ height: 56,
+ borderWidth: 1,
+ borderRadius: 4,
+ marginBottom: 6
+ },
+ playPauseButton: {
+ alignItems: 'center',
+ backgroundColor: '#929',
+ marginLeft: 16,
+ height: 32,
+ width: 32,
+ borderRadius: 4,
+ justifyContent: 'center'
+ },
+ audioLoading: {
+ marginHorizontal: 8
+ },
+ sliderContainer: {
+ flexDirection: 'row',
+ flex: 1,
+ alignItems: 'center',
+ height: '100%'
+ },
+ slider: {
+ marginRight: 12,
+ height: '100%',
+ justifyContent: 'center',
+ flex: 1
+ },
+ line: {
+ height: 4,
+ borderRadius: 2,
+ zIndex: 1,
+ position: 'absolute',
+ width: '100%'
+ },
+ duration: {
+ width: 40,
+ marginHorizontal: 12,
+ fontSize: 14,
+ ...sharedStyles.textRegular
+ },
+ thumbSlider: {
+ height: 12,
+ width: 12,
+ borderRadius: 6,
+ zIndex: 3
+ }
+});
+
+export default styles;