From bf9a22c1b03cc87946deeeaeae466256a77fa2b4 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 10 Aug 2021 13:59:39 +0300 Subject: [PATCH 1/9] Fix flickering lock view. --- .../home/room/detail/composer/VoiceMessageRecorderView.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index 48195dc8f1..00ab67656c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -220,6 +220,9 @@ class VoiceMessageRecorderView @JvmOverloads constructor( } RecordingState.STARTED -> { showRecordingViews() + val translationAmount = distanceX.coerceAtMost(distanceToCancel) + views.voiceMessageMicButton.translationX = -translationAmount * rtlXMultiplier + views.voiceMessageSlideToCancel.translationX = -translationAmount / 2 * rtlXMultiplier } RecordingState.NONE -> Timber.d("VoiceMessageRecorderView shouldn't be in NONE state while moving.") RecordingState.PLAYBACK -> Timber.d("VoiceMessageRecorderView shouldn't be in PLAYBACK state while moving.") @@ -235,7 +238,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor( if (recordingState == RecordingState.STARTED) { // Determine if cancelling or locking for the first move action. if (((currentX < firstX && rtlXMultiplier == 1) || (currentX > firstX && rtlXMultiplier == -1)) - && distanceX > distanceY) { + && distanceX > distanceY && distanceX > lastDistanceX) { recordingState = RecordingState.CANCELLING } else if (currentY < firstY && distanceY > distanceX) { recordingState = RecordingState.LOCKING From a0730943b494bca4ca97c35aeddbce001ab36b79 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 10 Aug 2021 14:17:33 +0300 Subject: [PATCH 2/9] Dynamically set content description of play/pause button. --- .../home/room/detail/composer/VoiceMessageRecorderView.kt | 2 ++ .../home/room/detail/timeline/item/MessageVoiceItem.kt | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index 00ab67656c..50d8d8e867 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -510,12 +510,14 @@ class VoiceMessageRecorderView @JvmOverloads constructor( } is VoiceMessagePlaybackTracker.Listener.State.Playing -> { views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause) + views.voicePlaybackControlButton.contentDescription = context.getString(R.string.a11y_pause_voice_message) val formattedTimerText = DateUtils.formatElapsedTime((state.playbackTime / 1000).toLong()) views.voicePlaybackTime.text = formattedTimerText } is VoiceMessagePlaybackTracker.Listener.State.Paused, is VoiceMessagePlaybackTracker.Listener.State.Idle -> { views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) + views.voicePlaybackControlButton.contentDescription = context.getString(R.string.a11y_play_voice_message) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt index dc204da291..fb7d0cabd5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt @@ -71,6 +71,7 @@ abstract class MessageVoiceItem : AbsMessageItem() { contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, izLocalFile, holder.progressLayout) } else { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_cross) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.error_voice_message_unable_to_play) holder.progressLayout.isVisible = false } @@ -98,16 +99,19 @@ abstract class MessageVoiceItem : AbsMessageItem() { private fun renderIdleState(holder: Holder) { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message) holder.voicePlaybackTime.text = formatPlaybackTime(duration) } private fun renderPlayingState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Playing) { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_pause_voice_message) holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime) } private fun renderPausedState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Paused) { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message) holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime) } From bf1db5dcf9af1f8591627e4495ec8927aa8eee3e Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 10 Aug 2021 14:36:01 +0300 Subject: [PATCH 3/9] Remove content description of mic button if it is not visible. --- .../room/detail/composer/VoiceMessageRecorderView.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index 50d8d8e867..033020bbce 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -20,6 +20,7 @@ import android.content.Context import android.text.format.DateUtils import android.util.AttributeSet import android.view.MotionEvent +import android.view.View import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isInvisible import androidx.core.view.isVisible @@ -87,6 +88,15 @@ class VoiceMessageRecorderView @JvmOverloads constructor( initListeners() } + override fun onVisibilityChanged(changedView: View, visibility: Int) { + super.onVisibilityChanged(changedView, visibility) + if (changedView == this && visibility == VISIBLE) { + views.voiceMessageMicButton.contentDescription = context.getString(R.string.a11y_start_voice_message) + } else { + views.voiceMessageMicButton.contentDescription = "" + } + } + fun initVoiceRecordingViews() { recordingState = RecordingState.NONE From 296a1c47702a5228c612df2c98c02e01bc75208f Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 10 Aug 2021 14:43:16 +0300 Subject: [PATCH 4/9] Vibrate when the recording is canceled. --- .../home/room/detail/composer/VoiceMessageRecorderView.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index 033020bbce..f059d4285e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -428,6 +428,10 @@ class VoiceMessageRecorderView @JvmOverloads constructor( if (recordingState == RecordingState.CANCELLED || recordingState == RecordingState.NONE) { hideToast() } + + if (isCancelled.orFalse()) { + vibrate(context) + } } private fun resetMicButtonUi() { From 0cd0484b41bd714502a063ca516ce7722f3c8a3e Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 10 Aug 2021 14:54:03 +0300 Subject: [PATCH 5/9] Fix flickering between locking states. --- .../home/room/detail/composer/VoiceMessageRecorderView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index f059d4285e..96a066b295 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -250,7 +250,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor( if (((currentX < firstX && rtlXMultiplier == 1) || (currentX > firstX && rtlXMultiplier == -1)) && distanceX > distanceY && distanceX > lastDistanceX) { recordingState = RecordingState.CANCELLING - } else if (currentY < firstY && distanceY > distanceX) { + } else if (currentY < firstY && distanceY > distanceX && distanceY > lastDistanceY) { recordingState = RecordingState.LOCKING } } else if (recordingState == RecordingState.CANCELLING) { From 9f4a45911656c0f873027fc4c83958b62057444d Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 10 Aug 2021 15:40:04 +0300 Subject: [PATCH 6/9] Fix cannot draw waveform while recording after onPause. --- .../vector/app/features/home/room/detail/RoomDetailFragment.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index 6a8b4fa863..c37f1840ac 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -1044,6 +1044,9 @@ class RoomDetailFragment @Inject constructor( notificationDrawerManager.setCurrentRoom(roomDetailArgs.roomId) roomDetailPendingActionStore.data?.let { handlePendingAction(it) } roomDetailPendingActionStore.data = null + + // Removed listeners should be set again + setupVoiceMessageView() } private fun handlePendingAction(roomDetailPendingAction: RoomDetailPendingAction) { From 5cc9c6231b372143d326369ffc0f6bea043ebfbe Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 10 Aug 2021 15:44:09 +0300 Subject: [PATCH 7/9] Changelog added. --- changelog.d/3798.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/3798.bugfix diff --git a/changelog.d/3798.bugfix b/changelog.d/3798.bugfix new file mode 100644 index 0000000000..92374d94d6 --- /dev/null +++ b/changelog.d/3798.bugfix @@ -0,0 +1 @@ +Voice Message - UI Improvements \ No newline at end of file From c2401e04b4966a76de2b058f1583431d69ee2134 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 11 Aug 2021 14:54:29 +0300 Subject: [PATCH 8/9] Fix collapsing mic and send buttons. --- .../vector/app/features/home/room/detail/RoomDetailFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index c37f1840ac..e50d6c8df3 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -1321,7 +1321,6 @@ class RoomDetailFragment @Inject constructor( if (text.isNotBlank()) { // We collapse ASAP, if not there will be a slight annoying delay views.composerLayout.collapse(true) - views.voiceMessageRecorderView.isVisible = vectorPreferences.labsUseVoiceMessage() lockSendButton = true roomDetailViewModel.handle(RoomDetailAction.SendMessage(text, vectorPreferences.isMarkdownEnabled())) emojiPopup.dismiss() From a8f4b318c18c067e9d63edfc2d87f7bf9745c5e5 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 11 Aug 2021 14:59:21 +0300 Subject: [PATCH 9/9] Fix tice vibration after cancelling the voice record. --- .../home/room/detail/composer/VoiceMessageRecorderView.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index 96a066b295..47e72b46f7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -219,6 +219,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor( } RecordingState.CANCELLED -> { hideRecordingViews(isCancelled = true) + vibrate(context) } RecordingState.LOCKED -> { if (isRecordingStateChanged) { // Do not update views if it was already in locked state. @@ -428,10 +429,6 @@ class VoiceMessageRecorderView @JvmOverloads constructor( if (recordingState == RecordingState.CANCELLED || recordingState == RecordingState.NONE) { hideToast() } - - if (isCancelled.orFalse()) { - vibrate(context) - } } private fun resetMicButtonUi() {