Skip to content

Commit 6c2e98e

Browse files
authored
fix: audio recordings fixes and performance improvements (#3514)
## 🎯 Goal This PR fixes several SDK side audio bugs and interaction issues around voice recordings and audio attachments. The main change is a (long overdue) rewrite of our audio playing management so that it no longer relies on `react-native-video` for `stream-chat-react-native`. The main rationale' was the fact that it would appear the specific format we use was not seekable at all (and no way to force `react-native-video` to seek with `AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING_ALWAYS`, at least that I know of). In addition to that, using `react-native-nitro-sound` is much more stable and performant. Additionally, this PR also includes: - a complete rewrite of how our waveform component works (`WaveProgressBar`) - smoother waveform playback/drag behavior in `WaveProgressBar` - fixed drag crash caused by incorrect `worklet` usage - fixed seek release oscillation in audio attachments - improved drag hit area - fixed thumb tail overshoot - reduced idle waveform rendering cost - stabilized duration label width to avoid layout churn - fixed Android native speed change while paused starting playback - fixed Expo iOS seek by converting ms to seconds in the Expo audio adapter ## 🛠 Implementation details <!-- Provide a description of the implementation --> ## 🎨 UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## 🧪 Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## ☑️ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
1 parent efb686c commit 6c2e98e

File tree

11 files changed

+928
-185
lines changed

11 files changed

+928
-185
lines changed

examples/ExpoMessaging/plugins/keyboardInsetMainActivityListener.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const requiredImports = [
44
'import android.os.Build',
55
'import android.os.Bundle',
66
'import android.view.View',
7+
'import androidx.core.graphics.Insets',
78
'import androidx.core.view.ViewCompat',
89
'import androidx.core.view.WindowInsetsCompat',
910
'import androidx.core.view.updatePadding',
@@ -13,19 +14,22 @@ const customInsetHandler = `
1314
if (Build.VERSION.SDK_INT >= 35) {
1415
val rootView = findViewById<View>(android.R.id.content)
1516
17+
val initial = Insets.of(
18+
rootView.paddingLeft,
19+
rootView.paddingTop,
20+
rootView.paddingRight,
21+
rootView.paddingBottom
22+
)
23+
1624
ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, insets ->
17-
val bars = insets.getInsets(
18-
WindowInsetsCompat.Type.systemBars()
19-
or WindowInsetsCompat.Type.displayCutout()
20-
or WindowInsetsCompat.Type.ime()
21-
)
25+
val ime = insets.getInsets(WindowInsetsCompat.Type.ime())
2226
rootView.updatePadding(
23-
left = bars.left,
24-
top = bars.top,
25-
right = bars.right,
26-
bottom = bars.bottom
27+
left = initial.left,
28+
top = initial.top,
29+
right = initial.right,
30+
bottom = initial.bottom + ime.bottom
2731
)
28-
WindowInsetsCompat.CONSUMED
32+
insets
2933
}
3034
}
3135
`;

package/expo-package/src/optionalDependencies/Sound.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ class ExpoAudioSoundAdapter {
138138
};
139139

140140
// eslint-disable-next-line require-await
141-
setPositionAsync: SoundReturnType['setPositionAsync'] = async (seconds) => {
142-
this.player.seekTo(seconds);
141+
setPositionAsync: SoundReturnType['setPositionAsync'] = async (millis) => {
142+
await this.player.seekTo(millis / 1000);
143143
};
144144

145145
// eslint-disable-next-line require-await

package/native-package/src/optionalDependencies/Audio.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class _Audio {
136136
};
137137
startPlayer = async (uri, _, onPlaybackStatusUpdate) => {
138138
try {
139-
const playback = await audioRecorderPlayer.startPlayer(uri);
139+
await audioRecorderPlayer.startPlayer(uri);
140140
audioRecorderPlayer.addPlayBackListener((status) => {
141141
onPlaybackStatusUpdate(status);
142142
});

0 commit comments

Comments
 (0)