fix: Improve camera-info.kt and CamerasSelection

This commit is contained in:
Myzel394 2023-12-04 09:27:28 +01:00
parent 7f757f46f3
commit 8a3bfcae4d
No known key found for this signature in database
GPG Key ID: 50098FCA22080F0F
6 changed files with 121 additions and 104 deletions

View File

@ -1,5 +1,4 @@
package app.myzel394.alibi.ui.components.RecorderScreen.atoms
import androidx.camera.core.ExperimentalLensFacing
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
@ -28,6 +27,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.ui.utils.CameraInfo
@Composable
fun CameraSelectionButton(
cameraID: CameraInfo.Lens,

View File

@ -1,10 +1,13 @@
package app.myzel394.alibi.ui.components.RecorderScreen.molecules
import CameraSelectionButton
import androidx.annotation.OptIn
import androidx.camera.core.CameraSelector
import androidx.camera.core.ExperimentalLensFacing
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import app.myzel394.alibi.R
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.CameraSelectionButton
import app.myzel394.alibi.ui.models.VideoRecorderSettingsModel
import app.myzel394.alibi.ui.utils.CameraInfo
@ -24,23 +27,23 @@ fun CamerasSelection(
CameraSelectionButton(
cameraID = CameraInfo.Lens.BACK,
label = stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_back_label),
selected = videoSettings.cameraID == 0,
selected = videoSettings.cameraID == CameraInfo.Lens.BACK.androidValue,
onSelected = {
videoSettings.cameraID = 0
videoSettings.cameraID = CameraInfo.Lens.BACK.androidValue
},
)
CameraSelectionButton(
cameraID = CameraInfo.Lens.FRONT,
label = stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_front_label),
selected = videoSettings.cameraID == 1,
selected = videoSettings.cameraID == CameraInfo.Lens.FRONT.androidValue,
onSelected = {
videoSettings.cameraID = 1
videoSettings.cameraID = CameraInfo.Lens.FRONT.androidValue
},
)
} else {
cameras.forEach { camera ->
CameraSelectionButton(
cameraID = CameraInfo.CAMERA_INT_TO_LENS_MAP[camera.id]!!,
cameraID = camera.lens,
selected = videoSettings.cameraID == camera.id,
onSelected = {
videoSettings.cameraID = camera.id

View File

@ -1,6 +1,7 @@
package app.myzel394.alibi.ui.components.RecorderScreen.molecules
import android.Manifest
import androidx.camera.core.CameraSelector
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
@ -10,6 +11,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@ -26,6 +28,10 @@ import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@ -45,12 +51,12 @@ import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.CameraPreview
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
import app.myzel394.alibi.ui.components.atoms.PermissionRequester
import app.myzel394.alibi.ui.effects.rememberPrevious
import app.myzel394.alibi.ui.models.VideoRecorderSettingsModel
import app.myzel394.alibi.ui.utils.CameraInfo
@OptIn(
ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
ExperimentalComposeUiApi::class
ExperimentalMaterial3Api::class,
)
@Composable
fun VideoRecorderPreparationSheet(
@ -69,19 +75,34 @@ fun VideoRecorderPreparationSheet(
videoSettings.init(context)
}
if (showPreview)
CameraPreview(
ModalBottomSheet(
onDismissRequest = onDismiss,
sheetState = sheetState,
dragHandle = if (showPreview) {
null
} else null,
) {
Box(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
)
else {
ModalBottomSheet(
onDismissRequest = onDismiss,
sheetState = sheetState,
.pointerInput(Unit) {
awaitEachGesture {
while (true) {
val event = awaitPointerEvent()
if (!event.changes.elementAt(0).pressed) {
onPreviewHidden()
break
}
}
}
}
) {
Box(
) {
if (showPreview) {
CameraPreview(
modifier = Modifier
.fillMaxSize(),
cameraSelector = videoSettings.cameraSelector,
)
} else
Column(
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 24.dp),
@ -119,80 +140,63 @@ fun VideoRecorderPreparationSheet(
)
}
Text(
stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_selection_label),
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.Start,
modifier = Modifier.fillMaxWidth()
)
CamerasSelection(
cameras = cameras,
videoSettings = videoSettings,
)
Box(
modifier = Modifier
.fillMaxWidth()
.height(BIG_PRIMARY_BUTTON_SIZE)
)
}
}
}
}
Popup(
alignment = Alignment.BottomCenter,
) {
val label =
stringResource(R.string.ui_videoRecorder_action_start_settings_start_label)
Box(
modifier = Modifier
.pointerInput(Unit) {
awaitEachGesture {
while (true) {
val event = awaitPointerEvent()
// consume all changes
if (!event.changes.elementAt(0).pressed) {
onPreviewHidden()
break
}
}
}
}
.let {
if (showPreview) it.alpha(0.2f) else it
}
) {
Row(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
.height(BIG_PRIMARY_BUTTON_SIZE)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.primary)
.padding(16.dp)
.semantics {
contentDescription = label
}
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
onPreviewVisible()
}
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(
stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_selection_label),
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.Start,
modifier = Modifier.fillMaxWidth()
)
},
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
label,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onPrimary,
)
}
CamerasSelection(
cameras = cameras,
videoSettings = videoSettings,
)
}
val label =
stringResource(R.string.ui_videoRecorder_action_start_settings_start_label)
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(BIG_PRIMARY_BUTTON_SIZE)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.primary)
.padding(16.dp)
.semantics {
contentDescription = label
}
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
onPreviewVisible()
}
)
},
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
label,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onPrimary,
)
}
Text(
stringResource(
R.string.ui_videoRecorder_action_preview_label
),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}
}
}

View File

@ -11,14 +11,18 @@ import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import app.myzel394.alibi.ui.utils.CameraInfo
import app.myzel394.alibi.ui.utils.PermissionHelper
class VideoRecorderSettingsModel : ViewModel() {
var enableAudio by mutableStateOf(true)
var cameraID by mutableIntStateOf(CameraSelector.LENS_FACING_BACK)
var cameraID by mutableIntStateOf(CameraInfo.Lens.BACK.androidValue)
val cameraSelector: CameraSelector
get() = CameraSelector.Builder().requireLensFacing(cameraID).build()
fun init(context: Context) {
enableAudio = PermissionHelper.hasGranted(context, Manifest.permission.RECORD_AUDIO)
cameraID = CameraSelector.LENS_FACING_BACK
cameraID = CameraInfo.Lens.BACK.androidValue
}
}

View File

@ -4,22 +4,28 @@ import android.content.Context
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CameraMetadata
import androidx.annotation.OptIn
import androidx.camera.core.CameraSelector
import androidx.camera.core.ExperimentalLensFacing
@OptIn(ExperimentalLensFacing::class)
data class CameraInfo(
val lens: Lens,
val id: Int,
) {
enum class Lens(val androidValue: Int) {
BACK(CameraMetadata.LENS_FACING_BACK),
FRONT(CameraMetadata.LENS_FACING_FRONT),
EXTERNAL(CameraMetadata.LENS_FACING_EXTERNAL),
BACK(CameraSelector.LENS_FACING_BACK),
FRONT(CameraSelector.LENS_FACING_FRONT),
EXTERNAL(CameraSelector.LENS_FACING_EXTERNAL),
}
val lens: Lens
get() = CAMERA_INT_TO_LENS_MAP[id]!!
companion object {
val CAMERA_INT_TO_LENS_MAP = mapOf(
0 to Lens.BACK,
1 to Lens.FRONT,
2 to Lens.EXTERNAL,
CameraSelector.LENS_FACING_BACK to Lens.BACK,
CameraSelector.LENS_FACING_FRONT to Lens.FRONT,
CameraSelector.LENS_FACING_EXTERNAL to Lens.EXTERNAL,
)
fun queryAvailableCameras(context: Context): List<CameraInfo> {
@ -36,7 +42,6 @@ data class CameraInfo(
fun fromCameraId(cameraId: String, lensFacing: Int): CameraInfo {
return CameraInfo(
lens = CAMERA_INT_TO_LENS_MAP[lensFacing]!!,
id = cameraId.toInt(),
)
}

View File

@ -147,4 +147,5 @@
<string name="ui_videoRecorder_action_start_settings_start_label">Start Recording</string>
<string name="ui_videoRecorder_action_start_settings_label">Prepare your recording</string>
<string name="ui_videoRecorder_action_start_settings_cameraLens_selection_label">Select camera</string>
<string name="ui_videoRecorder_action_preview_label">Hold down on button to preview your camera</string>
</resources>