Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
157 commits
Select commit Hold shift + click to select a range
fb664a1
feat: media auto-download view
reinaldonetof May 9, 2023
ab56ecd
media auto download view completed and saving the settings in mmkv
reinaldonetof May 9, 2023
871dc7f
audio download preference
reinaldonetof May 11, 2023
f5d6fce
Merge branch 'develop' into feat.media-auto-download-preference
reinaldonetof May 11, 2023
b73cf46
audio auto download when the user who sent the audio is the same logg…
reinaldonetof May 11, 2023
7fc975f
creation of isAutoDownloadEnabled, evaluate hist hook, Image Full Siz…
reinaldonetof May 11, 2023
d138a74
minor tweak audio show play button after download
reinaldonetof May 12, 2023
27eacaa
refactor audioFile to handleMediaDownload and fixed the audio download
reinaldonetof May 15, 2023
07e0970
desestructured params to download too
reinaldonetof May 15, 2023
cdad288
image download and autoDownload, algo fix the formatAttachmentUrl to …
reinaldonetof May 15, 2023
991cdf1
add the possibility to cancel image download and clear local images
reinaldonetof May 15, 2023
389057a
refactor blur component
reinaldonetof May 15, 2023
6c49c57
video download and auto download, also keeped the behavior to downloa…
reinaldonetof May 16, 2023
acb280f
add the possibility to start downloading a video, then exit the room,…
reinaldonetof May 16, 2023
7108e35
remove the custom hook for autoDownload
reinaldonetof May 16, 2023
d3c87a1
remove blurcomponent, fix the blur style in image.tsx, minor tweak vi…
reinaldonetof May 17, 2023
370f893
send messageId to video
reinaldonetof May 17, 2023
154deb6
introducing the reducer to keep the downloads in progress
reinaldonetof May 18, 2023
f136dfb
create a media download selector
reinaldonetof May 18, 2023
95cbe25
remove all the redux stuff and do the same as file upload
reinaldonetof May 19, 2023
aa2c288
video download behavior
reinaldonetof May 19, 2023
02ba6e9
done for image and audio
reinaldonetof May 19, 2023
99973c0
fix the try catch download media
reinaldonetof May 19, 2023
ce67d05
clean up
reinaldonetof May 19, 2023
41bce65
image container uiKit
reinaldonetof May 19, 2023
789ee3e
Merge branch 'develop' into feat.media-auto-download-preference
reinaldonetof May 19, 2023
74e6e8f
fix lint
reinaldonetof May 19, 2023
4dcb128
change rn-fetch-blob to expo-filesystem
reinaldonetof May 19, 2023
58f73e1
add pt-br
reinaldonetof May 19, 2023
67ba313
pass the correct message id when there is an attachment on reply
reinaldonetof May 19, 2023
1dc038d
refactor some changes requested
reinaldonetof May 30, 2023
c244dd4
fix audio and move the netInfo from autoDownloadPreference to redux
reinaldonetof Jun 7, 2023
6f3dc60
variable isAutoDownloadEnable name and handleMediaDownload getExtension
reinaldonetof Jun 7, 2023
8c0c1d7
message/Image refactored, change the component to show the image from…
reinaldonetof Jun 7, 2023
989e609
refactor handleMediaDownload and deleteMedia
reinaldonetof Jun 7, 2023
420bd49
minor tweak
reinaldonetof Jun 7, 2023
b341528
refactor audio
reinaldonetof Jun 7, 2023
b4a9b8a
refactor video
reinaldonetof Jun 7, 2023
07f0fd5
fix the type on the messagesView(the view of files)
reinaldonetof Jun 7, 2023
c1fbc20
minor tweak
reinaldonetof Jun 7, 2023
e7244d9
fix the name of searchMediaFIleAsync's result
reinaldonetof Jun 7, 2023
ce48ef0
minor tweak, add the default behavior, add the OFF as label
reinaldonetof Jun 9, 2023
63b49ab
minor tweaks
reinaldonetof Jun 12, 2023
e0942b2
verify if the media auto download exists on settings view
reinaldonetof Jun 12, 2023
332e51f
fix media auto download view layout and minor tweak wifi
reinaldonetof Jun 26, 2023
469d42b
avoid auto download from reply
reinaldonetof Jun 26, 2023
2d2988a
minor tweak at comment
reinaldonetof Jun 27, 2023
e0b86c0
tweak list.section
reinaldonetof Jun 27, 2023
a92d88c
change the name to netInfoState and Local_document_directory
reinaldonetof Jun 30, 2023
1be2326
Merge branch 'develop' into feat.media-auto-download-preference
reinaldonetof Jun 30, 2023
b6ae55e
remove mediaType and refactor audio and image
reinaldonetof Jul 3, 2023
b886031
separate blurview
reinaldonetof Jul 3, 2023
d39a5c7
thumbnail video and video behavior
reinaldonetof Jul 4, 2023
53ed61d
add Audio to i18n and minor tweak
reinaldonetof Jul 4, 2023
c85f989
set the blur as always dark and add the possibility to overlay
reinaldonetof Jul 4, 2023
b3f4605
don't need to controle the filepath in the view
reinaldonetof Jul 4, 2023
b6dceec
fix the loading in image and video at begin
reinaldonetof Jul 4, 2023
3072196
save the file with a similar filename as expected
reinaldonetof Jul 4, 2023
fb7da4f
removed the necessity of messageId or id
reinaldonetof Jul 4, 2023
f5c3c7a
minor tweak
reinaldonetof Jul 4, 2023
edd4fb6
switch useLayoutEffect to useEffect
reinaldonetof Jul 5, 2023
42507b6
avoid onpress do some edge case because of cached at video
reinaldonetof Jul 5, 2023
6ed1c7e
minor tweak
reinaldonetof Jul 5, 2023
abb7df7
tweak at audio comment extension
reinaldonetof Jul 5, 2023
8ed68ef
minor tweak type userpreferences
reinaldonetof Jul 5, 2023
5b57b35
remove test id from mediaAutoDownloadView
reinaldonetof Jul 5, 2023
65346b0
Merge branch 'develop' into feat.media-auto-download-preference
reinaldonetof Jul 20, 2023
c1b16d0
change action's name to SET_NET_INFO_STATE
reinaldonetof Jul 20, 2023
71ec969
caching and deleting video's thumbnails
reinaldonetof Jul 20, 2023
7e81d41
remove generate thumbnail
reinaldonetof Jul 24, 2023
3e75699
minor tweak in image
reinaldonetof Jul 24, 2023
3ada875
update camera-roll and save the file from local url
reinaldonetof Jul 25, 2023
fb576ef
remove local_cache_directory and deleteThumbnail
reinaldonetof Jul 25, 2023
892e7ba
update blur to fix error on android
reinaldonetof Jul 25, 2023
29b61e0
first commit
reinaldonetof Aug 2, 2023
c469d0f
fix togglePlayPause
reinaldonetof Aug 4, 2023
425522a
separate audio to a folder inside components and minor tweak attachment
reinaldonetof Aug 7, 2023
186ab33
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Aug 7, 2023
f344c9e
created the slider with text
reinaldonetof Aug 7, 2023
5bb14cb
play/pause button, currentTime equal the sound, can change the slider…
reinaldonetof Aug 8, 2023
dfa3688
play/pause, track is working and onEnd
reinaldonetof Aug 9, 2023
40b416f
update the icons with play-shaped-filled, pause-shape-filled, loading
reinaldonetof Aug 9, 2023
cd91664
start the tweaks on layout
reinaldonetof Aug 9, 2023
55afcaf
can play multiple audios, pausing the previous to execute the new one
reinaldonetof Aug 9, 2023
7e65c9f
loading animated
reinaldonetof Aug 10, 2023
bf77b6c
added the audio rate
reinaldonetof Aug 10, 2023
9c00ce0
layout fixed
reinaldonetof Aug 10, 2023
9066432
removed the sound manipulation from Slider to manipulate only in the …
reinaldonetof Aug 10, 2023
defd97c
fix time margin horizontal
reinaldonetof Aug 11, 2023
7900fad
fix play 2 audios and play/pause properly
reinaldonetof Aug 11, 2023
927225c
change the way we treat the audio
reinaldonetof Aug 16, 2023
e50e59d
remove audio copy
reinaldonetof Aug 16, 2023
b88c3b1
minor tweak
reinaldonetof Aug 16, 2023
1462582
fix rate state
reinaldonetof Aug 16, 2023
a026f2b
remove the PAUSE_AUDIO
reinaldonetof Aug 16, 2023
fe18a1a
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Aug 23, 2023
67b3200
fix unloadAll, add hit slop to slider, show the duration on the first…
reinaldonetof Aug 23, 2023
0738f60
refactor colors to be the same as figmas name
reinaldonetof Aug 23, 2023
8cab77f
change the class' name and add the method pauseCurrentAudio
reinaldonetof Aug 24, 2023
e84a5b3
pause audio when unmount a RoomView and unloadAll when focusing at Ro…
reinaldonetof Aug 24, 2023
e735cef
pause audio when entering a thread
reinaldonetof Aug 24, 2023
9854f16
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Sep 21, 2023
9094b73
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Sep 22, 2023
182af31
fix where call the pauseCurrentAudio
reinaldonetof Sep 22, 2023
8b053f6
moved the player from messageAudio to audioPlayer
reinaldonetof Oct 3, 2023
2b379ee
refactor audio component
reinaldonetof Oct 3, 2023
037a74f
remove loading
reinaldonetof Oct 4, 2023
86daf8c
update snapshot
reinaldonetof Oct 4, 2023
24ccc33
fix colors name
reinaldonetof Oct 4, 2023
f447757
pauseAudio when roomview is blur
reinaldonetof Oct 5, 2023
5625d53
moved audio from message/component/audio to message/Audio
reinaldonetof Oct 5, 2023
c157552
add navigation focus to AudioPlayer component and fix the jest
reinaldonetof Oct 5, 2023
023cd8f
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Oct 5, 2023
23e029d
add the { androidImplementation: 'MediaPlayer' }
reinaldonetof Oct 5, 2023
80f4f68
fix action sheet swipe 02-room
reinaldonetof Oct 6, 2023
dcf6c76
fix action sheet swipe 05-threads
reinaldonetof Oct 6, 2023
b1e0e12
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Oct 23, 2023
174ca91
tweak touchable
reinaldonetof Oct 23, 2023
8468c1c
remove react.memo from playbutton
reinaldonetof Oct 23, 2023
0154c5a
hitSlop
reinaldonetof Oct 23, 2023
eb33ce3
speed playback from array
reinaldonetof Oct 23, 2023
780156f
textinputprops
reinaldonetof Oct 23, 2023
3805bc9
tweak at names
reinaldonetof Oct 24, 2023
6b6904e
minor tweak at onEnd
reinaldonetof Oct 24, 2023
10216f5
minor tweak at names
reinaldonetof Oct 24, 2023
7e11357
update styles
reinaldonetof Oct 24, 2023
9b3986f
thumb seek size
reinaldonetof Oct 24, 2023
5910c8b
change marginBottom
reinaldonetof Oct 24, 2023
339769b
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Oct 25, 2023
db2061c
add the clamp, adjust the thumb position, remove the necessity of OnE…
reinaldonetof Oct 27, 2023
602d660
change the utils to constants
reinaldonetof Oct 27, 2023
5b0bca8
change to audioState
reinaldonetof Oct 27, 2023
4a9c83a
fix the seek for android
reinaldonetof Oct 27, 2023
d2bb297
TDownloadState
reinaldonetof Oct 27, 2023
669224b
speed array
reinaldonetof Oct 27, 2023
00fbe7b
pause audio from messagesView when open the files
reinaldonetof Oct 27, 2023
fb78b5c
update test
reinaldonetof Oct 27, 2023
f63d631
minor tweak
reinaldonetof Oct 27, 2023
64a17ed
change the time after ony one click, fixes the thumb to move sync wit…
reinaldonetof Oct 30, 2023
13b42ff
Fix seek
diegolmello Oct 31, 2023
ca985e8
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Nov 1, 2023
8a79d66
minor tweak Sound to Audio.Sound
reinaldonetof Nov 1, 2023
2a7b49d
name of Icon
reinaldonetof Nov 1, 2023
4f0a92a
enable PlaybackSpeed only when playing the audio
reinaldonetof Nov 1, 2023
32b6b46
playbackSpeed to mmkv
reinaldonetof Nov 1, 2023
f59d475
mock implementation
reinaldonetof Nov 1, 2023
a6990d5
create native button
reinaldonetof Nov 3, 2023
657f7a5
minor tweak
reinaldonetof Nov 3, 2023
f897e3d
Merge branch 'develop' into feat.new-audio-player
dnlsilva Nov 6, 2023
2b75b4b
minor tweaks
reinaldonetof Nov 7, 2023
1b6d50b
playbackSpeed after loadAudio
reinaldonetof Nov 13, 2023
0b62210
avoid show the error when try to setRate without audio
reinaldonetof Nov 13, 2023
d08f5d2
add messageID to differ audios inside a quote/forward from original one
reinaldonetof Nov 13, 2023
4bbe553
unloadRoomAudios instead of unloadAllAudios inside the roomsListView
reinaldonetof Nov 13, 2023
f48532e
Merge branch 'develop' into feat.new-audio-player
reinaldonetof Nov 13, 2023
13a82f4
minor tweak
reinaldonetof Nov 14, 2023
11f3b21
Merge branch 'develop' into feat.new-audio-player
dnlsilva Nov 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion __mocks__/react-native-mmkv-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ export const IOSAccessibleStates = {
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY: ''
};

export const create = jest.fn();
// fix the useUserPreference hook
export const create = jest.fn().mockImplementation(() => jest.fn().mockImplementation(() => [0, jest.fn()]));

Large diffs are not rendered by default.

Binary file modified android/app/src/main/assets/fonts/custom.ttf
Binary file not shown.
52 changes: 52 additions & 0 deletions app/containers/AudioPlayer/PlayButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';

import { CustomIcon } from '../CustomIcon';
import { useTheme } from '../../theme';
import styles from './styles';
import RCActivityIndicator from '../ActivityIndicator';
import { AUDIO_BUTTON_HIT_SLOP } from './constants';
import { TAudioState } from './types';
import NativeButton from '../NativeButton';

interface IButton {
disabled?: boolean;
onPress: () => void;
audioState: TAudioState;
}

type TCustomIconName = 'arrow-down' | 'play-shape-filled' | 'pause-shape-filled';

const Icon = ({ audioState, disabled }: { audioState: TAudioState; disabled: boolean }) => {
const { colors } = useTheme();

if (audioState === 'loading') {
return <RCActivityIndicator />;
}

let customIconName: TCustomIconName = 'arrow-down';
if (audioState === 'playing') {
customIconName = 'pause-shape-filled';
}
if (audioState === 'paused') {
customIconName = 'play-shape-filled';
}

return <CustomIcon name={customIconName} size={24} color={disabled ? colors.tintDisabled : colors.buttonFontPrimary} />;
};

const PlayButton = ({ onPress, disabled = false, audioState }: IButton) => {
const { colors } = useTheme();

return (
<NativeButton
style={[styles.playPauseButton, { backgroundColor: colors.buttonBackgroundPrimaryDefault }]}
disabled={disabled}
onPress={onPress}
hitSlop={AUDIO_BUTTON_HIT_SLOP}
>
<Icon audioState={audioState} disabled={disabled} />
</NativeButton>
);
};

export default PlayButton;
32 changes: 32 additions & 0 deletions app/containers/AudioPlayer/PlaybackSpeed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { Text } from 'react-native';

import styles from './styles';
import { useTheme } from '../../theme';
import { AUDIO_PLAYBACK_SPEED, AVAILABLE_SPEEDS } from './constants';
import { TAudioState } from './types';
import { useUserPreferences } from '../../lib/methods';
import NativeButton from '../NativeButton';

const PlaybackSpeed = ({ audioState }: { audioState: TAudioState }) => {
const [playbackSpeed, setPlaybackSpeed] = useUserPreferences<number>(AUDIO_PLAYBACK_SPEED, AVAILABLE_SPEEDS[1]);
const { colors } = useTheme();

const onPress = () => {
const speedIndex = AVAILABLE_SPEEDS.indexOf(playbackSpeed);
const nextSpeedIndex = speedIndex + 1 >= AVAILABLE_SPEEDS.length ? 0 : speedIndex + 1;
setPlaybackSpeed(AVAILABLE_SPEEDS[nextSpeedIndex]);
};

return (
<NativeButton
disabled={audioState !== 'playing'}
onPress={onPress}
style={[styles.containerPlaybackSpeed, { backgroundColor: colors.buttonBackgroundSecondaryDefault }]}
>
<Text style={[styles.playbackSpeedText, { color: colors.buttonFontSecondary }]}>{playbackSpeed}x</Text>
</NativeButton>
);
};

export default PlaybackSpeed;
129 changes: 129 additions & 0 deletions app/containers/AudioPlayer/Seek.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React from 'react';
import { LayoutChangeEvent, View, TextInput, TextInputProps, TouchableNativeFeedback } from 'react-native';
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
import Animated, {
SharedValue,
runOnJS,
useAnimatedGestureHandler,
useAnimatedProps,
useAnimatedStyle,
useDerivedValue,
useSharedValue
} from 'react-native-reanimated';

import styles from './styles';
import { useTheme } from '../../theme';
import { SEEK_HIT_SLOP, THUMB_SEEK_SIZE, ACTIVE_OFFSET_X, DEFAULT_TIME_LABEL } from './constants';

const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);

interface ISeek {
duration: SharedValue<number>;
currentTime: SharedValue<number>;
loaded: boolean;
onChangeTime: (time: number) => Promise<void>;
}

function clamp(value: number, min: number, max: number) {
'worklet';

return Math.min(Math.max(value, min), max);
}

// https://docs.swmansion.com/react-native-reanimated/docs/2.x/fundamentals/worklets/
const formatTime = (ms: number) => {
'worklet';

const minutes = Math.floor(ms / 60);
const remainingSeconds = Math.floor(ms % 60);
const formattedMinutes = String(minutes).padStart(2, '0');
const formattedSeconds = String(remainingSeconds).padStart(2, '0');
return `${formattedMinutes}:${formattedSeconds}`;
};

const Seek = ({ currentTime, duration, loaded = false, onChangeTime }: ISeek) => {
Comment thread
reinaldonetof marked this conversation as resolved.
Resolved
const { colors } = useTheme();

const maxWidth = useSharedValue(1);
const translateX = useSharedValue(0);
const timeLabel = useSharedValue(DEFAULT_TIME_LABEL);
const scale = useSharedValue(1);
const isPanning = useSharedValue(false);

const styleLine = useAnimatedStyle(() => ({
width: translateX.value
}));

const styleThumb = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value - THUMB_SEEK_SIZE / 2 }, { scale: scale.value }]
}));

const onLayout = (event: LayoutChangeEvent) => {
const { width } = event.nativeEvent.layout;
maxWidth.value = width;
};

const onGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent, { offsetX: number }>({
onStart: (event, ctx) => {
isPanning.value = true;
ctx.offsetX = translateX.value;
},
onActive: ({ translationX }, ctx) => {
translateX.value = clamp(ctx.offsetX + translationX, 0, maxWidth.value);
scale.value = 1.3;
},
onFinish() {
scale.value = 1;
isPanning.value = false;
runOnJS(onChangeTime)(Math.round(currentTime.value * 1000));
}
});

useDerivedValue(() => {
if (isPanning.value) {
// When the user is panning, always the currentTime.value is been set different from the currentTime provided by
// the audio in progress
currentTime.value = (translateX.value * duration.value) / maxWidth.value || 0;
} else {
translateX.value = (currentTime.value * maxWidth.value) / duration.value || 0;
}
timeLabel.value = formatTime(currentTime.value);
}, [translateX, maxWidth, duration, isPanning, currentTime]);

const timeLabelAnimatedProps = useAnimatedProps(() => {
if (currentTime.value !== 0) {
return {
text: timeLabel.value
} as TextInputProps;
}
return {
text: formatTime(duration.value)
} as TextInputProps;
}, [timeLabel, duration, currentTime]);

const thumbColor = loaded ? colors.buttonBackgroundPrimaryDefault : colors.tintDisabled;

// TouchableNativeFeedback is avoiding do a long press message when seeking the audio
return (
<TouchableNativeFeedback>
<View style={styles.seekContainer}>
<AnimatedTextInput
defaultValue={DEFAULT_TIME_LABEL}
editable={false}
style={[styles.duration, { color: colors.fontDefault }]}
animatedProps={timeLabelAnimatedProps}
/>
<View style={styles.seek} onLayout={onLayout}>
<View style={[styles.line, { backgroundColor: colors.strokeLight }]}>
<Animated.View style={[styles.line, styleLine, { backgroundColor: colors.buttonBackgroundPrimaryDefault }]} />
</View>
<PanGestureHandler enabled={loaded} onGestureEvent={onGestureEvent} activeOffsetX={[-ACTIVE_OFFSET_X, ACTIVE_OFFSET_X]}>
<Animated.View hitSlop={SEEK_HIT_SLOP} style={[styles.thumbSeek, { backgroundColor: thumbColor }, styleThumb]} />
</PanGestureHandler>
</View>
</View>
</TouchableNativeFeedback>
);
};

export default Seek;
13 changes: 13 additions & 0 deletions app/containers/AudioPlayer/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const AVAILABLE_SPEEDS = [0.5, 1, 1.5, 2];

export const AUDIO_BUTTON_HIT_SLOP = { top: 8, right: 8, bottom: 8, left: 8 };

export const SEEK_HIT_SLOP = { top: 12, right: 8, bottom: 12, left: 8 };

export const THUMB_SEEK_SIZE = 12;

export const AUDIO_PLAYBACK_SPEED = 'audioPlaybackSpeed';

export const DEFAULT_TIME_LABEL = '00:00';

export const ACTIVE_OFFSET_X = 0.001;
162 changes: 162 additions & 0 deletions app/containers/AudioPlayer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import React, { useEffect, useRef, useState } from 'react';
import { InteractionManager, View } from 'react-native';
import { AVPlaybackStatus } from 'expo-av';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import { useSharedValue } from 'react-native-reanimated';
import { useNavigation } from '@react-navigation/native';

import { useTheme } from '../../theme';
import styles from './styles';
import Seek from './Seek';
import PlaybackSpeed from './PlaybackSpeed';
import PlayButton from './PlayButton';
import audioPlayer from '../../lib/methods/audioPlayer';
import { AUDIO_PLAYBACK_SPEED, AVAILABLE_SPEEDS } from './constants';
import { TDownloadState } from '../../lib/methods/handleMediaDownload';
import { TAudioState } from './types';
import { useUserPreferences } from '../../lib/methods';

interface IAudioPlayerProps {
fileUri: string;
disabled?: boolean;
onPlayButtonPress?: Function;
downloadState: TDownloadState;
rid: string;
// It's optional when comes from MessagesView
msgId?: string;
}

const AudioPlayer = ({
fileUri,
disabled = false,
onPlayButtonPress = () => {},
downloadState,
msgId,
rid
}: IAudioPlayerProps) => {
const isLoading = downloadState === 'loading';
const isDownloaded = downloadState === 'downloaded';

const [playbackSpeed] = useUserPreferences<number>(AUDIO_PLAYBACK_SPEED, AVAILABLE_SPEEDS[1]);
const [paused, setPaused] = useState(true);
const duration = useSharedValue(0);
const currentTime = useSharedValue(0);
const { colors } = useTheme();
const audioUri = useRef<string>('');
const navigation = useNavigation();

const onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
if (status) {
onPlaying(status);
handlePlaybackStatusUpdate(status);
onEnd(status);
}
};

const onPlaying = (data: AVPlaybackStatus) => {
if (data.isLoaded && data.isPlaying) {
setPaused(false);
} else {
setPaused(true);
}
};

const handlePlaybackStatusUpdate = (data: AVPlaybackStatus) => {
if (data.isLoaded && data.durationMillis) {
const durationSeconds = data.durationMillis / 1000;
duration.value = durationSeconds > 0 ? durationSeconds : 0;
const currentSecond = data.positionMillis / 1000;
if (currentSecond <= durationSeconds) {
currentTime.value = currentSecond;
}
}
};

const onEnd = (data: AVPlaybackStatus) => {
if (data.isLoaded && data.didJustFinish) {
try {
setPaused(true);
currentTime.value = 0;
} catch {
// do nothing
}
}
};

const setPosition = async (time: number) => {
await audioPlayer.setPositionAsync(audioUri.current, time);
};

const togglePlayPause = async () => {
try {
if (!paused) {
await audioPlayer.pauseAudio(audioUri.current);
} else {
await audioPlayer.playAudio(audioUri.current);
}
} catch {
// Do nothing
}
};

useEffect(() => {
audioPlayer.setRateAsync(audioUri.current, playbackSpeed);
}, [playbackSpeed]);

const onPress = () => {
onPlayButtonPress();
if (isLoading) {
return;
}
if (isDownloaded) {
togglePlayPause();
}
};

useEffect(() => {
InteractionManager.runAfterInteractions(async () => {
audioUri.current = await audioPlayer.loadAudio({ msgId, rid, uri: fileUri });
audioPlayer.setOnPlaybackStatusUpdate(audioUri.current, onPlaybackStatusUpdate);
audioPlayer.setRateAsync(audioUri.current, playbackSpeed);
});
}, [fileUri]);

useEffect(() => {
if (paused) {
deactivateKeepAwake();
} else {
activateKeepAwake();
}
}, [paused]);

useEffect(() => {
const unsubscribeFocus = navigation.addListener('focus', () => {
audioPlayer.setOnPlaybackStatusUpdate(audioUri.current, onPlaybackStatusUpdate);
});

return () => {
unsubscribeFocus();
};
}, [navigation]);
Comment on lines +132 to +140

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need this to keep the onPlaybackStatusUpdate updated according to the audio player component in focus.

ex:

Screen.Recording.2023-10-05.at.16.49.04.mov
  • The sound starts to play in the main room.
  • a thread is created on this audio's message
  • when we open the thread, the audio pauses (this behavior is expected when open a thread)
  • then we can see that the audio component shows the current time the same as the pause of the main room
  • then we can play the audio again from where it paused, then stop and back to the main room
  • In the main room again, the focus listener calls the function to setOnPlaybackStatusUpdate and calls the onPlaybackStatusUpdate function of the audio component from the main room and the current time is the expected time from when paused in the thread room
  • Also, this approach is a possible solution for when the user go to the Files view and play an audio

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Main room <-> thread: audio stops
  • Main room <-> files: audio keeps playing


let audioState: TAudioState = 'to-download';
if (isLoading) {
audioState = 'loading';
}
if (isDownloaded && paused) {
audioState = 'paused';
}
if (isDownloaded && !paused) {
audioState = 'playing';
}

return (
<View style={[styles.audioContainer, { backgroundColor: colors.surfaceTint, borderColor: colors.strokeExtraLight }]}>
<PlayButton disabled={disabled} audioState={audioState} onPress={onPress} />
<Seek currentTime={currentTime} duration={duration} loaded={!disabled && isDownloaded} onChangeTime={setPosition} />
{audioState === 'playing' ? <PlaybackSpeed audioState={audioState} /> : null}
</View>
);
};

export default AudioPlayer;
Loading