mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
Improved deletion and removed cancelledUploads Hashset
This commit is contained in:
parent
9f77fbbc8c
commit
283e2c0a63
11 changed files with 43 additions and 69 deletions
|
|
@ -147,11 +147,6 @@ public class CommonsApplication extends MultiDexApplication {
|
||||||
*/
|
*/
|
||||||
public static Map<String, Boolean> pauseUploads = new HashMap<>();
|
public static Map<String, Boolean> pauseUploads = new HashMap<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* In-memory list of uploads that have been cancelled by the user
|
|
||||||
*/
|
|
||||||
public static HashSet<String> cancelledUploads = new HashSet<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to declare and initialize various components and dependencies
|
* Used to declare and initialize various components and dependencies
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,19 @@ public abstract class ContributionDao {
|
||||||
@Delete
|
@Delete
|
||||||
public abstract void deleteSynchronous(Contribution contribution);
|
public abstract void deleteSynchronous(Contribution contribution);
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
public abstract void deleteContributionsSynchronous(List<Contribution> contributions);
|
||||||
|
|
||||||
public Completable delete(final Contribution contribution) {
|
public Completable delete(final Contribution contribution) {
|
||||||
return Completable
|
return Completable
|
||||||
.fromAction(() -> deleteSynchronous(contribution));
|
.fromAction(() -> deleteSynchronous(contribution));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Completable deleteContributions(final List<Contribution> contributions) {
|
||||||
|
return Completable
|
||||||
|
.fromAction(() -> deleteContributionsSynchronous(contributions));
|
||||||
|
}
|
||||||
|
|
||||||
@Query("SELECT * from contribution WHERE media_filename=:fileName")
|
@Query("SELECT * from contribution WHERE media_filename=:fileName")
|
||||||
public abstract List<Contribution> getContributionWithTitle(String fileName);
|
public abstract List<Contribution> getContributionWithTitle(String fileName);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,10 @@ class ContributionsLocalDataSource {
|
||||||
return contributionDao.delete(contribution);
|
return contributionDao.delete(contribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Completable deleteContributions(final List<Contribution> contributions) {
|
||||||
|
return contributionDao.deleteContributions(contributions);
|
||||||
|
}
|
||||||
|
|
||||||
public Factory<Integer, Contribution> getContributions() {
|
public Factory<Integer, Contribution> getContributions() {
|
||||||
return contributionDao.fetchContributions();
|
return contributionDao.fetchContributions();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@ public class ContributionsRepository {
|
||||||
return localDataSource.deleteContribution(contribution);
|
return localDataSource.deleteContribution(contribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Completable deleteContributionsFromDB(List<Contribution> contributions) {
|
||||||
|
return localDataSource.deleteContributions(contributions);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get contribution object with title
|
* Get contribution object with title
|
||||||
* @param fileName
|
* @param fileName
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,6 @@ class FailedUploadsFragment : CommonsDaggerSupportFragment(), PendingUploadsCont
|
||||||
uploadProgressActivity.hidePendingIcons()
|
uploadProgressActivity.hidePendingIcons()
|
||||||
pendingUploadsPresenter.deleteUploads(
|
pendingUploadsPresenter.deleteUploads(
|
||||||
contributionsList,
|
contributionsList,
|
||||||
0,
|
|
||||||
this.requireContext().applicationContext
|
this.requireContext().applicationContext
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.facebook.imagepipeline.request.ImageRequest
|
import com.facebook.imagepipeline.request.ImageRequest
|
||||||
import fr.free.nrw.commons.R
|
import fr.free.nrw.commons.R
|
||||||
import fr.free.nrw.commons.contributions.Contribution
|
import fr.free.nrw.commons.contributions.Contribution
|
||||||
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -85,6 +86,7 @@ class PendingUploadsAdapter(private val callback: Callback) :
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bindState(state: Int) {
|
fun bindState(state: Int) {
|
||||||
|
Timber.tag("PRINT").e("State is: "+state)
|
||||||
if (state == Contribution.STATE_QUEUED || state == Contribution.STATE_PAUSED) {
|
if (state == Contribution.STATE_QUEUED || state == Contribution.STATE_PAUSED) {
|
||||||
errorTextView.text = "Queued"
|
errorTextView.text = "Queued"
|
||||||
errorTextView.visibility = View.VISIBLE
|
errorTextView.visibility = View.VISIBLE
|
||||||
|
|
@ -96,6 +98,7 @@ class PendingUploadsAdapter(private val callback: Callback) :
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bindProgress(transferred: Long, total: Long, state: Int) {
|
fun bindProgress(transferred: Long, total: Long, state: Int) {
|
||||||
|
Timber.tag("PRINT").e("State is2: "+state)
|
||||||
if (transferred == 0L) {
|
if (transferred == 0L) {
|
||||||
errorTextView.text = "Queued"
|
errorTextView.text = "Queued"
|
||||||
errorTextView.visibility = View.VISIBLE
|
errorTextView.visibility = View.VISIBLE
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,6 @@ class PendingUploadsFragment : CommonsDaggerSupportFragment(), PendingUploadsCon
|
||||||
uploadProgressActivity.hidePendingIcons()
|
uploadProgressActivity.hidePendingIcons()
|
||||||
pendingUploadsPresenter.deleteUploads(
|
pendingUploadsPresenter.deleteUploads(
|
||||||
contributionsList,
|
contributionsList,
|
||||||
0,
|
|
||||||
this.requireContext().applicationContext
|
this.requireContext().applicationContext
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ package fr.free.nrw.commons.upload;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.paging.DataSource;
|
|
||||||
import androidx.paging.DataSource.Factory;
|
import androidx.paging.DataSource.Factory;
|
||||||
import androidx.paging.LivePagedListBuilder;
|
import androidx.paging.LivePagedListBuilder;
|
||||||
import androidx.paging.PagedList;
|
import androidx.paging.PagedList;
|
||||||
|
|
@ -136,18 +135,10 @@ public class PendingUploadsPresenter implements UserActionListener {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteUploads(List<Contribution> contributionList, int index, Context context) {
|
public void deleteUploads(List<Contribution> contributionList, Context context) {
|
||||||
if (index >= contributionList.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Contribution it = contributionList.get(index);
|
|
||||||
compositeDisposable.add(repository
|
compositeDisposable.add(repository
|
||||||
.deleteContributionFromDB(it)
|
.deleteContributionsFromDB(contributionList)
|
||||||
.subscribeOn(ioThreadScheduler)
|
.subscribeOn(ioThreadScheduler)
|
||||||
.doOnComplete(() -> {
|
|
||||||
deleteUploads(contributionList, index + 1, context);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.subscribe(() ->
|
.subscribe(() ->
|
||||||
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
||||||
context, ExistingWorkPolicy.KEEP)
|
context, ExistingWorkPolicy.KEEP)
|
||||||
|
|
@ -159,11 +150,11 @@ public class PendingUploadsPresenter implements UserActionListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Contribution it = contributionList.get(index);
|
Contribution it = contributionList.get(index);
|
||||||
it.setState(Contribution.STATE_QUEUED);
|
if (it.getErrorInfo() == null && it.getState() == Contribution.STATE_FAILED) {
|
||||||
if (it.getErrorInfo() == null){
|
|
||||||
it.setChunkInfo(null);
|
it.setChunkInfo(null);
|
||||||
it.setTransferred(0);
|
it.setTransferred(0);
|
||||||
}
|
}
|
||||||
|
it.setState(Contribution.STATE_QUEUED);
|
||||||
compositeDisposable.add(repository
|
compositeDisposable.add(repository
|
||||||
.save(it)
|
.save(it)
|
||||||
.subscribeOn(ioThreadScheduler)
|
.subscribeOn(ioThreadScheduler)
|
||||||
|
|
@ -173,8 +164,8 @@ public class PendingUploadsPresenter implements UserActionListener {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.subscribe(() ->
|
.subscribe(() ->
|
||||||
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
||||||
context, ExistingWorkPolicy.KEEP),
|
context, ExistingWorkPolicy.KEEP),
|
||||||
throwable -> {
|
throwable -> {
|
||||||
Timber.e(throwable);
|
Timber.e(throwable);
|
||||||
restartUploads(contributionList, index + 1, context);
|
restartUploads(contributionList, index + 1, context);
|
||||||
|
|
@ -187,7 +178,7 @@ public class PendingUploadsPresenter implements UserActionListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Contribution it = contributionList.get(index);
|
Contribution it = contributionList.get(index);
|
||||||
if (it.getErrorInfo() == null){
|
if (it.getErrorInfo() == null && it.getState() == Contribution.STATE_FAILED) {
|
||||||
it.setChunkInfo(null);
|
it.setChunkInfo(null);
|
||||||
it.setTransferred(0);
|
it.setTransferred(0);
|
||||||
}
|
}
|
||||||
|
|
@ -196,8 +187,8 @@ public class PendingUploadsPresenter implements UserActionListener {
|
||||||
.save(it)
|
.save(it)
|
||||||
.subscribeOn(ioThreadScheduler)
|
.subscribeOn(ioThreadScheduler)
|
||||||
.subscribe(() ->
|
.subscribe(() ->
|
||||||
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
WorkRequestHelper.Companion.makeOneTimeWorkRequest(
|
||||||
context, ExistingWorkPolicy.KEEP),
|
context, ExistingWorkPolicy.KEEP),
|
||||||
throwable -> {
|
throwable -> {
|
||||||
Timber.e(throwable);
|
Timber.e(throwable);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import fr.free.nrw.commons.CommonsApplication
|
||||||
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
||||||
import fr.free.nrw.commons.contributions.ChunkInfo
|
import fr.free.nrw.commons.contributions.ChunkInfo
|
||||||
import fr.free.nrw.commons.contributions.Contribution
|
import fr.free.nrw.commons.contributions.Contribution
|
||||||
|
import fr.free.nrw.commons.contributions.ContributionDao
|
||||||
import fr.free.nrw.commons.upload.worker.UploadWorker.NotificationUpdateProgressListener
|
import fr.free.nrw.commons.upload.worker.UploadWorker.NotificationUpdateProgressListener
|
||||||
import fr.free.nrw.commons.wikidata.mwapi.MwException
|
import fr.free.nrw.commons.wikidata.mwapi.MwException
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
|
@ -33,7 +34,8 @@ class UploadClient @Inject constructor(
|
||||||
private val csrfTokenClient: CsrfTokenClient,
|
private val csrfTokenClient: CsrfTokenClient,
|
||||||
private val pageContentsCreator: PageContentsCreator,
|
private val pageContentsCreator: PageContentsCreator,
|
||||||
private val fileUtilsWrapper: FileUtilsWrapper,
|
private val fileUtilsWrapper: FileUtilsWrapper,
|
||||||
private val gson: Gson, private val timeProvider: TimeProvider
|
private val gson: Gson, private val timeProvider: TimeProvider,
|
||||||
|
private val contributionDao: ContributionDao
|
||||||
) {
|
) {
|
||||||
private val CHUNK_SIZE = 512 * 1024 // 512 KB
|
private val CHUNK_SIZE = 512 * 1024 // 512 KB
|
||||||
|
|
||||||
|
|
@ -78,7 +80,7 @@ class UploadClient @Inject constructor(
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
Observable.fromIterable(fileChunks).forEach { chunkFile: File ->
|
Observable.fromIterable(fileChunks).forEach { chunkFile: File ->
|
||||||
if (canProcess(contribution, failures)) {
|
if (canProcess(contribution, failures)) {
|
||||||
if (CommonsApplication.cancelledUploads.contains(contribution.pageId)) {
|
if (contributionDao.getContribution(contribution.pageId) == null) {
|
||||||
compositeDisposable.clear()
|
compositeDisposable.clear()
|
||||||
return@forEach
|
return@forEach
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -101,7 +103,7 @@ class UploadClient @Inject constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
CommonsApplication.cancelledUploads.contains(contribution.pageId) -> {
|
contributionDao.getContribution(contribution.pageId) == null -> {
|
||||||
return Observable.just(StashUploadResult(StashUploadState.CANCELLED, null, "Upload cancelled"))
|
return Observable.just(StashUploadResult(StashUploadState.CANCELLED, null, "Upload cancelled"))
|
||||||
}
|
}
|
||||||
contribution.isPaused() -> {
|
contribution.isPaused() -> {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import dagger.Binds;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
|
||||||
|
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||||
import fr.free.nrw.commons.di.NetworkingModule;
|
import fr.free.nrw.commons.di.NetworkingModule;
|
||||||
import fr.free.nrw.commons.upload.categories.CategoriesContract;
|
import fr.free.nrw.commons.upload.categories.CategoriesContract;
|
||||||
import fr.free.nrw.commons.upload.categories.CategoriesPresenter;
|
import fr.free.nrw.commons.upload.categories.CategoriesPresenter;
|
||||||
|
|
@ -50,8 +51,8 @@ public abstract class UploadModule {
|
||||||
public static UploadClient provideUploadClient(final UploadInterface uploadInterface,
|
public static UploadClient provideUploadClient(final UploadInterface uploadInterface,
|
||||||
@Named(NetworkingModule.NAMED_COMMONS_CSRF) final CsrfTokenClient csrfTokenClient,
|
@Named(NetworkingModule.NAMED_COMMONS_CSRF) final CsrfTokenClient csrfTokenClient,
|
||||||
final PageContentsCreator pageContentsCreator, final FileUtilsWrapper fileUtilsWrapper,
|
final PageContentsCreator pageContentsCreator, final FileUtilsWrapper fileUtilsWrapper,
|
||||||
final Gson gson) {
|
final Gson gson, final ContributionDao contributionDao) {
|
||||||
return new UploadClient(uploadInterface, csrfTokenClient, pageContentsCreator,
|
return new UploadClient(uploadInterface, csrfTokenClient, pageContentsCreator,
|
||||||
fileUtilsWrapper, gson, System::currentTimeMillis);
|
fileUtilsWrapper, gson, System::currentTimeMillis, contributionDao);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -213,32 +213,13 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
}
|
}
|
||||||
|
|
||||||
queuedContributions.asFlow().map { contribution ->
|
queuedContributions.asFlow().map { contribution ->
|
||||||
// Upload the contribution if it has not been cancelled by the user
|
if (contributionDao.getContribution(contribution.pageId) != null) {
|
||||||
if (!CommonsApplication.cancelledUploads.contains(contribution.pageId)) {
|
contribution.transferred = 0
|
||||||
/**
|
contribution.state = Contribution.STATE_IN_PROGRESS
|
||||||
* If the limited connection mode is on, lets iterate through the queued
|
contributionDao.saveSynchronous(contribution)
|
||||||
* contributions
|
setProgressAsync(Data.Builder().putInt("progress", countUpload).build())
|
||||||
* and set the state as STATE_QUEUED_LIMITED_CONNECTION_MODE ,
|
countUpload++
|
||||||
* otherwise proceed with the upload
|
uploadContribution(contribution = contribution)
|
||||||
*/
|
|
||||||
if (isLimitedConnectionModeEnabled()) {
|
|
||||||
if (contribution.state == Contribution.STATE_QUEUED) {
|
|
||||||
contribution.state = Contribution.STATE_QUEUED_LIMITED_CONNECTION_MODE
|
|
||||||
contributionDao.saveSynchronous(contribution)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
contribution.transferred = 0
|
|
||||||
contribution.state = Contribution.STATE_IN_PROGRESS
|
|
||||||
contributionDao.saveSynchronous(contribution)
|
|
||||||
setProgressAsync(Data.Builder().putInt("progress", countUpload).build())
|
|
||||||
countUpload++
|
|
||||||
uploadContribution(contribution = contribution)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* We can remove the cancelled upload from the hashset
|
|
||||||
as this contribution will not be processed again
|
|
||||||
*/
|
|
||||||
removeUploadFromInMemoryHashSet(contribution)
|
|
||||||
}
|
}
|
||||||
}.collect()
|
}.collect()
|
||||||
|
|
||||||
|
|
@ -259,13 +240,6 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the processed contribution from the cancelledUploads in-memory hashset
|
|
||||||
*/
|
|
||||||
private fun removeUploadFromInMemoryHashSet(contribution: Contribution) {
|
|
||||||
CommonsApplication.cancelledUploads.remove(contribution.pageId)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new notification for foreground service
|
* Create new notification for foreground service
|
||||||
*/
|
*/
|
||||||
|
|
@ -286,12 +260,6 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
.setContentTitle(appContext.getString(R.string.upload_in_progress))
|
.setContentTitle(appContext.getString(R.string.upload_in_progress))
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Returns true is the limited connection mode is enabled
|
|
||||||
*/
|
|
||||||
private fun isLimitedConnectionModeEnabled(): Boolean {
|
|
||||||
return sessionManager.getPreference(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload the contribution
|
* Upload the contribution
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue