From 6e23aae66e1bf06e8c634d069eed062974d5a1e3 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Wed, 11 Feb 2026 10:30:14 +1100 Subject: [PATCH 1/4] Making sure we display the duration of an audio message right away --- .../conversation/v2/messages/VoiceMessageView.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VoiceMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VoiceMessageView.kt index 7a28c5c5aa..e6df19be5f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VoiceMessageView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VoiceMessageView.kt @@ -143,7 +143,12 @@ class VoiceMessageView @JvmOverloads constructor( binding.voiceMessageSpeedButton.setTextColor(textColor) } - // text + // duration + this.durationMs = playable?.durationMs?.coerceAtLeast(0) ?: 0L + binding.voiceMessageViewDurationTextView.text = + MediaUtil.getFormattedVoiceMessageDuration(this.durationMs) + + // title binding.audioTitle.text = if(playable?.isVoiceNote == true) context.getString(R.string.messageVoice) else playable?.filename ?: context.getString(R.string.unknown) @@ -194,7 +199,7 @@ class VoiceMessageView @JvmOverloads constructor( is AudioPlaybackState.Idle -> { isPlaying = false binding.voiceMessageViewLoader.isVisible = false - updateSeekBar(0, 0) // Reset + updateSeekBar(0, this.durationMs) // Reset renderIcon() } is AudioPlaybackState.Active.Loading -> { From 33680a4cc2597e4809bd518cae7a8ad0037e99a9 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Wed, 11 Feb 2026 11:31:54 +1100 Subject: [PATCH 2/4] SES-4108 - addressing outgoing audio duration in details activity --- .../securesms/conversation/v2/MessageDetailsViewModel.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt index 31ec45ffbf..641f7dda27 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt @@ -235,7 +235,10 @@ class MessageDetailsViewModel @AssistedInject constructor( private fun AttachmentDatabase.duration(slide: Slide): String? = slide.takeIf { it.hasAudio() } ?.run { asAttachment() as? DatabaseAttachment } - ?.run { getAttachmentAudioExtras(attachmentId)?.durationMs } + ?.run { + getAttachmentAudioExtras(attachmentId)?.durationMs + ?: this.audioDurationMs + } ?.takeIf { it > 0 } ?.let { String.format( From f20f0efc5ba395b3641ddf7c9b89ebd19b79c553 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Wed, 11 Feb 2026 12:54:16 +1100 Subject: [PATCH 3/4] Idle state needs to remember the chosen playback speed --- .../securesms/audio/AudioPlaybackManager.kt | 10 +++++++--- .../securesms/audio/model/AudioPlaybackState.kt | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioPlaybackManager.kt b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioPlaybackManager.kt index 2824047648..a9df490ef5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioPlaybackManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioPlaybackManager.kt @@ -54,7 +54,7 @@ class AudioPlaybackManager @Inject constructor( private val TAG = "AudioPlaybackManager" private val _playbackState = - MutableStateFlow(AudioPlaybackState.Idle) + MutableStateFlow(AudioPlaybackState.Idle(1f)) val playbackState: StateFlow = _playbackState.asStateFlow() // Keeping certain aspect different from the state, like audio ending, which is more an event @@ -156,8 +156,10 @@ class AudioPlaybackManager @Inject constructor( stopProgressTracking() controller?.stop() controller?.clearMediaItems() + + val speed = currentPlayable?.let { getSavedState(it.messageId).playbackSpeed } ?: 1f currentPlayable = null - _playbackState.value = AudioPlaybackState.Idle + _playbackState.value = AudioPlaybackState.Idle(speed) } fun seekTo(positionMs: Long) { @@ -385,7 +387,9 @@ class AudioPlaybackManager @Inject constructor( false ) } else { - AudioPlaybackState.Idle + AudioPlaybackState.Idle( + saved.playbackSpeed + ) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/model/AudioPlaybackState.kt b/app/src/main/java/org/thoughtcrime/securesms/audio/model/AudioPlaybackState.kt index 62b20ef33b..a6ecdf07ed 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/model/AudioPlaybackState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/model/AudioPlaybackState.kt @@ -16,7 +16,7 @@ sealed class AudioPlaybackState( } } - data object Idle : AudioPlaybackState(1f) + data class Idle(override val playbackSpeed: Float = 1f) : AudioPlaybackState(playbackSpeed) sealed class Active( open val playable: PlayableAudio, From f066b4c15ffa90a9cd139a1f7fac12b0c3b1d8b5 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Wed, 11 Feb 2026 13:04:44 +1100 Subject: [PATCH 4/4] SES-5213 - MEssage details: File ID should not be the filename but the ID of the file on the server --- .../securesms/conversation/v2/MessageDetailsViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt index 641f7dda27..e91bf69d2a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailsViewModel.kt @@ -222,7 +222,7 @@ class MessageDetailsViewModel @AssistedInject constructor( private val Slide.details: List get() = listOfNotNull( - TitledText(R.string.attachmentsFileId, filename), + TitledText(R.string.attachmentsFileId, asAttachment().location), //File ID isn't the filename but the ID on the file server TitledText(R.string.attachmentsFileType, asAttachment().contentType), TitledText(R.string.attachmentsFileSize, Formatter.formatFileSize(context, fileSize)), takeIf { it is ImageSlide }