Design review fixes.

This commit is contained in:
Onuray Sahin 2021-07-07 16:44:42 +03:00
parent a9beded589
commit 3372177b0e
3 changed files with 27 additions and 14 deletions

View File

@ -84,6 +84,7 @@ import im.vector.app.core.extensions.showKeyboard
import im.vector.app.core.extensions.trackItemsVisibilityChange import im.vector.app.core.extensions.trackItemsVisibilityChange
import im.vector.app.core.glide.GlideApp import im.vector.app.core.glide.GlideApp
import im.vector.app.core.glide.GlideRequests import im.vector.app.core.glide.GlideRequests
import im.vector.app.core.hardware.vibrate
import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.intent.getFilenameFromUri
import im.vector.app.core.intent.getMimeTypeFromUri import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
@ -599,6 +600,7 @@ class RoomDetailFragment @Inject constructor(
views.composerLayout.isInvisible = true views.composerLayout.isInvisible = true
roomDetailViewModel.handle(RoomDetailAction.StartRecordingVoiceMessage) roomDetailViewModel.handle(RoomDetailAction.StartRecordingVoiceMessage)
context?.toast(R.string.voice_message_release_to_send_toast) context?.toast(R.string.voice_message_release_to_send_toast)
vibrate(requireContext())
} }
} }

View File

@ -30,6 +30,7 @@ import androidx.core.view.isVisible
import com.visualizer.amplitude.AudioRecordView import com.visualizer.amplitude.AudioRecordView
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.hardware.vibrate
import im.vector.app.core.utils.toast import im.vector.app.core.utils.toast
import im.vector.app.databinding.ViewVoiceMessageRecorderBinding 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.VoiceMessagePlaybackTracker
@ -37,6 +38,7 @@ import timber.log.Timber
import java.util.Timer import java.util.Timer
import java.util.TimerTask import java.util.TimerTask
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.floor
/** /**
* Encapsulates the voice message recording view and animations. * Encapsulates the voice message recording view and animations.
@ -152,13 +154,15 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
private fun handleMoveAction(event: MotionEvent) { private fun handleMoveAction(event: MotionEvent) {
val currentX = event.rawX val currentX = event.rawX
val currentY = event.rawY val currentY = event.rawY
updateRecordingState(currentX, currentY)
val isRecordingStateChanged = updateRecordingState(currentX, currentY)
when (recordingState) { when (recordingState) {
RecordingState.CANCELLING -> { RecordingState.CANCELLING -> {
val translationAmount = currentX - firstX val translationAmount = currentX - firstX
views.voiceMessageMicButton.translationX = translationAmount views.voiceMessageMicButton.translationX = translationAmount
views.voiceMessageSlideToCancel.translationX = translationAmount views.voiceMessageSlideToCancel.translationX = translationAmount
views.voiceMessageSlideToCancel.alpha = 1 - abs(translationAmount) / ((firstX - views.voiceMessageTimer.x) / 3)
views.voiceMessageLockBackground.isVisible = false views.voiceMessageLockBackground.isVisible = false
views.voiceMessageLockImage.isVisible = false views.voiceMessageLockImage.isVisible = false
views.voiceMessageLockArrow.isVisible = false views.voiceMessageLockArrow.isVisible = false
@ -174,11 +178,13 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
hideRecordingViews() hideRecordingViews()
} }
RecordingState.LOCKED -> { RecordingState.LOCKED -> {
if (isRecordingStateChanged) { // Do not update views if it was already in locked state.
views.voiceMessageLockImage.setImageResource(R.drawable.ic_voice_message_locked) views.voiceMessageLockImage.setImageResource(R.drawable.ic_voice_message_locked)
views.voiceMessageLockImage.postDelayed({ views.voiceMessageLockImage.postDelayed({
showRecordingLockedViews() showRecordingLockedViews()
}, 500) }, 500)
} }
}
RecordingState.STARTED -> { RecordingState.STARTED -> {
showRecordingViews() showRecordingViews()
} }
@ -189,7 +195,8 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
lastY = currentY lastY = currentY
} }
private fun updateRecordingState(currentX: Float, currentY: Float) { private fun updateRecordingState(currentX: Float, currentY: Float): Boolean {
val previousRecordingState = recordingState
val distanceX = abs(firstX - currentX) val distanceX = abs(firstX - currentX)
val distanceY = abs(firstY - currentY) val distanceY = abs(firstY - currentY)
if (recordingState == RecordingState.STARTED) { // Determine if cancelling or locking for the first move action. if (recordingState == RecordingState.STARTED) { // Determine if cancelling or locking for the first move action.
@ -211,10 +218,12 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
recordingState = RecordingState.LOCKED recordingState = RecordingState.LOCKED
} }
} }
return previousRecordingState != recordingState
} }
private fun shouldCancelRecording(): Boolean { private fun shouldCancelRecording(): Boolean {
return abs(views.voiceMessageTimer.x + views.voiceMessageTimer.width - views.voiceMessageSlideToCancel.x) < 10 return abs(views.voiceMessageTimer.x + views.voiceMessageTimer.width - views.voiceMessageSlideToCancel.x) < 10
|| views.voiceMessageSlideToCancel.x <= views.voiceMessageTimer.x + views.voiceMessageTimer.width // To handle super fast moving
} }
private fun shouldLockRecording(): Boolean { private fun shouldLockRecording(): Boolean {
@ -230,15 +239,14 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
val timeDiffToRecordingLimit = BuildConfig.VOICE_MESSAGE_DURATION_LIMIT_MS - recordingTime * 1000 val timeDiffToRecordingLimit = BuildConfig.VOICE_MESSAGE_DURATION_LIMIT_MS - recordingTime * 1000
if (timeDiffToRecordingLimit <= 0) { if (timeDiffToRecordingLimit <= 0) {
views.voiceMessageRecordingLayout.post { views.voiceMessageRecordingLayout.post {
callback?.onVoiceRecordingEnded(false) recordingState = RecordingState.PLAYBACK
recordingState = RecordingState.NONE showPlaybackViews()
stopRecordingTimer() stopRecordingTimer()
hideRecordingViews(animationDuration = 0)
} }
} else if (timeDiffToRecordingLimit in 10000..11000) { } else if (timeDiffToRecordingLimit in 10000..10999) {
views.voiceMessageRecordingLayout.post { views.voiceMessageRecordingLayout.post {
views.voiceMessageSendButton.isVisible = false context.toast(context.getString(R.string.voice_message_n_seconds_warning_toast, floor(timeDiffToRecordingLimit / 1000f).toInt()))
context.toast(context.getString(R.string.voice_message_n_seconds_warning_toast, (timeDiffToRecordingLimit / 1000).toInt())) vibrate(context)
} }
} }
} }
@ -290,12 +298,13 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
views.voiceMessageSlideToCancel.isVisible = true views.voiceMessageSlideToCancel.isVisible = true
views.voiceMessageTimerIndicator.isVisible = true views.voiceMessageTimerIndicator.isVisible = true
views.voiceMessageTimer.isVisible = true views.voiceMessageTimer.isVisible = true
views.voiceMessageSlideToCancel.alpha = 1f
views.voiceMessageSendButton.isVisible = false views.voiceMessageSendButton.isVisible = false
} }
fun hideRecordingViews(animationDuration: Int = 300) { fun hideRecordingViews(animationDuration: Int = 300) {
views.voiceMessageMicButton.setImageResource(R.drawable.ic_voice_mic) views.voiceMessageMicButton.setImageResource(R.drawable.ic_voice_mic)
views.voiceMessageMicButton.animate().translationX(0f).translationY(0f).setDuration(animationDuration.toLong()).start() views.voiceMessageMicButton.animate().translationX(0f).translationY(0f).setDuration(animationDuration.toLong()).setDuration(0).start()
(views.voiceMessageMicButton.layoutParams as MarginLayoutParams).apply { setMargins(0, 0, dpToPx(12).toInt(), dpToPx(12).toInt()) } (views.voiceMessageMicButton.layoutParams as MarginLayoutParams).apply { setMargins(0, 0, dpToPx(12).toInt(), dpToPx(12).toInt()) }
views.voiceMessageLockBackground.isVisible = false views.voiceMessageLockBackground.isVisible = false
views.voiceMessageLockBackground.animate().translationY(dpToPx(0)).start() views.voiceMessageLockBackground.animate().translationY(dpToPx(0)).start()
@ -316,6 +325,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
views.voiceMessagePlaybackLayout.findViewById<ImageView>(R.id.voiceMessagePlaybackTimerIndicator).isVisible = true views.voiceMessagePlaybackLayout.findViewById<ImageView>(R.id.voiceMessagePlaybackTimerIndicator).isVisible = true
views.voiceMessagePlaybackLayout.findViewById<ImageView>(R.id.voicePlaybackControlButton).isVisible = false views.voiceMessagePlaybackLayout.findViewById<ImageView>(R.id.voicePlaybackControlButton).isVisible = false
views.voiceMessageSendButton.isVisible = true views.voiceMessageSendButton.isVisible = true
context.toast(R.string.voice_message_tap_to_stop_toast)
} }
private fun showPlaybackViews() { private fun showPlaybackViews() {

View File

@ -3416,8 +3416,9 @@
<string name="a11y_pause_voice_message">Pause Voice Message</string> <string name="a11y_pause_voice_message">Pause Voice Message</string>
<string name="a11y_recording_voice_message">Recording voice message</string> <string name="a11y_recording_voice_message">Recording voice message</string>
<string name="a11y_delete_recorded_voice_message">Delete recorded voice message</string> <string name="a11y_delete_recorded_voice_message">Delete recorded voice message</string>
<string name="voice_message_release_to_send_toast">Release to send</string> <string name="voice_message_release_to_send_toast">Hold to record, release to send</string>
<string name="voice_message_n_seconds_warning_toast">%1$ds left</string> <string name="voice_message_n_seconds_warning_toast">%1$ds left</string>
<string name="voice_message_tap_on_waveform_to_stop_toast">Tap on the waveform to stop and playback</string> <string name="voice_message_tap_on_waveform_to_stop_toast">Tap on the waveform to stop and playback</string>
<string name="labs_use_voice_message">Enable voice message</string> <string name="labs_use_voice_message">Enable voice message</string>
<string name="voice_message_tap_to_stop_toast">Tap on the wavelength to stop and playback</string>
</resources> </resources>