mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-31 23:03:54 +01:00
Added image duplicity check on restart of failed image
This commit is contained in:
parent
ae00a9d19f
commit
e96cc8b5ca
6 changed files with 135 additions and 47 deletions
|
|
@ -5,6 +5,7 @@ import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED;
|
|||
import static fr.free.nrw.commons.contributions.Contribution.STATE_PAUSED;
|
||||
import static fr.free.nrw.commons.nearby.fragments.NearbyParentFragment.WLM_URL;
|
||||
import static fr.free.nrw.commons.profile.ProfileActivity.KEY_USERNAME;
|
||||
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
|
||||
import static fr.free.nrw.commons.utils.LengthUtils.computeBearing;
|
||||
import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween;
|
||||
|
||||
|
|
@ -831,10 +832,18 @@ public class ContributionsFragment
|
|||
* @param contribution
|
||||
*/
|
||||
public void restartUpload(Contribution contribution) {
|
||||
contribution.setState(Contribution.STATE_QUEUED);
|
||||
contribution.setDateUploadStarted(Calendar.getInstance().getTime());
|
||||
contributionsPresenter.saveContribution(contribution);
|
||||
Timber.d("Restarting for %s", contribution.toString());
|
||||
if (contribution.getState() == Contribution.STATE_FAILED) {
|
||||
if (contribution.getErrorInfo() == null){
|
||||
contribution.setChunkInfo(null);
|
||||
contribution.setTransferred(0);
|
||||
}
|
||||
contributionsPresenter.checkDuplicateImageAndRestartContribution(contribution);
|
||||
} else {
|
||||
contribution.setState(Contribution.STATE_QUEUED);
|
||||
contributionsPresenter.saveContribution(contribution);
|
||||
Timber.d("Restarting for %s", contribution.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -856,10 +865,6 @@ public class ContributionsFragment
|
|||
contribution.setRetries(retries + 1);
|
||||
Timber.d("Retried uploading %s %d times", contribution.getMedia().getFilename(),
|
||||
retries + 1);
|
||||
if (contribution.getErrorInfo() == null){
|
||||
contribution.setChunkInfo(null);
|
||||
contribution.setTransferred(0);
|
||||
}
|
||||
restartUpload(contribution);
|
||||
} else {
|
||||
// TODO: Show the exact reason for failure
|
||||
|
|
|
|||
|
|
@ -1,21 +1,26 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
|
||||
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import fr.free.nrw.commons.MediaDataExtractor;
|
||||
import fr.free.nrw.commons.contributions.ContributionsContract.UserActionListener;
|
||||
import fr.free.nrw.commons.di.CommonsApplicationModule;
|
||||
import fr.free.nrw.commons.repository.UploadRepository;
|
||||
import fr.free.nrw.commons.upload.worker.WorkRequestHelper;
|
||||
import io.reactivex.Scheduler;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* The presenter class for Contributions
|
||||
*/
|
||||
public class ContributionsPresenter implements UserActionListener {
|
||||
|
||||
private final ContributionsRepository repository;
|
||||
private final ContributionsRepository contributionsRepository;
|
||||
private final UploadRepository uploadRepository;
|
||||
private final Scheduler ioThreadScheduler;
|
||||
private CompositeDisposable compositeDisposable;
|
||||
private ContributionsContract.View view;
|
||||
|
|
@ -25,8 +30,10 @@ public class ContributionsPresenter implements UserActionListener {
|
|||
|
||||
@Inject
|
||||
ContributionsPresenter(ContributionsRepository repository,
|
||||
UploadRepository uploadRepository,
|
||||
@Named(CommonsApplicationModule.IO_THREAD) Scheduler ioThreadScheduler) {
|
||||
this.repository = repository;
|
||||
this.contributionsRepository = repository;
|
||||
this.uploadRepository = uploadRepository;
|
||||
this.ioThreadScheduler=ioThreadScheduler;
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +51,25 @@ public class ContributionsPresenter implements UserActionListener {
|
|||
|
||||
@Override
|
||||
public Contribution getContributionsWithTitle(String title) {
|
||||
return repository.getContributionWithFileName(title);
|
||||
return contributionsRepository.getContributionWithFileName(title);
|
||||
}
|
||||
|
||||
public void checkDuplicateImageAndRestartContribution(Contribution contribution){
|
||||
compositeDisposable.add(uploadRepository
|
||||
.checkDuplicateImage(contribution.getLocalUriPath().getPath())
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe(imageCheckResult -> {
|
||||
if (imageCheckResult == IMAGE_OK) {
|
||||
contribution.setState(Contribution.STATE_QUEUED);
|
||||
saveContribution(contribution);
|
||||
}else {
|
||||
Timber.e("Contribution already exists");
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.deleteContributionFromDB(contribution)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -54,7 +79,7 @@ public class ContributionsPresenter implements UserActionListener {
|
|||
* @param contribution
|
||||
*/
|
||||
public void saveContribution(Contribution contribution) {
|
||||
compositeDisposable.add(repository
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.save(contribution)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe(() -> WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
||||
|
|
|
|||
|
|
@ -203,6 +203,16 @@ public class UploadRepository {
|
|||
return uploadModel.getImageQuality(uploadItem, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* query the RemoteDataSource for image duplicity check
|
||||
*
|
||||
* @param filePath file to be checked
|
||||
* @return IMAGE_DUPLICATE or IMAGE_OK
|
||||
*/
|
||||
public Single<Integer> checkDuplicateImage(String filePath) {
|
||||
return uploadModel.checkDuplicateImage(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* query the RemoteDataSource for caption quality
|
||||
*
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ public class ImageProcessingService {
|
|||
* @param filePath file to be checked
|
||||
* @return IMAGE_DUPLICATE or IMAGE_OK
|
||||
*/
|
||||
private Single<Integer> checkDuplicateImage(String filePath) {
|
||||
Single<Integer> checkDuplicateImage(String filePath) {
|
||||
Timber.d("Checking for duplicate image %s", filePath);
|
||||
return Single.fromCallable(() -> fileUtilsWrapper.getFileInputStream(filePath))
|
||||
.map(fileUtilsWrapper::getSHA1)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
|
||||
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
|
|
@ -14,6 +16,7 @@ import fr.free.nrw.commons.contributions.ContributionBoundaryCallback;
|
|||
import fr.free.nrw.commons.contributions.ContributionsRemoteDataSource;
|
||||
import fr.free.nrw.commons.contributions.ContributionsRepository;
|
||||
import fr.free.nrw.commons.di.CommonsApplicationModule;
|
||||
import fr.free.nrw.commons.repository.UploadRepository;
|
||||
import fr.free.nrw.commons.upload.PendingUploadsContract.UserActionListener;
|
||||
import fr.free.nrw.commons.upload.PendingUploadsContract.View;
|
||||
import fr.free.nrw.commons.upload.worker.WorkRequestHelper;
|
||||
|
|
@ -33,7 +36,8 @@ import timber.log.Timber;
|
|||
public class PendingUploadsPresenter implements UserActionListener {
|
||||
|
||||
private final ContributionBoundaryCallback contributionBoundaryCallback;
|
||||
private final ContributionsRepository repository;
|
||||
private final ContributionsRepository contributionsRepository;
|
||||
private final UploadRepository uploadRepository;
|
||||
private final Scheduler ioThreadScheduler;
|
||||
|
||||
private final CompositeDisposable compositeDisposable;
|
||||
|
|
@ -46,10 +50,12 @@ public class PendingUploadsPresenter implements UserActionListener {
|
|||
PendingUploadsPresenter(
|
||||
final ContributionBoundaryCallback contributionBoundaryCallback,
|
||||
final ContributionsRemoteDataSource contributionsRemoteDataSource,
|
||||
final ContributionsRepository repository,
|
||||
final ContributionsRepository contributionsRepository,
|
||||
final UploadRepository uploadRepository,
|
||||
@Named(CommonsApplicationModule.IO_THREAD) final Scheduler ioThreadScheduler) {
|
||||
this.contributionBoundaryCallback = contributionBoundaryCallback;
|
||||
this.repository = repository;
|
||||
this.contributionsRepository = contributionsRepository;
|
||||
this.uploadRepository = uploadRepository;
|
||||
this.ioThreadScheduler = ioThreadScheduler;
|
||||
this.contributionsRemoteDataSource = contributionsRemoteDataSource;
|
||||
compositeDisposable = new CompositeDisposable();
|
||||
|
|
@ -68,7 +74,7 @@ public class PendingUploadsPresenter implements UserActionListener {
|
|||
.setPageSize(10).build();
|
||||
Factory<Integer, Contribution> factory;
|
||||
|
||||
factory = repository.fetchContributionsWithStatesSortedByDateUploadStarted(
|
||||
factory = contributionsRepository.fetchContributionsWithStatesSortedByDateUploadStarted(
|
||||
Arrays.asList(Contribution.STATE_QUEUED, Contribution.STATE_IN_PROGRESS,
|
||||
Contribution.STATE_PAUSED));
|
||||
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(factory,
|
||||
|
|
@ -82,7 +88,7 @@ public class PendingUploadsPresenter implements UserActionListener {
|
|||
.setPrefetchDistance(50)
|
||||
.setPageSize(10).build();
|
||||
Factory<Integer, Contribution> factory;
|
||||
factory = repository.fetchContributionsWithStatesSortedByDateUploadStarted(
|
||||
factory = contributionsRepository.fetchContributionsWithStatesSortedByDateUploadStarted(
|
||||
Collections.singletonList(Contribution.STATE_FAILED));
|
||||
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(factory,
|
||||
pagedListConfig);
|
||||
|
|
@ -103,7 +109,7 @@ public class PendingUploadsPresenter implements UserActionListener {
|
|||
|
||||
@Override
|
||||
public void deleteUpload(final Contribution contribution, Context context) {
|
||||
compositeDisposable.add(repository
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.deleteContributionFromDB(contribution)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe());
|
||||
|
|
@ -111,14 +117,14 @@ public class PendingUploadsPresenter implements UserActionListener {
|
|||
|
||||
public void pauseUploads(List<Integer> states, int newState) {
|
||||
CommonsApplication.isPaused = true ;
|
||||
compositeDisposable.add(repository
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.updateContributionWithStates(states, newState)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe());
|
||||
}
|
||||
|
||||
public void deleteUploads(List<Integer> states) {
|
||||
compositeDisposable.add(repository
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.deleteContributionsFromDBWithStates(states)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe());
|
||||
|
|
@ -132,27 +138,46 @@ public class PendingUploadsPresenter implements UserActionListener {
|
|||
Contribution it = contributionList.get(index);
|
||||
if (it.getState() == Contribution.STATE_FAILED) {
|
||||
it.setDateUploadStarted(Calendar.getInstance().getTime());
|
||||
if (it.getErrorInfo() == null){
|
||||
if (it.getErrorInfo() == null) {
|
||||
it.setChunkInfo(null);
|
||||
it.setTransferred(0);
|
||||
}
|
||||
}
|
||||
it.setState(Contribution.STATE_QUEUED);
|
||||
compositeDisposable.add(repository
|
||||
.save(it)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.doOnComplete(() -> {
|
||||
restartUploads(contributionList, index + 1, context);
|
||||
}
|
||||
)
|
||||
.subscribe(() ->
|
||||
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
||||
context, ExistingWorkPolicy.KEEP),
|
||||
throwable -> {
|
||||
compositeDisposable.add(uploadRepository
|
||||
.checkDuplicateImage(it.getLocalUriPath().getPath())
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe(imageCheckResult -> {
|
||||
if (imageCheckResult == IMAGE_OK) {
|
||||
it.setState(Contribution.STATE_QUEUED);
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.save(it)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.doOnComplete(() -> {
|
||||
restartUploads(contributionList, index + 1, context);
|
||||
})
|
||||
.subscribe());
|
||||
} else {
|
||||
Timber.e("Contribution already exists");
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.deleteContributionFromDB(it)
|
||||
.subscribeOn(ioThreadScheduler).doOnComplete(() -> {
|
||||
restartUploads(contributionList, index + 1, context);
|
||||
})
|
||||
.subscribe());
|
||||
}
|
||||
}, throwable -> {
|
||||
Timber.e(throwable);
|
||||
restartUploads(contributionList, index + 1, context);
|
||||
}
|
||||
));
|
||||
}));
|
||||
} else {
|
||||
it.setState(Contribution.STATE_QUEUED);
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.save(it)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.doOnComplete(() -> {
|
||||
restartUploads(contributionList, index + 1, context);
|
||||
})
|
||||
.subscribe());
|
||||
}
|
||||
}
|
||||
|
||||
public void restartUpload(List<Contribution> contributionList, int index, Context context) {
|
||||
|
|
@ -167,18 +192,31 @@ public class PendingUploadsPresenter implements UserActionListener {
|
|||
it.setChunkInfo(null);
|
||||
it.setTransferred(0);
|
||||
}
|
||||
compositeDisposable.add(uploadRepository
|
||||
.checkDuplicateImage(it.getLocalUriPath().getPath())
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe(imageCheckResult -> {
|
||||
if (imageCheckResult == IMAGE_OK) {
|
||||
it.setState(Contribution.STATE_QUEUED);
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.save(it)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe());
|
||||
}else {
|
||||
Timber.e("Contribution already exists");
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.deleteContributionFromDB(it)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe());
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
it.setState(Contribution.STATE_QUEUED);
|
||||
compositeDisposable.add(contributionsRepository
|
||||
.save(it)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe());
|
||||
}
|
||||
it.setState(Contribution.STATE_QUEUED);
|
||||
compositeDisposable.add(repository
|
||||
.save(it)
|
||||
.subscribeOn(ioThreadScheduler)
|
||||
.subscribe(() ->
|
||||
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
||||
context, ExistingWorkPolicy.KEEP),
|
||||
throwable -> {
|
||||
Timber.e(throwable);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,16 @@ public class UploadModel {
|
|||
return imageProcessingService.validateImage(uploadItem, inAppPictureLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls checkDuplicateImage() of ImageProcessingService to check if image is duplicate
|
||||
*
|
||||
* @param filePath file to be checked
|
||||
* @return IMAGE_DUPLICATE or IMAGE_OK
|
||||
*/
|
||||
public Single<Integer> checkDuplicateImage(String filePath){
|
||||
return imageProcessingService.checkDuplicateImage(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls validateCaption() of ImageProcessingService to check caption of image
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue