diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/CameraPreview.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/CameraPreview.kt index d0530ac..3046973 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/CameraPreview.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/CameraPreview.kt @@ -1,56 +1,56 @@ package app.myzel394.alibi.ui.components.RecorderScreen.atoms +import android.util.Log import android.view.ViewGroup import androidx.camera.core.CameraSelector import androidx.camera.core.Preview -import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.view.PreviewView +import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.viewinterop.AndroidView +import app.myzel394.alibi.ui.utils.getCameraProvider import kotlinx.coroutines.launch @Composable fun CameraPreview( - modifier: Modifier = Modifier, - scaleType: PreviewView.ScaleType = PreviewView.ScaleType.FILL_CENTER, + modifier: Modifier, cameraSelector: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA ) { val coroutineScope = rememberCoroutineScope() val lifecycleOwner = LocalLifecycleOwner.current - AndroidView( - modifier = modifier, - factory = { context -> - val previewView = PreviewView(context).apply { - this.scaleType = scaleType - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - } - // CameraX Preview UseCase - val previewUseCase = Preview.Builder() - .build() - .also { - it.setSurfaceProvider(previewView.surfaceProvider) - } - - coroutineScope.launch { - val cameraProvider = ProcessCameraProvider.getInstance(context).get() - try { - // Must unbind the use-cases before rebinding them. - cameraProvider.unbindAll() - cameraProvider.bindToLifecycle( - lifecycleOwner, cameraSelector, previewUseCase + Box(modifier = modifier) { + // Video preview + AndroidView( + factory = { context -> + val previewView = PreviewView(context).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ) - } catch (ex: Exception) { } - } + val previewUseCase = Preview.Builder() + .build() + .also { it.setSurfaceProvider(previewView.surfaceProvider) } - previewView - } - ) -} \ No newline at end of file + coroutineScope.launch { + val cameraProvider = context.getCameraProvider() + try { + cameraProvider.unbindAll() + cameraProvider.bindToLifecycle( + lifecycleOwner, + cameraSelector, + previewUseCase + ) + } catch (ex: Exception) { + Log.e("CameraPreview", "Use case binding failed", ex) + } + } + previewView + }, + ) + } +} diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/VideoRecordingStatus.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/VideoRecordingStatus.kt index 9009a99..7927f8b 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/VideoRecordingStatus.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/VideoRecordingStatus.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import app.myzel394.alibi.R +import app.myzel394.alibi.ui.components.RecorderScreen.atoms.CameraPreview import app.myzel394.alibi.dataStore import app.myzel394.alibi.ui.components.RecorderScreen.atoms.SaveCurrentNowModal import app.myzel394.alibi.ui.components.RecorderScreen.atoms.TorchStatus @@ -54,68 +55,79 @@ fun VideoRecordingStatus( 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 - .weight(1f) - .fillMaxWidth(0.9f) + Box { + CameraPreview( + modifier = Modifier, + cameraSelector = videoRecorder.cameraSelector + ) + Row( + modifier = Modifier.fillMaxSize(), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically, ) { Column( + horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement .spacedBy(32.dp), - horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .weight(1f) + .fillMaxWidth(0.9f) + .align(Alignment.CenterVertically), ) { - _VideoControls(videoRecorder) - HorizontalDivider() - _PrimitiveControls(videoRecorder) + _VideoGeneralInfo(videoRecorder) + _VideoRecordingStatus(videoRecorder) + } + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth(0.9f) + ) { + Column( + verticalArrangement = Arrangement + .spacedBy(32.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + _VideoControls(videoRecorder) + HorizontalDivider() + _PrimitiveControls(videoRecorder) + } } } } } else -> { - Column( - modifier = Modifier - .fillMaxSize() - .padding(bottom = 32.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceBetween, - ) { - Box {} + Box { + CameraPreview( + modifier = Modifier, + cameraSelector = videoRecorder.cameraSelector + ) Column( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 32.dp), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement - .spacedBy(16.dp), + verticalArrangement = Arrangement.SpaceBetween, ) { - _VideoGeneralInfo(videoRecorder) - _VideoRecordingStatus(videoRecorder) - } + 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) + Column( + verticalArrangement = Arrangement + .spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + _VideoControls(videoRecorder) + HorizontalDivider() + _PrimitiveControls(videoRecorder) + } } } } diff --git a/app/src/main/java/app/myzel394/alibi/ui/utils/Context.kt b/app/src/main/java/app/myzel394/alibi/ui/utils/Context.kt new file mode 100644 index 0000000..058f7dd --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/utils/Context.kt @@ -0,0 +1,16 @@ +package app.myzel394.alibi.ui.utils + +import android.content.Context +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.core.content.ContextCompat +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +suspend fun Context.getCameraProvider(): ProcessCameraProvider = suspendCoroutine { continuation -> + ProcessCameraProvider.getInstance(this).also { future -> + future.addListener({ + continuation.resume(future.get()) + }, ContextCompat.getMainExecutor(this)) + } +} +