mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-28 13:23:58 +01:00
Convert UploadPresenter to kotlin
This commit is contained in:
parent
7a9e5c59db
commit
798de8be71
2 changed files with 192 additions and 206 deletions
|
|
@ -1,206 +0,0 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.filepicker.UploadableFile;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.repository.UploadRepository;
|
||||
import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* The MVP pattern presenter of Upload GUI
|
||||
*/
|
||||
@Singleton
|
||||
public class UploadPresenter implements UploadContract.UserActionListener {
|
||||
|
||||
private static final UploadContract.View DUMMY = (UploadContract.View) Proxy.newProxyInstance(
|
||||
UploadContract.View.class.getClassLoader(),
|
||||
new Class[]{UploadContract.View.class}, (proxy, method, methodArgs) -> null);
|
||||
private final UploadRepository repository;
|
||||
private final JsonKvStore defaultKvStore;
|
||||
private UploadContract.View view = DUMMY;
|
||||
@Inject
|
||||
UploadMediaDetailsContract.UserActionListener presenter;
|
||||
|
||||
private CompositeDisposable compositeDisposable;
|
||||
public static final String COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES
|
||||
= "number_of_consecutive_uploads_without_coordinates";
|
||||
|
||||
public static final int CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES_REMINDER_THRESHOLD = 10;
|
||||
|
||||
|
||||
@Inject
|
||||
UploadPresenter(UploadRepository uploadRepository,
|
||||
@Named("default_preferences") JsonKvStore defaultKvStore) {
|
||||
this.repository = uploadRepository;
|
||||
this.defaultKvStore = defaultKvStore;
|
||||
compositeDisposable = new CompositeDisposable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by the submit button in {@link UploadActivity}
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
@Override
|
||||
public void handleSubmit() {
|
||||
boolean hasLocationProvidedForNewUploads = false;
|
||||
for (UploadItem item : repository.getUploads()) {
|
||||
if (item.getGpsCoords().getImageCoordsExists()) {
|
||||
hasLocationProvidedForNewUploads = true;
|
||||
}
|
||||
}
|
||||
boolean hasManyConsecutiveUploadsWithoutLocation = defaultKvStore.getInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0) >=
|
||||
CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES_REMINDER_THRESHOLD;
|
||||
|
||||
if (hasManyConsecutiveUploadsWithoutLocation && !hasLocationProvidedForNewUploads) {
|
||||
defaultKvStore.putInt(COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0);
|
||||
view.showAlertDialog(
|
||||
R.string.location_message,
|
||||
() -> {defaultKvStore.putInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES,
|
||||
0);
|
||||
processContributionsForSubmission();
|
||||
});
|
||||
} else {
|
||||
processContributionsForSubmission();
|
||||
}
|
||||
}
|
||||
|
||||
private void processContributionsForSubmission() {
|
||||
if (view.isLoggedIn()) {
|
||||
view.showProgress(true);
|
||||
repository.buildContributions()
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new Observer<Contribution>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
view.showProgress(false);
|
||||
if (defaultKvStore
|
||||
.getBoolean(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED,
|
||||
false)) {
|
||||
view.showMessage(R.string.uploading_queued);
|
||||
} else {
|
||||
view.showMessage(R.string.uploading_started);
|
||||
}
|
||||
|
||||
compositeDisposable.add(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(Contribution contribution) {
|
||||
if (contribution.getDecimalCoords() == null) {
|
||||
final int recentCount = defaultKvStore.getInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0);
|
||||
defaultKvStore.putInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, recentCount + 1);
|
||||
} else {
|
||||
defaultKvStore.putInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0);
|
||||
}
|
||||
repository.prepareMedia(contribution);
|
||||
contribution.setState(Contribution.STATE_QUEUED);
|
||||
repository.saveContribution(contribution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
view.showMessage(R.string.upload_failed);
|
||||
repository.cleanup();
|
||||
view.returnToMainActivity();
|
||||
compositeDisposable.clear();
|
||||
Timber.e("failed to upload: " + e.getMessage());
|
||||
|
||||
//is submission error, not need to go to the uploadActivity
|
||||
//not start the uploading progress
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
view.makeUploadRequest();
|
||||
repository.cleanup();
|
||||
view.returnToMainActivity();
|
||||
compositeDisposable.clear();
|
||||
|
||||
//after finish the uploadActivity, if successful,
|
||||
//directly go to the upload progress activity
|
||||
view.goToUploadProgressActivity();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
view.askUserToLogIn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls checkImageQuality of UploadMediaPresenter to check image quality of next image
|
||||
*
|
||||
* @param uploadItemIndex Index of next image, whose quality is to be checked
|
||||
*/
|
||||
@Override
|
||||
public void checkImageQuality(int uploadItemIndex) {
|
||||
UploadItem uploadItem = repository.getUploadItem(uploadItemIndex);
|
||||
presenter.checkImageQuality(uploadItem, uploadItemIndex);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deletePictureAtIndex(int index) {
|
||||
List<UploadableFile> uploadableFiles = view.getUploadableFiles();
|
||||
if (index == uploadableFiles.size() - 1) {
|
||||
// If the next fragment to be shown is not one of the MediaDetailsFragment
|
||||
// lets hide the top card so that it doesn't appear on the other fragments
|
||||
view.showHideTopCard(false);
|
||||
}
|
||||
view.setImageCancelled(true);
|
||||
repository.deletePicture(uploadableFiles.get(index).getFilePath());
|
||||
if (uploadableFiles.size() == 1) {
|
||||
view.showMessage(R.string.upload_cancelled);
|
||||
view.finish();
|
||||
return;
|
||||
} else {
|
||||
if (presenter != null) {
|
||||
presenter.updateImageQualitiesJSON(uploadableFiles.size(), index);
|
||||
}
|
||||
view.onUploadMediaDeleted(index);
|
||||
if (!(index == uploadableFiles.size()) && index != 0) {
|
||||
// if the deleted image was not the last item to be uploaded, check quality of next
|
||||
UploadItem uploadItem = repository.getUploadItem(index);
|
||||
presenter.checkImageQuality(uploadItem, index);
|
||||
}
|
||||
}
|
||||
if (uploadableFiles.size() < 2) {
|
||||
view.showHideTopCard(false);
|
||||
}
|
||||
|
||||
//In case lets update the number of uploadable media
|
||||
view.updateTopCardTitle();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachView(UploadContract.View view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachView() {
|
||||
this.view = DUMMY;
|
||||
compositeDisposable.clear();
|
||||
repository.cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
192
app/src/main/java/fr/free/nrw/commons/upload/UploadPresenter.kt
Normal file
192
app/src/main/java/fr/free/nrw/commons/upload/UploadPresenter.kt
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import fr.free.nrw.commons.CommonsApplication
|
||||
import fr.free.nrw.commons.CommonsApplication.Companion.IS_LIMITED_CONNECTION_MODE_ENABLED
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.contributions.Contribution
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore
|
||||
import fr.free.nrw.commons.repository.UploadRepository
|
||||
import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import timber.log.Timber
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Proxy
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* The MVP pattern presenter of Upload GUI
|
||||
*/
|
||||
@Singleton
|
||||
class UploadPresenter @Inject internal constructor(
|
||||
private val repository: UploadRepository,
|
||||
@param:Named("default_preferences") private val defaultKvStore: JsonKvStore
|
||||
) : UploadContract.UserActionListener {
|
||||
private var view = DUMMY
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: UploadMediaDetailsContract.UserActionListener
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
/**
|
||||
* Called by the submit button in [UploadActivity]
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
override fun handleSubmit() {
|
||||
var hasLocationProvidedForNewUploads = false
|
||||
for (item in repository.getUploads()) {
|
||||
if (item.gpsCoords.imageCoordsExists) {
|
||||
hasLocationProvidedForNewUploads = true
|
||||
}
|
||||
}
|
||||
val hasManyConsecutiveUploadsWithoutLocation = defaultKvStore.getInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0
|
||||
) >=
|
||||
CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES_REMINDER_THRESHOLD
|
||||
|
||||
if (hasManyConsecutiveUploadsWithoutLocation && !hasLocationProvidedForNewUploads) {
|
||||
defaultKvStore.putInt(COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0)
|
||||
view.showAlertDialog(
|
||||
R.string.location_message
|
||||
) {
|
||||
defaultKvStore.putInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES,
|
||||
0
|
||||
)
|
||||
processContributionsForSubmission()
|
||||
}
|
||||
} else {
|
||||
processContributionsForSubmission()
|
||||
}
|
||||
}
|
||||
|
||||
private fun processContributionsForSubmission() {
|
||||
if (view.isLoggedIn()) {
|
||||
view.showProgress(true)
|
||||
repository.buildContributions()
|
||||
?.observeOn(Schedulers.io())
|
||||
?.subscribe(object : Observer<Contribution> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
view.showProgress(false)
|
||||
if (defaultKvStore.getBoolean(IS_LIMITED_CONNECTION_MODE_ENABLED, false)) {
|
||||
view.showMessage(R.string.uploading_queued)
|
||||
} else {
|
||||
view.showMessage(R.string.uploading_started)
|
||||
}
|
||||
compositeDisposable.add(d)
|
||||
}
|
||||
|
||||
override fun onNext(contribution: Contribution) {
|
||||
if (contribution.decimalCoords == null) {
|
||||
val recentCount = defaultKvStore.getInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0
|
||||
)
|
||||
defaultKvStore.putInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, recentCount + 1
|
||||
)
|
||||
} else {
|
||||
defaultKvStore.putInt(
|
||||
COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES, 0
|
||||
)
|
||||
}
|
||||
repository.prepareMedia(contribution)
|
||||
contribution.state = Contribution.STATE_QUEUED
|
||||
repository.saveContribution(contribution)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
view.showMessage(R.string.upload_failed)
|
||||
repository.cleanup()
|
||||
view.returnToMainActivity()
|
||||
compositeDisposable.clear()
|
||||
Timber.e(e, "failed to upload")
|
||||
|
||||
//is submission error, not need to go to the uploadActivity
|
||||
//not start the uploading progress
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
view.makeUploadRequest()
|
||||
repository.cleanup()
|
||||
view.returnToMainActivity()
|
||||
compositeDisposable.clear()
|
||||
|
||||
//after finish the uploadActivity, if successful,
|
||||
//directly go to the upload progress activity
|
||||
view.goToUploadProgressActivity()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
view.askUserToLogIn()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls checkImageQuality of UploadMediaPresenter to check image quality of next image
|
||||
*
|
||||
* @param uploadItemIndex Index of next image, whose quality is to be checked
|
||||
*/
|
||||
override fun checkImageQuality(uploadItemIndex: Int) {
|
||||
val uploadItem = repository.getUploadItem(uploadItemIndex)
|
||||
presenter.checkImageQuality(uploadItem, uploadItemIndex)
|
||||
}
|
||||
|
||||
override fun deletePictureAtIndex(index: Int) {
|
||||
val uploadableFiles = view.getUploadableFiles()
|
||||
if (index == uploadableFiles!!.size - 1) {
|
||||
// If the next fragment to be shown is not one of the MediaDetailsFragment
|
||||
// lets hide the top card so that it doesn't appear on the other fragments
|
||||
view.showHideTopCard(false)
|
||||
}
|
||||
view.setImageCancelled(true)
|
||||
repository.deletePicture(uploadableFiles[index].getFilePath())
|
||||
if (uploadableFiles.size == 1) {
|
||||
view.showMessage(R.string.upload_cancelled)
|
||||
view.finish()
|
||||
return
|
||||
}
|
||||
|
||||
presenter.updateImageQualitiesJSON(uploadableFiles.size, index)
|
||||
view.onUploadMediaDeleted(index)
|
||||
if (index != uploadableFiles.size && index != 0) {
|
||||
// if the deleted image was not the last item to be uploaded, check quality of next
|
||||
val uploadItem = repository.getUploadItem(index)
|
||||
presenter.checkImageQuality(uploadItem, index)
|
||||
}
|
||||
|
||||
if (uploadableFiles.size < 2) {
|
||||
view.showHideTopCard(false)
|
||||
}
|
||||
|
||||
//In case lets update the number of uploadable media
|
||||
view.updateTopCardTitle()
|
||||
}
|
||||
|
||||
override fun onAttachView(view: UploadContract.View) {
|
||||
this.view = view
|
||||
}
|
||||
|
||||
override fun onDetachView() {
|
||||
view = DUMMY
|
||||
compositeDisposable.clear()
|
||||
repository.cleanup()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DUMMY = Proxy.newProxyInstance(
|
||||
UploadContract.View::class.java.classLoader,
|
||||
arrayOf<Class<*>>(UploadContract.View::class.java)
|
||||
) { _: Any?, _: Method?, _: Array<Any?>? -> null } as UploadContract.View
|
||||
|
||||
const val COUNTER_OF_CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES: String =
|
||||
"number_of_consecutive_uploads_without_coordinates"
|
||||
|
||||
const val CONSECUTIVE_UPLOADS_WITHOUT_COORDINATES_REMINDER_THRESHOLD: Int = 10
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue