moving the recording ui state to the textcomposer view model and state

This commit is contained in:
Adam Brown 2021-11-11 16:57:06 +00:00
parent 40d762c37d
commit 2ad121e96e
7 changed files with 50 additions and 45 deletions

View file

@ -696,26 +696,14 @@ class RoomDetailFragment @Inject constructor(
voiceMessagePlaybackTracker.track(VoiceMessagePlaybackTracker.RECORDING_ID, views.voiceMessageRecorderView)
views.voiceMessageRecorderView.callback = object : VoiceMessageRecorderView.Callback {
private var currentUiState: RecordingUiState = RecordingUiState.None
init {
display(currentUiState)
}
override fun onVoiceRecordingStarted() {
if (checkPermissions(PERMISSIONS_FOR_VOICE_MESSAGE, requireActivity(), permissionVoiceMessageLauncher)) {
roomDetailViewModel.handle(RoomDetailAction.StartRecordingVoiceMessage)
textComposerViewModel.handle(TextComposerAction.OnVoiceRecordingStateChanged(true))
vibrate(requireContext())
display(RecordingUiState.Started)
}
}
override fun onVoiceRecordingEnded(isCancelled: Boolean) {
roomDetailViewModel.handle(RoomDetailAction.EndRecordingVoiceMessage(isCancelled))
textComposerViewModel.handle(TextComposerAction.OnVoiceRecordingStateChanged(false))
}
override fun onVoiceRecordingPlaybackModeOn() {
roomDetailViewModel.handle(RoomDetailAction.PauseRecordingVoiceMessage)
}
@ -725,7 +713,8 @@ class RoomDetailFragment @Inject constructor(
}
override fun onRecordingStopped() {
if (currentUiState != RecordingUiState.Locked) {
roomDetailViewModel.handle(RoomDetailAction.EndRecordingVoiceMessage(isCancelled = true))
if (currentState() != RecordingUiState.Locked) {
display(RecordingUiState.None)
}
}
@ -739,6 +728,7 @@ class RoomDetailFragment @Inject constructor(
}
override fun deleteVoiceMessage() {
roomDetailViewModel.handle(RoomDetailAction.EndRecordingVoiceMessage(isCancelled = true))
display(RecordingUiState.Cancelled)
}
@ -751,13 +741,10 @@ class RoomDetailFragment @Inject constructor(
}
private fun display(state: RecordingUiState) {
if (currentUiState != state) {
views.voiceMessageRecorderView.display(state)
}
currentUiState = state
textComposerViewModel.handle(TextComposerAction.OnVoiceRecordingUiStateChanged(state))
}
override fun currentState() = currentUiState
override fun currentState() = withState(textComposerViewModel) { it.voiceRecordingUiState }
}
}
@ -1444,6 +1431,7 @@ class RoomDetailFragment @Inject constructor(
views.composerLayout.isInvisible = !textComposerState.isComposerVisible
views.voiceMessageRecorderView.isVisible = textComposerState.isVoiceMessageRecorderVisible
views.composerLayout.views.sendButton.isInvisible = !textComposerState.isSendButtonVisible
views.voiceMessageRecorderView.display(textComposerState.voiceRecordingUiState)
views.composerLayout.setRoomEncrypted(summary.isEncrypted)
// views.composerLayout.alwaysShowSendButton = false
if (textComposerState.canSendMessage) {

View file

@ -17,6 +17,7 @@
package im.vector.app.features.home.room.detail.composer
import im.vector.app.core.platform.VectorViewModelAction
import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView
sealed class TextComposerAction : VectorViewModelAction {
data class SaveDraft(val draft: String) : TextComposerAction()
@ -27,5 +28,5 @@ sealed class TextComposerAction : VectorViewModelAction {
data class EnterRegularMode(val text: String, val fromSharing: Boolean) : TextComposerAction()
data class UserIsTyping(val isTyping: Boolean) : TextComposerAction()
data class OnTextChanged(val text: CharSequence) : TextComposerAction()
data class OnVoiceRecordingStateChanged(val isRecording: Boolean) : TextComposerAction()
data class OnVoiceRecordingUiStateChanged(val uiState: VoiceMessageRecorderView.RecordingUiState) : TextComposerAction()
}

View file

@ -77,20 +77,20 @@ class TextComposerViewModel @AssistedInject constructor(
override fun handle(action: TextComposerAction) {
Timber.v("Handle action: $action")
when (action) {
is TextComposerAction.EnterEditMode -> handleEnterEditMode(action)
is TextComposerAction.EnterQuoteMode -> handleEnterQuoteMode(action)
is TextComposerAction.EnterRegularMode -> handleEnterRegularMode(action)
is TextComposerAction.EnterReplyMode -> handleEnterReplyMode(action)
is TextComposerAction.SaveDraft -> handleSaveDraft(action)
is TextComposerAction.SendMessage -> handleSendMessage(action)
is TextComposerAction.UserIsTyping -> handleUserIsTyping(action)
is TextComposerAction.OnTextChanged -> handleOnTextChanged(action)
is TextComposerAction.OnVoiceRecordingStateChanged -> handleOnVoiceRecordingStateChanged(action)
is TextComposerAction.EnterEditMode -> handleEnterEditMode(action)
is TextComposerAction.EnterQuoteMode -> handleEnterQuoteMode(action)
is TextComposerAction.EnterRegularMode -> handleEnterRegularMode(action)
is TextComposerAction.EnterReplyMode -> handleEnterReplyMode(action)
is TextComposerAction.SaveDraft -> handleSaveDraft(action)
is TextComposerAction.SendMessage -> handleSendMessage(action)
is TextComposerAction.UserIsTyping -> handleUserIsTyping(action)
is TextComposerAction.OnTextChanged -> handleOnTextChanged(action)
is TextComposerAction.OnVoiceRecordingUiStateChanged -> handleOnVoiceRecordingUiStateChanged(action)
}
}
private fun handleOnVoiceRecordingStateChanged(action: TextComposerAction.OnVoiceRecordingStateChanged) = setState {
copy(isVoiceRecording = action.isRecording)
private fun handleOnVoiceRecordingUiStateChanged(action: TextComposerAction.OnVoiceRecordingUiStateChanged) = setState {
copy(voiceRecordingUiState = action.uiState)
}
private fun handleOnTextChanged(action: TextComposerAction.OnTextChanged) {

View file

@ -18,6 +18,7 @@ package im.vector.app.features.home.room.detail.composer
import com.airbnb.mvrx.MavericksState
import im.vector.app.features.home.room.detail.RoomDetailArgs
import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
/**
@ -44,11 +45,21 @@ sealed class SendMode(open val text: String) {
data class TextComposerViewState(
val roomId: String,
val canSendMessage: Boolean = true,
val isVoiceRecording: Boolean = false,
val isSendButtonVisible: Boolean = false,
val sendMode: SendMode = SendMode.REGULAR("", false)
val sendMode: SendMode = SendMode.REGULAR("", false),
val voiceRecordingUiState: VoiceMessageRecorderView.RecordingUiState = VoiceMessageRecorderView.RecordingUiState.None
) : MavericksState {
val isVoiceRecording = when (voiceRecordingUiState) {
VoiceMessageRecorderView.RecordingUiState.None,
VoiceMessageRecorderView.RecordingUiState.Cancelled,
VoiceMessageRecorderView.RecordingUiState.Playback -> false
is VoiceMessageRecorderView.DraggingState.Cancelling,
is VoiceMessageRecorderView.DraggingState.Locking,
VoiceMessageRecorderView.RecordingUiState.Locked,
VoiceMessageRecorderView.RecordingUiState.Started -> true
}
val isComposerVisible = canSendMessage && !isVoiceRecording
val isVoiceMessageRecorderVisible = canSendMessage && !isSendButtonVisible

View file

@ -77,12 +77,10 @@ class DraggableStateProcessor(
}
is DraggingState.Cancelling -> {
// Check if cancelling conditions met, also check if it should be initial state
if (distanceX < minimumMove && distanceX < lastDistanceX) {
RecordingUiState.Started
} else if (shouldCancelRecording(distanceX)) {
RecordingUiState.Cancelled
} else {
DraggingState.Cancelling(distanceX)
when {
distanceX < minimumMove && distanceX < lastDistanceX -> RecordingUiState.Started
shouldCancelRecording(distanceX) -> RecordingUiState.Cancelled
else -> DraggingState.Cancelling(distanceX)
}
}
is DraggingState.Locking -> {

View file

@ -41,7 +41,6 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
interface Callback {
fun onVoiceRecordingStarted()
fun onVoiceRecordingEnded(isCancelled: Boolean)
fun onVoiceRecordingPlaybackModeOn()
fun onVoicePlaybackButtonClicked()
fun onRecordingStopped()
@ -59,6 +58,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
lateinit var callback: Callback
private var recordingTicker: CountUpTimer? = null
private var lastKnownState: RecordingUiState? = null
init {
inflate(this.context, R.layout.view_voice_message_recorder, this)
@ -92,8 +92,11 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
override fun isActive() = callback.currentState() != RecordingUiState.Cancelled
override fun updateState(updater: (RecordingUiState) -> RecordingUiState) {
updater(callback.currentState()).also { newState ->
callback.onUiStateChanged(newState)
updater(lastKnownState ?: RecordingUiState.None).also { newState ->
when (newState) {
is DraggingState -> display(newState)
else -> callback.onUiStateChanged(newState)
}
}
}
@ -102,7 +105,6 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
}
override fun delete() {
// this was previously marked as cancelled true
callback.deleteVoiceMessage()
}
@ -117,11 +119,12 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
}
fun display(recordingState: RecordingUiState) {
if (lastKnownState == recordingState) return
lastKnownState = recordingState
when (recordingState) {
RecordingUiState.None -> {
stopRecordingTicker()
voiceMessageViews.initViews()
callback.onVoiceRecordingEnded(false)
}
RecordingUiState.Started -> {
startRecordingTicker()
@ -130,13 +133,15 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
}
RecordingUiState.Cancelled -> {
stopRecordingTicker()
voiceMessageViews.hideRecordingViews(recordingState, isCancelled = true) { callback.onVoiceRecordingEnded(it) }
voiceMessageViews.hideRecordingViews(recordingState, isCancelled = true) { callback.deleteVoiceMessage() }
vibrate(context)
}
RecordingUiState.Locked -> {
voiceMessageViews.renderLocked()
postDelayed({
voiceMessageViews.showRecordingLockedViews(recordingState) { callback.onVoiceRecordingEnded(it) }
voiceMessageViews.showRecordingLockedViews(recordingState) {
// do nothing
}
}, 500)
}
RecordingUiState.Playback -> {

View file

@ -19,6 +19,7 @@ package im.vector.app.features.home.room.detail.composer.voice
import android.annotation.SuppressLint
import android.content.res.Resources
import android.text.format.DateUtils
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
@ -73,6 +74,7 @@ class VoiceMessageViews(
views.voiceMessageMicButton.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
Log.e("!!!", "event down: $event")
positions.reset(event)
actions.onRequestRecording()
true