From 71fef94f0dcf0e333a6e912d7affce7b74e8c3ae Mon Sep 17 00:00:00 2001 From: erik-everardo Date: Sun, 24 Dec 2023 13:18:50 -0600 Subject: [PATCH] eliminar imagenes --- .../java/com/isolaatti/common/Deletable.kt | 5 ++++ .../images/common/data/remote/ImagesApi.kt | 2 +- .../data/repository/ImagesRepositoryImpl.kt | 2 +- .../images/common/domain/entity/Image.kt | 3 ++- .../presentation/ImageListViewModel.kt | 20 ++++++++++++--- .../image_list/presentation/ImagesAdapter.kt | 17 ++++++------- .../images/image_list/ui/ImagesFragment.kt | 22 +++++++++++++++- .../image_maker/ui/ImageMakerActivity.kt | 3 +++ .../drawable/face_kiss_wink_heart_solid.xml | 9 +++++++ app/src/main/res/layout/fragment_images.xml | 25 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 11 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/com/isolaatti/common/Deletable.kt create mode 100644 app/src/main/res/drawable/face_kiss_wink_heart_solid.xml diff --git a/app/src/main/java/com/isolaatti/common/Deletable.kt b/app/src/main/java/com/isolaatti/common/Deletable.kt new file mode 100644 index 0000000..ea96bbc --- /dev/null +++ b/app/src/main/java/com/isolaatti/common/Deletable.kt @@ -0,0 +1,5 @@ +package com.isolaatti.common + +open class Deletable { + var delete = false +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/images/common/data/remote/ImagesApi.kt b/app/src/main/java/com/isolaatti/images/common/data/remote/ImagesApi.kt index adf57d0..899edc0 100644 --- a/app/src/main/java/com/isolaatti/images/common/data/remote/ImagesApi.kt +++ b/app/src/main/java/com/isolaatti/images/common/data/remote/ImagesApi.kt @@ -25,7 +25,7 @@ interface ImagesApi { @Part setAsProfile: MultipartBody.Part? = null, @Part squadId: MultipartBody.Part? = null): Call - @POST("images/delete_many") + @POST("images/delete/delete_many") fun deleteImages(@Body deleteImagesDto: DeleteImagesDto): Call @GET("images/of_squad/{squadId}") diff --git a/app/src/main/java/com/isolaatti/images/common/data/repository/ImagesRepositoryImpl.kt b/app/src/main/java/com/isolaatti/images/common/data/repository/ImagesRepositoryImpl.kt index 137ec28..b48e3c1 100644 --- a/app/src/main/java/com/isolaatti/images/common/data/repository/ImagesRepositoryImpl.kt +++ b/app/src/main/java/com/isolaatti/images/common/data/repository/ImagesRepositoryImpl.kt @@ -46,7 +46,7 @@ class ImagesRepositoryImpl @Inject constructor(private val imagesApi: ImagesApi, override fun deleteImages(images: List): Flow> = flow { emit(Resource.Loading()) - val dto = DeleteImagesDto(images.map { it.imageUrl }) + val dto = DeleteImagesDto(images.map { it.id }) try { val response = imagesApi.deleteImages(dto).awaitResponse() if(response.isSuccessful) { diff --git a/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt b/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt index 4bcb842..fc89f9f 100644 --- a/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt +++ b/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt @@ -1,5 +1,6 @@ package com.isolaatti.images.common.domain.entity +import com.isolaatti.common.Deletable import com.isolaatti.images.common.data.remote.ImageDto import com.isolaatti.utils.UrlGen import java.io.Serializable @@ -9,7 +10,7 @@ data class Image( val userId: Int, val name: String, val username: String -): Serializable { +): Deletable(), Serializable { val imageUrl: String get() = UrlGen.imageUrl(id) val smallImageUrl : String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_SMALL) val reducedImageUrl: String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_REDUCED) diff --git a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt index d26c6d0..aa078c9 100644 --- a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt +++ b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt @@ -18,10 +18,16 @@ import kotlin.properties.Delegates @HiltViewModel class ImageListViewModel @Inject constructor(private val imagesRepository: ImagesRepository) : ViewModel() { - val liveList: MutableLiveData> = MutableLiveData() + enum class Event { + REMOVED_IMAGE, ADDED_IMAGE_BEGINNING + } + + val liveList: MutableLiveData> = MutableLiveData(listOf()) val error: MutableLiveData = MutableLiveData() val loading: MutableLiveData = MutableLiveData() + val deleting: MutableLiveData = MutableLiveData() var noMoreContent = false + var lastEvent: Event? = null private var loadedFirstTime = false var userId by Delegates.notNull() @@ -74,10 +80,16 @@ class ImageListViewModel @Inject constructor(private val imagesRepository: Image viewModelScope.launch { imagesRepository.deleteImages(images).onEach { when(it) { - is Resource.Error -> {} - is Resource.Loading -> {} + is Resource.Error -> { + deleting.postValue(false) + } + is Resource.Loading -> { + deleting.postValue(true) + } is Resource.Success -> { - liveList.value = list.filterNot { image -> images.contains(image) } + deleting.postValue(false) + lastEvent = Event.REMOVED_IMAGE + liveList.postValue(list.filterNot { image -> images.contains(image) }) } } }.flowOn(Dispatchers.IO).launchIn(this) diff --git a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt index 1e24295..504f420 100644 --- a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt +++ b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt @@ -34,13 +34,11 @@ class ImagesAdapter( } } - private var selectionState: Array = arrayOf() - var deleteMode: Boolean = false set(value) { field = value if(!value) { - selectionState.forEachIndexed { index, _ -> selectionState[index] = false } + currentList.forEach { it.delete = false } } notifyDataSetChanged() } @@ -48,7 +46,7 @@ class ImagesAdapter( inner class ImageViewHolder(val imageItemBinding: ImageItemBinding) : RecyclerView.ViewHolder(imageItemBinding.root) fun getSelectedImages(): List { - return currentList.filterIndexed { index, _ -> selectionState[index] } + return currentList.filter { it.delete } } override fun onCurrentListChanged( @@ -57,7 +55,6 @@ class ImagesAdapter( ) { super.onCurrentListChanged(previousList, currentList) noMoreContent = (currentList.size - previousList.size) == 0 - selectionState = Array(currentList.size) { false } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder { @@ -89,11 +86,11 @@ class ImagesAdapter( holder.imageItemBinding.root.setOnClickListener { holder.imageItemBinding.imageCheckbox.isChecked = !holder.imageItemBinding.imageCheckbox.isChecked } - holder.imageItemBinding.imageCheckbox.isChecked = selectionState[position] + holder.imageItemBinding.imageCheckbox.isChecked = image.delete holder.imageItemBinding.imageCheckbox.setOnCheckedChangeListener { buttonView, isChecked -> - selectionState[position] = isChecked + image.delete = isChecked - onImageSelectedCountUpdate?.invoke(selectionState.count { it }) + onImageSelectedCountUpdate?.invoke(currentList.count { it.delete }) } holder.imageItemBinding.root.setOnLongClickListener(null) } else { @@ -105,9 +102,9 @@ class ImagesAdapter( } holder.imageItemBinding.imageCheckbox.setOnCheckedChangeListener(null) holder.imageItemBinding.root.setOnLongClickListener { - selectionState[position] = true + image.delete = true onDeleteMode?.invoke(true) - onImageSelectedCountUpdate?.invoke(selectionState.count { it }) + onImageSelectedCountUpdate?.invoke(currentList.count { it.delete }) true } } diff --git a/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt b/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt index cb0d6dc..c721959 100644 --- a/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt +++ b/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt @@ -1,5 +1,6 @@ package com.isolaatti.images.image_list.ui +import android.app.Dialog import android.content.res.Resources import android.net.Uri import android.os.Bundle @@ -51,6 +52,7 @@ class ImagesFragment : Fragment() { private val imageMakerLauncher = registerForActivityResult(ImageMakerContract()) { image -> image?.also { + viewModel.lastEvent = ImageListViewModel.Event.ADDED_IMAGE_BEGINNING viewModel.addImageAtTheBeginning(it) } } @@ -73,6 +75,8 @@ class ImagesFragment : Fragment() { return FileProvider.getUriForFile(requireContext(), "${MyApplication.myApp.packageName}.provider", cacheFile) } + private var deletingImagesDialog: Dialog? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -93,7 +97,6 @@ class ImagesFragment : Fragment() { viewModel.loadNext() } } - setupAdapter() setupObservers() setupListeners() @@ -201,6 +204,11 @@ class ImagesFragment : Fragment() { private fun setupObservers() { viewModel.liveList.observe(viewLifecycleOwner) { list -> + if(viewModel.lastEvent == ImageListViewModel.Event.REMOVED_IMAGE || viewModel.lastEvent == ImageListViewModel.Event.ADDED_IMAGE_BEGINNING) { + actionMode?.finish() + + } + viewBinding.noImagesCard.visibility = if(list.isEmpty()) View.VISIBLE else View.GONE adapter.submitList(list) } @@ -218,6 +226,18 @@ class ImagesFragment : Fragment() { viewModel.error.observe(viewLifecycleOwner) { errorViewModel.error.value = it } + + viewModel.deleting.observe(viewLifecycleOwner) { deleting -> + if(deleting) { + deletingImagesDialog = MaterialAlertDialogBuilder(requireContext()) + .setMessage(R.string.deleting_please_wait) + .setCancelable(false) + .show() + } else { + deletingImagesDialog?.dismiss() + deletingImagesDialog = null + } + } } companion object { diff --git a/app/src/main/java/com/isolaatti/images/image_maker/ui/ImageMakerActivity.kt b/app/src/main/java/com/isolaatti/images/image_maker/ui/ImageMakerActivity.kt index 1edf802..bcea37b 100644 --- a/app/src/main/java/com/isolaatti/images/image_maker/ui/ImageMakerActivity.kt +++ b/app/src/main/java/com/isolaatti/images/image_maker/ui/ImageMakerActivity.kt @@ -65,14 +65,17 @@ class ImageMakerActivity : IsolaattiBaseActivity() { is Resource.Error -> { errorViewModel.error.value = it.errorType binding.progressBarLoading.visibility = View.GONE + binding.uploadPhotoFab.visibility = View.VISIBLE binding.textImageName.isEnabled = true } is Resource.Loading -> { binding.progressBarLoading.visibility = View.VISIBLE + binding.uploadPhotoFab.visibility = View.INVISIBLE binding.textImageName.isEnabled = false } is Resource.Success -> { binding.progressBarLoading.visibility = View.GONE + binding.uploadPhotoFab.visibility = View.VISIBLE setResult(Activity.RESULT_OK, Intent().putExtra(EXTRA_IMAGE, it.data)) finish() } diff --git a/app/src/main/res/drawable/face_kiss_wink_heart_solid.xml b/app/src/main/res/drawable/face_kiss_wink_heart_solid.xml new file mode 100644 index 0000000..b7289ae --- /dev/null +++ b/app/src/main/res/drawable/face_kiss_wink_heart_solid.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_images.xml b/app/src/main/res/layout/fragment_images.xml index 9f39046..6634cd7 100644 --- a/app/src/main/res/layout/fragment_images.xml +++ b/app/src/main/res/layout/fragment_images.xml @@ -43,4 +43,29 @@ android:layout_margin="16dp" app:srcCompat="@drawable/baseline_add_24" android:contentDescription="@string/upload_a_picture" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 751fc93..5a69fb4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -124,4 +124,5 @@ Audio options Yes, discard image Discard image? + Deleting, please wait… \ No newline at end of file