Skip to content

Commit

Permalink
Merge pull request #20984 from wordpress-mobile/issue/v2c-show-elapse…
Browse files Browse the repository at this point in the history
…d-time

[Voice to Content\ Implement elapsed time indicator
  • Loading branch information
notandyvee committed Jun 17, 2024
2 parents 3f30c51 + b65e2a1 commit ff17d3b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import org.wordpress.android.R
import org.wordpress.android.ui.compose.components.buttons.Drawable
import org.wordpress.android.ui.compose.theme.AppTheme
import org.wordpress.android.util.audio.RecordingUpdate
import java.util.Locale

@Composable
fun VoiceToContentScreen(
Expand Down Expand Up @@ -100,7 +101,7 @@ fun VoiceToContentView(state: VoiceToContentUiState, recordingUpdate: RecordingU
VoiceToContentUIStateType.ERROR -> ErrorView(state)
else -> {
Header(state.header)
SecondaryHeader(state.secondaryHeader)
SecondaryHeader(state.secondaryHeader, recordingUpdate)
RecordingPanel(state, recordingUpdate)
}
}
Expand Down Expand Up @@ -159,14 +160,16 @@ fun Header(model: HeaderUIModel) {
}

@Composable
fun SecondaryHeader(model: SecondaryHeaderUIModel?) {
fun SecondaryHeader(model: SecondaryHeaderUIModel?, recordingUpdate: RecordingUpdate) {
model?.let {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(text = stringResource(id = model.label), style = secondaryHeaderStyle)
Spacer(modifier = Modifier.width(8.dp)) // Add space between text and progress
if (model.isLabelVisible) {
Text(text = stringResource(id = model.label), style = secondaryHeaderStyle)
Spacer(modifier = Modifier.width(8.dp)) // Add space between text and progress
}
if (model.isProgressIndicatorVisible) {
Box(
modifier = Modifier.size(20.dp) // size the progress indicator
Expand All @@ -176,13 +179,47 @@ fun SecondaryHeader(model: SecondaryHeaderUIModel?) {
)
}
} else {
Text(text = model.requestsAvailable, style = secondaryHeaderStyle)
Text(
text = if (model.isTimeElapsedVisible)
formatTime(recordingUpdate.remainingTimeInSeconds, model.timeMaxDurationInSeconds)
else model.requestsAvailable,
style = secondaryHeaderStyle
)
}
Spacer(modifier = Modifier.height(16.dp))
}
}
}

@Composable
fun formatTime(remainingTimeInSeconds: Int, maxDurationInSeconds: Int): String {
val default = getDefaultTimeString(maxDurationInSeconds)
if (remainingTimeInSeconds == -1) return default

val minutes = remainingTimeInSeconds / 60
val seconds = remainingTimeInSeconds % 60

val value = if (minutes == 1) default
else String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds)

return value
}

@Composable
fun getDefaultTimeString(maxDurationInSeconds: Int): String {
if (maxDurationInSeconds <= 0) {
return "00:00"
}

// Calculate minutes and seconds
val minutes = (maxDurationInSeconds - 1) / 60
val seconds = (maxDurationInSeconds - 1) % 60

// Format and return the default time string
return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds)
}


@Composable
fun RecordingPanel(model: VoiceToContentUiState, recordingUpdate: RecordingUpdate) {
model.recordingPanel?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ data class SecondaryHeaderUIModel(
val isLabelVisible: Boolean = true,
val isProgressIndicatorVisible: Boolean = false,
val requestsAvailable: String = "0",
val timeElapsed: String = "00:00:00",
val timeMaxDurationInSeconds: Int = 0,
val isTimeElapsedVisible: Boolean = false
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.RECORDI
import org.wordpress.android.util.audio.IAudioRecorder
import org.wordpress.android.util.audio.IAudioRecorder.AudioRecorderResult.Error
import org.wordpress.android.util.audio.IAudioRecorder.AudioRecorderResult.Success
import org.wordpress.android.util.audio.RecordingStrategy
import org.wordpress.android.util.audio.RecordingUpdate
import org.wordpress.android.viewmodel.ContextProvider
import org.wordpress.android.viewmodel.ScopedViewModel
Expand Down Expand Up @@ -136,6 +137,7 @@ class VoiceToContentViewModel @Inject constructor(
recordingUseCase.startRecording { audioRecorderResult ->
when (audioRecorderResult) {
is Success -> {
transitionToProcessing()
val file = getRecordingFile(audioRecorderResult.recordingPath)
file?.let {
executeVoiceToContent(it)
Expand Down Expand Up @@ -284,8 +286,9 @@ class VoiceToContentViewModel @Inject constructor(
uiStateType = RECORDING,
header = currentState.header.copy(label = R.string.voice_to_content_recording_label),
secondaryHeader = currentState.secondaryHeader?.copy(
timeElapsed = "00:00:00",
isTimeElapsedVisible = true
isTimeElapsedVisible = true,
timeMaxDurationInSeconds = MAX_DURATION,
isLabelVisible = false
),
recordingPanel = currentState.recordingPanel?.copy(
onStopTap = ::onStopTap,
Expand Down Expand Up @@ -338,6 +341,7 @@ class VoiceToContentViewModel @Inject constructor(
private val NetworkUnavailableMsg = R.string.error_network_connection
private val GenericFailureMsg = R.string.voice_to_content_generic_error
private const val VOICE_TO_CONTENT = "Voice to content"
private val MAX_DURATION = RecordingStrategy.VoiceToContentRecordingStrategy().maxDuration
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,16 @@ class AudioRecorder(
@Suppress("MagicNumber")
private fun startRecordingUpdates() {
recordingJob = coroutineScope.launch {
var elapsedTimeInSeconds = 0
val startTime = System.currentTimeMillis()
val amplitudeList = mutableListOf<Float>()
while (recorder != null) {
delay(RECORDING_UPDATE_INTERVAL)
elapsedTimeInSeconds += (RECORDING_UPDATE_INTERVAL / 1000).toInt()
// Calculate elapsed time in seconds
val elapsedTimeInSeconds = ((System.currentTimeMillis() - startTime) / 1000).toInt()

// Calculate remaining time
val remainingTimeInSeconds = recordingStrategy.maxDuration - elapsedTimeInSeconds

val fileSize = File(filePath).length()
val amplitude = recorder?.maxAmplitude?.toFloat() ?: 0f
amplitudeList.add(amplitude)
Expand All @@ -162,7 +167,7 @@ class AudioRecorder(
amplitudeList.removeAt(0)
}
_recordingUpdates.value = RecordingUpdate(
elapsedTime = elapsedTimeInSeconds,
remainingTimeInSeconds = remainingTimeInSeconds,
fileSize = fileSize,
fileSizeLimitExceeded = fileSize >= recordingStrategy.maxFileSize,
amplitudes = amplitudeList.toList()
Expand Down Expand Up @@ -208,7 +213,7 @@ class AudioRecorder(

companion object {
private const val TAG = "AudioRecorder"
private const val RECORDING_UPDATE_INTERVAL = 100L // in milliseconds
private const val RECORDING_UPDATE_INTERVAL = 75L // in milliseconds
private const val RESUME_DELAY = 500L // in milliseconds
private const val FILE_SIZE_THRESHOLD = 100000L
private const val DURATION_THRESHOLD = 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.wordpress.android.util.audio

data class RecordingUpdate(
val elapsedTime: Int = 0, // in seconds
val remainingTimeInSeconds: Int = -1,
val fileSize: Long = 0L, // in bytes
val fileSizeLimitExceeded: Boolean = false,
val amplitudes: List<Float> = emptyList()
Expand Down

0 comments on commit ff17d3b

Please sign in to comment.