From 28ab24a4ecdc4bc33200b6ee6b051050b6b06686 Mon Sep 17 00:00:00 2001 From: Pi Patel Date: Tue, 28 Apr 2026 04:59:28 +0530 Subject: [PATCH] area: upload: Fix duplicate validation bypass and thread starvation * Replaced synchronous .blockingGet() with .await() in CustomSelectorUtils.kt to prevent IO dispatcher starvation. * Overloaded checkImageQuality in UploadMediaDetailsContract and Presenter to allow single-parameter (index) validation without breaking existing call sites. * Triggered image verification in UploadMediaDetailFragment's onBecameVisible to ensure validation fires on ViewPager swipe. Fixes #6401 --- .../upload/mediaDetails/UploadMediaDetailFragment.kt | 3 +++ .../mediaDetails/UploadMediaDetailsContract.kt | 6 ++++++ .../upload/mediaDetails/UploadMediaPresenter.kt | 12 ++++++++++++ .../fr/free/nrw/commons/utils/CustomSelectorUtils.kt | 4 +++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.kt b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.kt index 8c2faff3433..20e996a4f05 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.kt @@ -495,6 +495,9 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra return } presenter.fetchTitleAndDescription(indexOfFragment) + if (indexOfFragment > 0) { + presenter.checkImageQuality(indexOfFragment) + } if (showNearbyFound) { if (UploadActivity.nearbyPopupAnswers!!.containsKey(nearbyPlace!!)) { val response = UploadActivity.nearbyPopupAnswers!![nearbyPlace!!]!! diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt index d6d77420852..a5501eb1128 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt @@ -105,6 +105,12 @@ interface UploadMediaDetailsContract { */ fun checkImageQuality(uploadItem: UploadItem, index: Int) + /** + * Forces a check on the image quality for a specific fragment index + * * @param index Index of the UploadItem whose quality is to be checked + */ + fun checkImageQuality(index: Int) + /** * Updates the image qualities stored in JSON, whenever an image is deleted * diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt index 6e26e02a6cc..243b1c0e544 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt @@ -372,6 +372,18 @@ class UploadMediaPresenter @Inject constructor( } } + /** + * Forces a check on the image quality for a specific fragment index + * + * @param index Index of the UploadItem whose quality is to be checked + */ + override fun checkImageQuality(index: Int) { + val uploadItems = repository.getUploads() + if (index in uploadItems.indices) { + checkImageQuality(uploadItems[index], index) + } + } + /** * Updates the image qualities stored in JSON, whenever an image is deleted * diff --git a/app/src/main/java/fr/free/nrw/commons/utils/CustomSelectorUtils.kt b/app/src/main/java/fr/free/nrw/commons/utils/CustomSelectorUtils.kt index 79cf87e538a..02aee73d12d 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/CustomSelectorUtils.kt +++ b/app/src/main/java/fr/free/nrw/commons/utils/CustomSelectorUtils.kt @@ -12,6 +12,7 @@ import fr.free.nrw.commons.upload.FileProcessor import fr.free.nrw.commons.upload.FileUtilsWrapper import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext +import kotlinx.coroutines.rx2.await import timber.log.Timber import java.io.FileNotFoundException import java.io.IOException @@ -82,7 +83,8 @@ class CustomSelectorUtils { withContext(ioDispatcher) { var result: ImageLoader.Result = ImageLoader.Result.FALSE try { - if (mediaClient.checkFileExistsUsingSha(SHA1).blockingGet()) { + // Changed .blockingGet() to .await() + if (mediaClient.checkFileExistsUsingSha(SHA1).await()) { result = ImageLoader.Result.TRUE } } catch (e: Exception) {