Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio files in the timeline now appear with the audio player #5586

Merged
merged 30 commits into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
00bced9
Changes unTrack to untrack
ericdecanini Mar 17, 2022
cde10ca
Fixes wrong spellings in Message file and voice items
ericdecanini Mar 17, 2022
2617632
Fixes epoxy errors with renamed epoxy attributes
ericdecanini Mar 18, 2022
d54b465
Uses messageVoiceItem for audio files
ericdecanini Mar 18, 2022
fab78c9
Refactors MessageAudioItem to work for both audio files and voice mes…
ericdecanini Mar 19, 2022
2e716cb
Adapts special body text for audio messages
ericdecanini Mar 19, 2022
7a7d36d
Renames functions and variables
ericdecanini Mar 21, 2022
ff26829
Adds new audio timeline stub
ericdecanini Mar 21, 2022
5a819bb
Merge remote-tracking branch 'origin/develop' into feature/eric/audio…
ericdecanini Mar 21, 2022
c9946b6
Code cleanup
ericdecanini Mar 21, 2022
06468a4
Adds changelog file
ericdecanini Mar 21, 2022
b035911
Fixes import lint error
ericdecanini Mar 21, 2022
249db18
Removes ic_headphones
ericdecanini Mar 22, 2022
82cde16
Merge remote-tracking branch 'origin/develop' into feature/eric/audio…
ericdecanini Mar 24, 2022
806af47
Fixes post merge errors
ericdecanini Mar 24, 2022
c8a56d6
Merge remote-tracking branch 'origin/develop' into feature/eric/audio…
ericdecanini Mar 24, 2022
313595e
Fixes textview layout bounds in item_timeline_event_audio_stub
ericdecanini Mar 25, 2022
8aaaf80
Fixes lint error
ericdecanini Mar 28, 2022
931c0e9
Improves accessibility talkback on MessageAudioItem
ericdecanini Mar 28, 2022
fa56a5e
Fixes playback button state not tracking after onPause
ericdecanini Mar 28, 2022
cc5e8f3
Improves code formatting
ericdecanini Mar 29, 2022
6adf487
Fixes bugs related to audio message duration being set incorrectly be…
ericdecanini Mar 29, 2022
8ad4f20
Fixes bug where audio can be played before waveform is ready
ericdecanini Mar 29, 2022
34dcd70
Adds layout with seek bar to audio stub
ericdecanini Apr 1, 2022
d0155c9
Adds proper handling of audio seek bar
ericdecanini Apr 4, 2022
76b2cfd
Readds onPermissionDeniedSnackbar import in TimelineFragment
ericdecanini Apr 5, 2022
dc36301
Improves accessibility on MessageAudioItem
ericdecanini Apr 5, 2022
355db98
Updates some text sizes and colours in audio timeline item
ericdecanini Apr 5, 2022
4159850
Removes underline in audio filename
ericdecanini Apr 6, 2022
d9f2033
Removes unused import
ericdecanini Apr 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/5586.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adds the ability for audio attachments to be played in the timeline
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the Github issue number instead for the Changelog entry? I know there were some discussions about it, but I don't know what was decided. I think all the team should use use the same pattern: either Github issue number or PR number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I learned about this process, I heard it's very ambiguous and we go either way, but I agree that one way or the other we should choose one and be consistent with it!

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import im.vector.app.databinding.ActivityRoomDetailBinding
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment
import im.vector.app.features.home.room.detail.arguments.TimelineArgs
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.room.RequireActiveMembershipAction
Expand Down Expand Up @@ -75,7 +75,7 @@ class RoomDetailActivity :
}

private var lastKnownPlayingOrRecordingState: Boolean? = null
private val playbackActivityListener = VoiceMessagePlaybackTracker.ActivityListener { isPlayingOrRecording ->
private val playbackActivityListener = AudioMessagePlaybackTracker.ActivityListener { isPlayingOrRecording ->
if (lastKnownPlayingOrRecordingState == isPlayingOrRecording) return@ActivityListener
when (isPlayingOrRecording) {
true -> keepScreenOn()
Expand All @@ -86,7 +86,7 @@ class RoomDetailActivity :

override fun getCoordinatorLayout() = views.coordinatorLayout

@Inject lateinit var playbackTracker: VoiceMessagePlaybackTracker
@Inject lateinit var playbackTracker: AudioMessagePlaybackTracker
private lateinit var sharedActionViewModel: RoomDetailSharedActionViewModel
private val requireActiveMembershipViewModel: RequireActiveMembershipViewModel by viewModel()

Expand Down Expand Up @@ -152,7 +152,7 @@ class RoomDetailActivity :
override fun onDestroy() {
supportFragmentManager.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks)
views.drawerLayout.removeDrawerListener(drawerListener)
playbackTracker.unTrackActivity(playbackActivityListener)
playbackTracker.untrackActivity(playbackActivityListener)
super.onDestroy()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,11 @@ import im.vector.app.features.home.room.detail.timeline.action.EventSharedAction
import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBottomSheet
import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel
import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
import im.vector.app.features.home.room.detail.timeline.image.buildImageContentRendererData
import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
import im.vector.app.features.home.room.detail.timeline.item.MessageAudioItem
import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem
import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem
import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData
Expand Down Expand Up @@ -260,7 +261,7 @@ class TimelineFragment @Inject constructor(
private val roomDetailPendingActionStore: RoomDetailPendingActionStore,
private val pillsPostProcessorFactory: PillsPostProcessor.Factory,
private val callManager: WebRtcCallManager,
private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker,
private val audioMessagePlaybackTracker: AudioMessagePlaybackTracker,
private val clock: Clock,
private val matrixConfiguration: MatrixConfiguration
) :
Expand Down Expand Up @@ -728,7 +729,7 @@ class TimelineFragment @Inject constructor(
}

private fun setupVoiceMessageView() {
voiceMessagePlaybackTracker.track(VoiceMessagePlaybackTracker.RECORDING_ID, views.voiceMessageRecorderView)
audioMessagePlaybackTracker.track(AudioMessagePlaybackTracker.RECORDING_ID, views.voiceMessageRecorderView)
views.voiceMessageRecorderView.callback = object : VoiceMessageRecorderView.Callback {

override fun onVoiceRecordingStarted() {
Expand Down Expand Up @@ -785,13 +786,13 @@ class TimelineFragment @Inject constructor(

override fun onVoiceWaveformTouchedUp(percentage: Float, duration: Int) {
messageComposerViewModel.handle(
MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
MessageComposerAction.VoiceWaveformTouchedUp(AudioMessagePlaybackTracker.RECORDING_ID, duration, percentage)
)
}

override fun onVoiceWaveformMoved(percentage: Float, duration: Int) {
messageComposerViewModel.handle(
MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
MessageComposerAction.VoiceWaveformTouchedUp(AudioMessagePlaybackTracker.RECORDING_ID, duration, percentage)
)
}

Expand Down Expand Up @@ -1189,13 +1190,10 @@ class TimelineFragment @Inject constructor(
}

val messageContent: MessageContent? = event.getLastMessageContent()
val nonFormattedBody = if (messageContent is MessageAudioContent && messageContent.voiceMessageIndicator != null) {
val formattedDuration = DateUtils.formatElapsedTime(((messageContent.audioInfo?.duration ?: 0) / 1000).toLong())
getString(R.string.voice_message_reply_content, formattedDuration)
} else if (messageContent is MessagePollContent) {
messageContent.getBestPollCreationInfo()?.question?.getBestQuestion()
} else {
messageContent?.body ?: ""
val nonFormattedBody = when (messageContent) {
is MessageAudioContent -> getAudioContentBodyText(messageContent)
is MessagePollContent -> messageContent.getBestPollCreationInfo()?.question?.getBestQuestion()
else -> messageContent?.body ?: ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is the orEmpty extension we can use here to replace Elvis operator. I found it easier to read:
messageContent?.body.orEmpty(). What do you think?

}
var formattedBody: CharSequence? = null
if (messageContent is MessageTextContent && messageContent.format == MessageFormat.FORMAT_MATRIX_HTML) {
Expand Down Expand Up @@ -1234,6 +1232,15 @@ class TimelineFragment @Inject constructor(
focusComposerAndShowKeyboard()
}

private fun getAudioContentBodyText(messageContent: MessageAudioContent): String {
val formattedDuration = DateUtils.formatElapsedTime(((messageContent.audioInfo?.duration ?: 0) / 1000).toLong())
return if (messageContent.voiceMessageIndicator != null) {
getString(R.string.voice_message_reply_content, formattedDuration)
} else {
getString(R.string.audio_message_reply_content, messageContent.body, formattedDuration)
}
}

override fun onResume() {
super.onResume()
notificationDrawerManager.setCurrentRoom(timelineArgs.roomId)
Expand All @@ -1258,7 +1265,7 @@ class TimelineFragment @Inject constructor(
override fun onPause() {
super.onPause()
notificationDrawerManager.setCurrentRoom(null)
voiceMessagePlaybackTracker.unTrack(VoiceMessagePlaybackTracker.RECORDING_ID)
audioMessagePlaybackTracker.pauseAllPlaybacks()

if (withState(messageComposerViewModel) { it.isVoiceRecording } && requireActivity().isChangingConfigurations) {
// we're rotating, maintain any active recordings
Expand Down Expand Up @@ -1386,6 +1393,7 @@ class TimelineFragment @Inject constructor(
}
return when (model) {
is MessageFileItem,
is MessageAudioItem,
is MessageVoiceItem,
is MessageImageVideoItem,
is MessageTextItem -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,6 @@ class MessageComposerViewModel @AssistedInject constructor(
private fun handleEntersBackground(composerText: String) {
// Always stop all voice actions. It may be playing in timeline or active recording
val playingAudioContent = voiceMessageHelper.stopAllVoiceActions(deleteRecord = false)
voiceMessageHelper.clearTracker()

val isVoiceRecording = com.airbnb.mvrx.withState(this) { it.isVoiceRecording }
if (isVoiceRecording) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import android.media.AudioAttributes
import android.media.MediaPlayer
import androidx.core.content.FileProvider
import im.vector.app.BuildConfig
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.app.features.voice.VoiceFailure
import im.vector.app.features.voice.VoiceRecorder
import im.vector.app.features.voice.VoiceRecorderProvider
Expand All @@ -42,7 +42,7 @@ import javax.inject.Inject
*/
class VoiceMessageHelper @Inject constructor(
private val context: Context,
private val playbackTracker: VoiceMessagePlaybackTracker,
private val playbackTracker: AudioMessagePlaybackTracker,
voiceRecorderProvider: VoiceRecorderProvider
) {
private var mediaPlayer: MediaPlayer? = null
Expand All @@ -58,7 +58,7 @@ class VoiceMessageHelper @Inject constructor(
amplitudeList.clear()
attachmentData.waveform?.let {
amplitudeList.addAll(it)
playbackTracker.updateCurrentRecording(VoiceMessagePlaybackTracker.RECORDING_ID, amplitudeList)
playbackTracker.updateCurrentRecording(AudioMessagePlaybackTracker.RECORDING_ID, amplitudeList)
}
}

Expand Down Expand Up @@ -127,7 +127,7 @@ class VoiceMessageHelper @Inject constructor(

fun startOrPauseRecordingPlayback() {
voiceRecorder.getCurrentRecord()?.let {
startOrPausePlayback(VoiceMessagePlaybackTracker.RECORDING_ID, it)
startOrPausePlayback(AudioMessagePlaybackTracker.RECORDING_ID, it)
}
}

Expand All @@ -136,7 +136,7 @@ class VoiceMessageHelper @Inject constructor(
mediaPlayer?.stop()
stopPlaybackTicker()
stopRecordingAmplitudes()
if (playbackState is VoiceMessagePlaybackTracker.Listener.State.Playing) {
if (playbackState is AudioMessagePlaybackTracker.Listener.State.Playing) {
playbackTracker.pausePlayback(id)
} else {
startPlayback(id, file)
Expand Down Expand Up @@ -171,7 +171,7 @@ class VoiceMessageHelper @Inject constructor(
}

fun stopPlayback() {
playbackTracker.pausePlayback(VoiceMessagePlaybackTracker.RECORDING_ID)
playbackTracker.pausePlayback(AudioMessagePlaybackTracker.RECORDING_ID)
mediaPlayer?.stop()
stopPlaybackTicker()
}
Expand Down Expand Up @@ -200,7 +200,7 @@ class VoiceMessageHelper @Inject constructor(
try {
val maxAmplitude = voiceRecorder.getMaxAmplitude()
amplitudeList.add(maxAmplitude)
playbackTracker.updateCurrentRecording(VoiceMessagePlaybackTracker.RECORDING_ID, amplitudeList)
playbackTracker.updateCurrentRecording(AudioMessagePlaybackTracker.RECORDING_ID, amplitudeList)
} catch (e: IllegalStateException) {
Timber.e(e, "Cannot get max amplitude. Amplitude recording timer will be stopped.")
stopRecordingAmplitudes()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import im.vector.app.core.hardware.vibrate
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.lib.core.utils.timer.CountUpTimer
import javax.inject.Inject
import kotlin.math.floor
Expand All @@ -40,7 +40,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr), VoiceMessagePlaybackTracker.Listener {
) : ConstraintLayout(context, attrs, defStyleAttr), AudioMessagePlaybackTracker.Listener {

interface Callback {
fun onVoiceRecordingStarted()
Expand Down Expand Up @@ -222,16 +222,16 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
recordingTicker = null
}

override fun onUpdate(state: VoiceMessagePlaybackTracker.Listener.State) {
override fun onUpdate(state: AudioMessagePlaybackTracker.Listener.State) {
when (state) {
is VoiceMessagePlaybackTracker.Listener.State.Recording -> {
is AudioMessagePlaybackTracker.Listener.State.Recording -> {
voiceMessageViews.renderRecordingWaveform(state.amplitudeList.toTypedArray())
}
is VoiceMessagePlaybackTracker.Listener.State.Playing -> {
is AudioMessagePlaybackTracker.Listener.State.Playing -> {
voiceMessageViews.renderPlaying(state)
}
is VoiceMessagePlaybackTracker.Listener.State.Paused,
is VoiceMessagePlaybackTracker.Listener.State.Idle -> {
is AudioMessagePlaybackTracker.Listener.State.Paused,
is AudioMessagePlaybackTracker.Listener.State.Idle -> {
voiceMessageViews.renderIdle()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView.DraggingState
import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView.RecordingUiState
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.voice.AudioWaveformView

Expand Down Expand Up @@ -303,7 +303,7 @@ class VoiceMessageViews(
views.voicePlaybackWaveform.post { views.voicePlaybackWaveform.clear() }
}

fun renderPlaying(state: VoiceMessagePlaybackTracker.Listener.State.Playing) {
fun renderPlaying(state: AudioMessagePlaybackTracker.Listener.State.Playing) {
views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause)
views.voicePlaybackControlButton.contentDescription = resources.getString(R.string.a11y_pause_voice_message)
val formattedTimerText = DateUtils.formatElapsedTime((state.playbackTime / 1000).toLong())
Expand Down
Loading