CameraScreen: click on a page to open it in DocumentScreen

This commit is contained in:
Pierre-Yves Nicolas
2025-06-24 12:24:17 +02:00
parent ef2a49cf76
commit dcb48b8cc8
4 changed files with 36 additions and 24 deletions

View File

@@ -56,13 +56,13 @@ class MainActivity : ComponentActivity() {
MyScanTheme { MyScanTheme {
Column { Column {
when (currentScreen) { when (val screen = currentScreen) {
is Screen.Camera -> { is Screen.Camera -> {
Scaffold { innerPadding-> Scaffold { innerPadding->
CameraScreen( CameraScreen(
viewModel, liveAnalysisState, viewModel, liveAnalysisState,
onImageAnalyzed = { image -> viewModel.liveAnalysis(image) }, onImageAnalyzed = { image -> viewModel.liveAnalysis(image) },
onFinalizePressed = { viewModel.navigateTo(Screen.FinalizeDocument) }, onFinalizePressed = { viewModel.navigateTo(Screen.FinalizeDocument()) },
modifier = Modifier.padding(innerPadding) modifier = Modifier.padding(innerPadding)
) )
} }
@@ -70,6 +70,7 @@ class MainActivity : ComponentActivity() {
is Screen.FinalizeDocument -> { is Screen.FinalizeDocument -> {
DocumentScreen ( DocumentScreen (
pageIds, pageIds,
initialPage = screen.initialPage,
imageLoader = { id -> viewModel.getBitmap(id) }, imageLoader = { id -> viewModel.getBitmap(id) },
toCameraScreen = { viewModel.navigateTo(Screen.Camera) }, toCameraScreen = { viewModel.navigateTo(Screen.Camera) },
onSavePressed = savePdf(viewModel, context), onSavePressed = savePdf(viewModel, context),

View File

@@ -16,5 +16,5 @@ package org.mydomain.myscan
sealed class Screen { sealed class Screen {
object Camera : Screen() object Camera : Screen()
object FinalizeDocument : Screen() data class FinalizeDocument(val initialPage: Int = 0) : Screen()
} }

View File

@@ -64,6 +64,7 @@ import kotlinx.coroutines.delay
import org.mydomain.myscan.LiveAnalysisState import org.mydomain.myscan.LiveAnalysisState
import org.mydomain.myscan.MainViewModel import org.mydomain.myscan.MainViewModel
import org.mydomain.myscan.MainViewModel.CaptureState import org.mydomain.myscan.MainViewModel.CaptureState
import org.mydomain.myscan.Screen
import org.mydomain.myscan.ui.theme.MyScanTheme import org.mydomain.myscan.ui.theme.MyScanTheme
@Composable @Composable
@@ -98,8 +99,12 @@ fun CameraScreen(
captureController = captureController, captureController = captureController,
onPreviewViewReady = { view -> previewView = view } onPreviewViewReady = { view -> previewView = view }
) }, ) },
pageIds = pageIds, pageList = { CameraCapturedPagesRow(
imageLoader = { id -> viewModel.getBitmap(id) }, pageIds = pageIds,
imageLoader = { id -> viewModel.getBitmap(id) },
onPageClick = { index -> viewModel.navigateTo(Screen.FinalizeDocument(index)) }
) },
pageCount = pageIds.size,
liveAnalysisState = liveAnalysisState, liveAnalysisState = liveAnalysisState,
onCapture = { onCapture = {
Log.i("MyScan", "Pressed <Capture>") Log.i("MyScan", "Pressed <Capture>")
@@ -117,8 +122,8 @@ fun CameraScreen(
private fun CameraScreenContent( private fun CameraScreenContent(
modifier: Modifier, modifier: Modifier,
cameraPreview: @Composable () -> Unit, cameraPreview: @Composable () -> Unit,
pageIds: List<String>, pageList: @Composable () -> Unit,
imageLoader: (String) -> Bitmap?, pageCount: Int,
liveAnalysisState: LiveAnalysisState, liveAnalysisState: LiveAnalysisState,
onCapture: () -> Unit, onCapture: () -> Unit,
onFinalizePressed: () -> Unit, onFinalizePressed: () -> Unit,
@@ -136,8 +141,8 @@ private fun CameraScreenContent(
.padding(16.dp) .padding(16.dp)
) )
CameraScreenFooter( CameraScreenFooter(
pageIds = pageIds, pageList = pageList,
imageLoader = imageLoader, pageCount = pageCount,
onFinalizePressed = onFinalizePressed, onFinalizePressed = onFinalizePressed,
modifier = Modifier, modifier = Modifier,
) )
@@ -224,12 +229,11 @@ fun MessageBox(inferenceTime: Long) {
@Composable @Composable
fun CameraScreenFooter( fun CameraScreenFooter(
pageIds: List<String>, pageList: @Composable () -> Unit,
imageLoader: (String) -> Bitmap?, pageCount: Int,
onFinalizePressed: () -> Unit, onFinalizePressed: () -> Unit,
modifier: Modifier, modifier: Modifier,
) { ) {
val pageCount = pageIds.size
Surface ( Surface (
color = MaterialTheme.colorScheme.inverseOnSurface, color = MaterialTheme.colorScheme.inverseOnSurface,
tonalElevation = 4.dp, tonalElevation = 4.dp,
@@ -238,10 +242,7 @@ fun CameraScreenFooter(
.height(180.dp) .height(180.dp)
) { ) {
Column { Column {
CameraCapturedPagesRow( pageList()
pageIds = pageIds,
imageLoader = imageLoader
)
Row ( Row (
modifier = Modifier modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp) .padding(horizontal = 16.dp, vertical = 8.dp)
@@ -268,7 +269,8 @@ fun CameraScreenFooter(
@Composable @Composable
fun CameraCapturedPagesRow( fun CameraCapturedPagesRow(
pageIds: List<String>, pageIds: List<String>,
imageLoader: (String) -> Bitmap? imageLoader: (String) -> Bitmap?,
onPageClick: (Int) -> Unit,
) { ) {
if (pageIds.isEmpty()) return if (pageIds.isEmpty()) return
@@ -292,6 +294,7 @@ fun CameraCapturedPagesRow(
bitmap = bitmap, bitmap = bitmap,
contentDescription = "Page ${index + 1}", contentDescription = "Page ${index + 1}",
modifier = modifier modifier = modifier
.clickable { onPageClick(index) }
.clip(RoundedCornerShape(4.dp)) .clip(RoundedCornerShape(4.dp))
) )
} }
@@ -332,16 +335,22 @@ private fun ScreenPreview(captureState: CaptureState) {
) )
} }
}, },
pageIds = listOf(1, 2, 2, 2).map { "gallica.bnf.fr-bpt6k5530456s-$it.jpg" }, pageList = {
imageLoader = { id -> CameraCapturedPagesRow(
context.assets.open(id).use { input -> pageIds = listOf(1, 2, 2, 2).map { "gallica.bnf.fr-bpt6k5530456s-$it.jpg" },
BitmapFactory.decodeStream(input) imageLoader = { id ->
} context.assets.open(id).use { input ->
BitmapFactory.decodeStream(input)
}
},
onPageClick = {}
)
}, },
pageCount = 4,
liveAnalysisState = LiveAnalysisState(), liveAnalysisState = LiveAnalysisState(),
onCapture = {}, onCapture = {},
onFinalizePressed = {}, onFinalizePressed = {},
captureState = captureState captureState = captureState,
) )
} }
} }

View File

@@ -77,6 +77,7 @@ import org.mydomain.myscan.ui.theme.MyScanTheme
@Composable @Composable
fun DocumentScreen( fun DocumentScreen(
pageIds: List<String>, pageIds: List<String>,
initialPage: Int,
imageLoader: (String) -> Bitmap?, imageLoader: (String) -> Bitmap?,
toCameraScreen: () -> Unit, toCameraScreen: () -> Unit,
onSavePressed: () -> Unit, onSavePressed: () -> Unit,
@@ -86,7 +87,7 @@ fun DocumentScreen(
) { ) {
// TODO Check how often images are loaded // TODO Check how often images are loaded
var showDialog = rememberSaveable { mutableStateOf(false) } var showDialog = rememberSaveable { mutableStateOf(false) }
val currentPageIndex = rememberSaveable { mutableIntStateOf(0) } val currentPageIndex = rememberSaveable { mutableIntStateOf(initialPage) }
if (currentPageIndex.intValue >= pageIds.size) { if (currentPageIndex.intValue >= pageIds.size) {
currentPageIndex.intValue = pageIds.size - 1 currentPageIndex.intValue = pageIds.size - 1
} }
@@ -280,6 +281,7 @@ fun DocumentScreenPreview() {
MyScanTheme { MyScanTheme {
DocumentScreen( DocumentScreen(
pageIds = listOf(1, 2, 2, 2).map { "gallica.bnf.fr-bpt6k5530456s-$it.jpg" }, pageIds = listOf(1, 2, 2, 2).map { "gallica.bnf.fr-bpt6k5530456s-$it.jpg" },
initialPage = 1,
imageLoader = { id -> imageLoader = { id ->
context.assets.open(id).use { input -> context.assets.open(id).use { input ->
BitmapFactory.decodeStream(input) BitmapFactory.decodeStream(input)