Avoid resolution of current page in DocumentScreen
This commit is contained in:
@@ -62,7 +62,6 @@ import org.fairscan.app.ui.screens.about.createEmailWithImageIntent
|
||||
import org.fairscan.app.ui.screens.camera.CameraEvent
|
||||
import org.fairscan.app.ui.screens.camera.CameraScreen
|
||||
import org.fairscan.app.ui.screens.camera.CameraViewModel
|
||||
import org.fairscan.app.ui.screens.document.DocumentUiState
|
||||
import org.fairscan.app.ui.screens.export.ExportActions
|
||||
import org.fairscan.app.ui.screens.export.ExportEvent
|
||||
import org.fairscan.app.ui.screens.export.ExportResult
|
||||
@@ -182,9 +181,9 @@ class MainActivity : ComponentActivity() {
|
||||
uiState = documentUiState,
|
||||
navigation = navigation,
|
||||
onExportClick = onExportClick,
|
||||
onDeleteImage = { id -> viewModel.deletePage(id) },
|
||||
onRotateImage = { id, clockwise -> viewModel.rotateImage(id, clockwise) },
|
||||
onToggleColorMode = { id -> viewModel.togglePageColorMode(id) },
|
||||
onDeleteImage = { viewModel.deleteCurrentPage() },
|
||||
onRotateImage = { clockwise -> viewModel.rotateCurrentPage(clockwise) },
|
||||
onToggleColorMode = { viewModel.toggleCurrentPageColorMode() },
|
||||
onPageReorder = { id, newIndex -> viewModel.movePage(id, newIndex) },
|
||||
onPageSelected = viewModel::onPageSelected
|
||||
)
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
*/
|
||||
package org.fairscan.app
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -43,6 +42,7 @@ import org.fairscan.app.ui.screens.document.DocumentUiState
|
||||
import org.fairscan.app.ui.state.DocumentUiModel
|
||||
import org.fairscan.app.ui.state.PageThumbnail
|
||||
import org.fairscan.imageprocessing.ColorMode
|
||||
import java.lang.IllegalStateException
|
||||
import kotlin.math.min
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@@ -77,15 +77,16 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
||||
|
||||
private val _currentPageIndex = MutableStateFlow(0)
|
||||
|
||||
val currentPageUiState: Flow<CurrentPageUiState> =
|
||||
private val currentPageUiState: Flow<CurrentPageUiState?> =
|
||||
combine(_currentPageIndex, _pages) { index, pages -> pages.getOrNull(index) }
|
||||
.mapLatest { page ->
|
||||
page?.let {
|
||||
CurrentPageUiState(
|
||||
page.id,
|
||||
imageRepository.jpegBytes(it.key())?.toBitmap(),
|
||||
page.colorMode
|
||||
)
|
||||
} ?: CurrentPageUiState()
|
||||
}
|
||||
}
|
||||
.flowOn(Dispatchers.IO)
|
||||
|
||||
@@ -95,7 +96,7 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
||||
}
|
||||
.stateIn(
|
||||
viewModelScope, SharingStarted.Eagerly,
|
||||
DocumentUiState(0, CurrentPageUiState(), DocumentUiModel())
|
||||
DocumentUiState(0, null, DocumentUiModel())
|
||||
)
|
||||
|
||||
fun onPageSelected(index: Int) {
|
||||
@@ -116,10 +117,10 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
||||
_navigationState.update { stack -> stack.navigateBack() }
|
||||
}
|
||||
|
||||
fun rotateImage(id: String, clockwise: Boolean) {
|
||||
fun rotateCurrentPage(clockwise: Boolean) {
|
||||
viewModelScope.launch {
|
||||
val pages = withContext(Dispatchers.IO) {
|
||||
imageRepository.rotate(id, clockwise)
|
||||
imageRepository.rotate(currentPage().id, clockwise)
|
||||
imageRepository.pages()
|
||||
}
|
||||
_pages.value = pages
|
||||
@@ -136,10 +137,10 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
||||
}
|
||||
}
|
||||
|
||||
fun deletePage(id: String) {
|
||||
fun deleteCurrentPage() {
|
||||
viewModelScope.launch {
|
||||
val pages = withContext(Dispatchers.IO) {
|
||||
imageRepository.delete(id)
|
||||
imageRepository.delete(currentPage().id)
|
||||
imageRepository.pages()
|
||||
}
|
||||
|
||||
@@ -153,14 +154,14 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
||||
}
|
||||
}
|
||||
|
||||
fun togglePageColorMode(id: String) {
|
||||
fun toggleCurrentPageColorMode() {
|
||||
viewModelScope.launch {
|
||||
val currentColorMode = _pages.value.find { p -> p.id == id }?.colorMode
|
||||
currentColorMode?.let {
|
||||
val currentPage = currentPage()
|
||||
currentPage.colorMode?.let {
|
||||
val newColorMode =
|
||||
if (it == ColorMode.COLOR) ColorMode.GRAYSCALE else ColorMode.COLOR
|
||||
val pages = withContext(Dispatchers.IO) {
|
||||
imageRepository.setColorMode(id, newColorMode)
|
||||
imageRepository.setColorMode(currentPage.id, newColorMode)
|
||||
imageRepository.pages()
|
||||
}
|
||||
_pages.value = pages
|
||||
@@ -168,6 +169,13 @@ class MainViewModel(val imageRepository: ImageRepository, launchMode: LaunchMode
|
||||
}
|
||||
}
|
||||
|
||||
private fun currentPage(): ScanPage {
|
||||
val index = _currentPageIndex.value
|
||||
val pages = _pages.value
|
||||
return pages.getOrNull(index) ?: throw IllegalStateException(
|
||||
"No current page for index $index (${pages.size} pages)")
|
||||
}
|
||||
|
||||
fun startNewDocument() {
|
||||
_pages.value = persistentListOf()
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -86,9 +86,9 @@ fun DocumentScreen(
|
||||
uiState: DocumentUiState,
|
||||
navigation: Navigation,
|
||||
onExportClick: () -> Unit,
|
||||
onDeleteImage: (String) -> Unit,
|
||||
onRotateImage: (String, Boolean) -> Unit,
|
||||
onToggleColorMode: (String) -> Unit,
|
||||
onDeleteImage: () -> Unit,
|
||||
onRotateImage: (Boolean) -> Unit,
|
||||
onToggleColorMode: () -> Unit,
|
||||
onPageReorder: (String, Int) -> Unit,
|
||||
onPageSelected: (Int) -> Unit,
|
||||
) {
|
||||
@@ -130,7 +130,7 @@ fun DocumentScreen(
|
||||
title = stringResource(R.string.delete_page),
|
||||
message = stringResource(R.string.delete_page_warning),
|
||||
showDialog = showDeletePageDialog
|
||||
) { onDeleteImage(document.pageId(currentPageIndex)) }
|
||||
) { onDeleteImage() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,14 +138,13 @@ fun DocumentScreen(
|
||||
@Composable
|
||||
private fun DocumentPreview(
|
||||
uiState: DocumentUiState,
|
||||
onDeleteImage: (String) -> Unit,
|
||||
onRotateImage: (String, Boolean) -> Unit,
|
||||
onToggleColorMode: (String) -> Unit,
|
||||
onDeleteImage: () -> Unit,
|
||||
onRotateImage: (Boolean) -> Unit,
|
||||
onToggleColorMode: () -> Unit,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
val currentPageIndex = uiState.currentPageIndex
|
||||
val document = uiState.document
|
||||
val imageId = document.pageId(currentPageIndex)
|
||||
Column (
|
||||
modifier = modifier
|
||||
.background(MaterialTheme.colorScheme.surfaceContainerLow)
|
||||
@@ -153,10 +152,11 @@ private fun DocumentPreview(
|
||||
Box (
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
val bitmap = uiState.currentPage.bitmap
|
||||
if (bitmap != null) {
|
||||
val bitmap = uiState.currentPage?.bitmap
|
||||
val pageId = uiState.currentPage?.id
|
||||
if (bitmap != null && pageId != null) {
|
||||
val imageBitmap = bitmap.asImageBitmap()
|
||||
val zoomState = remember(imageId) {
|
||||
val zoomState = remember(pageId) {
|
||||
ZoomState(
|
||||
contentSize = Size(bitmap.width.toFloat(), bitmap.height.toFloat())
|
||||
)
|
||||
@@ -175,20 +175,20 @@ private fun DocumentPreview(
|
||||
)
|
||||
}
|
||||
}
|
||||
uiState.currentPage.colorMode?.let {
|
||||
uiState.currentPage?.colorMode?.let {
|
||||
ColorModeButton(
|
||||
currentColorMode = it,
|
||||
onToggle = { onToggleColorMode(imageId) },
|
||||
onToggle = { onToggleColorMode() },
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.padding(8.dp)
|
||||
)
|
||||
}
|
||||
RotationButtons(imageId, onRotateImage, Modifier.align(Alignment.BottomCenter))
|
||||
RotationButtons(onRotateImage, Modifier.align(Alignment.BottomCenter))
|
||||
SecondaryActionButton(
|
||||
Icons.Outlined.Delete,
|
||||
contentDescription = stringResource(R.string.delete_page),
|
||||
onClick = { onDeleteImage(imageId) },
|
||||
onClick = { onDeleteImage() },
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(8.dp)
|
||||
@@ -210,8 +210,7 @@ private fun DocumentPreview(
|
||||
|
||||
@Composable
|
||||
fun RotationButtons(
|
||||
imageId: String,
|
||||
onRotateImage: (String, Boolean) -> Unit,
|
||||
onRotateImage: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
// RotateLeft on the left, RotateRight on the right: for both LTR and RTL languages
|
||||
@@ -222,14 +221,14 @@ fun RotationButtons(
|
||||
SecondaryActionButton(
|
||||
icon = Icons.Default.RotateLeft,
|
||||
contentDescription = stringResource(R.string.rotate_left),
|
||||
onClick = { onRotateImage(imageId, false) }
|
||||
onClick = { onRotateImage(false) }
|
||||
)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
@Suppress("DEPRECATION")
|
||||
SecondaryActionButton(
|
||||
icon = Icons.Default.RotateRight,
|
||||
contentDescription = stringResource(R.string.rotate_right),
|
||||
onClick = { onRotateImage(imageId, true) }
|
||||
onClick = { onRotateImage(true) }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -307,12 +306,12 @@ fun DocumentScreenPreview() {
|
||||
LocalContext.current
|
||||
)
|
||||
DocumentScreen(
|
||||
uiState = DocumentUiState(1, CurrentPageUiState(image, COLOR), document),
|
||||
uiState = DocumentUiState(1, CurrentPageUiState("123",image, COLOR), document),
|
||||
navigation = dummyNavigation(),
|
||||
onExportClick = {},
|
||||
onDeleteImage = { _ -> },
|
||||
onRotateImage = { _,_ -> },
|
||||
onToggleColorMode = { _ -> },
|
||||
onDeleteImage = { },
|
||||
onRotateImage = { _ -> },
|
||||
onToggleColorMode = { },
|
||||
onPageReorder = { _,_ -> },
|
||||
onPageSelected = { _ -> },
|
||||
)
|
||||
|
||||
@@ -20,11 +20,12 @@ import org.fairscan.imageprocessing.ColorMode
|
||||
|
||||
data class DocumentUiState(
|
||||
val currentPageIndex: Int,
|
||||
val currentPage: CurrentPageUiState,
|
||||
val currentPage: CurrentPageUiState?,
|
||||
val document: DocumentUiModel,
|
||||
)
|
||||
|
||||
data class CurrentPageUiState(
|
||||
val bitmap: Bitmap? = null,
|
||||
val colorMode: ColorMode? = null,
|
||||
val id: String,
|
||||
val bitmap: Bitmap?,
|
||||
val colorMode: ColorMode?,
|
||||
)
|
||||
|
||||
@@ -25,9 +25,6 @@ data class DocumentUiModel(
|
||||
fun pageCount(): Int {
|
||||
return pages.size
|
||||
}
|
||||
fun pageId(index: Int): String {
|
||||
return pages[index].key.pageId
|
||||
}
|
||||
fun isEmpty(): Boolean {
|
||||
return pages.isEmpty()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user