mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Fix - No Precise Error Message After Error Due to Password Change (#5643)
* initial commit * Fix No Precise Message After Clicking Review Buttons * Fix For ThanksClient * Fix For Depictions * Fix For Categories * Fix For Description & Coordinates * Fix For Description & Coordinates * Fix For Description & Coordinates * Fix For Mark as Read notifications * resolve conflicts * fix merge conflicts
This commit is contained in:
parent
e56de2c343
commit
3d1efecb55
18 changed files with 361 additions and 110 deletions
|
|
@ -30,9 +30,13 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import fr.free.nrw.commons.CameraPosition;
|
import fr.free.nrw.commons.CameraPosition;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.Media;
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.Utils;
|
import fr.free.nrw.commons.Utils;
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||||
import fr.free.nrw.commons.coordinates.CoordinateEditHelper;
|
import fr.free.nrw.commons.coordinates.CoordinateEditHelper;
|
||||||
import fr.free.nrw.commons.filepicker.Constants;
|
import fr.free.nrw.commons.filepicker.Constants;
|
||||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||||
|
|
@ -141,6 +145,8 @@ public class LocationPickerActivity extends BaseActivity implements
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
LocationServiceManager locationManager;
|
LocationServiceManager locationManager;
|
||||||
|
@Inject
|
||||||
|
SessionManager sessionManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
|
|
@ -404,13 +410,29 @@ public class LocationPickerActivity extends BaseActivity implements
|
||||||
if (media == null) {
|
if (media == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
compositeDisposable.add(coordinateEditHelper.makeCoordinatesEdit(getApplicationContext(),media,
|
|
||||||
Latitude, Longitude, Accuracy)
|
try {
|
||||||
.subscribeOn(Schedulers.io())
|
compositeDisposable.add(
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
coordinateEditHelper.makeCoordinatesEdit(getApplicationContext(), media,
|
||||||
.subscribe(s -> {
|
Latitude, Longitude, Accuracy)
|
||||||
Timber.d("Coordinates are added.");
|
.subscribeOn(Schedulers.io())
|
||||||
}));
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(s -> {
|
||||||
|
Timber.d("Coordinates are added.");
|
||||||
|
}));
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e.getLocalizedMessage().equals(CsrfTokenClient.ANONYMOUS_TOKEN_MESSAGE)) {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
this,
|
||||||
|
getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
this, logoutListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package fr.free.nrw.commons.actions
|
package fr.free.nrw.commons.actions
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
||||||
|
|
@ -28,7 +29,11 @@ class PageEditClient(
|
||||||
pageEditInterface.postEdit(pageTitle, summary, text, csrfTokenClient.getTokenBlocking())
|
pageEditInterface.postEdit(pageTitle, summary, text, csrfTokenClient.getTokenBlocking())
|
||||||
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
Observable.just(false)
|
if (throwable is InvalidLoginTokenException) {
|
||||||
|
throw throwable
|
||||||
|
} else {
|
||||||
|
Observable.just(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +49,11 @@ class PageEditClient(
|
||||||
pageEditInterface.postAppendEdit(pageTitle, summary, appendText, csrfTokenClient.getTokenBlocking())
|
pageEditInterface.postAppendEdit(pageTitle, summary, appendText, csrfTokenClient.getTokenBlocking())
|
||||||
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
Observable.just(false)
|
if (throwable is InvalidLoginTokenException) {
|
||||||
|
throw throwable
|
||||||
|
} else {
|
||||||
|
Observable.just(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,12 +67,17 @@ class PageEditClient(
|
||||||
fun prependEdit(pageTitle: String, prependText: String, summary: String): Observable<Boolean> {
|
fun prependEdit(pageTitle: String, prependText: String, summary: String): Observable<Boolean> {
|
||||||
return try {
|
return try {
|
||||||
pageEditInterface.postPrependEdit(pageTitle, summary, prependText, csrfTokenClient.getTokenBlocking())
|
pageEditInterface.postPrependEdit(pageTitle, summary, prependText, csrfTokenClient.getTokenBlocking())
|
||||||
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
.map { editResponse -> editResponse.edit()?.editSucceeded() ?: false }
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
Observable.just(false)
|
if (throwable is InvalidLoginTokenException) {
|
||||||
|
throw throwable
|
||||||
|
} else {
|
||||||
|
Observable.just(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set new labels to Wikibase server of commons
|
* Set new labels to Wikibase server of commons
|
||||||
* @param summary Edit summary
|
* @param summary Edit summary
|
||||||
|
|
@ -79,7 +93,11 @@ class PageEditClient(
|
||||||
value, csrfTokenClient.getTokenBlocking()
|
value, csrfTokenClient.getTokenBlocking()
|
||||||
).map { it.success }
|
).map { it.success }
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
Observable.just(0)
|
if (throwable is InvalidLoginTokenException) {
|
||||||
|
throw throwable
|
||||||
|
} else {
|
||||||
|
Observable.just(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,4 +111,4 @@ class PageEditClient(
|
||||||
it.query()?.pages()?.get(0)?.revisions()?.get(0)?.content()
|
it.query()?.pages()?.get(0)?.revisions()?.get(0)?.content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import fr.free.nrw.commons.CommonsApplication
|
||||||
import fr.free.nrw.commons.di.NetworkingModule.NAMED_COMMONS_CSRF
|
import fr.free.nrw.commons.di.NetworkingModule.NAMED_COMMONS_CSRF
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
|
||||||
|
import fr.free.nrw.commons.auth.login.LoginFailedException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Named
|
import javax.inject.Named
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
@ -32,8 +34,15 @@ class ThanksClient @Inject constructor(
|
||||||
).map {
|
).map {
|
||||||
mwThankPostResponse -> mwThankPostResponse.result?.success == 1
|
mwThankPostResponse -> mwThankPostResponse.result?.success == 1
|
||||||
}
|
}
|
||||||
} catch (throwable: Throwable) {
|
}
|
||||||
Observable.just(false)
|
catch (throwable: Throwable) {
|
||||||
|
if (throwable is InvalidLoginTokenException) {
|
||||||
|
Observable.error(throwable)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Observable.just(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,16 +48,19 @@ class CsrfTokenClient(
|
||||||
|
|
||||||
token = response.body()!!.query()!!.csrfToken()!!
|
token = response.body()!!.query()!!.csrfToken()!!
|
||||||
if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) {
|
if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) {
|
||||||
throw RuntimeException("App believes we're logged in, but got anonymous token.")
|
throw InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
} catch (t: Throwable) {
|
} catch (e: LoginFailedException) {
|
||||||
|
throw InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||||
|
}
|
||||||
|
catch (t: Throwable) {
|
||||||
Timber.w(t)
|
Timber.w(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.isEmpty() || token == ANON_TOKEN) {
|
if (token.isEmpty() || token == ANON_TOKEN) {
|
||||||
throw IOException(INVALID_TOKEN_ERROR_MESSAGE)
|
throw InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||||
}
|
}
|
||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +71,7 @@ class CsrfTokenClient(
|
||||||
override fun success(token: String?) {
|
override fun success(token: String?) {
|
||||||
if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) {
|
if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) {
|
||||||
retryWithLogin(cb) {
|
retryWithLogin(cb) {
|
||||||
RuntimeException("App believes we're logged in, but got anonymous token.")
|
InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cb.success(token)
|
cb.success(token)
|
||||||
|
|
@ -161,5 +164,8 @@ class CsrfTokenClient(
|
||||||
private const val MAX_RETRIES = 1
|
private const val MAX_RETRIES = 1
|
||||||
private const val MAX_RETRIES_OF_LOGIN_BLOCKING = 2
|
private const val MAX_RETRIES_OF_LOGIN_BLOCKING = 2
|
||||||
const val INVALID_TOKEN_ERROR_MESSAGE = "Invalid token, or login failure."
|
const val INVALID_TOKEN_ERROR_MESSAGE = "Invalid token, or login failure."
|
||||||
|
const val ANONYMOUS_TOKEN_MESSAGE = "App believes we're logged in, but got anonymous token."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class InvalidLoginTokenException(message: String) : Exception(message)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.Media;
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.actions.PageEditClient;
|
import fr.free.nrw.commons.actions.PageEditClient;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||||
import fr.free.nrw.commons.notification.NotificationHelper;
|
import fr.free.nrw.commons.notification.NotificationHelper;
|
||||||
import fr.free.nrw.commons.review.ReviewController;
|
import fr.free.nrw.commons.review.ReviewController;
|
||||||
import fr.free.nrw.commons.utils.ViewUtilWrapper;
|
import fr.free.nrw.commons.utils.ViewUtilWrapper;
|
||||||
|
|
@ -66,7 +67,13 @@ public class DeleteHelper {
|
||||||
|
|
||||||
return delete(media, reason)
|
return delete(media, reason)
|
||||||
.flatMapSingle(result -> Single.just(showDeletionNotification(context, media, result)))
|
.flatMapSingle(result -> Single.just(showDeletionNotification(context, media, result)))
|
||||||
.firstOrError();
|
.firstOrError()
|
||||||
|
.onErrorResumeNext(throwable -> {
|
||||||
|
if (throwable instanceof InvalidLoginTokenException) {
|
||||||
|
return Single.error(throwable);
|
||||||
|
}
|
||||||
|
return Single.error(throwable);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -104,22 +111,30 @@ public class DeleteHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageEditClient.prependEdit(media.getFilename(), fileDeleteString + "\n", summary)
|
return pageEditClient.prependEdit(media.getFilename(), fileDeleteString + "\n", summary)
|
||||||
.flatMap(result -> {
|
.onErrorResumeNext(throwable -> {
|
||||||
if (result) {
|
if (throwable instanceof InvalidLoginTokenException) {
|
||||||
return pageEditClient.edit("Commons:Deletion_requests/" + media.getFilename(), subpageString + "\n", summary);
|
return Observable.error(throwable);
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Failed to nominate for deletion");
|
return Observable.error(throwable);
|
||||||
}).flatMap(result -> {
|
})
|
||||||
if (result) {
|
.flatMap(result -> {
|
||||||
return pageEditClient.appendEdit("Commons:Deletion_requests/" + date, logPageString + "\n", summary);
|
if (result) {
|
||||||
}
|
return pageEditClient.edit("Commons:Deletion_requests/" + media.getFilename(), subpageString + "\n", summary);
|
||||||
throw new RuntimeException("Failed to nominate for deletion");
|
}
|
||||||
}).flatMap(result -> {
|
return Observable.error(new RuntimeException("Failed to nominate for deletion"));
|
||||||
if (result) {
|
})
|
||||||
return pageEditClient.appendEdit("User_Talk:" + creator, userPageString + "\n", summary);
|
.flatMap(result -> {
|
||||||
}
|
if (result) {
|
||||||
throw new RuntimeException("Failed to nominate for deletion");
|
return pageEditClient.appendEdit("Commons:Deletion_requests/" + date, logPageString + "\n", summary);
|
||||||
});
|
}
|
||||||
|
return Observable.error(new RuntimeException("Failed to nominate for deletion"));
|
||||||
|
})
|
||||||
|
.flatMap(result -> {
|
||||||
|
if (result) {
|
||||||
|
return pageEditClient.appendEdit("User_Talk:" + creator, userPageString + "\n", summary);
|
||||||
|
}
|
||||||
|
return Observable.error(new RuntimeException("Failed to nominate for deletion"));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean showDeletionNotification(Context context, Media media, boolean result) {
|
private boolean showDeletionNotification(Context context, Media media, boolean result) {
|
||||||
|
|
@ -226,14 +241,15 @@ public class DeleteHelper {
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(aBoolean -> {
|
.subscribe(aBoolean -> {
|
||||||
if (aBoolean) {
|
reviewCallback.onSuccess();
|
||||||
reviewCallback.onSuccess();
|
}, throwable -> {
|
||||||
|
if (throwable instanceof InvalidLoginTokenException) {
|
||||||
|
reviewCallback.onTokenException((InvalidLoginTokenException) throwable);
|
||||||
} else {
|
} else {
|
||||||
reviewCallback.onFailure();
|
reviewCallback.onFailure();
|
||||||
}
|
}
|
||||||
reviewCallback.enableButtons();
|
reviewCallback.enableButtons();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
alert.setNegativeButton(context.getString(R.string.cancel), (dialog, which) -> reviewCallback.onFailure());
|
alert.setNegativeButton(context.getString(R.string.cancel), (dialog, which) -> reviewCallback.onFailure());
|
||||||
d = alert.create();
|
d = alert.create();
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ import com.facebook.imagepipeline.image.ImageInfo;
|
||||||
import com.facebook.imagepipeline.request.ImageRequest;
|
import com.facebook.imagepipeline.request.ImageRequest;
|
||||||
import fr.free.nrw.commons.BuildConfig;
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.CameraPosition;
|
import fr.free.nrw.commons.CameraPosition;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.LocationPicker.LocationPicker;
|
import fr.free.nrw.commons.LocationPicker.LocationPicker;
|
||||||
import fr.free.nrw.commons.Media;
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.MediaDataExtractor;
|
import fr.free.nrw.commons.MediaDataExtractor;
|
||||||
|
|
@ -57,6 +58,8 @@ import fr.free.nrw.commons.Utils;
|
||||||
import fr.free.nrw.commons.actions.ThanksClient;
|
import fr.free.nrw.commons.actions.ThanksClient;
|
||||||
import fr.free.nrw.commons.auth.AccountUtil;
|
import fr.free.nrw.commons.auth.AccountUtil;
|
||||||
import fr.free.nrw.commons.auth.SessionManager;
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||||
import fr.free.nrw.commons.category.CategoryClient;
|
import fr.free.nrw.commons.category.CategoryClient;
|
||||||
import fr.free.nrw.commons.category.CategoryDetailsActivity;
|
import fr.free.nrw.commons.category.CategoryDetailsActivity;
|
||||||
import fr.free.nrw.commons.category.CategoryEditHelper;
|
import fr.free.nrw.commons.category.CategoryEditHelper;
|
||||||
|
|
@ -780,9 +783,23 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
||||||
firstRevision.getRevisionId()))
|
firstRevision.getRevisionId()))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe((result) -> {
|
.subscribe(result -> {
|
||||||
displayThanksToast(context, result);
|
displayThanksToast(getContext(), result);
|
||||||
}, Timber::e);
|
}, throwable -> {
|
||||||
|
if (throwable instanceof InvalidLoginTokenException) {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
getActivity(),
|
||||||
|
requireActivity().getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
requireActivity(), logoutListener);
|
||||||
|
} else {
|
||||||
|
Timber.e(throwable);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1056,13 +1073,28 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
||||||
|
|
||||||
if (requestCode == REQUEST_CODE_EDIT_DESCRIPTION && resultCode == RESULT_OK) {
|
if (requestCode == REQUEST_CODE_EDIT_DESCRIPTION && resultCode == RESULT_OK) {
|
||||||
final String updatedWikiText = data.getStringExtra(UPDATED_WIKITEXT);
|
final String updatedWikiText = data.getStringExtra(UPDATED_WIKITEXT);
|
||||||
compositeDisposable.add(descriptionEditHelper.addDescription(getContext(), media,
|
|
||||||
updatedWikiText)
|
try {
|
||||||
.subscribeOn(Schedulers.io())
|
compositeDisposable.add(descriptionEditHelper.addDescription(getContext(), media,
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
updatedWikiText)
|
||||||
.subscribe(s -> {
|
.subscribeOn(Schedulers.io())
|
||||||
Timber.d("Descriptions are added.");
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
}));
|
.subscribe(s -> {
|
||||||
|
Timber.d("Descriptions are added.");
|
||||||
|
}));
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e.getLocalizedMessage().equals(CsrfTokenClient.ANONYMOUS_TOKEN_MESSAGE)) {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
getActivity(),
|
||||||
|
requireActivity().getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
requireActivity(), logoutListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final ArrayList<UploadMediaDetail> uploadMediaDetails
|
final ArrayList<UploadMediaDetail> uploadMediaDetails
|
||||||
= data.getParcelableArrayListExtra(LIST_OF_DESCRIPTION_AND_CAPTION);
|
= data.getParcelableArrayListExtra(LIST_OF_DESCRIPTION_AND_CAPTION);
|
||||||
|
|
@ -1070,14 +1102,29 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
||||||
LinkedHashMap<String, String> updatedCaptions = new LinkedHashMap<>();
|
LinkedHashMap<String, String> updatedCaptions = new LinkedHashMap<>();
|
||||||
for (UploadMediaDetail mediaDetail:
|
for (UploadMediaDetail mediaDetail:
|
||||||
uploadMediaDetails) {
|
uploadMediaDetails) {
|
||||||
compositeDisposable.add(descriptionEditHelper.addCaption(getContext(), media,
|
try {
|
||||||
mediaDetail.getLanguageCode(), mediaDetail.getCaptionText())
|
compositeDisposable.add(descriptionEditHelper.addCaption(getContext(), media,
|
||||||
.subscribeOn(Schedulers.io())
|
mediaDetail.getLanguageCode(), mediaDetail.getCaptionText())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(s -> {
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
updateCaptions(mediaDetail, updatedCaptions);
|
.subscribe(s -> {
|
||||||
Timber.d("Caption is added.");
|
updateCaptions(mediaDetail, updatedCaptions);
|
||||||
}));
|
Timber.d("Caption is added.");
|
||||||
|
}));
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e.getLocalizedMessage().equals(CsrfTokenClient.ANONYMOUS_TOKEN_MESSAGE)) {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
getActivity(),
|
||||||
|
requireActivity().getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
requireActivity(), logoutListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
binding.progressBarEdit.setVisibility(GONE);
|
binding.progressBarEdit.setVisibility(GONE);
|
||||||
binding.descriptionEdit.setVisibility(VISIBLE);
|
binding.descriptionEdit.setVisibility(VISIBLE);
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,12 @@ import android.view.View;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.Utils;
|
import fr.free.nrw.commons.Utils;
|
||||||
import fr.free.nrw.commons.databinding.ActivityNotificationBinding;
|
import fr.free.nrw.commons.databinding.ActivityNotificationBinding;
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||||
import fr.free.nrw.commons.notification.models.Notification;
|
import fr.free.nrw.commons.notification.models.Notification;
|
||||||
import fr.free.nrw.commons.theme.BaseActivity;
|
import fr.free.nrw.commons.theme.BaseActivity;
|
||||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||||
|
|
@ -41,6 +44,9 @@ public class NotificationActivity extends BaseActivity {
|
||||||
@Inject
|
@Inject
|
||||||
NotificationController controller;
|
NotificationController controller;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SessionManager sessionManager;
|
||||||
|
|
||||||
private static final String TAG_NOTIFICATION_WORKER_FRAGMENT = "NotificationWorkerFragment";
|
private static final String TAG_NOTIFICATION_WORKER_FRAGMENT = "NotificationWorkerFragment";
|
||||||
private NotificationWorkerFragment mNotificationWorkerFragment;
|
private NotificationWorkerFragment mNotificationWorkerFragment;
|
||||||
private NotificatinAdapter adapter;
|
private NotificatinAdapter adapter;
|
||||||
|
|
@ -107,10 +113,23 @@ public class NotificationActivity extends BaseActivity {
|
||||||
ViewUtil.showLongToast(this,getString(R.string.some_error));
|
ViewUtil.showLongToast(this,getString(R.string.some_error));
|
||||||
}
|
}
|
||||||
}, throwable -> {
|
}, throwable -> {
|
||||||
|
if (throwable instanceof InvalidLoginTokenException) {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
this,
|
||||||
|
getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
Timber.e(throwable, "Error occurred while loading notifications");
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
throwable.printStackTrace();
|
this, logoutListener);
|
||||||
|
} else {
|
||||||
|
Timber.e(throwable, "Error occurred while loading notifications");
|
||||||
|
throwable.printStackTrace();
|
||||||
ViewUtil.showShortSnackbar(binding.container, R.string.error_notifications);
|
ViewUtil.showShortSnackbar(binding.container, R.string.error_notifications);
|
||||||
|
binding.progressBar.setVisibility(View.GONE);
|
||||||
|
ViewUtil.showShortSnackbar(binding.container, R.string.error_notifications);
|
||||||
|
}
|
||||||
binding.progressBar.setVisibility(View.GONE);
|
binding.progressBar.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
compositeDisposable.add(disposable);
|
compositeDisposable.add(disposable);
|
||||||
|
|
@ -170,7 +189,7 @@ public class NotificationActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
binding.progressBar.setVisibility(View.GONE);
|
binding.progressBar.setVisibility(View.GONE);
|
||||||
}, throwable -> {
|
}, throwable -> {
|
||||||
Timber.e(throwable, "Error occurred while loading notifications");
|
Timber.e(throwable, "Error occurred while loading notifications ");
|
||||||
ViewUtil.showShortSnackbar(binding.container, R.string.error_notifications);
|
ViewUtil.showShortSnackbar(binding.container, R.string.error_notifications);
|
||||||
binding.progressBar.setVisibility(View.GONE);
|
binding.progressBar.setVisibility(View.GONE);
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import fr.free.nrw.commons.notification.models.NotificationType
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
|
||||||
import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse
|
import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse
|
||||||
import fr.free.nrw.commons.utils.DateUtil
|
import fr.free.nrw.commons.utils.DateUtil
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -39,7 +40,11 @@ class NotificationClient @Inject constructor(
|
||||||
unreadList = ""
|
unreadList = ""
|
||||||
).map(MwQueryResponse::success)
|
).map(MwQueryResponse::success)
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
Observable.just(false)
|
if (throwable is InvalidLoginTokenException) {
|
||||||
|
Observable.error(throwable)
|
||||||
|
} else {
|
||||||
|
Observable.just(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||||
import fr.free.nrw.commons.wikidata.mwapi.MwQueryPage;
|
import fr.free.nrw.commons.wikidata.mwapi.MwQueryPage;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -39,6 +41,9 @@ public class ReviewController {
|
||||||
protected static ArrayList<String> categories;
|
protected static ArrayList<String> categories;
|
||||||
@Inject
|
@Inject
|
||||||
ThanksClient thanksClient;
|
ThanksClient thanksClient;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SessionManager sessionManager;
|
||||||
private final DeleteHelper deleteHelper;
|
private final DeleteHelper deleteHelper;
|
||||||
@Nullable
|
@Nullable
|
||||||
MwQueryPage.Revision firstRevision; // TODO: maybe we can expand this class to include fileName
|
MwQueryPage.Revision firstRevision; // TODO: maybe we can expand this class to include fileName
|
||||||
|
|
@ -155,9 +160,23 @@ public class ReviewController {
|
||||||
Observable.defer((Callable<ObservableSource<Boolean>>) () -> thanksClient.thank(firstRevision.getRevisionId()))
|
Observable.defer((Callable<ObservableSource<Boolean>>) () -> thanksClient.thank(firstRevision.getRevisionId()))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe((result) -> {
|
.subscribe(result -> {
|
||||||
displayThanksToast(context,result);
|
displayThanksToast(context, result);
|
||||||
}, Timber::e);
|
}, throwable -> {
|
||||||
|
if (throwable instanceof InvalidLoginTokenException) {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
activity,
|
||||||
|
activity.getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
activity, logoutListener);
|
||||||
|
} else {
|
||||||
|
Timber.e(throwable);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("StringFormatInvalid")
|
@SuppressLint("StringFormatInvalid")
|
||||||
|
|
@ -192,6 +211,8 @@ public class ReviewController {
|
||||||
|
|
||||||
void onFailure();
|
void onFailure();
|
||||||
|
|
||||||
|
void onTokenException(Exception e);
|
||||||
|
|
||||||
void disableButtons();
|
void disableButtons();
|
||||||
|
|
||||||
void enableButtons();
|
void enableButtons();
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,17 @@ import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.Media;
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||||
import fr.free.nrw.commons.databinding.FragmentReviewImageBinding;
|
import fr.free.nrw.commons.databinding.FragmentReviewImageBinding;
|
||||||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
||||||
|
|
||||||
|
|
@ -28,7 +30,8 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
||||||
|
|
||||||
private FragmentReviewImageBinding binding;
|
private FragmentReviewImageBinding binding;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SessionManager sessionManager;
|
||||||
|
|
||||||
|
|
||||||
// Constant variable used to store user's key name for onSaveInstanceState method
|
// Constant variable used to store user's key name for onSaveInstanceState method
|
||||||
|
|
@ -37,20 +40,20 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
||||||
// Variable that stores the value of user
|
// Variable that stores the value of user
|
||||||
private String user;
|
private String user;
|
||||||
|
|
||||||
public void update(int position) {
|
public void update(final int position) {
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String updateCategoriesQuestion() {
|
private String updateCategoriesQuestion() {
|
||||||
Media media = getReviewActivity().getMedia();
|
final Media media = getReviewActivity().getMedia();
|
||||||
if (media != null && media.getCategoriesHiddenStatus() != null && isAdded()) {
|
if (media != null && media.getCategoriesHiddenStatus() != null && isAdded()) {
|
||||||
// Filter category name attribute from all categories
|
// Filter category name attribute from all categories
|
||||||
List<String> categories = new ArrayList<>();
|
final List<String> categories = new ArrayList<>();
|
||||||
for(String key : media.getCategoriesHiddenStatus().keySet()) {
|
for(final String key : media.getCategoriesHiddenStatus().keySet()) {
|
||||||
String value = String.valueOf(key);
|
String value = String.valueOf(key);
|
||||||
// Each category returned has a format like "Category:<some-category-name>"
|
// Each category returned has a format like "Category:<some-category-name>"
|
||||||
// so remove the prefix "Category:"
|
// so remove the prefix "Category:"
|
||||||
int index = key.indexOf("Category:");
|
final int index = key.indexOf("Category:");
|
||||||
if(index == 0) {
|
if(index == 0) {
|
||||||
value = key.substring(9);
|
value = key.substring(9);
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +62,7 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
||||||
String catString = TextUtils.join(", ", categories);
|
String catString = TextUtils.join(", ", categories);
|
||||||
if (catString != null && !catString.equals("") && binding.tvReviewQuestionContext != null) {
|
if (catString != null && !catString.equals("") && binding.tvReviewQuestionContext != null) {
|
||||||
catString = "<b>" + catString + "</b>";
|
catString = "<b>" + catString + "</b>";
|
||||||
String stringToConvertHtml = String.format(getResources().getString(R.string.review_category_explanation), catString);
|
final String stringToConvertHtml = String.format(getResources().getString(R.string.review_category_explanation), catString);
|
||||||
return Html.fromHtml(stringToConvertHtml).toString();
|
return Html.fromHtml(stringToConvertHtml).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,17 +70,20 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
final Bundle savedInstanceState) {
|
||||||
position = getArguments().getInt("position");
|
position = getArguments().getInt("position");
|
||||||
binding = FragmentReviewImageBinding.inflate(inflater, container, false);
|
binding = FragmentReviewImageBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
String question, explanation=null, yesButtonText, noButtonText;
|
final String question;
|
||||||
|
String explanation=null;
|
||||||
|
String yesButtonText;
|
||||||
|
final String noButtonText;
|
||||||
|
|
||||||
binding.buttonYes.setOnClickListener(view -> onYesButtonClicked());
|
binding.buttonYes.setOnClickListener(view -> onYesButtonClicked());
|
||||||
|
|
||||||
|
|
@ -182,6 +188,22 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTokenException(final Exception e) {
|
||||||
|
if (e instanceof InvalidLoginTokenException){
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
getActivity(),
|
||||||
|
requireActivity().getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
requireActivity(), logoutListener);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called when an image is being loaded
|
* This function is called when an image is being loaded
|
||||||
* to disable the review buttons
|
* to disable the review buttons
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,12 @@ public interface CategoriesContract {
|
||||||
* Refreshes the categories
|
* Refreshes the categories
|
||||||
*/
|
*/
|
||||||
void refreshCategories();
|
void refreshCategories();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate the user to Login Activity
|
||||||
|
*/
|
||||||
|
void navigateToLoginScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserActionListener extends BasePresenter<View> {
|
interface UserActionListener extends BasePresenter<View> {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import fr.free.nrw.commons.Media
|
import fr.free.nrw.commons.Media
|
||||||
import fr.free.nrw.commons.R
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
|
||||||
import fr.free.nrw.commons.category.CategoryEditHelper
|
import fr.free.nrw.commons.category.CategoryEditHelper
|
||||||
import fr.free.nrw.commons.category.CategoryItem
|
import fr.free.nrw.commons.category.CategoryItem
|
||||||
import fr.free.nrw.commons.di.CommonsApplicationModule
|
import fr.free.nrw.commons.di.CommonsApplicationModule
|
||||||
|
|
@ -211,25 +212,31 @@ class CategoriesPresenter @Inject constructor(
|
||||||
|
|
||||||
if (selectedCategories.isNotEmpty()) {
|
if (selectedCategories.isNotEmpty()) {
|
||||||
view.showProgressDialog()
|
view.showProgressDialog()
|
||||||
compositeDisposable.add(
|
|
||||||
categoryEditHelper.makeCategoryEdit(view.fragmentContext, media,
|
try {
|
||||||
selectedCategories, wikiText)
|
compositeDisposable.add(
|
||||||
.subscribeOn(Schedulers.io())
|
categoryEditHelper.makeCategoryEdit(
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
view.fragmentContext, media,
|
||||||
.subscribe({
|
selectedCategories, wikiText
|
||||||
Timber.d("Categories are added.")
|
)
|
||||||
media.addedCategories = selectedCategories
|
.subscribeOn(Schedulers.io())
|
||||||
repository.cleanup()
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
view.dismissProgressDialog()
|
.subscribe({
|
||||||
view.refreshCategories()
|
Timber.d("Categories are added.")
|
||||||
view.goBackToPreviousScreen()
|
media.addedCategories = selectedCategories
|
||||||
})
|
repository.cleanup()
|
||||||
{
|
view.dismissProgressDialog()
|
||||||
Timber.e(
|
view.refreshCategories()
|
||||||
"Failed to update categories"
|
view.goBackToPreviousScreen()
|
||||||
)
|
}, {
|
||||||
}
|
Timber.e(
|
||||||
)
|
"Failed to update categories"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} catch (e: InvalidLoginTokenException) {
|
||||||
|
view.navigateToLoginScreen();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import com.jakewharton.rxbinding2.view.RxView;
|
import com.jakewharton.rxbinding2.view.RxView;
|
||||||
import com.jakewharton.rxbinding2.widget.RxTextView;
|
import com.jakewharton.rxbinding2.widget.RxTextView;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.Media;
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.category.CategoryItem;
|
import fr.free.nrw.commons.category.CategoryItem;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
||||||
import fr.free.nrw.commons.databinding.UploadCategoriesFragmentBinding;
|
import fr.free.nrw.commons.databinding.UploadCategoriesFragmentBinding;
|
||||||
|
|
@ -41,6 +43,8 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CategoriesContract.UserActionListener presenter;
|
CategoriesContract.UserActionListener presenter;
|
||||||
|
@Inject
|
||||||
|
SessionManager sessionManager;
|
||||||
private UploadCategoryAdapter adapter;
|
private UploadCategoryAdapter adapter;
|
||||||
private Disposable subscribe;
|
private Disposable subscribe;
|
||||||
/**
|
/**
|
||||||
|
|
@ -295,6 +299,22 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
|
||||||
mediaDetailFragment.updateCategories();
|
mediaDetailFragment.updateCategories();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void navigateToLoginScreen() {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
getActivity(),
|
||||||
|
requireActivity().getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
requireActivity(), logoutListener);
|
||||||
|
}
|
||||||
|
|
||||||
public void onNextButtonClicked() {
|
public void onNextButtonClicked() {
|
||||||
if (media != null) {
|
if (media != null) {
|
||||||
presenter.updateCategories(media, wikiText);
|
presenter.updateCategories(media, wikiText);
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,11 @@ public interface DepictsContract {
|
||||||
* Update the depictions
|
* Update the depictions
|
||||||
*/
|
*/
|
||||||
void updateDepicts();
|
void updateDepicts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate the user to Login Activity
|
||||||
|
*/
|
||||||
|
void navigateToLoginScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserActionListener extends BasePresenter<View> {
|
interface UserActionListener extends BasePresenter<View> {
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,10 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import com.jakewharton.rxbinding2.view.RxView;
|
import com.jakewharton.rxbinding2.view.RxView;
|
||||||
import com.jakewharton.rxbinding2.widget.RxTextView;
|
import com.jakewharton.rxbinding2.widget.RxTextView;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.Media;
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
||||||
import fr.free.nrw.commons.databinding.UploadDepictsFragmentBinding;
|
import fr.free.nrw.commons.databinding.UploadDepictsFragmentBinding;
|
||||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||||
|
|
@ -63,6 +65,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
|
||||||
|
|
||||||
private UploadDepictsFragmentBinding binding;
|
private UploadDepictsFragmentBinding binding;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SessionManager sessionManager;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public android.view.View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
public android.view.View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
|
@ -311,6 +316,22 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
|
||||||
mediaDetailFragment.onResume();
|
mediaDetailFragment.onResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to the login Activity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void navigateToLoginScreen() {
|
||||||
|
final String username = sessionManager.getUserName();
|
||||||
|
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
|
||||||
|
getActivity(),
|
||||||
|
requireActivity().getString(R.string.invalid_login_message),
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
CommonsApplication.getInstance().clearApplicationData(
|
||||||
|
requireActivity(), logoutListener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the calling fragment by media nullability and act accordingly
|
* Determines the calling fragment by media nullability and act accordingly
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsController
|
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsController
|
||||||
import fr.free.nrw.commons.Media
|
import fr.free.nrw.commons.Media
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
|
||||||
import fr.free.nrw.commons.di.CommonsApplicationModule
|
import fr.free.nrw.commons.di.CommonsApplicationModule
|
||||||
import fr.free.nrw.commons.repository.UploadRepository
|
import fr.free.nrw.commons.repository.UploadRepository
|
||||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
|
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
|
||||||
|
|
@ -218,13 +219,18 @@ class DepictsPresenter @Inject constructor(
|
||||||
view.dismissProgressDialog()
|
view.dismissProgressDialog()
|
||||||
view.updateDepicts()
|
view.updateDepicts()
|
||||||
view.goBackToPreviousScreen()
|
view.goBackToPreviousScreen()
|
||||||
|
}, { error ->
|
||||||
|
if (error is InvalidLoginTokenException) {
|
||||||
|
view.navigateToLoginScreen();
|
||||||
|
} else {
|
||||||
|
Timber.e(
|
||||||
|
"Failed to update depictions"
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
{
|
|
||||||
Timber.e(
|
|
||||||
"Failed to update depictions"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
repository.cleanup()
|
repository.cleanup()
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,6 @@ class WikiBaseClient @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun csrfToken(): Observable<String> = Observable.fromCallable {
|
private fun csrfToken(): Observable<String> = Observable.fromCallable {
|
||||||
try {
|
csrfTokenClient.getTokenBlocking()
|
||||||
csrfTokenClient.getTokenBlocking()
|
|
||||||
} catch (throwable: Throwable) {
|
|
||||||
Timber.e(throwable)
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import android.content.Context;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||||
import fr.free.nrw.commons.contributions.Contribution;
|
import fr.free.nrw.commons.contributions.Contribution;
|
||||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||||
import fr.free.nrw.commons.upload.UploadResult;
|
import fr.free.nrw.commons.upload.UploadResult;
|
||||||
|
|
@ -123,8 +124,13 @@ public class WikidataEditService {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.doOnError(throwable -> {
|
.doOnError(throwable -> {
|
||||||
Timber.e(throwable, "Error occurred while setting DEPICTS property");
|
if (throwable instanceof InvalidLoginTokenException) {
|
||||||
ViewUtil.showLongToast(context, throwable.toString());
|
Observable.error(throwable);
|
||||||
|
} else {
|
||||||
|
Timber.e(throwable, "Error occurred while setting DEPICTS property");
|
||||||
|
ViewUtil.showLongToast(context, throwable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
.subscribeOn(Schedulers.io());
|
.subscribeOn(Schedulers.io());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue