mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Feedback Module: Add reverts rate parameter (#1649)
* Fetched Revert Count * Refactored Achievements class and display the fetched results * Refactored the levelController to include revert as parameter * Fixed error * Fixed bug * Added information for parameters and improved code quality * Javadocs added * Added null check and javadocs
This commit is contained in:
parent
bd1555f558
commit
12fb75a8bb
10 changed files with 353 additions and 67 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
package fr.free.nrw.commons.achievements;
|
package fr.free.nrw.commons.achievements;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* represnts Achievements
|
* represnts Achievements class ans stores all the parameters
|
||||||
*/
|
*/
|
||||||
public class Achievements {
|
public class Achievements {
|
||||||
private int uniqueUsedImages;
|
private int uniqueUsedImages;
|
||||||
|
|
@ -10,24 +12,41 @@ public class Achievements {
|
||||||
private int imagesEditedBySomeoneElse;
|
private int imagesEditedBySomeoneElse;
|
||||||
private int featuredImages;
|
private int featuredImages;
|
||||||
private int imagesUploaded;
|
private int imagesUploaded;
|
||||||
|
private int revertCount;
|
||||||
|
|
||||||
public Achievements(){
|
public Achievements(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor for achievements class to set its data members
|
||||||
|
* @param uniqueUsedImages
|
||||||
|
* @param articlesUsingImages
|
||||||
|
* @param thanksReceived
|
||||||
|
* @param imagesEditedBySomeoneElse
|
||||||
|
* @param featuredImages
|
||||||
|
* @param imagesUploaded
|
||||||
|
* @param revertCount
|
||||||
|
*/
|
||||||
public Achievements(int uniqueUsedImages,
|
public Achievements(int uniqueUsedImages,
|
||||||
int articlesUsingImages,
|
int articlesUsingImages,
|
||||||
int thanksReceived,
|
int thanksReceived,
|
||||||
int imagesEditedBySomeoneElse,
|
int imagesEditedBySomeoneElse,
|
||||||
int featuredImages,
|
int featuredImages,
|
||||||
int imagesUploaded) {
|
int imagesUploaded,
|
||||||
|
int revertCount) {
|
||||||
this.uniqueUsedImages = uniqueUsedImages;
|
this.uniqueUsedImages = uniqueUsedImages;
|
||||||
this.articlesUsingImages = articlesUsingImages;
|
this.articlesUsingImages = articlesUsingImages;
|
||||||
this.thanksReceived = thanksReceived;
|
this.thanksReceived = thanksReceived;
|
||||||
this.imagesEditedBySomeoneElse = imagesEditedBySomeoneElse;
|
this.imagesEditedBySomeoneElse = imagesEditedBySomeoneElse;
|
||||||
this.featuredImages = featuredImages;
|
this.featuredImages = featuredImages;
|
||||||
this.imagesUploaded = imagesUploaded;
|
this.imagesUploaded = imagesUploaded;
|
||||||
|
this.revertCount = revertCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder class for Achievements class
|
||||||
|
*/
|
||||||
public class AchievementsBuilder {
|
public class AchievementsBuilder {
|
||||||
private int nestedUniqueUsedImages;
|
private int nestedUniqueUsedImages;
|
||||||
private int nestedArticlesUsingImages;
|
private int nestedArticlesUsingImages;
|
||||||
|
|
@ -35,6 +54,7 @@ public class Achievements {
|
||||||
private int nestedImagesEditedBySomeoneElse;
|
private int nestedImagesEditedBySomeoneElse;
|
||||||
private int nestedFeaturedImages;
|
private int nestedFeaturedImages;
|
||||||
private int nestedImagesUploaded;
|
private int nestedImagesUploaded;
|
||||||
|
private int nestedRevertCount;
|
||||||
|
|
||||||
public AchievementsBuilder setUniqueUsedImages(int uniqueUsedImages) {
|
public AchievementsBuilder setUniqueUsedImages(int uniqueUsedImages) {
|
||||||
this.nestedUniqueUsedImages = uniqueUsedImages;
|
this.nestedUniqueUsedImages = uniqueUsedImages;
|
||||||
|
|
@ -66,62 +86,120 @@ public class Achievements {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AchievementsBuilder setRevertCount( int revertCount){
|
||||||
|
this.nestedRevertCount = revertCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Achievements createAchievements(){
|
public Achievements createAchievements(){
|
||||||
return new Achievements(nestedUniqueUsedImages,
|
return new Achievements(nestedUniqueUsedImages,
|
||||||
nestedArticlesUsingImages,
|
nestedArticlesUsingImages,
|
||||||
nestedThanksReceived,
|
nestedThanksReceived,
|
||||||
nestedImagesEditedBySomeoneElse,
|
nestedImagesEditedBySomeoneElse,
|
||||||
nestedFeaturedImages,
|
nestedFeaturedImages,
|
||||||
nestedImagesUploaded);
|
nestedImagesUploaded,
|
||||||
|
nestedRevertCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getter function to get count of images uploaded
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public int getImagesUploaded() {
|
public int getImagesUploaded() {
|
||||||
return imagesUploaded;
|
return imagesUploaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getter function to get count of featured images
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public int getFeaturedImages() {
|
public int getFeaturedImages() {
|
||||||
return featuredImages;
|
return featuredImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getImagesEditedBySomeoneElse() {
|
/**
|
||||||
return imagesEditedBySomeoneElse;
|
* getter function to get count of thanks received
|
||||||
}
|
* @return
|
||||||
|
*/
|
||||||
public int getThanksReceived() {
|
public int getThanksReceived() {
|
||||||
return thanksReceived;
|
return thanksReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getArticlesUsingImages() {
|
/**
|
||||||
return articlesUsingImages;
|
* getter function to get count of unique images used by wiki
|
||||||
}
|
* @return
|
||||||
|
*/
|
||||||
public int getUniqueUsedImages() {
|
public int getUniqueUsedImages() {
|
||||||
return uniqueUsedImages;
|
return uniqueUsedImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setter function to count of images uploaded
|
||||||
|
* @param imagesUploaded
|
||||||
|
*/
|
||||||
public void setImagesUploaded(int imagesUploaded) {
|
public void setImagesUploaded(int imagesUploaded) {
|
||||||
this.imagesUploaded = imagesUploaded;
|
this.imagesUploaded = imagesUploaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setter function to set count of featured images
|
||||||
|
* @param featuredImages
|
||||||
|
*/
|
||||||
public void setFeaturedImages(int featuredImages) {
|
public void setFeaturedImages(int featuredImages) {
|
||||||
this.featuredImages = featuredImages;
|
this.featuredImages = featuredImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setter function to set the count of images edited by someone
|
||||||
|
* @param imagesEditedBySomeoneElse
|
||||||
|
*/
|
||||||
public void setImagesEditedBySomeoneElse(int imagesEditedBySomeoneElse) {
|
public void setImagesEditedBySomeoneElse(int imagesEditedBySomeoneElse) {
|
||||||
this.imagesEditedBySomeoneElse = imagesEditedBySomeoneElse;
|
this.imagesEditedBySomeoneElse = imagesEditedBySomeoneElse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setter function to set count of thanks received
|
||||||
|
* @param thanksReceived
|
||||||
|
*/
|
||||||
public void setThanksReceived(int thanksReceived) {
|
public void setThanksReceived(int thanksReceived) {
|
||||||
this.thanksReceived = thanksReceived;
|
this.thanksReceived = thanksReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setter function to count of articles using images uploaded
|
||||||
|
* @param articlesUsingImages
|
||||||
|
*/
|
||||||
public void setArticlesUsingImages(int articlesUsingImages) {
|
public void setArticlesUsingImages(int articlesUsingImages) {
|
||||||
this.articlesUsingImages = articlesUsingImages;
|
this.articlesUsingImages = articlesUsingImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setter function to set count of uniques images used by wiki
|
||||||
|
* @param uniqueUsedImages
|
||||||
|
*/
|
||||||
public void setUniqueUsedImages(int uniqueUsedImages) {
|
public void setUniqueUsedImages(int uniqueUsedImages) {
|
||||||
this.uniqueUsedImages = uniqueUsedImages;
|
this.uniqueUsedImages = uniqueUsedImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* to set count of images reverted
|
||||||
|
* @param revertCount
|
||||||
|
*/
|
||||||
|
public void setRevertCount(int revertCount) {
|
||||||
|
this.revertCount = revertCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to calculate the percentages of images that haven't been reverted
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getNotRevertPercentage(){
|
||||||
|
try {
|
||||||
|
return ((imagesUploaded - revertCount) * 100)/imagesUploaded;
|
||||||
|
} catch (ArithmeticException divideByZero ){
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package fr.free.nrw.commons.achievements;
|
package fr.free.nrw.commons.achievements;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
@ -38,6 +40,7 @@ import org.json.JSONObject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
|
@ -49,6 +52,7 @@ import fr.free.nrw.commons.Utils;
|
||||||
import fr.free.nrw.commons.auth.SessionManager;
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
@ -63,8 +67,8 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
private static final double BADGE_IMAGE_HEIGHT_RATIO = 0.3;
|
private static final double BADGE_IMAGE_HEIGHT_RATIO = 0.3;
|
||||||
private Boolean isUploadFetched = false;
|
private Boolean isUploadFetched = false;
|
||||||
private Boolean isStatisticsFetched = false;
|
private Boolean isStatisticsFetched = false;
|
||||||
|
private Boolean isRevertFetched = false;
|
||||||
private Achievements achievements = new Achievements();
|
private Achievements achievements = new Achievements();
|
||||||
private LevelController level;
|
|
||||||
private LevelController.LevelInfo levelInfo;
|
private LevelController.LevelInfo levelInfo;
|
||||||
|
|
||||||
@BindView(R.id.achievement_badge)
|
@BindView(R.id.achievement_badge)
|
||||||
|
|
@ -79,8 +83,12 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
CircleProgressBar imagesUploadedProgressbar;
|
CircleProgressBar imagesUploadedProgressbar;
|
||||||
@BindView(R.id.images_used_by_wiki_progressbar)
|
@BindView(R.id.images_used_by_wiki_progressbar)
|
||||||
CircleProgressBar imagesUsedByWikiProgessbar;
|
CircleProgressBar imagesUsedByWikiProgessbar;
|
||||||
|
@BindView(R.id.image_reverts_progressbar)
|
||||||
|
CircleProgressBar imageRevertsProgressbar;
|
||||||
@BindView(R.id.image_featured)
|
@BindView(R.id.image_featured)
|
||||||
TextView imagesFeatured;
|
TextView imagesFeatured;
|
||||||
|
@BindView(R.id.images_revert_limit_text)
|
||||||
|
TextView imagesRevertLimitText;
|
||||||
@BindView(R.id.progressBar)
|
@BindView(R.id.progressBar)
|
||||||
ProgressBar progressBar;
|
ProgressBar progressBar;
|
||||||
@BindView(R.id.layout_image_uploaded)
|
@BindView(R.id.layout_image_uploaded)
|
||||||
|
|
@ -133,6 +141,7 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
hideLayouts();
|
hideLayouts();
|
||||||
setAchievements();
|
setAchievements();
|
||||||
setUploadCount();
|
setUploadCount();
|
||||||
|
setRevertCount();
|
||||||
initDrawer();
|
initDrawer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,14 +150,8 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
*/
|
*/
|
||||||
@OnClick(R.id.achievement_info)
|
@OnClick(R.id.achievement_info)
|
||||||
public void showInfoDialog(){
|
public void showInfoDialog(){
|
||||||
new AlertDialog.Builder(AchievementsActivity.this)
|
launchAlert(getResources().getString(R.string.Achievements)
|
||||||
.setTitle(R.string.Achievements)
|
,getResources().getString(R.string.achievements_info_message));
|
||||||
.setMessage(R.string.achievements_info_message)
|
|
||||||
.setCancelable(true)
|
|
||||||
.setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel())
|
|
||||||
.create()
|
|
||||||
.show();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -198,27 +201,72 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
* which then calls parseJson when results are fetched
|
* which then calls parseJson when results are fetched
|
||||||
*/
|
*/
|
||||||
private void setAchievements() {
|
private void setAchievements() {
|
||||||
|
if(checkAccount()) {
|
||||||
compositeDisposable.add(mediaWikiApi
|
compositeDisposable.add(mediaWikiApi
|
||||||
.getAchievements(sessionManager.getCurrentAccount().name)
|
.getAchievements(sessionManager.getCurrentAccount().name)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
jsonObject -> parseJson(jsonObject)
|
jsonObject -> parseJson(jsonObject),
|
||||||
|
t -> Timber.e(t, "Fetching achievements statisticss failed")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To call the API to get reverts count in form of JSONObject
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
private void setRevertCount(){
|
||||||
|
if(checkAccount()) {
|
||||||
|
compositeDisposable.add(mediaWikiApi
|
||||||
|
.getRevertCount(sessionManager.getCurrentAccount().name)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
object -> parseJsonRevertCount(object),
|
||||||
|
t -> Timber.e(t, "Fetching revert count failed")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to set number of deleted images
|
||||||
|
* @param object
|
||||||
|
*/
|
||||||
|
private void parseJsonRevertCount(JSONObject object){
|
||||||
|
try {
|
||||||
|
achievements.setRevertCount(object.getInt("deletedUploads"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Timber.d( e, e.getMessage());
|
||||||
|
}
|
||||||
|
isRevertFetched = true;
|
||||||
|
hideProgressBar();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used to the count of images uploaded by user
|
* used to the count of images uploaded by user
|
||||||
*/
|
*/
|
||||||
private void setUploadCount() {
|
private void setUploadCount() {
|
||||||
|
if(checkAccount()) {
|
||||||
compositeDisposable.add(mediaWikiApi
|
compositeDisposable.add(mediaWikiApi
|
||||||
.getUploadCount(sessionManager.getCurrentAccount().name)
|
.getUploadCount(sessionManager.getCurrentAccount().name)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
uploadCount -> achievements.setImagesUploaded(uploadCount),
|
uploadCount -> setAchievementsUploadCount(uploadCount),
|
||||||
t -> Timber.e(t, "Fetching upload count failed")
|
t -> Timber.e(t, "Fetching upload count failed")
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to set achievements upload count and call hideProgressbar
|
||||||
|
* @param uploadCount
|
||||||
|
*/
|
||||||
|
private void setAchievementsUploadCount(int uploadCount){
|
||||||
|
achievements.setImagesUploaded(uploadCount);
|
||||||
isUploadFetched = true;
|
isUploadFetched = true;
|
||||||
hideProgressBar();
|
hideProgressBar();
|
||||||
}
|
}
|
||||||
|
|
@ -227,17 +275,26 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
* used to the uploaded images progressbar
|
* used to the uploaded images progressbar
|
||||||
* @param uploadCount
|
* @param uploadCount
|
||||||
*/
|
*/
|
||||||
private void setUploadProgress( int uploadCount){
|
private void setUploadProgress(int uploadCount){
|
||||||
|
|
||||||
imagesUploadedProgressbar.setProgress
|
imagesUploadedProgressbar.setProgress
|
||||||
(100*uploadCount/levelInfo.getMaxUploadCount());
|
(100*uploadCount/levelInfo.getMaxUploadCount());
|
||||||
imagesUploadedProgressbar.setProgressTextFormatPattern
|
imagesUploadedProgressbar.setProgressTextFormatPattern
|
||||||
(uploadCount +"/" + levelInfo.getMaxUploadCount() );
|
(uploadCount +"/" + levelInfo.getMaxUploadCount() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to set the non revert image percentage
|
||||||
|
* @param notRevertPercentage
|
||||||
|
*/
|
||||||
|
private void setImageRevertPercentage(int notRevertPercentage){
|
||||||
|
imageRevertsProgressbar.setProgress(notRevertPercentage);
|
||||||
|
String revertPercentage = Integer.toString(notRevertPercentage);
|
||||||
|
imageRevertsProgressbar.setProgressTextFormatPattern(revertPercentage + "%%");
|
||||||
|
imagesRevertLimitText.setText(getResources().getString(R.string.achievements_revert_limit_message)+ levelInfo.getMinNonRevertPercentage() + "%");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used to parse the JSONObject containing results
|
* used to parse the JSONObject containing results
|
||||||
*
|
|
||||||
* @param object
|
* @param object
|
||||||
*/
|
*/
|
||||||
private void parseJson(JSONObject object) {
|
private void parseJson(JSONObject object) {
|
||||||
|
|
@ -262,7 +319,7 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
* and assign badge and level
|
* and assign badge and level
|
||||||
* @param achievements
|
* @param achievements
|
||||||
*/
|
*/
|
||||||
private void inflateAchievements( Achievements achievements ){
|
private void inflateAchievements(Achievements achievements ){
|
||||||
thanksReceived.setText(Integer.toString(achievements.getThanksReceived()));
|
thanksReceived.setText(Integer.toString(achievements.getThanksReceived()));
|
||||||
imagesUsedByWikiProgessbar.setProgress
|
imagesUsedByWikiProgessbar.setProgress
|
||||||
(100*achievements.getUniqueUsedImages()/levelInfo.getMaxUniqueImages() );
|
(100*achievements.getUniqueUsedImages()/levelInfo.getMaxUniqueImages() );
|
||||||
|
|
@ -281,7 +338,6 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a way to change current activity to AchievementActivity
|
* Creates a way to change current activity to AchievementActivity
|
||||||
*
|
|
||||||
* @param context
|
* @param context
|
||||||
*/
|
*/
|
||||||
public static void startYourself(Context context) {
|
public static void startYourself(Context context) {
|
||||||
|
|
@ -295,10 +351,13 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
* to hide progressbar
|
* to hide progressbar
|
||||||
*/
|
*/
|
||||||
private void hideProgressBar() {
|
private void hideProgressBar() {
|
||||||
if (progressBar != null && isUploadFetched && isStatisticsFetched) {
|
if (progressBar != null && isUploadFetched && isStatisticsFetched && isRevertFetched) {
|
||||||
levelInfo = LevelController.LevelInfo.from(achievements.getImagesUploaded(),achievements.getUniqueUsedImages());
|
levelInfo = LevelController.LevelInfo.from(achievements.getImagesUploaded(),
|
||||||
|
achievements.getUniqueUsedImages(),
|
||||||
|
achievements.getNotRevertPercentage());
|
||||||
inflateAchievements(achievements);
|
inflateAchievements(achievements);
|
||||||
setUploadProgress(achievements.getImagesUploaded());
|
setUploadProgress(achievements.getImagesUploaded());
|
||||||
|
setImageRevertPercentage(achievements.getNotRevertPercentage());
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
layoutImageReverts.setVisibility(View.VISIBLE);
|
layoutImageReverts.setVisibility(View.VISIBLE);
|
||||||
layoutImageUploaded.setVisibility(View.VISIBLE);
|
layoutImageUploaded.setVisibility(View.VISIBLE);
|
||||||
|
|
@ -348,4 +407,52 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
||||||
alertadd.show();
|
alertadd.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.images_upload_info)
|
||||||
|
public void showUploadInfo(){
|
||||||
|
launchAlert(getResources().getString(R.string.images_uploaded)
|
||||||
|
,getResources().getString(R.string.images_uploaded_explanation));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.images_reverted_info)
|
||||||
|
public void showRevertedInfo(){
|
||||||
|
launchAlert(getResources().getString(R.string.image_reverts)
|
||||||
|
,getResources().getString(R.string.images_reverted_explanation));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.images_used_by_wiki_info)
|
||||||
|
public void showUsedByWikiInfo(){
|
||||||
|
launchAlert(getResources().getString(R.string.images_used_by_wiki)
|
||||||
|
,getResources().getString(R.string.images_used_explanation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* takes title and message as input to display alerts
|
||||||
|
* @param title
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
private void launchAlert(String title, String message){
|
||||||
|
new AlertDialog.Builder(AchievementsActivity.this)
|
||||||
|
.setTitle(title)
|
||||||
|
.setMessage(message)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel())
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check to ensure that user is logged in
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean checkAccount(){
|
||||||
|
Account currentAccount = sessionManager.getCurrentAccount();
|
||||||
|
if(currentAccount == null) {
|
||||||
|
Timber.d("Current account is null");
|
||||||
|
ViewUtil.showLongToast(this, getResources().getString(R.string.user_not_logged_in));
|
||||||
|
sessionManager.forceLogin(this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package fr.free.nrw.commons.achievements;
|
package fr.free.nrw.commons.achievements;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -9,39 +11,49 @@ public class LevelController {
|
||||||
|
|
||||||
public LevelInfo level;
|
public LevelInfo level;
|
||||||
public enum LevelInfo{
|
public enum LevelInfo{
|
||||||
LEVEL_15(15,R.style.LevelFive, 80, 160),
|
LEVEL_1(1, R.style.LevelOne, 5, 20, 85),
|
||||||
LEVEL_14(14,R.style.LevelFour, 75 , 150),
|
LEVEL_2(2, R.style.LevelTwo, 10, 30, 86),
|
||||||
LEVEL_13(13,R.style.LevelThree, 70, 140),
|
LEVEL_3(3, R.style.LevelThree, 15,40, 87),
|
||||||
LEVEL_12(12,R.style.LevelTwo,65 , 130),
|
LEVEL_4(4, R.style.LevelFour,20,50, 88),
|
||||||
LEVEL_11(11,R.style.LevelOne, 60, 120),
|
LEVEL_5(5, R.style.LevelFive, 25, 60, 89),
|
||||||
LEVEL_10(10, R.style.LevelFive, 55, 110),
|
LEVEL_6(6,R.style.LevelOne,30,70, 90),
|
||||||
LEVEL_9(9, R.style.LevelFour, 50, 100),
|
LEVEL_7(7, R.style.LevelTwo, 40, 80, 90),
|
||||||
LEVEL_8(8, R.style.LevelThree, 45, 90),
|
LEVEL_8(8, R.style.LevelThree, 45, 90, 90),
|
||||||
LEVEL_7(7, R.style.LevelTwo, 40, 80),
|
LEVEL_9(9, R.style.LevelFour, 50, 100, 90),
|
||||||
LEVEL_6(6,R.style.LevelOne,30,70),
|
LEVEL_10(10, R.style.LevelFive, 55, 110, 90),
|
||||||
LEVEL_5(5, R.style.LevelFive, 25, 60),
|
LEVEL_11(11,R.style.LevelOne, 60, 120, 90),
|
||||||
LEVEL_4(4, R.style.LevelFour,20,50),
|
LEVEL_12(12,R.style.LevelTwo,65 , 130, 90),
|
||||||
LEVEL_3(3, R.style.LevelThree, 15,40),
|
LEVEL_13(13,R.style.LevelThree, 70, 140, 90),
|
||||||
LEVEL_2(2, R.style.LevelTwo, 10, 30),
|
LEVEL_14(14,R.style.LevelFour, 75 , 150, 90),
|
||||||
LEVEL_1(1, R.style.LevelOne, 5, 20 );
|
LEVEL_15(15,R.style.LevelFive, 80, 160, 90);
|
||||||
|
|
||||||
private int levelNumber;
|
private int levelNumber;
|
||||||
private int levelStyle;
|
private int levelStyle;
|
||||||
private int maxUniqueImages;
|
private int maxUniqueImages;
|
||||||
private int maxUploadCount;
|
private int maxUploadCount;
|
||||||
|
private int minNonRevertPercentage;
|
||||||
|
|
||||||
LevelInfo(int levelNumber, int levelStyle, int maxUniqueImages, int maxUploadCount) {
|
LevelInfo(int levelNumber,
|
||||||
|
int levelStyle,
|
||||||
|
int maxUniqueImages,
|
||||||
|
int maxUploadCount,
|
||||||
|
int minNonRevertPercentage) {
|
||||||
this.levelNumber = levelNumber;
|
this.levelNumber = levelNumber;
|
||||||
this.levelStyle = levelStyle;
|
this.levelStyle = levelStyle;
|
||||||
this.maxUniqueImages = maxUniqueImages;
|
this.maxUniqueImages = maxUniqueImages;
|
||||||
this.maxUploadCount = maxUploadCount;
|
this.maxUploadCount = maxUploadCount;
|
||||||
|
this.minNonRevertPercentage = minNonRevertPercentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LevelInfo from(int imagesUploaded, int uniqueImagesUsed) {
|
public static LevelInfo from(int imagesUploaded,
|
||||||
LevelInfo level = LEVEL_1;
|
int uniqueImagesUsed,
|
||||||
|
int nonRevertRate) {
|
||||||
|
LevelInfo level = LEVEL_15;
|
||||||
|
|
||||||
for (LevelInfo levelInfo : LevelInfo.values()) {
|
for (LevelInfo levelInfo : LevelInfo.values()) {
|
||||||
if (imagesUploaded > levelInfo.maxUploadCount && uniqueImagesUsed > levelInfo.maxUniqueImages) {
|
if (imagesUploaded < levelInfo.maxUploadCount
|
||||||
|
|| uniqueImagesUsed < levelInfo.maxUniqueImages
|
||||||
|
|| nonRevertRate < levelInfo.minNonRevertPercentage ) {
|
||||||
level = levelInfo;
|
level = levelInfo;
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
@ -57,10 +69,6 @@ public class LevelController {
|
||||||
return levelNumber;
|
return levelNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLevelStyle(int levelStyle) {
|
|
||||||
this.levelStyle = levelStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMaxUniqueImages() {
|
public int getMaxUniqueImages() {
|
||||||
return maxUniqueImages;
|
return maxUniqueImages;
|
||||||
}
|
}
|
||||||
|
|
@ -68,6 +76,10 @@ public class LevelController {
|
||||||
public int getMaxUploadCount() {
|
public int getMaxUploadCount() {
|
||||||
return maxUploadCount;
|
return maxUploadCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMinNonRevertPercentage(){
|
||||||
|
return minNonRevertPercentage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import android.accounts.AccountAuthenticatorResponse;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -440,4 +441,9 @@ public class LoginActivity extends AccountAuthenticatorActivity {
|
||||||
loginButton.setEnabled(enabled);
|
loginButton.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void startYourself(Context context) {
|
||||||
|
Intent intent = new Intent(context, LoginActivity.class);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,4 +88,10 @@ public class SessionManager {
|
||||||
.map(a -> accountManager.removeAccount(a, null, null).getResult()))
|
.map(a -> accountManager.removeAccount(a, null, null).getResult()))
|
||||||
.doOnComplete(() -> currentAccount = null);
|
.doOnComplete(() -> currentAccount = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void forceLogin(Context context) {
|
||||||
|
if (context != null) {
|
||||||
|
LoginActivity.startYourself(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -651,6 +651,37 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This takes userName as input, which is then used to fetch the no of images deleted
|
||||||
|
* using OkHttp and JavaRx. This function return JSONObject
|
||||||
|
* @param userName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Single<JSONObject> getRevertCount(String userName){
|
||||||
|
final String fetchRevertCountUrlTemplate =
|
||||||
|
wikiMediaToolforgeUrl + "urbanecmbot/commonsmisc/feedback.py";
|
||||||
|
return Single.fromCallable(() -> {
|
||||||
|
String url = String.format(
|
||||||
|
Locale.ENGLISH,
|
||||||
|
fetchRevertCountUrlTemplate,
|
||||||
|
new PageTitle(userName).getText());
|
||||||
|
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
|
||||||
|
urlBuilder.addQueryParameter("user", userName);
|
||||||
|
urlBuilder.addQueryParameter("fetch","deletedUploads");
|
||||||
|
Log.i("url", urlBuilder.toString());
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(urlBuilder.toString())
|
||||||
|
.build();
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
String jsonData = response.body().string();
|
||||||
|
JSONObject jsonRevertObject = new JSONObject(jsonData);
|
||||||
|
return jsonRevertObject;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private Date parseMWDate(String mwDate) {
|
private Date parseMWDate(String mwDate) {
|
||||||
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC
|
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,9 @@ public interface MediaWikiApi {
|
||||||
@NonNull
|
@NonNull
|
||||||
Single<JSONObject> getAchievements(String userName);
|
Single<JSONObject> getAchievements(String userName);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
Single<JSONObject> getRevertCount(String userName);
|
||||||
|
|
||||||
interface ProgressListener {
|
interface ProgressListener {
|
||||||
void onProgress(long transferred, long total);
|
void onProgress(long transferred, long total);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/ic_info_outline_blue_24dp.xml
Normal file
5
app/src/main/res/drawable/ic_info_outline_blue_24dp.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#00376d"
|
||||||
|
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -71,9 +71,20 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="@dimen/activity_margin_horizontal"
|
android:layout_marginLeft="@dimen/activity_margin_horizontal"
|
||||||
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
||||||
|
android:id="@+id/images_upload_text_param"
|
||||||
android:layout_marginTop="@dimen/achievements_activity_margin_vertical"
|
android:layout_marginTop="@dimen/achievements_activity_margin_vertical"
|
||||||
android:text="@string/images_uploaded" />
|
android:text="@string/images_uploaded" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="12dp"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:id="@+id/images_upload_info"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="@dimen/activity_margin_horizontal"
|
||||||
|
android:layout_toRightOf="@+id/images_upload_text_param"
|
||||||
|
app:srcCompat="@drawable/ic_info_outline_blue_24dp"
|
||||||
|
android:layout_marginLeft="8dp" />
|
||||||
|
|
||||||
<com.dinuscxj.progressbar.CircleProgressBar
|
<com.dinuscxj.progressbar.CircleProgressBar
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
|
|
@ -111,11 +122,22 @@
|
||||||
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
||||||
android:text="@string/image_reverts" />
|
android:text="@string/image_reverts" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="12dp"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="@dimen/activity_margin_horizontal"
|
||||||
|
android:id="@+id/images_reverted_info"
|
||||||
|
android:layout_toRightOf="@+id/images_reverted_text"
|
||||||
|
app:srcCompat="@drawable/ic_info_outline_blue_24dp"
|
||||||
|
android:layout_marginLeft="8dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="(minimum required: 90%)"
|
android:text="@string/achievements_revert_limit_message"
|
||||||
android:textSize="10dp"
|
android:textSize="10dp"
|
||||||
|
android:id="@+id/images_revert_limit_text"
|
||||||
android:layout_marginLeft="@dimen/activity_margin_horizontal"
|
android:layout_marginLeft="@dimen/activity_margin_horizontal"
|
||||||
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
||||||
android:layout_below="@+id/images_reverted_text"/>
|
android:layout_below="@+id/images_reverted_text"/>
|
||||||
|
|
@ -153,11 +175,22 @@
|
||||||
style="?android:textAppearanceMedium"
|
style="?android:textAppearanceMedium"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/images_used_by_wiki_text"
|
||||||
android:layout_marginLeft="@dimen/activity_margin_horizontal"
|
android:layout_marginLeft="@dimen/activity_margin_horizontal"
|
||||||
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
android:layout_marginStart="@dimen/activity_margin_horizontal"
|
||||||
android:layout_marginTop="@dimen/achievements_activity_margin_vertical"
|
android:layout_marginTop="@dimen/achievements_activity_margin_vertical"
|
||||||
android:text="@string/images_used_by_wiki" />
|
android:text="@string/images_used_by_wiki" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="12dp"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:id="@+id/images_used_by_wiki_info"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="@dimen/activity_margin_horizontal"
|
||||||
|
android:layout_toRightOf="@+id/images_used_by_wiki_text"
|
||||||
|
app:srcCompat="@drawable/ic_info_outline_blue_24dp"
|
||||||
|
android:layout_marginLeft="8dp" />
|
||||||
|
|
||||||
<com.dinuscxj.progressbar.CircleProgressBar
|
<com.dinuscxj.progressbar.CircleProgressBar
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,12 @@
|
||||||
<string name="level">LEVEL</string>
|
<string name="level">LEVEL</string>
|
||||||
<string name="images_uploaded">Images Uploaded</string>
|
<string name="images_uploaded">Images Uploaded</string>
|
||||||
<string name="image_reverts">Images Not Reverted</string>
|
<string name="image_reverts">Images Not Reverted</string>
|
||||||
<string name="images_used_by_wiki">Images Used By Wiki</string>
|
<string name="images_used_by_wiki">Images Used</string>
|
||||||
<string name="achievements_share_message">Share your achievements with your friends!</string>
|
<string name="achievements_share_message">Share your achievements with your friends!</string>
|
||||||
<string name="achievements_info_message">Your level increases as you meet these requirements. Items in the "statistics" section do not count towards your level.</string>
|
<string name="achievements_info_message">Your level increases as you meet these requirements. Items in the "statistics" section do not count towards your level.</string>
|
||||||
|
<string name="achievements_revert_limit_message">minimum required: </string>
|
||||||
|
<string name="images_uploaded_explanation">The number of images you have uploaded to Commons, via any upload software</string>
|
||||||
|
<string name="images_reverted_explanation">The percentage of images you have uploaded to Commons that were not deleted</string>
|
||||||
|
<string name="images_used_explanation">The number of images you have uploaded to Commons that were used in Wikimedia articles</string>
|
||||||
|
<string name="user_not_logged_in">Login session expired, please log in again.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue