mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
fix: Improve camera-info.kt and CamerasSelection
This commit is contained in:
parent
7f757f46f3
commit
8a3bfcae4d
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
@ -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>
|
Loading…
x
Reference in New Issue
Block a user