mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-23 09:56:00 +03:00
moving the recording ui state to the textcomposer view model and state
This commit is contained in:
parent
40d762c37d
commit
2ad121e96e
7 changed files with 50 additions and 45 deletions
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue