mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 16:10:00 +00:00
Let a voice message without a waveform be seeked
A voice message that arrives without amplitude data — bridged messages and those sent by clients that omit it — is unusable. The waveform is empty, so its measured width is zero: the progress overlay never draws, the cursor is pinned to the left edge, and the touch handler rejects every event because no x coordinate can fall inside a zero-width range. The message plays, but there is no way to see where it is or to move it. Fall back to a flat run of zero amplitudes sized to the canvas when there is no waveform. Width, progress, cursor and seeking then all work exactly as they do for a real waveform, and the existing minimum amplitude renders those zeros as the same flat track a genuinely silent recording already draws, so no new drawing code is needed. Nothing changes for a message that has a waveform, and the model still carries the empty list, which is the honest value. Computing a real waveform from the audio is a separate piece of work.
This commit is contained in:
+5
-1
@@ -200,11 +200,15 @@ internal fun WaveformPlaybackViewPreview() = ElementPreview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ImmutableList<Float>.normalisedData(maxSamplesCount: Int): ImmutableList<Float> {
|
internal fun ImmutableList<Float>.normalisedData(maxSamplesCount: Int): ImmutableList<Float> {
|
||||||
if (maxSamplesCount <= 0) {
|
if (maxSamplesCount <= 0) {
|
||||||
return persistentListOf()
|
return persistentListOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isEmpty()) {
|
||||||
|
return List(maxSamplesCount) { 0f }.toImmutableList()
|
||||||
|
}
|
||||||
|
|
||||||
// Filter the data to keep only the expected number of samples
|
// Filter the data to keep only the expected number of samples
|
||||||
val result = if (this.size > maxSamplesCount) {
|
val result = if (this.size > maxSamplesCount) {
|
||||||
(0..<maxSamplesCount)
|
(0..<maxSamplesCount)
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.designsystem.components.media
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class WaveformNormalisationTest {
|
||||||
|
@Test
|
||||||
|
fun `an empty waveform is padded to the requested number of samples`() {
|
||||||
|
val result = persistentListOf<Float>().normalisedData(30)
|
||||||
|
assertThat(result).hasSize(30)
|
||||||
|
assertThat(result.toSet()).containsExactly(0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `an empty waveform stays empty when there is no room to display it`() {
|
||||||
|
assertThat(persistentListOf<Float>().normalisedData(0)).isEmpty()
|
||||||
|
assertThat(persistentListOf<Float>().normalisedData(-1)).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `a waveform shorter than the display count is kept as it is`() {
|
||||||
|
val waveform = persistentListOf(0.1f, 0.2f, 0.3f)
|
||||||
|
assertThat(waveform.normalisedData(30)).containsExactly(0.1f, 0.2f, 0.3f).inOrder()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `a waveform longer than the display count is downsampled`() {
|
||||||
|
val waveform = persistentListOf(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f)
|
||||||
|
assertThat(waveform.normalisedData(3)).hasSize(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user