Refactoring: introduce CommonPageList
This commit is contained in:
@@ -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 ->
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
82
app/src/main/java/org/mydomain/myscan/view/PageList.kt
Normal file
82
app/src/main/java/org/mydomain/myscan/view/PageList.kt
Normal 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) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user