avoiding stopping any active recording if we're rotating
- had to keep track of the recording start time in order to maintain the current length counter
This commit is contained in:
parent
bbb3a6139f
commit
4a5e21ad21
|
@ -699,7 +699,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
if (checkPermissions(PERMISSIONS_FOR_VOICE_MESSAGE, requireActivity(), permissionVoiceMessageLauncher)) {
|
||||
messageComposerViewModel.handle(MessageComposerAction.StartRecordingVoiceMessage)
|
||||
vibrate(requireContext())
|
||||
updateRecordingUiState(RecordingUiState.Started)
|
||||
updateRecordingUiState(RecordingUiState.Started(System.currentTimeMillis()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,7 +713,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onVoiceRecordingLocked() {
|
||||
updateRecordingUiState(RecordingUiState.Locked)
|
||||
val startedState = withState(messageComposerViewModel) { it.voiceRecordingUiState as? RecordingUiState.Started }
|
||||
val startTime = startedState?.recordingStartTimestamp ?: System.currentTimeMillis()
|
||||
updateRecordingUiState(RecordingUiState.Locked(startTime))
|
||||
}
|
||||
|
||||
override fun onVoiceRecordingEnded() {
|
||||
|
@ -1131,11 +1133,15 @@ class RoomDetailFragment @Inject constructor(
|
|||
super.onPause()
|
||||
notificationDrawerManager.setCurrentRoom(null)
|
||||
voiceMessagePlaybackTracker.unTrack(VoiceMessagePlaybackTracker.RECORDING_ID)
|
||||
messageComposerViewModel.handle(MessageComposerAction.SaveDraft(views.composerLayout.text.toString()))
|
||||
|
||||
// We should improve the UX to support going into playback mode when paused and delete the media when the view is destroyed.
|
||||
messageComposerViewModel.handle(MessageComposerAction.EndAllVoiceActions(deleteRecord = false))
|
||||
views.voiceMessageRecorderView.render(RecordingUiState.None)
|
||||
if (withState(messageComposerViewModel) { it.isVoiceRecording } && requireActivity().isChangingConfigurations) {
|
||||
// we're rotating, maintain any active recordings
|
||||
} else {
|
||||
messageComposerViewModel.handle(MessageComposerAction.SaveDraft(views.composerLayout.text.toString()))
|
||||
// We should improve the UX to support going into playback mode when paused and delete the media when the view is destroyed.
|
||||
messageComposerViewModel.handle(MessageComposerAction.EndAllVoiceActions(deleteRecord = false))
|
||||
views.voiceMessageRecorderView.render(RecordingUiState.None)
|
||||
}
|
||||
}
|
||||
|
||||
private val attachmentFileActivityResultLauncher = registerStartForActivityResult {
|
||||
|
|
|
@ -54,8 +54,8 @@ data class MessageComposerViewState(
|
|||
VoiceMessageRecorderView.RecordingUiState.None,
|
||||
VoiceMessageRecorderView.RecordingUiState.Cancelled,
|
||||
VoiceMessageRecorderView.RecordingUiState.Playback -> false
|
||||
VoiceMessageRecorderView.RecordingUiState.Locked,
|
||||
VoiceMessageRecorderView.RecordingUiState.Started -> true
|
||||
is VoiceMessageRecorderView.RecordingUiState.Locked,
|
||||
is VoiceMessageRecorderView.RecordingUiState.Started -> true
|
||||
}
|
||||
|
||||
val isVoiceMessageIdle = !isVoiceRecording
|
||||
|
|
|
@ -105,32 +105,35 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
|
|||
|
||||
fun render(recordingState: RecordingUiState) {
|
||||
if (lastKnownState == recordingState) return
|
||||
lastKnownState = recordingState
|
||||
when (recordingState) {
|
||||
RecordingUiState.None -> {
|
||||
RecordingUiState.None -> {
|
||||
reset()
|
||||
}
|
||||
RecordingUiState.Started -> {
|
||||
startRecordingTicker()
|
||||
is RecordingUiState.Started -> {
|
||||
startRecordingTicker(startFromLocked = false, startAt = recordingState.recordingStartTimestamp)
|
||||
voiceMessageViews.renderToast(context.getString(R.string.voice_message_release_to_send_toast))
|
||||
voiceMessageViews.showRecordingViews()
|
||||
dragState = DraggingState.Ready
|
||||
}
|
||||
RecordingUiState.Cancelled -> {
|
||||
RecordingUiState.Cancelled -> {
|
||||
reset()
|
||||
vibrate(context)
|
||||
}
|
||||
RecordingUiState.Locked -> {
|
||||
is RecordingUiState.Locked -> {
|
||||
if (lastKnownState == null) {
|
||||
startRecordingTicker(startFromLocked = true, startAt = recordingState.recordingStartTimestamp)
|
||||
}
|
||||
voiceMessageViews.renderLocked()
|
||||
postDelayed({
|
||||
voiceMessageViews.showRecordingLockedViews(recordingState)
|
||||
}, 500)
|
||||
}
|
||||
RecordingUiState.Playback -> {
|
||||
RecordingUiState.Playback -> {
|
||||
stopRecordingTicker()
|
||||
voiceMessageViews.showPlaybackViews()
|
||||
}
|
||||
}
|
||||
lastKnownState = recordingState
|
||||
}
|
||||
|
||||
private fun reset() {
|
||||
|
@ -159,22 +162,23 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
|
|||
dragState = newDragState
|
||||
}
|
||||
|
||||
private fun startRecordingTicker() {
|
||||
private fun startRecordingTicker(startFromLocked: Boolean, startAt: Long) {
|
||||
val startMs = ((System.currentTimeMillis() - startAt)).coerceAtLeast(0)
|
||||
recordingTicker?.stop()
|
||||
recordingTicker = CountUpTimer().apply {
|
||||
tickListener = object : CountUpTimer.TickListener {
|
||||
override fun onTick(milliseconds: Long) {
|
||||
onRecordingTick(milliseconds)
|
||||
val isLocked = startFromLocked || lastKnownState is RecordingUiState.Locked
|
||||
onRecordingTick(isLocked, milliseconds + startMs)
|
||||
}
|
||||
}
|
||||
resume()
|
||||
}
|
||||
onRecordingTick(0L)
|
||||
onRecordingTick(startFromLocked, milliseconds = startMs)
|
||||
}
|
||||
|
||||
private fun onRecordingTick(milliseconds: Long) {
|
||||
val currentState = lastKnownState ?: return
|
||||
voiceMessageViews.renderRecordingTimer(currentState, milliseconds / 1_000)
|
||||
private fun onRecordingTick(isLocked: Boolean, milliseconds: Long) {
|
||||
voiceMessageViews.renderRecordingTimer(isLocked, milliseconds / 1_000)
|
||||
val timeDiffToRecordingLimit = BuildConfig.VOICE_MESSAGE_DURATION_LIMIT_MS - milliseconds
|
||||
if (timeDiffToRecordingLimit <= 0) {
|
||||
post {
|
||||
|
@ -211,9 +215,9 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
|
|||
|
||||
sealed interface RecordingUiState {
|
||||
object None : RecordingUiState
|
||||
object Started : RecordingUiState
|
||||
data class Started(val recordingStartTimestamp: Long) : RecordingUiState
|
||||
object Cancelled : RecordingUiState
|
||||
object Locked : RecordingUiState
|
||||
data class Locked(val recordingStartTimestamp: Long) : RecordingUiState
|
||||
object Playback : RecordingUiState
|
||||
}
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ class VoiceMessageViews(
|
|||
|
||||
fun hideRecordingViews(recordingState: RecordingUiState) {
|
||||
// We need to animate the lock image first
|
||||
if (recordingState != RecordingUiState.Locked) {
|
||||
if (recordingState !is RecordingUiState.Locked) {
|
||||
views.voiceMessageLockImage.isVisible = false
|
||||
views.voiceMessageLockImage.animate().translationY(0f).start()
|
||||
views.voiceMessageLockBackground.isVisible = false
|
||||
|
@ -171,7 +171,7 @@ class VoiceMessageViews(
|
|||
views.voiceMessageTimerIndicator.isVisible = false
|
||||
views.voiceMessageTimer.isVisible = false
|
||||
|
||||
if (recordingState != RecordingUiState.Locked) {
|
||||
if (recordingState !is RecordingUiState.Locked) {
|
||||
views.voiceMessageMicButton
|
||||
.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -304,9 +304,9 @@ class VoiceMessageViews(
|
|||
views.voiceMessageToast.isVisible = false
|
||||
}
|
||||
|
||||
fun renderRecordingTimer(recordingState: RecordingUiState, recordingTimeMillis: Long) {
|
||||
fun renderRecordingTimer(isLocked: Boolean, recordingTimeMillis: Long) {
|
||||
val formattedTimerText = DateUtils.formatElapsedTime(recordingTimeMillis)
|
||||
if (recordingState == RecordingUiState.Locked) {
|
||||
if (isLocked) {
|
||||
views.voicePlaybackTime.apply {
|
||||
post {
|
||||
text = formattedTimerText
|
||||
|
|
Loading…
Reference in New Issue