Move camera permission rationale to CameraScreen
This commit is contained in:
@@ -15,8 +15,6 @@
|
|||||||
package org.fairscan.app.ui.screens.camera
|
package org.fairscan.app.ui.screens.camera
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.camera.core.ImageProxy
|
import androidx.camera.core.ImageProxy
|
||||||
@@ -34,11 +32,14 @@ import androidx.compose.foundation.gestures.detectTapGestures
|
|||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
@@ -48,6 +49,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Done
|
import androidx.compose.material.icons.filled.Done
|
||||||
import androidx.compose.material.icons.filled.Highlight
|
import androidx.compose.material.icons.filled.Highlight
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -223,7 +226,9 @@ fun CameraScreen(
|
|||||||
},
|
},
|
||||||
thumbnailCoords = thumbnailCoords,
|
thumbnailCoords = thumbnailCoords,
|
||||||
navigation = navigation,
|
navigation = navigation,
|
||||||
captureController
|
captureController,
|
||||||
|
cameraPermission.isGranted,
|
||||||
|
{ cameraPermission.request() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,6 +244,8 @@ private fun CameraScreenScaffold(
|
|||||||
thumbnailCoords: MutableState<Offset>,
|
thumbnailCoords: MutableState<Offset>,
|
||||||
navigation: Navigation,
|
navigation: Navigation,
|
||||||
captureController: CameraCaptureController,
|
captureController: CameraCaptureController,
|
||||||
|
isCameraPermissionGranted: Boolean,
|
||||||
|
onRequestCameraPermission: () -> Unit,
|
||||||
) {
|
) {
|
||||||
var focusPoint by remember { mutableStateOf<Offset?>(null) }
|
var focusPoint by remember { mutableStateOf<Offset?>(null) }
|
||||||
LaunchedEffect(focusPoint) {
|
LaunchedEffect(focusPoint) {
|
||||||
@@ -272,20 +279,24 @@ private fun CameraScreenScaffold(
|
|||||||
onBack = navigation.back,
|
onBack = navigation.back,
|
||||||
bottomBar = { Bar(cameraUiState.pageCount, onFinalizePressed) }
|
bottomBar = { Bar(cameraUiState.pageCount, onFinalizePressed) }
|
||||||
) { modifier ->
|
) { modifier ->
|
||||||
CameraPreviewBox(
|
if (!isCameraPermissionGranted) {
|
||||||
cameraPreview,
|
CameraPermissionRationale(onRequestCameraPermission, modifier)
|
||||||
cameraUiState,
|
} else {
|
||||||
focusPoint,
|
CameraPreviewBox(
|
||||||
onCapture,
|
cameraPreview,
|
||||||
onTorchSwitched,
|
cameraUiState,
|
||||||
modifier.pointerInput(Unit) {
|
focusPoint,
|
||||||
detectTapGestures { offset ->
|
onCapture,
|
||||||
focusPoint = offset
|
onTorchSwitched,
|
||||||
captureController.tapToFocus(offset)
|
modifier.pointerInput(Unit) {
|
||||||
onPageCountClick()
|
detectTapGestures { offset ->
|
||||||
|
focusPoint = offset
|
||||||
|
captureController.tapToFocus(offset)
|
||||||
|
onPageCountClick()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
if (cameraUiState.captureState is CaptureState.CapturePreview) {
|
if (cameraUiState.captureState is CaptureState.CapturePreview) {
|
||||||
val page = cameraUiState.captureState.capturedPage.pageJpeg.toBitmap()
|
val page = cameraUiState.captureState.capturedPage.pageJpeg.toBitmap()
|
||||||
@@ -522,6 +533,31 @@ private fun Bar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun CameraPermissionRationale(onRequestCameraPermission: () -> Unit, modifier:Modifier) {
|
||||||
|
Box (modifier = modifier, contentAlignment = Alignment.Center) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(12.dp)
|
||||||
|
) {
|
||||||
|
Column(Modifier.padding(16.dp)) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.camera_permission_rationale),
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
Button(
|
||||||
|
onClick = onRequestCameraPermission,
|
||||||
|
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.grant_permission))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Preview(name="Pixel 1", showSystemUi = true, device = Devices.PIXEL)
|
@Preview(name="Pixel 1", showSystemUi = true, device = Devices.PIXEL)
|
||||||
@Preview(name="Pixel 4", showSystemUi = true, device = Devices.PIXEL_4)
|
@Preview(name="Pixel 4", showSystemUi = true, device = Devices.PIXEL_4)
|
||||||
@Preview(name="Pixel 9 pro XL", showSystemUi = true, device = Devices.PIXEL_9_PRO_XL)
|
@Preview(name="Pixel 9 pro XL", showSystemUi = true, device = Devices.PIXEL_9_PRO_XL)
|
||||||
@@ -550,8 +586,18 @@ fun CameraScreenPreviewInLandscapeMode() {
|
|||||||
ScreenPreview(CaptureState.Idle, rotationDegrees = 90f)
|
ScreenPreview(CaptureState.Idle, rotationDegrees = 90f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun ScreenPreview(captureState: CaptureState, rotationDegrees: Float = 0f) {
|
fun CameraScreenPreviewWithNoPermission() {
|
||||||
|
ScreenPreview(CaptureState.Idle, isCameraPermissionGranted = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ScreenPreview(
|
||||||
|
captureState: CaptureState,
|
||||||
|
rotationDegrees: Float = 0f,
|
||||||
|
isCameraPermissionGranted: Boolean = true,
|
||||||
|
) {
|
||||||
FairScanTheme {
|
FairScanTheme {
|
||||||
val thumbnailCoords = remember { mutableStateOf(Offset.Zero) }
|
val thumbnailCoords = remember { mutableStateOf(Offset.Zero) }
|
||||||
CameraScreenScaffold(
|
CameraScreenScaffold(
|
||||||
@@ -589,7 +635,9 @@ private fun ScreenPreview(captureState: CaptureState, rotationDegrees: Float = 0
|
|||||||
onTorchSwitched = {},
|
onTorchSwitched = {},
|
||||||
thumbnailCoords = thumbnailCoords,
|
thumbnailCoords = thumbnailCoords,
|
||||||
navigation = dummyNavigation(),
|
navigation = dummyNavigation(),
|
||||||
captureController = CameraCaptureController()
|
captureController = CameraCaptureController(),
|
||||||
|
isCameraPermissionGranted = isCameraPermissionGranted,
|
||||||
|
onRequestCameraPermission = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,17 +96,13 @@ fun HomeScreen(
|
|||||||
) {
|
) {
|
||||||
Spacer(Modifier.weight(1f))
|
Spacer(Modifier.weight(1f))
|
||||||
|
|
||||||
if (!cameraPermission.isGranted) {
|
ScanButton(
|
||||||
CameraPermissionRationale(cameraPermission)
|
onClick = {
|
||||||
} else {
|
onClearScan()
|
||||||
ScanButton(
|
navigation.toCameraScreen()
|
||||||
onClick = {
|
},
|
||||||
onClearScan()
|
Modifier.align(Alignment.CenterHorizontally)
|
||||||
navigation.toCameraScreen()
|
)
|
||||||
},
|
|
||||||
Modifier.align(Alignment.CenterHorizontally)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(Modifier.weight(1f))
|
Spacer(Modifier.weight(1f))
|
||||||
|
|
||||||
@@ -123,28 +119,6 @@ fun HomeScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun CameraPermissionRationale(cameraPermission: CameraPermissionState) {
|
|
||||||
Card(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(12.dp)
|
|
||||||
) {
|
|
||||||
Column(Modifier.padding(16.dp)) {
|
|
||||||
Text(
|
|
||||||
stringResource(R.string.camera_permission_rationale),
|
|
||||||
)
|
|
||||||
Spacer(Modifier.height(8.dp))
|
|
||||||
Button(
|
|
||||||
onClick = { cameraPermission.request() },
|
|
||||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
|
||||||
) {
|
|
||||||
Text(stringResource(R.string.grant_permission))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ScanButton(onClick: () -> Unit, modifier: Modifier) {
|
fun ScanButton(onClick: () -> Unit, modifier: Modifier) {
|
||||||
Button(
|
Button(
|
||||||
|
|||||||
Reference in New Issue
Block a user