Merge pull request #5527 from element-hq/renovate/org.matrix.rustcomponents-sdk-android-25.x

fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v25.10.13
This commit is contained in:
Benoit Marty 2025-10-13 18:04:52 +02:00 committed by GitHub
commit 67cd95872f
29 changed files with 110 additions and 130 deletions

View file

@ -8,15 +8,14 @@
package io.element.android.features.messages.api.timeline.voicemessages.composer package io.element.android.features.messages.api.timeline.voicemessages.composer
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.components.media.createFakeWaveform import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.textcomposer.model.VoiceMessageState import io.element.android.libraries.textcomposer.model.VoiceMessageState
import kotlinx.collections.immutable.toImmutableList
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
open class VoiceMessageComposerStateProvider : PreviewParameterProvider<VoiceMessageComposerState> { open class VoiceMessageComposerStateProvider : PreviewParameterProvider<VoiceMessageComposerState> {
override val values: Sequence<VoiceMessageComposerState> override val values: Sequence<VoiceMessageComposerState>
get() = sequenceOf( get() = sequenceOf(
aVoiceMessageComposerState(voiceMessageState = VoiceMessageState.Recording(duration = 61.seconds, levels = aWaveformLevels)), aVoiceMessageComposerState(voiceMessageState = VoiceMessageState.Recording(duration = 61.seconds, levels = WaveFormSamples.allRangeWaveForm)),
) )
} }
@ -39,7 +38,5 @@ fun aVoiceMessagePreviewState() = VoiceMessageState.Preview(
showCursor = false, showCursor = false,
playbackProgress = 0f, playbackProgress = 0f,
time = 10.seconds, time = 10.seconds,
waveform = createFakeWaveform(), waveform = WaveFormSamples.realisticWaveForm,
) )
internal var aWaveformLevels = List(100) { it.toFloat() / 100 }.toImmutableList()

View file

@ -167,7 +167,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version
# https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt
# All new features should not be implemented in the pull request that upgrades the version, developers should # All new features should not be implemented in the pull request that upgrades the version, developers should
# only fix API breaks and may add some TODOs. # only fix API breaks and may add some TODOs.
matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.10.7" matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.10.13"
# Others # Others
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }

View file

@ -1,25 +0,0 @@
/*
* Copyright 2023, 2024 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 kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlin.random.Random
/**
* Generate a waveform for testing purposes.
*
* The waveform is a list of floats between 0 and 1.
*
* @param length The length of the waveform.
*/
fun createFakeWaveform(length: Int = 1000): ImmutableList<Float> {
val random = Random(seed = 2)
return List(length) { random.nextFloat() }
.toImmutableList()
}

View file

@ -0,0 +1,29 @@
/*
* 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 kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
object WaveFormSamples {
val allRangeWaveForm = List(100) { it.toFloat() / 100 }.toImmutableList()
val realisticWaveForm = persistentListOf(
0.000f, 0.000f, 0.000f, 0.003f, 0.354f,
0.353f, 0.365f, 0.790f, 0.787f, 0.167f,
0.333f, 0.975f, 0.000f, 0.102f, 0.003f,
0.531f, 0.584f, 0.317f, 0.140f, 0.475f,
0.496f, 0.561f, 0.042f, 0.263f, 0.169f,
0.829f, 0.349f, 0.010f, 0.000f, 0.000f,
1.000f, 0.334f, 0.321f, 0.011f, 0.000f,
0.000f, 0.003f,
)
val longRealisticWaveForm = List(4) { realisticWaveForm }.flatten().toPersistentList()
}

View file

@ -49,7 +49,7 @@ private const val DEFAULT_GRAPHICS_LAYER_ALPHA: Float = 0.99F
* *
* @param playbackProgress The current playback progress, between 0 and 1. * @param playbackProgress The current playback progress, between 0 and 1.
* @param showCursor Whether to show the cursor or not. * @param showCursor Whether to show the cursor or not.
* @param waveform The waveform to display. Use [createFakeWaveform] to generate a fake waveform. * @param waveform The waveform to display.
* @param onSeek Callback when the user seeks the waveform. Called with a value between 0 and 1. * @param onSeek Callback when the user seeks the waveform. Called with a value between 0 and 1.
* @param modifier The modifier to be applied to the view. * @param modifier The modifier to be applied to the view.
* @param seekEnabled Whether the user can seek the waveform or not. * @param seekEnabled Whether the user can seek the waveform or not.
@ -187,14 +187,14 @@ internal fun WaveformPlaybackViewPreview() = ElementPreview {
showCursor = false, showCursor = false,
playbackProgress = 0.5f, playbackProgress = 0.5f,
onSeek = {}, onSeek = {},
waveform = aWaveForm().toImmutableList(), waveform = WaveFormSamples.realisticWaveForm,
) )
WaveformPlaybackView( WaveformPlaybackView(
modifier = Modifier.height(34.dp), modifier = Modifier.height(34.dp),
showCursor = true, showCursor = true,
playbackProgress = 0.5f, playbackProgress = 0.5f,
onSeek = {}, onSeek = {},
waveform = List(1024) { it / 1024f }.toImmutableList(), waveform = WaveFormSamples.allRangeWaveForm,
) )
} }
} }
@ -217,45 +217,3 @@ private fun ImmutableList<Float>.normalisedData(maxSamplesCount: Int): Immutable
return result.toImmutableList() return result.toImmutableList()
} }
fun aWaveForm(): List<Float> {
return listOf(
0.000f,
0.000f,
0.000f,
0.003f,
0.354f,
0.353f,
0.365f,
0.790f,
0.787f,
0.167f,
0.333f,
0.975f,
0.000f,
0.102f,
0.003f,
0.531f,
0.584f,
0.317f,
0.140f,
0.475f,
0.496f,
0.561f,
0.042f,
0.263f,
0.169f,
0.829f,
0.349f,
0.010f,
0.000f,
0.000f,
1.000f,
0.334f,
0.321f,
0.011f,
0.000f,
0.000f,
0.003f,
)
}

View file

@ -12,6 +12,7 @@ sealed interface QrCodeLoginStep {
data class EstablishingSecureChannel(val checkCode: String) : QrCodeLoginStep data class EstablishingSecureChannel(val checkCode: String) : QrCodeLoginStep
data object Starting : QrCodeLoginStep data object Starting : QrCodeLoginStep
data class WaitingForToken(val userCode: String) : QrCodeLoginStep data class WaitingForToken(val userCode: String) : QrCodeLoginStep
data object SyncingSecrets : QrCodeLoginStep
data class Failed(val error: QrLoginException) : QrCodeLoginStep data class Failed(val error: QrLoginException) : QrCodeLoginStep
data object Finished : QrCodeLoginStep data object Finished : QrCodeLoginStep
} }

View file

@ -15,6 +15,7 @@ fun QrLoginProgress.toStep(): QrCodeLoginStep {
is QrLoginProgress.EstablishingSecureChannel -> QrCodeLoginStep.EstablishingSecureChannel(checkCodeString) is QrLoginProgress.EstablishingSecureChannel -> QrCodeLoginStep.EstablishingSecureChannel(checkCodeString)
is QrLoginProgress.Starting -> QrCodeLoginStep.Starting is QrLoginProgress.Starting -> QrCodeLoginStep.Starting
is QrLoginProgress.WaitingForToken -> QrCodeLoginStep.WaitingForToken(userCode) is QrLoginProgress.WaitingForToken -> QrCodeLoginStep.WaitingForToken(userCode)
is QrLoginProgress.SyncingSecrets -> QrCodeLoginStep.SyncingSecrets
is QrLoginProgress.Done -> QrCodeLoginStep.Finished is QrLoginProgress.Done -> QrCodeLoginStep.Finished
} }
} }

View file

@ -29,7 +29,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransa
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl
import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.media.map
import io.element.android.libraries.matrix.impl.media.toMSC3246range
import io.element.android.libraries.matrix.impl.poll.toInner import io.element.android.libraries.matrix.impl.poll.toInner
import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.RoomContentForwarder
import io.element.android.libraries.matrix.impl.room.location.toInner import io.element.android.libraries.matrix.impl.room.location.toInner
@ -484,7 +483,7 @@ class RustTimeline(
inReplyTo = inReplyToEventId?.value, inReplyTo = inReplyToEventId?.value,
), ),
audioInfo = audioInfo.map(), audioInfo = audioInfo.map(),
waveform = waveform.toMSC3246range(), waveform = waveform,
) )
} }
} }

View file

@ -9,7 +9,7 @@ package io.element.android.libraries.mediaviewer.impl.gallery
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.components.media.aWaveForm import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState
import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState
@ -71,7 +71,7 @@ open class MediaGalleryStateProvider : PreviewParameterProvider<MediaGalleryStat
aMediaItemAudio(id = UniqueId("4")), aMediaItemAudio(id = UniqueId("4")),
aMediaItemVoice( aMediaItemVoice(
id = UniqueId("5"), id = UniqueId("5"),
waveform = aWaveForm(), waveform = WaveFormSamples.realisticWaveForm,
), ),
aMediaItemLoadingIndicator(), aMediaItemLoadingIndicator(),
).toImmutableList() ).toImmutableList()

View file

@ -8,7 +8,7 @@
package io.element.android.libraries.mediaviewer.impl.local.audio package io.element.android.libraries.mediaviewer.impl.local.audio
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.components.media.aWaveForm import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.MediaInfo
import io.element.android.libraries.mediaviewer.api.anAudioMediaInfo import io.element.android.libraries.mediaviewer.api.anAudioMediaInfo
@ -17,7 +17,7 @@ open class MediaInfoAudioProvider : PreviewParameterProvider<MediaInfo> {
get() = sequenceOf( get() = sequenceOf(
anAudioMediaInfo(), anAudioMediaInfo(),
anAudioMediaInfo( anAudioMediaInfo(
waveForm = aWaveForm(), waveForm = WaveFormSamples.realisticWaveForm,
), ),
) )
} }

View file

@ -7,7 +7,7 @@
package io.element.android.libraries.mediaviewer.impl.model package io.element.android.libraries.mediaviewer.impl.model
import io.element.android.libraries.designsystem.components.media.aWaveForm import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
@ -91,7 +91,7 @@ fun aMediaItemVoice(
filename: String = "filename.ogg", filename: String = "filename.ogg",
caption: String? = null, caption: String? = null,
duration: String? = "1:23", duration: String? = "1:23",
waveform: List<Float> = aWaveForm(), waveform: List<Float> = WaveFormSamples.realisticWaveForm,
): MediaItem.Voice { ): MediaItem.Voice {
return MediaItem.Voice( return MediaItem.Voice(
id = id, id = id,

View file

@ -11,7 +11,7 @@ import android.net.Uri
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.components.media.aWaveForm import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.Timeline
@ -138,7 +138,7 @@ open class MediaViewerStateProvider : PreviewParameterProvider<MediaViewerState>
mediaBottomSheetState = aMediaDeleteConfirmationState(), mediaBottomSheetState = aMediaDeleteConfirmationState(),
), ),
anAudioMediaInfo( anAudioMediaInfo(
waveForm = aWaveForm(), waveForm = WaveFormSamples.realisticWaveForm,
).let { ).let {
aMediaViewerState( aMediaViewerState(
listOf( listOf(

View file

@ -10,7 +10,7 @@ package io.element.android.libraries.mediaviewer.impl.viewer
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.components.media.createFakeWaveform import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID
@ -128,7 +128,7 @@ class SingleMediaGalleryDataSourceTest {
fun `createFrom should create a SingleMediaGalleryDataSource with a voice item`() { fun `createFrom should create a SingleMediaGalleryDataSource with a voice item`() {
testFactory( testFactory(
mediaInfo = aVoiceMediaInfo( mediaInfo = aVoiceMediaInfo(
waveForm = createFakeWaveform(), waveForm = WaveFormSamples.longRealisticWaveForm,
duration = "12:34", duration = "12:34",
), ),
expectedResult = { params -> expectedResult = { params ->

View file

@ -52,7 +52,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.androidutils.ui.showKeyboard import io.element.android.libraries.androidutils.ui.showKeyboard
import io.element.android.libraries.designsystem.components.media.createFakeWaveform import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.designsystem.preview.DAY_MODE_NAME import io.element.android.libraries.designsystem.preview.DAY_MODE_NAME
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.NIGHT_MODE_NAME import io.element.android.libraries.designsystem.preview.NIGHT_MODE_NAME
@ -808,30 +808,33 @@ internal fun TextComposerCaptionPreview() = ElementPreview {
internal fun TextComposerVoicePreview() = ElementPreview { internal fun TextComposerVoicePreview() = ElementPreview {
PreviewColumn( PreviewColumn(
items = persistentListOf( items = persistentListOf(
VoiceMessageState.Recording(61.seconds, createFakeWaveform()), VoiceMessageState.Recording(
duration = 61.seconds,
levels = WaveFormSamples.realisticWaveForm,
),
VoiceMessageState.Preview( VoiceMessageState.Preview(
isSending = false, isSending = false,
isPlaying = false, isPlaying = false,
showCursor = false, showCursor = false,
waveform = createFakeWaveform(), waveform = WaveFormSamples.realisticWaveForm,
time = 0.seconds, time = 0.seconds,
playbackProgress = 0.0f playbackProgress = 0.0f,
), ),
VoiceMessageState.Preview( VoiceMessageState.Preview(
isSending = false, isSending = false,
isPlaying = true, isPlaying = true,
showCursor = true, showCursor = true,
waveform = createFakeWaveform(), waveform = WaveFormSamples.realisticWaveForm,
time = 3.seconds, time = 3.seconds,
playbackProgress = 0.2f playbackProgress = 0.2f,
), ),
VoiceMessageState.Preview( VoiceMessageState.Preview(
isSending = true, isSending = true,
isPlaying = false, isPlaying = false,
showCursor = false, showCursor = false,
waveform = createFakeWaveform(), waveform = WaveFormSamples.realisticWaveForm,
time = 61.seconds, time = 61.seconds,
playbackProgress = 0.0f playbackProgress = 0.0f,
), ),
) )
) { voiceMessageState -> ) { voiceMessageState ->
@ -848,12 +851,15 @@ internal fun TextComposerVoicePreview() = ElementPreview {
internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview { internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview {
PreviewColumn( PreviewColumn(
items = persistentListOf( items = persistentListOf(
VoiceMessageState.Recording(61.seconds, createFakeWaveform()), VoiceMessageState.Recording(
duration = 61.seconds,
levels = WaveFormSamples.realisticWaveForm,
),
VoiceMessageState.Preview( VoiceMessageState.Preview(
isSending = false, isSending = false,
isPlaying = false, isPlaying = false,
showCursor = false, showCursor = false,
waveform = createFakeWaveform(), waveform = WaveFormSamples.realisticWaveForm,
time = 0.seconds, time = 0.seconds,
playbackProgress = 0.0f playbackProgress = 0.0f
), ),
@ -861,7 +867,7 @@ internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview {
isSending = false, isSending = false,
isPlaying = true, isPlaying = true,
showCursor = true, showCursor = true,
waveform = createFakeWaveform(), waveform = WaveFormSamples.realisticWaveForm,
time = 3.seconds, time = 3.seconds,
playbackProgress = 0.2f playbackProgress = 0.2f
), ),
@ -869,7 +875,7 @@ internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview {
isSending = true, isSending = true,
isPlaying = false, isPlaying = false,
showCursor = false, showCursor = false,
waveform = createFakeWaveform(), waveform = WaveFormSamples.realisticWaveForm,
time = 61.seconds, time = 61.seconds,
playbackProgress = 0.0f playbackProgress = 0.0f
), ),

View file

@ -29,8 +29,8 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.designsystem.components.media.WaveformPlaybackView import io.element.android.libraries.designsystem.components.media.WaveformPlaybackView
import io.element.android.libraries.designsystem.components.media.createFakeWaveform
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
@ -138,14 +138,18 @@ private fun PlayerButton(
private fun PauseIcon() = Icon( private fun PauseIcon() = Icon(
imageVector = CompoundIcons.PauseSolid(), imageVector = CompoundIcons.PauseSolid(),
contentDescription = stringResource(id = CommonStrings.a11y_pause), contentDescription = stringResource(id = CommonStrings.a11y_pause),
modifier = Modifier.size(20.dp).padding(2.dp), modifier = Modifier
.size(20.dp)
.padding(2.dp),
) )
@Composable @Composable
private fun PlayIcon() = Icon( private fun PlayIcon() = Icon(
imageVector = CompoundIcons.PlaySolid(), imageVector = CompoundIcons.PlaySolid(),
contentDescription = stringResource(id = CommonStrings.a11y_play), contentDescription = stringResource(id = CommonStrings.a11y_play),
modifier = Modifier.size(20.dp).padding(2.dp), modifier = Modifier
.size(20.dp)
.padding(2.dp),
) )
@PreviewsDayNight @PreviewsDayNight
@ -160,7 +164,7 @@ internal fun VoiceMessagePreviewPreview() = ElementPreview {
time = 2.seconds, time = 2.seconds,
playbackProgress = 0.2f, playbackProgress = 0.2f,
showCursor = true, showCursor = true,
waveform = createFakeWaveform() waveform = WaveFormSamples.longRealisticWaveForm,
) )
AVoiceMessagePreview( AVoiceMessagePreview(
isInteractive = true, isInteractive = true,
@ -168,7 +172,7 @@ internal fun VoiceMessagePreviewPreview() = ElementPreview {
time = 0.seconds, time = 0.seconds,
playbackProgress = 0.0f, playbackProgress = 0.0f,
showCursor = true, showCursor = true,
waveform = createFakeWaveform() waveform = WaveFormSamples.longRealisticWaveForm,
) )
AVoiceMessagePreview( AVoiceMessagePreview(
isInteractive = false, isInteractive = false,
@ -176,7 +180,7 @@ internal fun VoiceMessagePreviewPreview() = ElementPreview {
time = 789.seconds, time = 789.seconds,
playbackProgress = 0.0f, playbackProgress = 0.0f,
showCursor = false, showCursor = false,
waveform = createFakeWaveform() waveform = WaveFormSamples.longRealisticWaveForm,
) )
} }
} }

View file

@ -21,11 +21,13 @@ sealed interface VoiceMessageState {
val showCursor: Boolean, val showCursor: Boolean,
val playbackProgress: Float, val playbackProgress: Float,
val time: Duration, val time: Duration,
// Values are between 0 and 1
val waveform: ImmutableList<Float>, val waveform: ImmutableList<Float>,
) : VoiceMessageState ) : VoiceMessageState
data class Recording( data class Recording(
val duration: Duration, val duration: Duration,
// Values are between 0 and 1
val levels: ImmutableList<Float>, val levels: ImmutableList<Float>,
) : VoiceMessageState ) : VoiceMessageState
} }

View file

@ -22,16 +22,19 @@ sealed interface VoiceRecorderState {
* The recorder is currently recording. * The recorder is currently recording.
* *
* @property elapsedTime The elapsed time since the recording started. * @property elapsedTime The elapsed time since the recording started.
* @property levels The current audio levels of the recording as a fraction of 1. * @property levels The current audio levels of the recording as a fraction of 1. All values are between 0 and 1.
*/ */
data class Recording(val elapsedTime: Duration, val levels: List<Float>) : VoiceRecorderState data class Recording(
val elapsedTime: Duration,
val levels: List<Float>,
) : VoiceRecorderState
/** /**
* The recorder has finished recording. * The recorder has finished recording.
* *
* @property file The recorded file. * @property file The recorded file.
* @property mimeType The mime type of the file. * @property mimeType The mime type of the file.
* @property waveform The waveform of the recording. * @property waveform The waveform of the recording. All values are between 0 and 1.
* @property duration The total time spent recording. * @property duration The total time spent recording.
*/ */
data class Finished( data class Finished(

View file

@ -63,6 +63,8 @@ class DefaultVoiceRecorder(
private var outputFile: File? = null private var outputFile: File? = null
private var audioReader: AudioReader? = null private var audioReader: AudioReader? = null
private var recordingJob: Job? = null private var recordingJob: Job? = null
// List of Float between 0 and 1 representing the audio levels
private val levels: MutableList<Float> = mutableListOf() private val levels: MutableList<Float> = mutableListOf()
private val lock = Mutex() private val lock = Mutex()

View file

@ -7,6 +7,8 @@
package io.element.android.libraries.voicerecorder.impl.audio package io.element.android.libraries.voicerecorder.impl.audio
import androidx.annotation.FloatRange
interface AudioLevelCalculator { interface AudioLevelCalculator {
/** /**
* Calculate the audio level of the audio buffer. * Calculate the audio level of the audio buffer.
@ -14,5 +16,6 @@ interface AudioLevelCalculator {
* @param buffer The audio buffer containing 16bit PCM audio data. * @param buffer The audio buffer containing 16bit PCM audio data.
* @return A float value between 0 and 1 proportional to the audio level. * @return A float value between 0 and 1 proportional to the audio level.
*/ */
@FloatRange(from = 0.0, to = 1.0)
fun calculateAudioLevel(buffer: ShortArray): Float fun calculateAudioLevel(buffer: ShortArray): Float
} }

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4d80066ecad50390fbd0529d4e0f25462ac91d9e168817ecfdbf472129b95410 oid sha256:ac595ce33affb3eec6c465fd68ab1fa57eb942f58944cc16e5e01892a21ba4a7
size 50641 size 50323

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7d90b319d5b4fd3ec77fdfe15bed786e5acbc66b86da83f24efce313eb8d178b oid sha256:72023d9b9eaade788d33ef6c123a89edc079c4cc543421c256676b75fba6adc1
size 44750 size 44505

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f162675e687af3aa9c352cdf7ae177f4760d1ce008cd217641b6722a71d34d49 oid sha256:837bb03b66cccdfebb039b36da1096589da31e898de36975e413782349896ba0
size 10271 size 10167

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:30328b9c5a43508d135d086fcbafe5ad5cf9989e208f8f25b1450e61df08994e oid sha256:091bd502d78b80633e267670e2cfdde1696f22d26b9b729d8e33d6d33b8e6d58
size 9549 size 9469

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:3ed72cd85cc94390214b721b26229c8784174c54fb2a58eb1cc01431e6c57898 oid sha256:45422a841a79f4236a56a72773cfe8485e267f345abb03c2b376b3307e430fab
size 20699 size 18537

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ea8534fe10a038e86e9c9c572391f29c1241fc77a1ce93c549bf6350f48c01bb oid sha256:dedaa24fb05db78c0b9d4c2357c5c76ac181365c09f6e6b666387112f7962a4a
size 19500 size 17424

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2429482b11d6a507830a38c9bf483687d2d6b4c9e33ee2ad063d2fb6199e0f44 oid sha256:98dbb0ac81d2079ac41f107b78e6fb7ccbf1f53fcd9e95e8716fb05ca1b14ea3
size 37673 size 36091

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2fdc8ba783be4355b0a436473082151225811652c2b03cb11c19c26bca0e2ac7 oid sha256:c454bf724b6875610870eec156f0c544e84baf9c6e9a755b965f692f498a1b1e
size 35756 size 34222

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:9477cd51e70796a6e3d1eeaad1270db5c37ae40f0cfffea38f8d09f8f743b266 oid sha256:274f54991bbd79c4220d945964caf7fc523ce99a70b748ef992cc15ee030fdf5
size 26488 size 25124

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f891e663e2d8649629ef9fe5c4f79a71ad5304fdc1b450946ddd6975237eb329 oid sha256:258643d514aeb7a53788ba2addc53fe46f888193ced2970c73887f9eb1584753
size 25502 size 24039