Refactoring: introduce CommonPageList

This commit is contained in:
Pierre-Yves Nicolas
2025-06-24 14:29:29 +02:00
parent 2452e1d556
commit 1159b77c6e
3 changed files with 91 additions and 88 deletions

View File

@@ -36,11 +36,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
@@ -54,7 +51,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
@@ -116,7 +112,7 @@ fun CameraScreen(
) )
}, },
pageList = { pageList = {
CameraCapturedPagesRow( CommonPageList(
pageIds = pageIds, pageIds = pageIds,
imageLoader = { id -> viewModel.getBitmap(id) }, imageLoader = { id -> viewModel.getBitmap(id) },
onPageClick = { index -> viewModel.navigateTo(Screen.FinalizeDocument(index)) }, onPageClick = { index -> viewModel.navigateTo(Screen.FinalizeDocument(index)) },
@@ -280,46 +276,6 @@ fun CameraScreenFooter(
} }
} }
@Composable
fun CameraCapturedPagesRow(
pageIds: List<String>,
imageLoader: (String) -> Bitmap?,
onPageClick: (Int) -> Unit,
listState: LazyListState,
) {
if (pageIds.isEmpty()) return
LazyRow (
state = listState,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
itemsIndexed(pageIds) { index, id ->
val image = imageLoader(id)
if (image != null) {
Box {
val bitmap = image.asImageBitmap()
val modifier =
if (bitmap.height > bitmap.width)
Modifier.height(120.dp)
else
Modifier.width(120.dp)
Image(
bitmap = bitmap,
contentDescription = "Page ${index + 1}",
modifier = modifier
.clickable { onPageClick(index) }
.clip(RoundedCornerShape(4.dp))
)
}
}
}
}
}
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
fun CameraScreenPreview() { fun CameraScreenPreview() {
@@ -352,7 +308,7 @@ private fun ScreenPreview(captureState: CaptureState) {
} }
}, },
pageList = { pageList = {
CameraCapturedPagesRow( CommonPageList(
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" },
imageLoader = { id -> imageLoader = { id ->
context.assets.open(id).use { input -> context.assets.open(id).use { input ->

View File

@@ -18,21 +18,14 @@ import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
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.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
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.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
@@ -64,7 +57,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@@ -188,7 +180,7 @@ private fun DocumentPreview(
) { ) {
Icon(imageVector = Icons.Outlined.Delete, contentDescription = "Delete page") Icon(imageVector = Icons.Outlined.Delete, contentDescription = "Delete page")
} }
Text("${currentPageIndex.value + 1} / ${pageIds.size}", Text("${currentPageIndex.intValue + 1} / ${pageIds.size}",
color = MaterialTheme.colorScheme.inverseOnSurface, color = MaterialTheme.colorScheme.inverseOnSurface,
modifier = Modifier modifier = Modifier
.align(Alignment.BottomEnd) .align(Alignment.BottomEnd)
@@ -208,39 +200,12 @@ private fun PageList(
toCameraScreen: () -> Unit toCameraScreen: () -> Unit
) { ) {
Box { Box {
LazyRow( CommonPageList(
contentPadding = PaddingValues(8.dp), pageIds,
modifier = Modifier imageLoader,
.fillMaxWidth() onPageClick = { index -> currentPageIndex.value = index },
.padding(vertical = 4.dp) currentPageIndex = currentPageIndex.value,
.background(MaterialTheme.colorScheme.secondaryContainer),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
itemsIndexed (pageIds) { index, id ->
// TODO Use small images rather than big ones
val image = imageLoader(id)
if (image != null) {
val bitmap = image.asImageBitmap()
val isSelected = index == currentPageIndex.value
val borderColor =
if (isSelected) MaterialTheme.colorScheme.primary else Color.Transparent
val modifier =
if (bitmap.height > bitmap.width)
Modifier.height(120.dp)
else
Modifier.width(120.dp)
Image(
bitmap = bitmap,
contentDescription = null,
modifier = modifier
.padding(4.dp)
.border(2.dp, borderColor)
.clickable { currentPageIndex.value = index }
) )
}
}
}
SmallFloatingActionButton( SmallFloatingActionButton(
onClick = toCameraScreen, onClick = toCameraScreen,
modifier = Modifier modifier = Modifier

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2025 Pierre-Yves Nicolas
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.mydomain.myscan.view
import android.graphics.Bitmap
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.unit.dp
@Composable
fun CommonPageList(
pageIds: List<String>,
imageLoader: (String) -> Bitmap?,
onPageClick: (Int) -> Unit,
listState: LazyListState = rememberLazyListState(),
currentPageIndex: Int? = null,
) {
if (pageIds.isEmpty()) return
LazyRow (
state = listState,
contentPadding = PaddingValues(4.dp),
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.secondaryContainer),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
itemsIndexed(pageIds) { index, id ->
// TODO Use small images rather than big ones
val image = imageLoader(id)
if (image != null) {
val bitmap = image.asImageBitmap()
val isSelected = index == currentPageIndex
val borderColor =
if (isSelected) MaterialTheme.colorScheme.primary else Color.Transparent
val modifier =
if (bitmap.height > bitmap.width)
Modifier.height(120.dp)
else
Modifier.width(120.dp)
Image(
bitmap = bitmap,
contentDescription = null,
modifier = modifier
.padding(4.dp)
.border(2.dp, borderColor)
.clickable { onPageClick(index) }
)
}
}
}
}