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 com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import fr.free.nrw.commons.CameraPosition;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.Media;
|
||||
import fr.free.nrw.commons.R;
|
||||
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.filepicker.Constants;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
|
|
@ -141,6 +145,8 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
|
||||
@Inject
|
||||
LocationServiceManager locationManager;
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
@ -404,13 +410,29 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
if (media == null) {
|
||||
return;
|
||||
}
|
||||
compositeDisposable.add(coordinateEditHelper.makeCoordinatesEdit(getApplicationContext(),media,
|
||||
|
||||
try {
|
||||
compositeDisposable.add(
|
||||
coordinateEditHelper.makeCoordinatesEdit(getApplicationContext(), media,
|
||||
Latitude, Longitude, Accuracy)
|
||||
.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
|
||||
|
||||
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
||||
|
|
@ -28,9 +29,13 @@ class PageEditClient(
|
|||
pageEditInterface.postEdit(pageTitle, summary, text, csrfTokenClient.getTokenBlocking())
|
||||
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is InvalidLoginTokenException) {
|
||||
throw throwable
|
||||
} else {
|
||||
Observable.just(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append text to the end of a wiki page
|
||||
|
|
@ -44,9 +49,13 @@ class PageEditClient(
|
|||
pageEditInterface.postAppendEdit(pageTitle, summary, appendText, csrfTokenClient.getTokenBlocking())
|
||||
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is InvalidLoginTokenException) {
|
||||
throw throwable
|
||||
} else {
|
||||
Observable.just(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend text to the beginning of a wiki page
|
||||
|
|
@ -58,11 +67,16 @@ class PageEditClient(
|
|||
fun prependEdit(pageTitle: String, prependText: String, summary: String): Observable<Boolean> {
|
||||
return try {
|
||||
pageEditInterface.postPrependEdit(pageTitle, summary, prependText, csrfTokenClient.getTokenBlocking())
|
||||
.map { editResponse -> editResponse.edit()!!.editSucceeded() }
|
||||
.map { editResponse -> editResponse.edit()?.editSucceeded() ?: false }
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is InvalidLoginTokenException) {
|
||||
throw throwable
|
||||
} else {
|
||||
Observable.just(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set new labels to Wikibase server of commons
|
||||
|
|
@ -79,9 +93,13 @@ class PageEditClient(
|
|||
value, csrfTokenClient.getTokenBlocking()
|
||||
).map { it.success }
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is InvalidLoginTokenException) {
|
||||
throw throwable
|
||||
} else {
|
||||
Observable.just(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whole WikiText of required file
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import fr.free.nrw.commons.CommonsApplication
|
|||
import fr.free.nrw.commons.di.NetworkingModule.NAMED_COMMONS_CSRF
|
||||
import io.reactivex.Observable
|
||||
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.Named
|
||||
import javax.inject.Singleton
|
||||
|
|
@ -32,8 +34,15 @@ class ThanksClient @Inject constructor(
|
|||
).map {
|
||||
mwThankPostResponse -> mwThankPostResponse.result?.success == 1
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
}
|
||||
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()!!
|
||||
if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) {
|
||||
throw RuntimeException("App believes we're logged in, but got anonymous token.")
|
||||
throw InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||
}
|
||||
break
|
||||
} catch (t: Throwable) {
|
||||
} catch (e: LoginFailedException) {
|
||||
throw InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||
}
|
||||
catch (t: Throwable) {
|
||||
Timber.w(t)
|
||||
}
|
||||
}
|
||||
|
||||
if (token.isEmpty() || token == ANON_TOKEN) {
|
||||
throw IOException(INVALID_TOKEN_ERROR_MESSAGE)
|
||||
throw InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
|
@ -68,7 +71,7 @@ class CsrfTokenClient(
|
|||
override fun success(token: String?) {
|
||||
if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) {
|
||||
retryWithLogin(cb) {
|
||||
RuntimeException("App believes we're logged in, but got anonymous token.")
|
||||
InvalidLoginTokenException(ANONYMOUS_TOKEN_MESSAGE)
|
||||
}
|
||||
} else {
|
||||
cb.success(token)
|
||||
|
|
@ -161,5 +164,8 @@ class CsrfTokenClient(
|
|||
private const val MAX_RETRIES = 1
|
||||
private const val MAX_RETRIES_OF_LOGIN_BLOCKING = 2
|
||||
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.R;
|
||||
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.review.ReviewController;
|
||||
import fr.free.nrw.commons.utils.ViewUtilWrapper;
|
||||
|
|
@ -66,7 +67,13 @@ public class DeleteHelper {
|
|||
|
||||
return delete(media, reason)
|
||||
.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,21 +111,29 @@ public class DeleteHelper {
|
|||
}
|
||||
|
||||
return pageEditClient.prependEdit(media.getFilename(), fileDeleteString + "\n", summary)
|
||||
.onErrorResumeNext(throwable -> {
|
||||
if (throwable instanceof InvalidLoginTokenException) {
|
||||
return Observable.error(throwable);
|
||||
}
|
||||
return Observable.error(throwable);
|
||||
})
|
||||
.flatMap(result -> {
|
||||
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"));
|
||||
})
|
||||
.flatMap(result -> {
|
||||
if (result) {
|
||||
return pageEditClient.appendEdit("Commons:Deletion_requests/" + date, logPageString + "\n", summary);
|
||||
}
|
||||
throw new RuntimeException("Failed to nominate for deletion");
|
||||
}).flatMap(result -> {
|
||||
return Observable.error(new RuntimeException("Failed to nominate for deletion"));
|
||||
})
|
||||
.flatMap(result -> {
|
||||
if (result) {
|
||||
return pageEditClient.appendEdit("User_Talk:" + creator, userPageString + "\n", summary);
|
||||
}
|
||||
throw new RuntimeException("Failed to nominate for deletion");
|
||||
return Observable.error(new RuntimeException("Failed to nominate for deletion"));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -226,14 +241,15 @@ public class DeleteHelper {
|
|||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aBoolean -> {
|
||||
if (aBoolean) {
|
||||
reviewCallback.onSuccess();
|
||||
}, throwable -> {
|
||||
if (throwable instanceof InvalidLoginTokenException) {
|
||||
reviewCallback.onTokenException((InvalidLoginTokenException) throwable);
|
||||
} else {
|
||||
reviewCallback.onFailure();
|
||||
}
|
||||
reviewCallback.enableButtons();
|
||||
});
|
||||
|
||||
});
|
||||
alert.setNegativeButton(context.getString(R.string.cancel), (dialog, which) -> reviewCallback.onFailure());
|
||||
d = alert.create();
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import com.facebook.imagepipeline.image.ImageInfo;
|
|||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.CameraPosition;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.LocationPicker.LocationPicker;
|
||||
import fr.free.nrw.commons.Media;
|
||||
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.auth.AccountUtil;
|
||||
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.CategoryDetailsActivity;
|
||||
import fr.free.nrw.commons.category.CategoryEditHelper;
|
||||
|
|
@ -780,9 +783,23 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
|||
firstRevision.getRevisionId()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((result) -> {
|
||||
displayThanksToast(context, result);
|
||||
}, Timber::e);
|
||||
.subscribe(result -> {
|
||||
displayThanksToast(getContext(), result);
|
||||
}, 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,6 +1073,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
|||
|
||||
if (requestCode == REQUEST_CODE_EDIT_DESCRIPTION && resultCode == RESULT_OK) {
|
||||
final String updatedWikiText = data.getStringExtra(UPDATED_WIKITEXT);
|
||||
|
||||
try {
|
||||
compositeDisposable.add(descriptionEditHelper.addDescription(getContext(), media,
|
||||
updatedWikiText)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
|
@ -1063,6 +1082,19 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
|||
.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
|
||||
= data.getParcelableArrayListExtra(LIST_OF_DESCRIPTION_AND_CAPTION);
|
||||
|
|
@ -1070,6 +1102,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
|||
LinkedHashMap<String, String> updatedCaptions = new LinkedHashMap<>();
|
||||
for (UploadMediaDetail mediaDetail:
|
||||
uploadMediaDetails) {
|
||||
try {
|
||||
compositeDisposable.add(descriptionEditHelper.addCaption(getContext(), media,
|
||||
mediaDetail.getLanguageCode(), mediaDetail.getCaptionText())
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
|
@ -1078,6 +1111,20 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
|||
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.descriptionEdit.setVisibility(VISIBLE);
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@ import android.view.View;
|
|||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
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.theme.BaseActivity;
|
||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||
|
|
@ -41,6 +44,9 @@ public class NotificationActivity extends BaseActivity {
|
|||
@Inject
|
||||
NotificationController controller;
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
|
||||
private static final String TAG_NOTIFICATION_WORKER_FRAGMENT = "NotificationWorkerFragment";
|
||||
private NotificationWorkerFragment mNotificationWorkerFragment;
|
||||
private NotificatinAdapter adapter;
|
||||
|
|
@ -107,10 +113,23 @@ public class NotificationActivity extends BaseActivity {
|
|||
ViewUtil.showLongToast(this,getString(R.string.some_error));
|
||||
}
|
||||
}, 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
|
||||
);
|
||||
|
||||
CommonsApplication.getInstance().clearApplicationData(
|
||||
this, logoutListener);
|
||||
} else {
|
||||
Timber.e(throwable, "Error occurred while loading notifications");
|
||||
throwable.printStackTrace();
|
||||
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);
|
||||
});
|
||||
compositeDisposable.add(disposable);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import fr.free.nrw.commons.notification.models.NotificationType
|
|||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
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.utils.DateUtil
|
||||
import javax.inject.Inject
|
||||
|
|
@ -39,9 +40,13 @@ class NotificationClient @Inject constructor(
|
|||
unreadList = ""
|
||||
).map(MwQueryResponse::success)
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is InvalidLoginTokenException) {
|
||||
Observable.error(throwable)
|
||||
} else {
|
||||
Observable.just(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun WikimediaNotification.toCommonsNotification() = Notification(
|
||||
notificationType = NotificationType.UNKNOWN,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
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 java.util.ArrayList;
|
||||
|
|
@ -39,6 +41,9 @@ public class ReviewController {
|
|||
protected static ArrayList<String> categories;
|
||||
@Inject
|
||||
ThanksClient thanksClient;
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
private final DeleteHelper deleteHelper;
|
||||
@Nullable
|
||||
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()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((result) -> {
|
||||
.subscribe(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")
|
||||
|
|
@ -192,6 +211,8 @@ public class ReviewController {
|
|||
|
||||
void onFailure();
|
||||
|
||||
void onTokenException(Exception e);
|
||||
|
||||
void disableButtons();
|
||||
|
||||
void enableButtons();
|
||||
|
|
|
|||
|
|
@ -7,15 +7,17 @@ import android.text.TextUtils;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.Media;
|
||||
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.di.CommonsDaggerSupportFragment;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
||||
|
||||
|
|
@ -28,7 +30,8 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
|||
|
||||
private FragmentReviewImageBinding binding;
|
||||
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
|
||||
|
||||
// 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
|
||||
private String user;
|
||||
|
||||
public void update(int position) {
|
||||
public void update(final int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
private String updateCategoriesQuestion() {
|
||||
Media media = getReviewActivity().getMedia();
|
||||
final Media media = getReviewActivity().getMedia();
|
||||
if (media != null && media.getCategoriesHiddenStatus() != null && isAdded()) {
|
||||
// Filter category name attribute from all categories
|
||||
List<String> categories = new ArrayList<>();
|
||||
for(String key : media.getCategoriesHiddenStatus().keySet()) {
|
||||
final List<String> categories = new ArrayList<>();
|
||||
for(final String key : media.getCategoriesHiddenStatus().keySet()) {
|
||||
String value = String.valueOf(key);
|
||||
// Each category returned has a format like "Category:<some-category-name>"
|
||||
// so remove the prefix "Category:"
|
||||
int index = key.indexOf("Category:");
|
||||
final int index = key.indexOf("Category:");
|
||||
if(index == 0) {
|
||||
value = key.substring(9);
|
||||
}
|
||||
|
|
@ -59,7 +62,7 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
|||
String catString = TextUtils.join(", ", categories);
|
||||
if (catString != null && !catString.equals("") && binding.tvReviewQuestionContext != null) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -67,17 +70,20 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
position = getArguments().getInt("position");
|
||||
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());
|
||||
|
||||
|
|
@ -182,6 +188,22 @@ public class ReviewImageFragment extends CommonsDaggerSupportFragment {
|
|||
//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
|
||||
* to disable the review buttons
|
||||
|
|
|
|||
|
|
@ -56,6 +56,12 @@ public interface CategoriesContract {
|
|||
* Refreshes the categories
|
||||
*/
|
||||
void refreshCategories();
|
||||
|
||||
|
||||
/**
|
||||
* Navigate the user to Login Activity
|
||||
*/
|
||||
void navigateToLoginScreen();
|
||||
}
|
||||
|
||||
interface UserActionListener extends BasePresenter<View> {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import fr.free.nrw.commons.Media
|
||||
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.CategoryItem
|
||||
import fr.free.nrw.commons.di.CommonsApplicationModule
|
||||
|
|
@ -211,9 +212,13 @@ class CategoriesPresenter @Inject constructor(
|
|||
|
||||
if (selectedCategories.isNotEmpty()) {
|
||||
view.showProgressDialog()
|
||||
|
||||
try {
|
||||
compositeDisposable.add(
|
||||
categoryEditHelper.makeCategoryEdit(view.fragmentContext, media,
|
||||
selectedCategories, wikiText)
|
||||
categoryEditHelper.makeCategoryEdit(
|
||||
view.fragmentContext, media,
|
||||
selectedCategories, wikiText
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
|
|
@ -223,13 +228,15 @@ class CategoriesPresenter @Inject constructor(
|
|||
view.dismissProgressDialog()
|
||||
view.refreshCategories()
|
||||
view.goBackToPreviousScreen()
|
||||
})
|
||||
{
|
||||
}, {
|
||||
Timber.e(
|
||||
"Failed to update categories"
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
} catch (e: InvalidLoginTokenException) {
|
||||
view.navigateToLoginScreen();
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import com.jakewharton.rxbinding2.view.RxView;
|
||||
import com.jakewharton.rxbinding2.widget.RxTextView;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.Media;
|
||||
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.contributions.ContributionsFragment;
|
||||
import fr.free.nrw.commons.databinding.UploadCategoriesFragmentBinding;
|
||||
|
|
@ -41,6 +43,8 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
|
|||
|
||||
@Inject
|
||||
CategoriesContract.UserActionListener presenter;
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
private UploadCategoryAdapter adapter;
|
||||
private Disposable subscribe;
|
||||
/**
|
||||
|
|
@ -295,6 +299,22 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
|
|||
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() {
|
||||
if (media != null) {
|
||||
presenter.updateCategories(media, wikiText);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,11 @@ public interface DepictsContract {
|
|||
* Update the depictions
|
||||
*/
|
||||
void updateDepicts();
|
||||
|
||||
/**
|
||||
* Navigate the user to Login Activity
|
||||
*/
|
||||
void navigateToLoginScreen();
|
||||
}
|
||||
|
||||
interface UserActionListener extends BasePresenter<View> {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import com.jakewharton.rxbinding2.view.RxView;
|
||||
import com.jakewharton.rxbinding2.widget.RxTextView;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.Media;
|
||||
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.databinding.UploadDepictsFragmentBinding;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
|
|
@ -63,6 +65,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
|
|||
|
||||
private UploadDepictsFragmentBinding binding;
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public android.view.View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
|
|
@ -311,6 +316,22 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
|
|||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsController
|
||||
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.repository.UploadRepository
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
|
||||
|
|
@ -218,13 +219,18 @@ class DepictsPresenter @Inject constructor(
|
|||
view.dismissProgressDialog()
|
||||
view.updateDepicts()
|
||||
view.goBackToPreviousScreen()
|
||||
})
|
||||
{
|
||||
}, { error ->
|
||||
if (error is InvalidLoginTokenException) {
|
||||
view.navigateToLoginScreen();
|
||||
} else {
|
||||
Timber.e(
|
||||
"Failed to update depictions"
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
repository.cleanup()
|
||||
|
|
|
|||
|
|
@ -59,11 +59,6 @@ class WikiBaseClient @Inject constructor(
|
|||
}
|
||||
|
||||
private fun csrfToken(): Observable<String> = Observable.fromCallable {
|
||||
try {
|
||||
csrfTokenClient.getTokenBlocking()
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.e(throwable)
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.content.Context;
|
|||
import androidx.annotation.Nullable;
|
||||
import com.google.gson.Gson;
|
||||
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.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.upload.UploadResult;
|
||||
|
|
@ -123,8 +124,13 @@ public class WikidataEditService {
|
|||
}
|
||||
})
|
||||
.doOnError(throwable -> {
|
||||
if (throwable instanceof InvalidLoginTokenException) {
|
||||
Observable.error(throwable);
|
||||
} else {
|
||||
Timber.e(throwable, "Error occurred while setting DEPICTS property");
|
||||
ViewUtil.showLongToast(context, throwable.toString());
|
||||
}
|
||||
|
||||
})
|
||||
.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue