fix(ui): Make VideoRecordingStatus more responsive for landscape

Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
This commit is contained in:
Myzel394 2024-02-23 22:41:31 +01:00
parent e5d594a273
commit 590f3f2d13
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
2 changed files with 190 additions and 126 deletions

View File

@ -29,6 +29,7 @@ import kotlinx.coroutines.delay
@Composable
fun RecordingControl(
modifier: Modifier = Modifier,
orientation: Int = LocalConfiguration.current.orientation,
initialDelay: Long = 0L,
isPaused: Boolean,
recordingTime: Long,
@ -36,7 +37,6 @@ fun RecordingControl(
onPauseResume: () -> Unit,
onSave: () -> Unit,
) {
val orientation = LocalConfiguration.current.orientation
val animateIn = rememberInitialRecordingAnimation(recordingTime)
var deleteButtonAlphaIsIn by rememberSaveable {

View File

@ -1,10 +1,13 @@
package app.myzel394.alibi.ui.components.RecorderScreen.organisms
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@ -19,6 +22,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
@ -37,141 +41,201 @@ import kotlinx.coroutines.launch
fun VideoRecordingStatus(
videoRecorder: VideoRecorderModel,
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val availableCameras = CameraInfo.queryAvailableCameras(context)
val orientation = LocalConfiguration.current.orientation
KeepScreenOn()
Column(
modifier = Modifier
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween,
) {
Box {}
Column(
verticalArrangement = Arrangement
.spacedBy(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
Icons.Default.CameraAlt,
contentDescription = null,
modifier = Modifier.size(64.dp)
)
if (videoRecorder.isStartingRecording) {
when (orientation) {
Configuration.ORIENTATION_LANDSCAPE -> {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement
.spacedBy(32.dp),
modifier = Modifier
.weight(1f)
.fillMaxWidth(0.9f)
.align(Alignment.CenterVertically),
) {
_VideoGeneralInfo(videoRecorder)
_VideoRecordingStatus(videoRecorder)
}
Box(
modifier = Modifier
.width(128.dp)
.height(
with(LocalDensity.current) {
MaterialTheme.typography.labelMedium.fontSize.toDp()
}
)
.shimmer()
.background(
MaterialTheme.colorScheme.surfaceVariant,
MaterialTheme.shapes.small
)
)
} else {
Text(
stringResource(
R.string.form_value_selected,
if (CameraInfo.checkHasNormalCameras(availableCameras)) {
videoRecorder.cameraID.let {
if (it == CameraInfo.Lens.BACK.androidValue)
stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_back_label)
else
stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_front_label)
}
} else {
stringResource(
R.string.ui_videoRecorder_action_start_settings_cameraLens_label,
videoRecorder.cameraID
)
}
),
style = MaterialTheme.typography.labelMedium,
)
}
}
if (videoRecorder.isStartingRecording) {
Text(
stringResource(R.string.ui_videoRecorder_info_starting),
style = MaterialTheme.typography.labelMedium,
)
} else {
RecordingStatus(
recordingTime = videoRecorder.recordingTime,
progress = videoRecorder.progress,
recordingStart = videoRecorder.recordingStart,
maxDuration = videoRecorder.settings!!.maxDuration,
)
}
Column(
verticalArrangement = Arrangement
.spacedBy(32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(bottom = 32.dp),
) {
if (!videoRecorder.isStartingRecording) {
val cameraControl = videoRecorder.recorderService!!.cameraControl!!
if (cameraControl.hasTorchAvailable()) {
val isTorchEnabled = cameraControl.isTorchEnabled()
TorchStatus(
enabled = isTorchEnabled,
onChange = {
if (isTorchEnabled) {
cameraControl.disableTorch()
} else {
cameraControl.enableTorch()
}
},
)
.weight(1f)
.fillMaxWidth(0.9f)
) {
Column(
verticalArrangement = Arrangement
.spacedBy(32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
_VideoControls(videoRecorder)
HorizontalDivider()
_PrimitiveControls(videoRecorder)
}
}
}
}
HorizontalDivider()
if (!videoRecorder.isStartingRecording) {
RecordingControl(
// There may be some edge cases where the app may crash if the
// user stops or pauses the recording too soon, so we simply add a
// small delay to prevent that
initialDelay = 1000L,
isPaused = videoRecorder.isPaused,
recordingTime = videoRecorder.recordingTime,
onDelete = {
scope.launch {
runCatching {
videoRecorder.stopRecording(context)
}
runCatching {
videoRecorder.destroyService(context)
}
videoRecorder.batchesFolder!!.deleteRecordings()
}
},
onPauseResume = {
if (videoRecorder.isPaused) {
videoRecorder.resumeRecording()
} else {
videoRecorder.pauseRecording()
}
},
onSave = {
videoRecorder.onRecordingSave(false)
}
)
} else {
else -> {
Column(
modifier = Modifier
.fillMaxSize()
.padding(bottom = 32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween,
) {
Box {}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement
.spacedBy(16.dp),
) {
_VideoGeneralInfo(videoRecorder)
_VideoRecordingStatus(videoRecorder)
}
Column(
verticalArrangement = Arrangement
.spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
_VideoControls(videoRecorder)
HorizontalDivider()
_PrimitiveControls(videoRecorder)
}
}
}
}
}
@Composable
fun _VideoGeneralInfo(videoRecorder: VideoRecorderModel) {
val context = LocalContext.current
val availableCameras = CameraInfo.queryAvailableCameras(context)
val orientation = LocalConfiguration.current.orientation
Column(
verticalArrangement = Arrangement
.spacedBy(if (orientation == Configuration.ORIENTATION_LANDSCAPE) 12.dp else 24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
Icons.Default.CameraAlt,
contentDescription = null,
modifier = Modifier.size(if (orientation == Configuration.ORIENTATION_LANDSCAPE) 48.dp else 64.dp)
)
if (videoRecorder.isStartingRecording) {
Box(
modifier = Modifier
.width(128.dp)
.height(
with(LocalDensity.current) {
MaterialTheme.typography.labelMedium.fontSize.toDp()
}
)
.shimmer()
.background(
MaterialTheme.colorScheme.surfaceVariant,
MaterialTheme.shapes.small
)
)
} else {
Text(
stringResource(
R.string.form_value_selected,
if (CameraInfo.checkHasNormalCameras(availableCameras)) {
videoRecorder.cameraID.let {
if (it == CameraInfo.Lens.BACK.androidValue)
stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_back_label)
else
stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_front_label)
}
} else {
stringResource(
R.string.ui_videoRecorder_action_start_settings_cameraLens_label,
videoRecorder.cameraID
)
}
),
style = MaterialTheme.typography.labelMedium,
)
}
}
}
@Composable
fun _VideoRecordingStatus(videoRecorder: VideoRecorderModel) {
RecordingStatus(
recordingTime = videoRecorder.recordingTime,
progress = videoRecorder.progress,
recordingStart = videoRecorder.recordingStart,
maxDuration = videoRecorder.settings!!.maxDuration,
)
}
@Composable
fun _PrimitiveControls(videoRecorder: VideoRecorderModel) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
RecordingControl(
orientation = Configuration.ORIENTATION_PORTRAIT,
// There may be some edge cases where the app may crash if the
// user stops or pauses the recording too soon, so we simply add a
// small delay to prevent that
initialDelay = 1000L,
isPaused = videoRecorder.isPaused,
recordingTime = videoRecorder.recordingTime,
onDelete = {
scope.launch {
runCatching {
videoRecorder.stopRecording(context)
}
runCatching {
videoRecorder.destroyService(context)
}
videoRecorder.batchesFolder!!.deleteRecordings()
}
},
onPauseResume = {
if (videoRecorder.isPaused) {
videoRecorder.resumeRecording()
} else {
videoRecorder.pauseRecording()
}
},
onSave = {
videoRecorder.onRecordingSave(false)
}
)
}
@Composable
fun _VideoControls(videoRecorder: VideoRecorderModel) {
if (!videoRecorder.isStartingRecording) {
val cameraControl = videoRecorder.recorderService!!.cameraControl!!
if (cameraControl.hasTorchAvailable()) {
val isTorchEnabled = cameraControl.isTorchEnabled()
TorchStatus(
enabled = isTorchEnabled,
onChange = {
if (isTorchEnabled) {
cameraControl.disableTorch()
} else {
cameraControl.enableTorch()
}
},
)
}
}
}