Avoid a possible crash when deleting an image
This commit is contained in:
@@ -39,12 +39,12 @@ class ImageRepository(appFilesDir: File) {
|
||||
fileNames.add(fileName)
|
||||
}
|
||||
|
||||
fun getContent(id: String): ByteArray {
|
||||
fun getContent(id: String): ByteArray? {
|
||||
if (fileNames.contains(id)) {
|
||||
val file = File(scanDir, id)
|
||||
return file.readBytes()
|
||||
}
|
||||
throw IllegalArgumentException("No image for id: $id")
|
||||
return null
|
||||
}
|
||||
|
||||
fun delete(id: String) {
|
||||
|
||||
@@ -137,14 +137,15 @@ class MainViewModel(
|
||||
|
||||
fun pageCount(): Int = pageIds.value.size
|
||||
|
||||
fun getBitmap(id: String): Bitmap {
|
||||
fun getBitmap(id: String): Bitmap? {
|
||||
val bytes = imageRepository.getContent(id)
|
||||
return BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
|
||||
return bytes?.let { BitmapFactory.decodeByteArray(it, 0, it.size) }
|
||||
}
|
||||
|
||||
fun createPdf(outputStream: OutputStream) {
|
||||
val jpegs = imageRepository.imageIds().asSequence()
|
||||
.map { id -> imageRepository.getContent(id) }
|
||||
.filterNotNull()
|
||||
writePdfFromJpegs(jpegs, outputStream)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ import org.mydomain.myscan.ui.theme.MyScanTheme
|
||||
@Composable
|
||||
fun DocumentScreen(
|
||||
pageIds: List<String>,
|
||||
imageLoader: (String) -> Bitmap,
|
||||
imageLoader: (String) -> Bitmap?,
|
||||
toCameraScreen: () -> Unit,
|
||||
onSavePressed: () -> Unit,
|
||||
onSharePressed: () -> Unit,
|
||||
@@ -135,7 +135,7 @@ fun DocumentScreen(
|
||||
@Composable
|
||||
private fun DocumentPreview(
|
||||
pageIds: List<String>,
|
||||
imageLoader: (String) -> Bitmap,
|
||||
imageLoader: (String) -> Bitmap?,
|
||||
currentPageIndex: MutableIntState,
|
||||
onDeleteImage: (String) -> Unit,
|
||||
padding: PaddingValues,
|
||||
@@ -151,21 +151,24 @@ private fun DocumentPreview(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
val bitmap = imageLoader(imageId)
|
||||
val imageBitmap = bitmap.asImageBitmap()
|
||||
val zoomState = rememberZoomState(
|
||||
contentSize = Size(bitmap.width.toFloat(), bitmap.height.toFloat()))
|
||||
if (bitmap != null) {
|
||||
val imageBitmap = bitmap.asImageBitmap()
|
||||
val zoomState = rememberZoomState(
|
||||
contentSize = Size(bitmap.width.toFloat(), bitmap.height.toFloat())
|
||||
)
|
||||
|
||||
LaunchedEffect(imageId) {
|
||||
zoomState.reset()
|
||||
LaunchedEffect(imageId) {
|
||||
zoomState.reset()
|
||||
}
|
||||
Image(
|
||||
bitmap = imageBitmap,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.align(Alignment.Center)
|
||||
.zoomable(zoomState)
|
||||
)
|
||||
}
|
||||
Image(
|
||||
bitmap = imageBitmap,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.align(Alignment.Center)
|
||||
.zoomable(zoomState)
|
||||
)
|
||||
SmallFloatingActionButton(
|
||||
onClick = { onDeleteImage(imageId) },
|
||||
modifier = Modifier.align(Alignment.TopEnd).padding(4.dp)
|
||||
@@ -186,7 +189,7 @@ private fun DocumentPreview(
|
||||
@Composable
|
||||
private fun PageList(
|
||||
pageIds: List<String>,
|
||||
imageLoader: (String) -> Bitmap,
|
||||
imageLoader: (String) -> Bitmap?,
|
||||
currentPageIndex: MutableState<Int>,
|
||||
toCameraScreen: () -> Unit
|
||||
) {
|
||||
@@ -202,22 +205,26 @@ private fun PageList(
|
||||
) {
|
||||
itemsIndexed (pageIds) { index, id ->
|
||||
// TODO Use small images rather than big ones
|
||||
val bitmap = imageLoader(id).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 }
|
||||
)
|
||||
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(
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
*/
|
||||
package org.mydomain.myscan
|
||||
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@@ -73,10 +72,9 @@ class ImageRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should throw on invalid id`() {
|
||||
fun `should return null on invalid id`() {
|
||||
val repo = repo()
|
||||
assertThat(repo.imageIds()).isEmpty()
|
||||
Assertions.assertThatThrownBy { repo.getContent("x") }
|
||||
.isInstanceOf(IllegalArgumentException::class.java)
|
||||
assertThat(repo.getContent("x")).isNull()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user