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