mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
add logic to mark or unmark images as not for upload
This commit is contained in:
parent
e611cbc86f
commit
d1fdab4d8b
3 changed files with 119 additions and 7 deletions
|
|
@ -1,8 +1,14 @@
|
|||
package fr.free.nrw.commons.customselector.ui.screens
|
||||
|
||||
interface CustomSelectorEvent {
|
||||
import fr.free.nrw.commons.customselector.ui.states.ImageUiState
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
sealed interface CustomSelectorEvent {
|
||||
data class OnFolderClick(val bucketId: Long): CustomSelectorEvent
|
||||
data class OnImageSelection(val imageId: Long): CustomSelectorEvent
|
||||
data class OnDragImageSelection(val imageIds: Set<Long>): CustomSelectorEvent
|
||||
data object OnUnselectAll: CustomSelectorEvent
|
||||
data class OnUpdateImageStatus(val scope: CoroutineScope, val image: ImageUiState) : CustomSelectorEvent
|
||||
data object MarkAsNotForUpload: CustomSelectorEvent
|
||||
data object UnmarkAsNotForUpload: CustomSelectorEvent
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package fr.free.nrw.commons.customselector.ui.screens
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import fr.free.nrw.commons.customselector.domain.ImageRepository
|
||||
|
|
@ -83,6 +82,75 @@ class CustomSelectorViewModel @Inject constructor(
|
|||
CustomSelectorEvent.OnUnselectAll-> {
|
||||
_uiState.update { it.copy(selectedImageIds = emptySet()) }
|
||||
}
|
||||
|
||||
is CustomSelectorEvent.OnUpdateImageStatus -> {
|
||||
e.scope.launch { updateNotForUploadStatus(e.image) }
|
||||
}
|
||||
|
||||
is CustomSelectorEvent.MarkAsNotForUpload -> {
|
||||
viewModelScope.launch {
|
||||
val selectedImageIds = _uiState.value.selectedImageIds
|
||||
|
||||
val selectedImages = allImages.filter { image ->
|
||||
selectedImageIds.contains(image.id)
|
||||
}
|
||||
|
||||
selectedImages.forEach { image ->
|
||||
cacheSHA1[image.id]?.let { sha ->
|
||||
if(!imageRepository.isNotForUpload(sha)) {
|
||||
imageRepository.markAsNotForUpload(sha)
|
||||
updateImageStatus(true, image.id)
|
||||
_uiState.update { it.copy(selectedImageIds = emptySet()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomSelectorEvent.UnmarkAsNotForUpload -> {
|
||||
viewModelScope.launch {
|
||||
val selectedImageIds = _uiState.value.selectedImageIds
|
||||
|
||||
val selectedImages = allImages.filter { image ->
|
||||
selectedImageIds.contains(image.id)
|
||||
}
|
||||
|
||||
selectedImages.forEach { image ->
|
||||
cacheSHA1[image.id]?.let { sha ->
|
||||
if(imageRepository.isNotForUpload(sha)) {
|
||||
imageRepository.unmarkAsNotForUpload(sha)
|
||||
updateImageStatus(false, image.id)
|
||||
_uiState.update { it.copy(selectedImageIds = emptySet()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateImageStatus(isNotForUpload: Boolean, imageId: Long) {
|
||||
_uiState.update { state ->
|
||||
val updatedImages = state.filteredImages.map {
|
||||
if (it.id == imageId) {
|
||||
it.copy(isNotForUpload = isNotForUpload)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
val updateMap = state.imagesNotForUpload.toMutableMap()
|
||||
updateMap[imageId] = isNotForUpload
|
||||
|
||||
state.copy(filteredImages = updatedImages, imagesNotForUpload = updateMap)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateNotForUploadStatus(image: ImageUiState) {
|
||||
val imageSHA = cacheSHA1.getOrPut(image.id) {
|
||||
imageUseCase.getImageSHA1(image.uri).also { sha -> cacheSHA1[image.id] = sha }
|
||||
}
|
||||
|
||||
val isNotForUpload = imageRepository.isNotForUpload(imageSHA)
|
||||
updateImageStatus(isNotForUpload, image.id)
|
||||
}
|
||||
}
|
||||
|
|
@ -85,6 +85,9 @@ fun ImagesPane(
|
|||
.windowWidthSizeClass == WindowWidthSizeClass.COMPACT
|
||||
}
|
||||
}
|
||||
val isSelectedImageNotForUpload by remember(uiState.selectedImageIds) {
|
||||
derivedStateOf { uiState.selectedImageIds.any { uiState.imagesNotForUpload[it] == true } }
|
||||
}
|
||||
|
||||
LaunchedEffect(autoScrollSpeed) {
|
||||
if (autoScrollSpeed != 0f) {
|
||||
|
|
@ -117,8 +120,16 @@ fun ImagesPane(
|
|||
Surface(tonalElevation = 1.dp) {
|
||||
CustomSelectorBottomBar(
|
||||
onPrimaryAction = { /*TODO("Implement action to upload selected images")*/ },
|
||||
onSecondaryAction = { /*TODO("Implement action to mark/unmark as not for upload")*/ },
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
onSecondaryAction = {
|
||||
if(isSelectedImageNotForUpload) {
|
||||
onEvent(CustomSelectorEvent.UnmarkAsNotForUpload)
|
||||
} else {
|
||||
onEvent(CustomSelectorEvent.MarkAsNotForUpload)
|
||||
}
|
||||
},
|
||||
isAnyImageNotForUpload = isSelectedImageNotForUpload,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
.navigationBarsPadding()
|
||||
)
|
||||
}
|
||||
|
|
@ -161,6 +172,10 @@ fun ImagesPane(
|
|||
imagePainter = rememberAsyncImagePainter(model = image.uri),
|
||||
isSelected = isSelected,
|
||||
inSelectionMode = uiState.inSelectionMode,
|
||||
isNotForUpload = image.isNotForUpload,
|
||||
onImageStatusChange = { scope ->
|
||||
onEvent(CustomSelectorEvent.OnUpdateImageStatus(scope, image))
|
||||
},
|
||||
modifier = Modifier.combinedClickable(
|
||||
onClick = {
|
||||
if (uiState.inSelectionMode) {
|
||||
|
|
@ -184,9 +199,16 @@ fun ImagesPane(
|
|||
fun ImageItem(
|
||||
imagePainter: Painter,
|
||||
isSelected: Boolean,
|
||||
onImageStatusChange: (scope: CoroutineScope) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
inSelectionMode: Boolean = false
|
||||
inSelectionMode: Boolean = false,
|
||||
isNotForUpload: Boolean = false
|
||||
) {
|
||||
// This side-effect updates the image status, like:- isNotForUpload, for visible image only
|
||||
LaunchedEffect(Unit) {
|
||||
onImageStatusChange(this)
|
||||
}
|
||||
|
||||
Box(modifier = modifier.clip(RoundedCornerShape(12.dp))) {
|
||||
Image(
|
||||
painter = imagePainter,
|
||||
|
|
@ -217,11 +239,25 @@ fun ImageItem(
|
|||
modifier = Modifier
|
||||
.size(24.dp)
|
||||
.clip(RoundedCornerShape(bottomEnd = 12.dp))
|
||||
.background(color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f))
|
||||
.padding(2.dp)
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f)
|
||||
).padding(2.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if(isNotForUpload) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.not_for_upload),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.clip(RoundedCornerShape(bottomStart = 12.dp))
|
||||
.background(color = MaterialTheme.colorScheme.errorContainer)
|
||||
.padding(4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,6 +270,8 @@ private fun ImageItemPreview() {
|
|||
imagePainter = painterResource(id = R.drawable.image_placeholder_96),
|
||||
isSelected = false,
|
||||
inSelectionMode = true,
|
||||
isNotForUpload = true,
|
||||
onImageStatusChange = { },
|
||||
modifier = Modifier
|
||||
.padding(16.dp)
|
||||
.size(116.dp)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue