Merge pull request #7588 from vector-im/feature/fre/voice_broadcast_recording_time
Voice Broadcast - Add max length for recording
This commit is contained in:
commit
54fcdcdb6d
|
@ -0,0 +1 @@
|
||||||
|
Voice Broadcast - Add maximum length
|
|
@ -3101,6 +3101,8 @@
|
||||||
<string name="error_voice_broadcast_permission_denied_message">You don’t have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.</string>
|
<string name="error_voice_broadcast_permission_denied_message">You don’t have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.</string>
|
||||||
<string name="error_voice_broadcast_blocked_by_someone_else_message">Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.</string>
|
<string name="error_voice_broadcast_blocked_by_someone_else_message">Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.</string>
|
||||||
<string name="error_voice_broadcast_already_in_progress_message">You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.</string>
|
<string name="error_voice_broadcast_already_in_progress_message">You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.</string>
|
||||||
|
<!-- Examples of usage: 6h 15min 30sec left / 15min 30sec left / 30sec left -->
|
||||||
|
<string name="voice_broadcast_recording_time_left">%1$s left</string>
|
||||||
|
|
||||||
<string name="upgrade_room_for_restricted">Anyone in %s will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime.</string>
|
<string name="upgrade_room_for_restricted">Anyone in %s will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime.</string>
|
||||||
<string name="upgrade_room_for_restricted_no_param">Anyone in a parent space will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime.</string>
|
<string name="upgrade_room_for_restricted_no_param">Anyone in a parent space will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime.</string>
|
||||||
|
|
|
@ -66,7 +66,7 @@ class AudioMessageHelper @Inject constructor(
|
||||||
|
|
||||||
fun startRecording(roomId: String) {
|
fun startRecording(roomId: String) {
|
||||||
stopPlayback()
|
stopPlayback()
|
||||||
playbackTracker.makeAllPlaybacksIdle()
|
playbackTracker.pauseAllPlaybacks()
|
||||||
amplitudeList.clear()
|
amplitudeList.clear()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -51,15 +51,7 @@ class AudioMessagePlaybackTracker @Inject constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pauseAllPlaybacks() {
|
fun pauseAllPlaybacks() {
|
||||||
listeners.keys.forEach { key ->
|
listeners.keys.forEach(::pausePlayback)
|
||||||
pausePlayback(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun makeAllPlaybacksIdle() {
|
|
||||||
listeners.keys.forEach { key ->
|
|
||||||
setState(key, Listener.State.Idle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,10 +21,12 @@ import androidx.core.view.isVisible
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.epoxy.onClick
|
import im.vector.app.core.epoxy.onClick
|
||||||
|
import im.vector.app.core.utils.TextUtils
|
||||||
import im.vector.app.features.home.room.detail.RoomDetailAction.VoiceBroadcastAction
|
import im.vector.app.features.home.room.detail.RoomDetailAction.VoiceBroadcastAction
|
||||||
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
|
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
|
||||||
import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder
|
import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder
|
||||||
import im.vector.app.features.voicebroadcast.views.VoiceBroadcastMetadataView
|
import im.vector.app.features.voicebroadcast.views.VoiceBroadcastMetadataView
|
||||||
|
import org.threeten.bp.Duration
|
||||||
|
|
||||||
@EpoxyModelClass
|
@EpoxyModelClass
|
||||||
abstract class MessageVoiceBroadcastRecordingItem : AbsMessageVoiceBroadcastItem<MessageVoiceBroadcastRecordingItem.Holder>() {
|
abstract class MessageVoiceBroadcastRecordingItem : AbsMessageVoiceBroadcastItem<MessageVoiceBroadcastRecordingItem.Holder>() {
|
||||||
|
@ -37,11 +39,15 @@ abstract class MessageVoiceBroadcastRecordingItem : AbsMessageVoiceBroadcastItem
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindVoiceBroadcastItem(holder: Holder) {
|
private fun bindVoiceBroadcastItem(holder: Holder) {
|
||||||
if (recorder != null && recorder?.state != VoiceBroadcastRecorder.State.Idle) {
|
if (recorder != null && recorder?.recordingState != VoiceBroadcastRecorder.State.Idle) {
|
||||||
recorderListener = object : VoiceBroadcastRecorder.Listener {
|
recorderListener = object : VoiceBroadcastRecorder.Listener {
|
||||||
override fun onStateUpdated(state: VoiceBroadcastRecorder.State) {
|
override fun onStateUpdated(state: VoiceBroadcastRecorder.State) {
|
||||||
renderRecordingState(holder, state)
|
renderRecordingState(holder, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRemainingTimeUpdated(remainingTime: Long?) {
|
||||||
|
renderRemainingTime(holder, remainingTime)
|
||||||
|
}
|
||||||
}.also { recorder?.addListener(it) }
|
}.also { recorder?.addListener(it) }
|
||||||
} else {
|
} else {
|
||||||
renderVoiceBroadcastState(holder)
|
renderVoiceBroadcastState(holder)
|
||||||
|
@ -58,9 +64,19 @@ abstract class MessageVoiceBroadcastRecordingItem : AbsMessageVoiceBroadcastItem
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renderMetadata(holder: Holder) {
|
override fun renderMetadata(holder: Holder) {
|
||||||
with(holder) {
|
holder.listenersCountMetadata.isVisible = false
|
||||||
listenersCountMetadata.isVisible = false
|
}
|
||||||
remainingTimeMetadata.isVisible = false
|
|
||||||
|
private fun renderRemainingTime(holder: Holder, remainingTime: Long?) {
|
||||||
|
if (remainingTime != null) {
|
||||||
|
val formattedDuration = TextUtils.formatDurationWithUnits(
|
||||||
|
holder.view.context,
|
||||||
|
Duration.ofSeconds(remainingTime.coerceAtLeast(0L))
|
||||||
|
)
|
||||||
|
holder.remainingTimeMetadata.value = holder.view.resources.getString(R.string.voice_broadcast_recording_time_left, formattedDuration)
|
||||||
|
holder.remainingTimeMetadata.isVisible = true
|
||||||
|
} else {
|
||||||
|
holder.remainingTimeMetadata.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,4 +28,7 @@ object VoiceBroadcastConstants {
|
||||||
|
|
||||||
/** Default voice broadcast chunk duration, in seconds. */
|
/** Default voice broadcast chunk duration, in seconds. */
|
||||||
const val DEFAULT_CHUNK_LENGTH_IN_SECONDS = 120
|
const val DEFAULT_CHUNK_LENGTH_IN_SECONDS = 120
|
||||||
|
|
||||||
|
/** Maximum length of the voice broadcast in seconds. */
|
||||||
|
const val MAX_VOICE_BROADCAST_LENGTH_IN_SECONDS = 14_400 // 4 hours
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,23 @@ import java.io.File
|
||||||
|
|
||||||
interface VoiceBroadcastRecorder : VoiceRecorder {
|
interface VoiceBroadcastRecorder : VoiceRecorder {
|
||||||
|
|
||||||
|
/** The current chunk number. */
|
||||||
val currentSequence: Int
|
val currentSequence: Int
|
||||||
val state: State
|
|
||||||
|
|
||||||
fun startRecord(roomId: String, chunkLength: Int)
|
/** Current state of the recorder. */
|
||||||
|
val recordingState: State
|
||||||
|
|
||||||
|
/** Current remaining time of recording, in seconds, if any. */
|
||||||
|
val currentRemainingTime: Long?
|
||||||
|
|
||||||
|
fun startRecord(roomId: String, chunkLength: Int, maxLength: Int)
|
||||||
fun addListener(listener: Listener)
|
fun addListener(listener: Listener)
|
||||||
fun removeListener(listener: Listener)
|
fun removeListener(listener: Listener)
|
||||||
|
|
||||||
interface Listener {
|
interface Listener {
|
||||||
fun onVoiceMessageCreated(file: File, @IntRange(from = 1) sequence: Int) = Unit
|
fun onVoiceMessageCreated(file: File, @IntRange(from = 1) sequence: Int) = Unit
|
||||||
fun onStateUpdated(state: State) = Unit
|
fun onStateUpdated(state: State) = Unit
|
||||||
|
fun onRemainingTimeUpdated(remainingTime: Long?) = Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class State {
|
enum class State {
|
||||||
|
|
|
@ -21,9 +21,11 @@ import android.media.MediaRecorder
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import im.vector.app.features.voice.AbstractVoiceRecorderQ
|
import im.vector.app.features.voice.AbstractVoiceRecorderQ
|
||||||
|
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
|
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.Q)
|
@RequiresApi(Build.VERSION_CODES.Q)
|
||||||
class VoiceBroadcastRecorderQ(
|
class VoiceBroadcastRecorderQ(
|
||||||
|
@ -32,13 +34,21 @@ class VoiceBroadcastRecorderQ(
|
||||||
|
|
||||||
private var maxFileSize = 0L // zero or negative for no limit
|
private var maxFileSize = 0L // zero or negative for no limit
|
||||||
private var currentRoomId: String? = null
|
private var currentRoomId: String? = null
|
||||||
|
private var currentMaxLength: Int = 0
|
||||||
|
|
||||||
override var currentSequence = 0
|
override var currentSequence = 0
|
||||||
override var state = VoiceBroadcastRecorder.State.Idle
|
override var recordingState = VoiceBroadcastRecorder.State.Idle
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
listeners.forEach { it.onStateUpdated(value) }
|
listeners.forEach { it.onStateUpdated(value) }
|
||||||
}
|
}
|
||||||
|
override var currentRemainingTime: Long? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
listeners.forEach { it.onRemainingTimeUpdated(value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val recordingTicker = RecordingTicker()
|
||||||
private val listeners = CopyOnWriteArrayList<VoiceBroadcastRecorder.Listener>()
|
private val listeners = CopyOnWriteArrayList<VoiceBroadcastRecorder.Listener>()
|
||||||
|
|
||||||
override val outputFormat = MediaRecorder.OutputFormat.MPEG_4
|
override val outputFormat = MediaRecorder.OutputFormat.MPEG_4
|
||||||
|
@ -58,33 +68,47 @@ class VoiceBroadcastRecorderQ(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startRecord(roomId: String, chunkLength: Int) {
|
override fun startRecord(roomId: String, chunkLength: Int, maxLength: Int) {
|
||||||
currentRoomId = roomId
|
currentRoomId = roomId
|
||||||
maxFileSize = (chunkLength * audioEncodingBitRate / 8).toLong()
|
maxFileSize = (chunkLength * audioEncodingBitRate / 8).toLong()
|
||||||
|
currentMaxLength = maxLength
|
||||||
currentSequence = 1
|
currentSequence = 1
|
||||||
startRecord(roomId)
|
startRecord(roomId)
|
||||||
state = VoiceBroadcastRecorder.State.Recording
|
recordingState = VoiceBroadcastRecorder.State.Recording
|
||||||
|
recordingTicker.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pauseRecord() {
|
override fun pauseRecord() {
|
||||||
tryOrNull { mediaRecorder?.stop() }
|
tryOrNull { mediaRecorder?.stop() }
|
||||||
mediaRecorder?.reset()
|
mediaRecorder?.reset()
|
||||||
|
recordingState = VoiceBroadcastRecorder.State.Paused
|
||||||
|
recordingTicker.pause()
|
||||||
notifyOutputFileCreated()
|
notifyOutputFileCreated()
|
||||||
state = VoiceBroadcastRecorder.State.Paused
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resumeRecord() {
|
override fun resumeRecord() {
|
||||||
currentSequence++
|
currentSequence++
|
||||||
currentRoomId?.let { startRecord(it) }
|
currentRoomId?.let { startRecord(it) }
|
||||||
state = VoiceBroadcastRecorder.State.Recording
|
recordingState = VoiceBroadcastRecorder.State.Recording
|
||||||
|
recordingTicker.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stopRecord() {
|
override fun stopRecord() {
|
||||||
super.stopRecord()
|
super.stopRecord()
|
||||||
|
|
||||||
|
// Stop recording
|
||||||
|
recordingState = VoiceBroadcastRecorder.State.Idle
|
||||||
|
recordingTicker.stop()
|
||||||
notifyOutputFileCreated()
|
notifyOutputFileCreated()
|
||||||
|
|
||||||
|
// Remove listeners
|
||||||
listeners.clear()
|
listeners.clear()
|
||||||
|
|
||||||
|
// Reset data
|
||||||
currentSequence = 0
|
currentSequence = 0
|
||||||
state = VoiceBroadcastRecorder.State.Idle
|
currentMaxLength = 0
|
||||||
|
currentRemainingTime = null
|
||||||
|
currentRoomId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun release() {
|
override fun release() {
|
||||||
|
@ -94,7 +118,8 @@ class VoiceBroadcastRecorderQ(
|
||||||
|
|
||||||
override fun addListener(listener: VoiceBroadcastRecorder.Listener) {
|
override fun addListener(listener: VoiceBroadcastRecorder.Listener) {
|
||||||
listeners.add(listener)
|
listeners.add(listener)
|
||||||
listener.onStateUpdated(state)
|
listener.onStateUpdated(recordingState)
|
||||||
|
listener.onRemainingTimeUpdated(currentRemainingTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeListener(listener: VoiceBroadcastRecorder.Listener) {
|
override fun removeListener(listener: VoiceBroadcastRecorder.Listener) {
|
||||||
|
@ -117,4 +142,53 @@ class VoiceBroadcastRecorderQ(
|
||||||
nextOutputFile = null
|
nextOutputFile = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onElapsedTimeUpdated(elapsedTimeMillis: Long) {
|
||||||
|
currentRemainingTime = if (currentMaxLength > 0 && recordingState != VoiceBroadcastRecorder.State.Idle) {
|
||||||
|
val currentMaxLengthMillis = TimeUnit.SECONDS.toMillis(currentMaxLength.toLong())
|
||||||
|
val remainingTimeMillis = currentMaxLengthMillis - elapsedTimeMillis
|
||||||
|
TimeUnit.MILLISECONDS.toSeconds(remainingTimeMillis)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class RecordingTicker(
|
||||||
|
private var recordingTicker: CountUpTimer? = null,
|
||||||
|
) {
|
||||||
|
fun start() {
|
||||||
|
recordingTicker?.stop()
|
||||||
|
recordingTicker = CountUpTimer().apply {
|
||||||
|
tickListener = CountUpTimer.TickListener { onTick(elapsedTime()) }
|
||||||
|
resume()
|
||||||
|
onTick(elapsedTime())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pause() {
|
||||||
|
recordingTicker?.apply {
|
||||||
|
pause()
|
||||||
|
onTick(elapsedTime())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resume() {
|
||||||
|
recordingTicker?.apply {
|
||||||
|
resume()
|
||||||
|
onTick(elapsedTime())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
recordingTicker?.apply {
|
||||||
|
stop()
|
||||||
|
onTick(elapsedTime())
|
||||||
|
recordingTicker = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onTick(elapsedTimeMillis: Long) {
|
||||||
|
onElapsedTimeUpdated(elapsedTimeMillis)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import im.vector.app.core.resources.BuildMeta
|
import im.vector.app.core.resources.BuildMeta
|
||||||
import im.vector.app.features.attachments.toContentAttachmentData
|
import im.vector.app.features.attachments.toContentAttachmentData
|
||||||
|
import im.vector.app.features.session.coroutineScope
|
||||||
import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
|
import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
|
||||||
import im.vector.app.features.voicebroadcast.VoiceBroadcastFailure
|
import im.vector.app.features.voicebroadcast.VoiceBroadcastFailure
|
||||||
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
|
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
|
||||||
|
@ -28,6 +29,7 @@ import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
|
||||||
import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder
|
import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder
|
||||||
import im.vector.app.features.voicebroadcast.usecase.GetOngoingVoiceBroadcastsUseCase
|
import im.vector.app.features.voicebroadcast.usecase.GetOngoingVoiceBroadcastsUseCase
|
||||||
import im.vector.lib.multipicker.utils.toMultiPickerAudioType
|
import im.vector.lib.multipicker.utils.toMultiPickerAudioType
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.jetbrains.annotations.VisibleForTesting
|
import org.jetbrains.annotations.VisibleForTesting
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
@ -51,6 +53,7 @@ class StartVoiceBroadcastUseCase @Inject constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
private val getOngoingVoiceBroadcastsUseCase: GetOngoingVoiceBroadcastsUseCase,
|
private val getOngoingVoiceBroadcastsUseCase: GetOngoingVoiceBroadcastsUseCase,
|
||||||
|
private val stopVoiceBroadcastUseCase: StopVoiceBroadcastUseCase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun execute(roomId: String): Result<Unit> = runCatching {
|
suspend fun execute(roomId: String): Result<Unit> = runCatching {
|
||||||
|
@ -64,7 +67,8 @@ class StartVoiceBroadcastUseCase @Inject constructor(
|
||||||
|
|
||||||
private suspend fun startVoiceBroadcast(room: Room) {
|
private suspend fun startVoiceBroadcast(room: Room) {
|
||||||
Timber.d("## StartVoiceBroadcastUseCase: Send new voice broadcast info state event")
|
Timber.d("## StartVoiceBroadcastUseCase: Send new voice broadcast info state event")
|
||||||
val chunkLength = VoiceBroadcastConstants.DEFAULT_CHUNK_LENGTH_IN_SECONDS // Todo Get the length from the room settings
|
val chunkLength = VoiceBroadcastConstants.DEFAULT_CHUNK_LENGTH_IN_SECONDS // Todo Get the chunk length from the room settings
|
||||||
|
val maxLength = VoiceBroadcastConstants.MAX_VOICE_BROADCAST_LENGTH_IN_SECONDS // Todo Get the max length from the room settings
|
||||||
val eventId = room.stateService().sendStateEvent(
|
val eventId = room.stateService().sendStateEvent(
|
||||||
eventType = VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO,
|
eventType = VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO,
|
||||||
stateKey = session.myUserId,
|
stateKey = session.myUserId,
|
||||||
|
@ -75,16 +79,22 @@ class StartVoiceBroadcastUseCase @Inject constructor(
|
||||||
).toContent()
|
).toContent()
|
||||||
)
|
)
|
||||||
|
|
||||||
startRecording(room, eventId, chunkLength)
|
startRecording(room, eventId, chunkLength, maxLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startRecording(room: Room, eventId: String, chunkLength: Int) {
|
private fun startRecording(room: Room, eventId: String, chunkLength: Int, maxLength: Int) {
|
||||||
voiceBroadcastRecorder?.addListener(object : VoiceBroadcastRecorder.Listener {
|
voiceBroadcastRecorder?.addListener(object : VoiceBroadcastRecorder.Listener {
|
||||||
override fun onVoiceMessageCreated(file: File, sequence: Int) {
|
override fun onVoiceMessageCreated(file: File, sequence: Int) {
|
||||||
sendVoiceFile(room, file, eventId, sequence)
|
sendVoiceFile(room, file, eventId, sequence)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRemainingTimeUpdated(remainingTime: Long?) {
|
||||||
|
if (remainingTime != null && remainingTime <= 0) {
|
||||||
|
session.coroutineScope.launch { stopVoiceBroadcastUseCase.execute(room.roomId) }
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
voiceBroadcastRecorder?.startRecord(room.roomId, chunkLength)
|
voiceBroadcastRecorder?.startRecord(room.roomId, chunkLength, maxLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendVoiceFile(room: Room, voiceMessageFile: File, referenceEventId: String, sequence: Int) {
|
private fun sendVoiceFile(room: Room, voiceMessageFile: File, referenceEventId: String, sequence: Int) {
|
||||||
|
@ -127,7 +137,8 @@ class StartVoiceBroadcastUseCase @Inject constructor(
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
fun assertNoOngoingVoiceBroadcast(room: Room) {
|
fun assertNoOngoingVoiceBroadcast(room: Room) {
|
||||||
when {
|
when {
|
||||||
voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Recording || voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Paused -> {
|
voiceBroadcastRecorder?.recordingState == VoiceBroadcastRecorder.State.Recording ||
|
||||||
|
voiceBroadcastRecorder?.recordingState == VoiceBroadcastRecorder.State.Paused -> {
|
||||||
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: another voice broadcast")
|
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: another voice broadcast")
|
||||||
throw VoiceBroadcastFailure.RecordingError.UserAlreadyBroadcasting
|
throw VoiceBroadcastFailure.RecordingError.UserAlreadyBroadcasting
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ class StartVoiceBroadcastUseCaseTest {
|
||||||
context = FakeContext().instance,
|
context = FakeContext().instance,
|
||||||
buildMeta = mockk(),
|
buildMeta = mockk(),
|
||||||
getOngoingVoiceBroadcastsUseCase = fakeGetOngoingVoiceBroadcastsUseCase,
|
getOngoingVoiceBroadcastsUseCase = fakeGetOngoingVoiceBroadcastsUseCase,
|
||||||
|
stopVoiceBroadcastUseCase = mockk()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ class StartVoiceBroadcastUseCaseTest {
|
||||||
fun setup() {
|
fun setup() {
|
||||||
every { fakeRoom.roomId } returns A_ROOM_ID
|
every { fakeRoom.roomId } returns A_ROOM_ID
|
||||||
justRun { startVoiceBroadcastUseCase.assertHasEnoughPowerLevels(fakeRoom) }
|
justRun { startVoiceBroadcastUseCase.assertHasEnoughPowerLevels(fakeRoom) }
|
||||||
every { fakeVoiceBroadcastRecorder.state } returns VoiceBroadcastRecorder.State.Idle
|
every { fakeVoiceBroadcastRecorder.recordingState } returns VoiceBroadcastRecorder.State.Idle
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue