Skip to content
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
306 commits
Select commit Hold shift + click to select a range
acd8675
Merge branch 'develop' into test.poc-a11y-bottom-shet
OtavioStasiak Mar 9, 2026
854b508
fix: add sleep to pass tests
OtavioStasiak Mar 10, 2026
9feee82
fix: e2e tests
OtavioStasiak Mar 10, 2026
b5aaff9
Merge branch 'develop' into reanimated-v4
Rohit3523 Mar 10, 2026
6413650
conflict fix
Rohit3523 Mar 10, 2026
d0f3d39
Merge branch 'develop' into reanimated-v4
Rohit3523 Mar 10, 2026
a8cdebd
Move worklet plugin to last
Rohit3523 Mar 10, 2026
ebe4419
Merge branch 'reanimated-v4' of https://github.com/RocketChat/Rocket.…
Rohit3523 Mar 10, 2026
b054ed4
fix: roomView test
OtavioStasiak Mar 10, 2026
bcbc7fe
fix: e2e tests
OtavioStasiak Mar 10, 2026
8a0d12c
Merge branch 'develop' into test.poc-a11y-bottom-shet
OtavioStasiak Mar 10, 2026
02cd74f
fix: code improvements
OtavioStasiak Mar 11, 2026
e50f3ad
fix: update required height
OtavioStasiak Mar 11, 2026
af3098d
Update patches/@lodev09+react-native-true-sheet+3.7.3.patch
OtavioStasiak Mar 11, 2026
b7c2b2f
code improvements
OtavioStasiak Mar 11, 2026
22ff512
fix: style
OtavioStasiak Mar 11, 2026
cc271ef
chore: format code and fix lint issues
OtavioStasiak Mar 11, 2026
eb37e68
remove unused style
OtavioStasiak Mar 11, 2026
b5a87b7
clean patch package
OtavioStasiak Mar 12, 2026
a0a6854
fix: remove border rounded and fixing padding issues
OtavioStasiak Mar 12, 2026
ebd8f88
fix: list padding
OtavioStasiak Mar 12, 2026
f4defa6
adjust bottom padding
OtavioStasiak Mar 12, 2026
d66c812
fix: android Directory view Actionsheet click and Servers List render
OtavioStasiak Mar 12, 2026
7662c7f
fix: orientation and unit test
OtavioStasiak Mar 12, 2026
88e8b42
Merge branch 'develop' into test.poc-a11y-bottom-shet
OtavioStasiak Mar 12, 2026
c19cadf
chore: format code and fix lint issues
OtavioStasiak Mar 12, 2026
7946eb4
fix: remve highlight of handle
OtavioStasiak Mar 12, 2026
d6a3237
cleanup
OtavioStasiak Mar 13, 2026
6fc21de
more bottom sheet changes
Rohit3523 Mar 14, 2026
7d1f242
adjustment for android
Rohit3523 Mar 15, 2026
301b0c3
chore: format code and fix lint issues
Rohit3523 Mar 15, 2026
8daab95
rerun
Rohit3523 Mar 15, 2026
d23a7e0
revert
Rohit3523 Mar 15, 2026
7c02045
Merge branch 'test.poc-a11y-bottom-shet' of https://github.com/Rocket…
Rohit3523 Mar 15, 2026
38cd2c9
test update
Rohit3523 Mar 15, 2026
930c88a
some improvements
Rohit3523 Mar 16, 2026
d0d218b
fix test
Rohit3523 Mar 16, 2026
3bab462
test fix
Rohit3523 Mar 16, 2026
cd35041
Remove unused bottomSheet prop
Rohit3523 Mar 16, 2026
35b55df
memorise bottom sheet handle
Rohit3523 Mar 16, 2026
50e1ffc
remove unused import
Rohit3523 Mar 16, 2026
ec14b28
ios test fix
Rohit3523 Mar 16, 2026
28d9062
clear timeout
Rohit3523 Mar 16, 2026
fb40b8b
wait for animation to close
Rohit3523 Mar 16, 2026
ae5df9f
Merge branch 'develop' into test.poc-a11y-bottom-shet
Rohit3523 Mar 16, 2026
fdaf544
lint fix
Rohit3523 Mar 16, 2026
05c7b5a
chore: format code and fix lint issues
Rohit3523 Mar 16, 2026
5064359
add comment for extra style
Rohit3523 Mar 16, 2026
650104e
tap on point to hide sheet
Rohit3523 Mar 16, 2026
7144138
Merge branch 'test.poc-a11y-bottom-shet' of https://github.com/Rocket…
Rohit3523 Mar 16, 2026
8db5f90
suggested changes by copilot and copilot
Rohit3523 Mar 17, 2026
d3f23e7
chore: format code and fix lint issues
Rohit3523 Mar 17, 2026
c03938c
revert the test
Rohit3523 Mar 17, 2026
4e7cc2b
Merge branch 'test.poc-a11y-bottom-shet' of https://github.com/Rocket…
Rohit3523 Mar 17, 2026
0e45349
Change sheet min height
Rohit3523 Mar 17, 2026
dbffe97
disable content panning for android
Rohit3523 Mar 17, 2026
d33a796
chore: format code and fix lint issues
Rohit3523 Mar 17, 2026
719c192
rerun
Rohit3523 Mar 17, 2026
1e6da08
revert
Rohit3523 Mar 17, 2026
e8abcf1
test update
Rohit3523 Mar 17, 2026
8b410dc
correct cancel button height
Rohit3523 Mar 19, 2026
b81a3ae
Remove timeout to present sheet
Rohit3523 Mar 19, 2026
4a7a9fb
Merge branch 'develop' into react-native-81
Rohit3523 Mar 19, 2026
709d7d8
chore: format code and fix lint issues
Rohit3523 Mar 19, 2026
9e60c47
Remove space
Rohit3523 Mar 19, 2026
449360a
ios fix
Rohit3523 Mar 19, 2026
9b1713c
Merge branch 'react-native-81' of https://github.com/RocketChat/Rocke…
Rohit3523 Mar 19, 2026
3dc77ca
package align
Rohit3523 Mar 19, 2026
9c25b88
Added bottom sheet in dev because of storybook
Rohit3523 Mar 19, 2026
9ff7576
snap update
Rohit3523 Mar 19, 2026
28d8d4e
Test fix
Rohit3523 Mar 19, 2026
1ddf1c6
test fix
Rohit3523 Mar 5, 2026
54c2e9d
Merge branch 'develop' into reanimated-v4
Rohit3523 Mar 19, 2026
a367e02
chore: format code and fix lint issues
Rohit3523 Mar 19, 2026
2b3e51a
lock file fixed
Rohit3523 Mar 19, 2026
5756896
Merge branch 'develop' into test.poc-a11y-bottom-shet
Rohit3523 Mar 19, 2026
45d1292
increase reaction open time
Rohit3523 Mar 20, 2026
ac20a76
Merge branch 'test.poc-a11y-bottom-shet' of https://github.com/Rocket…
Rohit3523 Mar 20, 2026
cdda960
increase timeout
Rohit3523 Mar 20, 2026
cf08b03
Upgrade to RN 0.81.6
Rohit3523 Mar 20, 2026
cff02b6
Removed deprecated addWhitelistedNativeProps
Rohit3523 Mar 21, 2026
c48a040
Merge branch 'test.poc-a11y-bottom-shet' into reanimated-v4
Rohit3523 Mar 23, 2026
175bd53
Merge branch 'reanimated-v4' into react-native-81
Rohit3523 Mar 23, 2026
1d7d89d
revert to rn 0.81.5
Rohit3523 Mar 23, 2026
bf5c915
snap update
Rohit3523 Mar 23, 2026
5042da6
remove worklet from jest
Rohit3523 Mar 23, 2026
912278c
Replace thumb button with touch
Rohit3523 Mar 23, 2026
2f1ba4a
update expo-file-system import to legacy
Rohit3523 Mar 23, 2026
59cae3a
ts fix
Rohit3523 Mar 23, 2026
1529a23
patch for webview
Rohit3523 Mar 23, 2026
4ed67ee
remove rn web 13.15.0 patch
Rohit3523 Mar 23, 2026
0232059
use custom snapshot serializer
Rohit3523 Mar 23, 2026
01552c7
snapshot update
Rohit3523 Mar 23, 2026
a603042
chore: format code and fix lint issues
Rohit3523 Mar 23, 2026
e9590e3
prettier ;-;
Rohit3523 Mar 23, 2026
063ce88
Merge branch 'react-native-81' of https://github.com/RocketChat/Rocke…
Rohit3523 Mar 23, 2026
f80ab8e
pod update
Rohit3523 Mar 23, 2026
53d9751
fix for expo-file-system in android
Rohit3523 Mar 24, 2026
cdf85b0
Merge branch 'develop' into reanimated-v4
Rohit3523 Mar 24, 2026
4ff6637
pod update
Rohit3523 Mar 24, 2026
c2a6ca4
Merge branch 'develop' into react-native-81
Rohit3523 Mar 24, 2026
31d5e63
lock file fix
Rohit3523 Mar 24, 2026
be5e8e9
Merge branch 'develop' into expo-audio
Rohit3523 Mar 24, 2026
cfc5f2e
enable liquid glass ui
Rohit3523 Mar 24, 2026
2116a2d
list item are not accessible for e2e, so maestro can interact with sw…
Rohit3523 Mar 24, 2026
c8a5cce
chore: format code and fix lint issues
Rohit3523 Mar 24, 2026
291143b
Merge branch 'develop' into react-native-81
Rohit3523 Mar 24, 2026
bdf46e7
Merge branch 'develop' into react-native-81
Rohit3523 Mar 24, 2026
21f08c8
revert last change
Rohit3523 Mar 24, 2026
fd24f10
Merge branch 'react-native-81' of https://github.com/RocketChat/Rocke…
Rohit3523 Mar 24, 2026
8048a08
improve logic...
Rohit3523 Mar 24, 2026
fbe735c
A temp change
Rohit3523 Mar 24, 2026
05cacf5
use rect button
Rohit3523 Mar 25, 2026
be81a47
test update
Rohit3523 Mar 25, 2026
f3c0d50
use match like in accessibility test
Rohit3523 Mar 25, 2026
6929797
ios profile test fix
Rohit3523 Mar 25, 2026
d327896
test fix
Rohit3523 Mar 25, 2026
09d63d8
Added test id in directory
Rohit3523 Mar 25, 2026
951558d
chore: format code and fix lint issues
Rohit3523 Mar 25, 2026
b4cd9b5
path fix ;-;
Rohit3523 Mar 25, 2026
ee7133d
Merge branch 'react-native-81' of https://github.com/RocketChat/Rocke…
Rohit3523 Mar 25, 2026
7f5e04d
coderabbit suggestion
Rohit3523 Mar 25, 2026
88be3cd
coderabbit suggestion
Rohit3523 Mar 25, 2026
6bb597e
Merge branch 'develop' into reanimated-v4
Rohit3523 Mar 25, 2026
03e0ae0
seekbar improvement
Rohit3523 Mar 25, 2026
a130cd1
Replace more runOnJS to scheduleOnRN
Rohit3523 Mar 25, 2026
a541660
Merge branch 'reanimated-v4' of https://github.com/RocketChat/Rocket.…
Rohit3523 Mar 25, 2026
6e35a0b
update seekbar
Rohit3523 Mar 25, 2026
49eb0d8
Merge branch 'reanimated-v4' into react-native-81
Rohit3523 Mar 25, 2026
6d0ef3a
trying to use RectButton in handle
Rohit3523 Mar 25, 2026
4688922
chore: format code and fix lint issues
Rohit3523 Mar 25, 2026
857ea2c
using TouchableNativeFeedback from RNGH
Rohit3523 Mar 26, 2026
8f9b788
readded message parser patch ;-;
Rohit3523 Mar 26, 2026
5646bdf
Merge branch 'react-native-81' of https://github.com/RocketChat/Rocke…
Rohit3523 Mar 26, 2026
9ca79ca
Switch from TouchableNativeFeedback to TouchableHighlight ;-;
Rohit3523 Mar 26, 2026
d169c97
chore: format code and fix lint issues
Rohit3523 Mar 26, 2026
0125108
rerun ci
Rohit3523 Mar 26, 2026
75e2166
revert
Rohit3523 Mar 26, 2026
ee646a4
Merge branch 'react-native-81' into expo-audio
Rohit3523 Mar 30, 2026
062be8f
lint fix
Rohit3523 Mar 30, 2026
10fd51f
eslint fix and api align
Rohit3523 Mar 30, 2026
41aaa31
Added changes for expo-video
Rohit3523 Mar 30, 2026
c9ac652
Remove expo-av
Rohit3523 Mar 30, 2026
f281134
code format
Rohit3523 Mar 30, 2026
4db9e2f
fix react hook rule
Rohit3523 Mar 30, 2026
59278db
remove plugins because it is not needed
Rohit3523 Apr 5, 2026
b01fe2c
fix audio play and seek fix
Rohit3523 Apr 6, 2026
e1c28fd
Merge branch 'develop' into expo-audio
Rohit3523 Apr 23, 2026
78f1f18
Merge branch 'develop' into expo-audio
Rohit3523 Apr 23, 2026
81881b9
changes revert
Rohit3523 Apr 23, 2026
380197d
Merge branch 'expo-audio' of https://github.com/RocketChat/Rocket.Cha…
Rohit3523 Apr 23, 2026
dd072db
chore: format code and fix lint issues
Rohit3523 Apr 23, 2026
097117b
making code rabbit happy
Rohit3523 Apr 23, 2026
0725500
making eslint happy...
Rohit3523 Apr 23, 2026
60f1eba
mock fix
Rohit3523 Apr 23, 2026
f9cc233
more changes
Rohit3523 Apr 23, 2026
e38798f
chore: format code and fix lint issues
Rohit3523 Apr 23, 2026
13ca710
video player fix
Rohit3523 Apr 23, 2026
a819401
Merge branch 'expo-audio' of https://github.com/RocketChat/Rocket.Cha…
Rohit3523 Apr 23, 2026
27182e1
Merge branch 'develop' into expo-audio
Rohit3523 Apr 28, 2026
8682447
Merge branch 'develop' into expo-audio
Rohit3523 May 5, 2026
087c7e8
Merge branch 'develop' into expo-audio
Rohit3523 May 5, 2026
3b9a6a9
pod install
Rohit3523 May 5, 2026
50e459e
Merge branch 'develop' into expo-audio
Rohit3523 May 11, 2026
96d5b49
code update
Rohit3523 May 11, 2026
6ef935f
test update
Rohit3523 May 11, 2026
97f4d75
making code rabbit happy
Rohit3523 May 11, 2026
ed07693
chore: format code and fix lint issues
Rohit3523 May 11, 2026
d74c32a
test fix
Rohit3523 May 11, 2026
b7f988d
Merge branch 'expo-audio' of https://github.com/RocketChat/Rocket.Cha…
Rohit3523 May 11, 2026
f761897
Merge branch 'develop' into expo-audio
Rohit3523 May 11, 2026
1f3a18d
Merge branch 'develop' into expo-audio
Rohit3523 May 26, 2026
a354032
improvements
Rohit3523 May 26, 2026
0bea258
remove expo-av
Rohit3523 May 26, 2026
424f719
Merge branch 'develop' into expo-audio
Rohit3523 May 28, 2026
56be8c6
Merge branch 'develop' into expo-audio
Rohit3523 Jun 8, 2026
01d3838
Merge branch 'develop' into expo-audio
Rohit3523 Jun 25, 2026
83237ae
Merge branch 'develop' into expo-audio
Rohit3523 Jun 30, 2026
2bf6ad9
Using memo directly
Rohit3523 Jun 30, 2026
1802321
test fix
Rohit3523 Jun 30, 2026
cadc0e4
make setPositionAsync async
Rohit3523 Jun 30, 2026
838c45e
Merge branch 'develop' into expo-audio
Rohit3523 Jul 9, 2026
fa95705
lint fix
Rohit3523 Jul 9, 2026
7b0ec08
Merge branch 'expo-audio' of https://github.com/RocketChat/Rocket.Cha…
Rohit3523 Jul 9, 2026
2668539
changes
Rohit3523 Jul 9, 2026
729821a
action: organized translations
Rohit3523 Jul 9, 2026
2d645ba
move back to class
Rohit3523 Jul 9, 2026
60433f6
Merge branch 'expo-audio' of https://github.com/RocketChat/Rocket.Cha…
Rohit3523 Jul 9, 2026
06344d1
Changes
Rohit3523 Jul 9, 2026
5d58df8
More changes
Rohit3523 Jul 10, 2026
ae39003
Merge branch 'develop' into expo-audio
Rohit3523 Jul 26, 2026
1b00101
changes
Rohit3523 Jul 26, 2026
9e86240
using PermissionStatus instead of string check
Rohit3523 Jul 26, 2026
7816a92
move record back to effect
Rohit3523 Jul 26, 2026
c9ec946
readded RECORDING_SETTINGS
Rohit3523 Jul 26, 2026
37fa278
fix type
Rohit3523 Jul 26, 2026
a063301
more type fix
Rohit3523 Jul 26, 2026
49de44f
readded constructor
Rohit3523 Jul 26, 2026
13e6e46
position change
Rohit3523 Jul 26, 2026
45c3dd8
some more revert
Rohit3523 Jul 26, 2026
d713664
more revert
Rohit3523 Jul 26, 2026
073e935
lint
Rohit3523 Jul 26, 2026
f1793f5
more changes
Rohit3523 Jul 26, 2026
97f5654
lint fix
Rohit3523 Jul 26, 2026
4554f90
using didJustFinish
Rohit3523 Jul 26, 2026
4f3894e
using enum
Rohit3523 Jul 27, 2026
228bd17
added return type
Rohit3523 Jul 27, 2026
77256b6
remove comment
Rohit3523 Jul 27, 2026
9a4ec0b
some changes
Rohit3523 Jul 27, 2026
20b6031
using createAudioPlayer in ringer
Rohit3523 Jul 28, 2026
5402cb5
fix audio recoding
Rohit3523 Jul 28, 2026
dbf1d61
podfile fix
Rohit3523 Jul 28, 2026
2b4e753
Added translation
Rohit3523 Jul 28, 2026
94ae616
action: organized translations
Rohit3523 Jul 28, 2026
876e66e
Merge branch 'develop' into expo-audio
Rohit3523 Jul 28, 2026
65039ec
stop playing audio on ios after opening room
Rohit3523 Jul 28, 2026
0cf30f0
improvement for ios
Rohit3523 Jul 28, 2026
30c3231
correct translation
Rohit3523 Jul 28, 2026
efb4f03
remove unwanted code
Rohit3523 Jul 28, 2026
d706b0c
Merge branch 'develop' into expo-audio
Rohit3523 Jul 28, 2026
740ece7
Merge branch 'develop' into expo-audio
Rohit3523 Aug 3, 2026
e3a830d
Merge branch 'develop' into expo-audio
Rohit3523 Aug 7, 2026
8c5ac58
recent changes
Rohit3523 Aug 7, 2026
86d163c
fix recording on ios
Rohit3523 Aug 12, 2026
f33838d
Merge branch 'develop' into expo-audio
Rohit3523 Aug 18, 2026
02bbd94
patch to fix seek on android
Rohit3523 Aug 18, 2026
68cfa9b
Merge branch 'develop' into expo-audio
Rohit3523 Aug 20, 2026
15bcde8
fix config
Rohit3523 Aug 23, 2026
6ea0591
Merge branch 'develop' into expo-audio
Rohit3523 Aug 23, 2026
c108964
chore: format code and fix lint issues
Rohit3523 Aug 23, 2026
d47fb5f
do not play video automatically in shareview
Rohit3523 Sep 2, 2026
d988aeb
Merge branch 'develop' into expo-audio
Rohit3523 Sep 2, 2026
5b5be6a
changes
Rohit3523 Sep 2, 2026
7045b9e
Merge branch 'develop' into expo-audio
Rohit3523 Sep 2, 2026
85a45cc
test fix
Rohit3523 Sep 2, 2026
471cb29
added safe area in video view and move style to it's own file
Rohit3523 Sep 2, 2026
72c184c
chore: format code and fix lint issues
Rohit3523 Sep 2, 2026
756e606
fix: VideoPlayer stories snapshot coverage and broken theme exports
Rohit3523 Sep 10, 2026
806c0c3
fix: handle permission API failures in MicOrSendButton
Rohit3523 Sep 10, 2026
7304eb4
fix: add explicit return types to AudioManager and test setup
Rohit3523 Sep 10, 2026
5ca7d61
Merge branch 'develop' into expo-audio
Rohit3523 Sep 10, 2026
735ce4a
remove Error_play_video
Rohit3523 Sep 10, 2026
c632717
fix: address Otavio review feedback
Rohit3523 Sep 11, 2026
e4ad02f
fix: handle floating setPositionAsync promise in AudioPlayer onEnd
Rohit3523 Sep 11, 2026
e12e721
Merge branch 'develop' into expo-audio
Rohit3523 Sep 11, 2026
ee140b0
Merge branch 'develop' into expo-audio
Rohit3523 Sep 11, 2026
d72d2a5
fix: preserve audio pitch, sequential replay and room cleanup
diegolmello Sep 14, 2026
b7a01f6
Merge branch 'develop' into expo-audio
diegolmello Sep 14, 2026
dc13f5f
fix: preserve seek position and simplify audio recording
diegolmello Sep 14, 2026
846cda3
Merge develop into expo-audio and resolve composer test imports
diegolmello Sep 15, 2026
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
20 changes: 11 additions & 9 deletions app/containers/AudioPlayer/Seek.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface ISeek {
duration: SharedValue<number>;
currentTime: SharedValue<number>;
loaded: boolean;
onChangeTime: (time: number) => Promise<void>;
onChangeTime: (time: number) => void;
}

function clamp(value: number, min: number, max: number) {
Expand Down Expand Up @@ -49,6 +49,8 @@ const Seek = ({ currentTime, duration, loaded = false, onChangeTime }: ISeek) =>
const scale = useSharedValue(1);
const isPanning = useSharedValue(false);
const contextX = useSharedValue(0);
const savedTranslateX = useSharedValue(0);
const savedCurrentTime = useSharedValue(0);

const styleLine = useAnimatedStyle(() => ({
width: translateX.value
Expand All @@ -69,23 +71,23 @@ const Seek = ({ currentTime, duration, loaded = false, onChangeTime }: ISeek) =>
.onStart(() => {
isPanning.value = true;
contextX.value = translateX.value;
savedTranslateX.value = translateX.value;
savedCurrentTime.value = currentTime.value;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We are temporary storing the current play time, so if the seek fail, we can revert the time

scale.value = withTiming(1.3, { duration: 150 });
})
.onUpdate(event => {
const newX = contextX.value + event.translationX;
translateX.value = clamp(newX, 0, maxWidth.value);
})
.onEnd(() => {
scheduleOnRN(onChangeTime, Math.round(currentTime.value * 1000));
})
.onFinalize((_, didSucceed) => {
if (isPanning.value && !didSucceed) {
translateX.value = contextX.value;
currentTime.value = (contextX.value * duration.value) / maxWidth.value || 0;
}

isPanning.value = false;
scale.value = withTiming(1, { duration: 150 });
if (didSucceed) {
scheduleOnRN(onChangeTime, currentTime.value);
Comment thread
OtavioStasiak marked this conversation as resolved.
Resolved
} else {
translateX.value = savedTranslateX.value;
currentTime.value = savedCurrentTime.value;
}
});

useDerivedValue(() => {
Expand Down
74 changes: 37 additions & 37 deletions app/containers/AudioPlayer/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ jest.mock('../../theme', () => ({
}));

const mockTaskCancel = jest.fn();
let capturedFocusCb: Function | undefined;
let capturedBlurCb: Function | undefined;
let capturedFocusCb: (() => void) | undefined;
let capturedBlurCb: (() => void) | undefined;
let mockUnsubscribe: jest.Mock;
let capturedAudioFocusedCb: Function | undefined;
let capturedAudioFocusedCb: ((audioFocused: string) => void) | undefined;

const defaultProps = {
fileUri: 'file:///audio.mp3',
Expand All @@ -67,15 +67,15 @@ describe('AudioPlayer', () => {
capturedFocusCb = undefined;
capturedBlurCb = undefined;
mockUnsubscribe = jest.fn();
const mockAddListener = jest.fn((event: string, cb: Function) => {
const mockAddListener = jest.fn((event: string, cb: () => void) => {
if (event === 'focus') capturedFocusCb = cb;
if (event === 'blur') capturedBlurCb = cb;
return mockUnsubscribe;
});
(useNavigation as jest.Mock).mockReturnValue({ navigate: jest.fn(), addListener: mockAddListener });

capturedAudioFocusedCb = undefined;
(emitter.on as jest.Mock).mockImplementation((event: string, cb: Function) => {
(emitter.on as jest.Mock).mockImplementation((event: string, cb: (audioFocused: string) => void) => {
if (event === 'audioFocused') capturedAudioFocusedCb = cb;
});
});
Expand Down Expand Up @@ -273,7 +273,7 @@ describe('AudioPlayer', () => {
await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb({ isLoaded: true, isPlaying: true }));
act(() => statusCb({ isLoaded: true, playing: true }));

fireEvent.press(getByTestId('play-button'));

Expand All @@ -299,7 +299,7 @@ describe('AudioPlayer', () => {
await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb({ isLoaded: true, isPlaying: true }));
act(() => statusCb({ isLoaded: true, playing: true }));

await waitFor(() => expect(getByTestId('play-button').props.accessibilityLabel).toBe('Pause'));
});
Expand All @@ -310,10 +310,10 @@ describe('AudioPlayer', () => {
await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb({ isLoaded: true, isPlaying: true }));
act(() => statusCb({ isLoaded: true, playing: true }));
await waitFor(() => expect(getByTestId('play-button').props.accessibilityLabel).toBe('Pause'));

act(() => statusCb({ isLoaded: true, isPlaying: false }));
act(() => statusCb({ isLoaded: true, playing: false }));
await waitFor(() => expect(getByTestId('play-button').props.accessibilityLabel).toBe('Play'));
});

Expand All @@ -324,13 +324,13 @@ describe('AudioPlayer', () => {
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;
const currentTimeValue = (useSharedValue as jest.Mock).mock.results[1].value as { value: number };

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 30000, positionMillis: 1000 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 30, currentTime: 1 }));
expect(currentTimeValue.value).toBe(1);

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 30000, positionMillis: 2000 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 30, currentTime: 2 }));
expect(currentTimeValue.value).toBe(2);

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 30000, positionMillis: 3000 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 30, currentTime: 3 }));
expect(currentTimeValue.value).toBe(3);
});
});
Expand All @@ -356,7 +356,7 @@ describe('AudioPlayer', () => {
await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb({ isLoaded: true, isPlaying: true }));
act(() => statusCb({ isLoaded: true, playing: true }));

await waitFor(() => expect(queryByTestId('playback-speed')).not.toBeNull());
});
Expand All @@ -383,7 +383,7 @@ describe('AudioPlayer', () => {
await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb({ isLoaded: true, isPlaying: true }));
act(() => statusCb({ isLoaded: true, playing: true }));

await waitFor(() => expect(activateKeepAwake).toHaveBeenCalled());
});
Expand Down Expand Up @@ -466,24 +466,24 @@ describe('AudioPlayer', () => {
});

describe('onPlaybackStatusUpdate callback chain', () => {
it('sets paused to false (audioState: playing) when status has isPlaying: true', async () => {
it('sets paused to false (audioState: playing) when status has playing: true', async () => {
const { queryByTestId } = render(<AudioPlayer {...defaultProps} />);

await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb({ isLoaded: true, isPlaying: true }));
act(() => statusCb({ isLoaded: true, playing: true }));

await waitFor(() => expect(queryByTestId('playback-speed')).not.toBeNull());
});

it('keeps paused true when status has isPlaying: false', async () => {
it('keeps paused true when status has playing: false', async () => {
const { queryByTestId } = render(<AudioPlayer {...defaultProps} />);

await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb({ isLoaded: true, isPlaying: false }));
act(() => statusCb({ isLoaded: true, playing: false }));

await act(async () => {});

Expand All @@ -500,36 +500,36 @@ describe('AudioPlayer', () => {
const durationValue = sharedValueMock.mock.results[0].value as { value: number };
const currentTimeValue = sharedValueMock.mock.results[1].value as { value: number };

act(() => statusCb({ isLoaded: true, durationMillis: 10000, positionMillis: 3000, isPlaying: false }));
act(() => statusCb({ isLoaded: true, duration: 10, currentTime: 3, playing: false }));

expect(durationValue.value).toBe(10);
expect(currentTimeValue.value).toBe(3);
});

it('does not update currentTime.value when positionMillis exceeds durationMillis', async () => {
it('does not update currentTime.value when currentTime exceeds duration', async () => {
render(<AudioPlayer {...defaultProps} />);

await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

const currentTimeValue = (useSharedValue as jest.Mock).mock.results[1].value as { value: number };

act(() => statusCb({ isLoaded: true, durationMillis: 5000, positionMillis: 2000, isPlaying: false }));
act(() => statusCb({ isLoaded: true, duration: 5, currentTime: 2, playing: false }));
expect(currentTimeValue.value).toBe(2);

act(() => statusCb({ isLoaded: true, durationMillis: 5000, positionMillis: 9000, isPlaying: false }));
act(() => statusCb({ isLoaded: true, duration: 5, currentTime: 9, playing: false }));
expect(currentTimeValue.value).toBe(2);
});

it('does not update shared values when durationMillis is absent', async () => {
it('does not update shared values when duration is absent', async () => {
render(<AudioPlayer {...defaultProps} />);

await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

const durationValue = (useSharedValue as jest.Mock).mock.results[0].value as { value: number };

act(() => statusCb({ isLoaded: true, isPlaying: false }));
act(() => statusCb({ isLoaded: true, playing: false }));

expect(durationValue.value).toBe(0);
});
Expand All @@ -542,9 +542,9 @@ describe('AudioPlayer', () => {

const currentTimeValue = (useSharedValue as jest.Mock).mock.results[1].value as { value: number };

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 5000, positionMillis: 4000 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 5, currentTime: 4 }));

act(() => statusCb({ isLoaded: true, isPlaying: false, didJustFinish: true }));
act(() => statusCb({ isLoaded: true, playing: false, didJustFinish: true, currentTime: 5, duration: 5 }));

await waitFor(() => {
expect(queryByTestId('playback-speed')).toBeNull();
Expand All @@ -560,16 +560,16 @@ describe('AudioPlayer', () => {

const currentTimeValue = (useSharedValue as jest.Mock).mock.results[1].value as { value: number };

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 10000, positionMillis: 0 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 10, currentTime: 0 }));
expect(currentTimeValue.value).toBe(0);

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 10000, positionMillis: 2500 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 10, currentTime: 2.5 }));
expect(currentTimeValue.value).toBe(2.5);

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 10000, positionMillis: 5000 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 10, currentTime: 5 }));
expect(currentTimeValue.value).toBe(5);

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 10000, positionMillis: 7500 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 10, currentTime: 7.5 }));
expect(currentTimeValue.value).toBe(7.5);
});

Expand All @@ -580,7 +580,7 @@ describe('AudioPlayer', () => {
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;
const durationValue = (useSharedValue as jest.Mock).mock.results[0].value as { value: number };

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 10000, positionMillis: 0 }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 10, currentTime: 0 }));

expect(durationValue.value).toBe(10);
});
Expand All @@ -592,7 +592,7 @@ describe('AudioPlayer', () => {
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;
const currentTimeValue = (useSharedValue as jest.Mock).mock.results[1].value as { value: number };

act(() => statusCb({ isLoaded: true, isPlaying: false, durationMillis: 10000, positionMillis: 3500 }));
act(() => statusCb({ isLoaded: true, playing: false, duration: 10, currentTime: 3.5 }));

expect(currentTimeValue.value).toBe(3.5);
});
Expand All @@ -604,19 +604,19 @@ describe('AudioPlayer', () => {
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;
const currentTimeValue = (useSharedValue as jest.Mock).mock.results[1].value as { value: number };

act(() => statusCb({ isLoaded: true, isPlaying: true, durationMillis: 10000, positionMillis: 7777 }));
act(() => statusCb({ isLoaded: true, isPlaying: false, didJustFinish: true }));
act(() => statusCb({ isLoaded: true, playing: true, duration: 10, currentTime: 7.777 }));
act(() => statusCb({ isLoaded: true, playing: false, didJustFinish: true, currentTime: 10, duration: 10 }));

expect(currentTimeValue.value).toBe(0);
});

it('does not crash when status is null', async () => {
it('does not crash or update state when status is not loaded', async () => {
render(<AudioPlayer {...defaultProps} />);

await waitFor(() => expect(AudioManager.setOnPlaybackStatusUpdate).toHaveBeenCalled());
const statusCb = (AudioManager.setOnPlaybackStatusUpdate as jest.Mock).mock.calls[0][1] as Function;

act(() => statusCb(null));
act(() => statusCb({ isLoaded: false }));

await act(async () => {});
});
Expand All @@ -634,7 +634,7 @@ describe('AudioPlayer', () => {
await waitFor(() => expect(AudioManager.playAudio).toHaveBeenCalledWith('mock-audio-key'));

act(() => {
statusCb({ isLoaded: true, isPlaying: true, positionMillis: 5000, durationMillis: 30000 });
statusCb({ isLoaded: true, playing: true, currentTime: 5, duration: 30 });
});

expect(currentTimeValue.value).toBe(5);
Expand Down
28 changes: 14 additions & 14 deletions app/containers/AudioPlayer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useEffect, useRef, useState } from 'react';
import { InteractionManager, View } from 'react-native';
import { type AVPlaybackStatus } from 'expo-av';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import { useSharedValue } from 'react-native-reanimated';
import { useNavigation } from '@react-navigation/native';
import type { AudioStatus } from 'expo-audio';

import { useTheme } from '../../theme';
import styles from './styles';
Expand Down Expand Up @@ -47,45 +47,45 @@
const audioUri = useRef<string>('');
const navigation = useNavigation();

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

const onPlaying = (data: AVPlaybackStatus) => {
if (data.isLoaded && data.isPlaying) {
const onPlaying = (data: AudioStatus): void => {
if (data.isLoaded && data.playing) {
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 handlePlaybackStatusUpdate = (data: AudioStatus): void => {
if (!data.isLoaded) return;
const durationSeconds = data.duration || 0;
duration.value = durationSeconds > 0 ? durationSeconds : 0;
const currentSecond = data.currentTime || 0;
if (currentSecond <= durationSeconds) {
currentTime.value = currentSecond;
}
};

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

const setPosition = async (time: number) => {
const setPosition = async (time: number): Promise<void> => {
await AudioManager.setPositionAsync(audioUri.current, time);
};

Expand Down Expand Up @@ -128,7 +128,7 @@
});
return () => task.cancel();
}
}, [fileUri, isDownloaded]);

Check warning on line 131 in app/containers/AudioPlayer/index.tsx

View workflow job for this annotation

GitHub Actions / format

React Hook useEffect has missing dependencies: 'msgId', 'onPlaybackStatusUpdate', 'playbackSpeed', and 'rid'. Either include them or remove the dependency array

Check warning on line 131 in app/containers/AudioPlayer/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint and Test / run-eslint-and-test

React Hook useEffect has missing dependencies: 'msgId', 'onPlaybackStatusUpdate', 'playbackSpeed', and 'rid'. Either include them or remove the dependency array

useEffect(() => {
if (paused) {
Expand All @@ -151,7 +151,7 @@
unsubscribeFocus();
unsubscribeBlur();
};
}, [navigation]);

Check warning on line 154 in app/containers/AudioPlayer/index.tsx

View workflow job for this annotation

GitHub Actions / format

React Hook useEffect has a missing dependency: 'onPlaybackStatusUpdate'. Either include it or remove the dependency array

Check warning on line 154 in app/containers/AudioPlayer/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint and Test / run-eslint-and-test

React Hook useEffect has a missing dependency: 'onPlaybackStatusUpdate'. Either include it or remove the dependency array

useEffect(() => {
const audioFocusedEventHandler = (audioFocused: string) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Audio } from 'expo-av';
import { requestRecordingPermissionsAsync, getRecordingPermissionsAsync, PermissionStatus } from 'expo-audio';
import { useContext, type ReactElement } from 'react';
import { Alert } from 'react-native';
import { PermissionStatus } from 'expo-camera';

import i18n from '../../../../i18n';
import { useAppSelector } from '../../../../lib/hooks/useAppSelector';
Expand All @@ -25,12 +24,12 @@ export const MicOrSendButton = (): ReactElement | null => {
const { setRecordingAudio } = useMessageComposerApi();

const requestPermissionAndStartToRecordAudio = () =>
Audio.requestPermissionsAsync()
requestRecordingPermissionsAsync()
Comment thread
Rohit3523 marked this conversation as resolved.
Resolved
.then(({ granted }) => setRecordingAudio(granted))
.catch(() => {});

const startRecording = async () => {
const { status, granted, canAskAgain } = await Audio.getPermissionsAsync();
const { status, granted, canAskAgain } = await getRecordingPermissionsAsync();
if (granted) return setRecordingAudio(true);
if (status === PermissionStatus.UNDETERMINED) return requestPermissionAndStartToRecordAudio();
if (canAskAgain) return requestPermissionAndStartToRecordAudio();
Expand Down
Loading
Loading