mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 06:30:43 +00:00
finish recording gracefully when audio focus is lost
if something else grabs focus mid-recording (phone call, etc), stop the recording and keep the partial result in preview state instead of silently recording garbage Signed-off-by: vmfunc <celeste@linux.com>
This commit is contained in:
+5
-1
@@ -249,7 +249,11 @@ class DefaultVoiceMessageComposerPresenter(
|
|||||||
|
|
||||||
private fun CoroutineScope.startRecording() = launch {
|
private fun CoroutineScope.startRecording() = launch {
|
||||||
try {
|
try {
|
||||||
audioFocus.requestAudioFocus(AudioFocusRequester.RecordVoiceMessage) {}
|
audioFocus.requestAudioFocus(AudioFocusRequester.RecordVoiceMessage) {
|
||||||
|
// something else grabbed focus (phone call, etc) - finish gracefully
|
||||||
|
// so the user keeps their partial recording
|
||||||
|
sessionCoroutineScope.finishRecording()
|
||||||
|
}
|
||||||
voiceRecorder.startRecord()
|
voiceRecorder.startRecord()
|
||||||
} catch (e: SecurityException) {
|
} catch (e: SecurityException) {
|
||||||
audioFocus.releaseAudioFocus()
|
audioFocus.releaseAudioFocus()
|
||||||
|
|||||||
+25
@@ -199,6 +199,30 @@ class DefaultVoiceMessageComposerPresenterTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - audio focus loss during recording finishes gracefully`() = runTest {
|
||||||
|
var onFocusLost: (() -> Unit)? = null
|
||||||
|
val testAudioFocus = FakeAudioFocus(
|
||||||
|
requestAudioFocusResult = { _, callback -> onFocusLost = callback },
|
||||||
|
releaseAudioFocusResult = { },
|
||||||
|
)
|
||||||
|
val presenter = createDefaultVoiceMessageComposerPresenter(audioFocus = testAudioFocus)
|
||||||
|
presenter.test {
|
||||||
|
awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Start))
|
||||||
|
awaitItem()
|
||||||
|
|
||||||
|
// simulate focus loss (phone call, etc)
|
||||||
|
onFocusLost?.invoke()
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
val finalState = awaitItem()
|
||||||
|
assertThat(finalState.voiceMessageState).isEqualTo(aPreviewState())
|
||||||
|
voiceRecorder.assertCalls(started = 1, stopped = 1)
|
||||||
|
|
||||||
|
cancelAndIgnoreRemainingEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - abort recording`() = runTest {
|
fun `present - abort recording`() = runTest {
|
||||||
val presenter = createDefaultVoiceMessageComposerPresenter()
|
val presenter = createDefaultVoiceMessageComposerPresenter()
|
||||||
@@ -687,6 +711,7 @@ class DefaultVoiceMessageComposerPresenterTest {
|
|||||||
private fun TestScope.createDefaultVoiceMessageComposerPresenter(
|
private fun TestScope.createDefaultVoiceMessageComposerPresenter(
|
||||||
permissionsPresenter: PermissionsPresenter = createFakePermissionsPresenter(),
|
permissionsPresenter: PermissionsPresenter = createFakePermissionsPresenter(),
|
||||||
voiceRecorder: VoiceRecorder = this@DefaultVoiceMessageComposerPresenterTest.voiceRecorder,
|
voiceRecorder: VoiceRecorder = this@DefaultVoiceMessageComposerPresenterTest.voiceRecorder,
|
||||||
|
audioFocus: AudioFocus = this@DefaultVoiceMessageComposerPresenterTest.audioFocus,
|
||||||
): DefaultVoiceMessageComposerPresenter {
|
): DefaultVoiceMessageComposerPresenter {
|
||||||
return DefaultVoiceMessageComposerPresenter(
|
return DefaultVoiceMessageComposerPresenter(
|
||||||
sessionCoroutineScope = backgroundScope,
|
sessionCoroutineScope = backgroundScope,
|
||||||
|
|||||||
Reference in New Issue
Block a user