Skip to content

[GSoC] Merge Leaderboard branch with master #3905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b381d40
[GSoC] Fixes #3789 Updated UI of achievements activity to display lev…
madhurgupta10 Jun 4, 2020
eec0f14
Merge branch 'leaderboard' into merge-master-temp-branch
maskaravivek Jul 2, 2020
196b914
Fixes #3861 Use the APIs to fetch leaderboard’s based on uploads via …
madhurgupta10 Jul 8, 2020
5877d7a
[GSoC] Added Unit Tests and Fixed Landscape Mode Bug (#3872)
madhurgupta10 Jul 15, 2020
5f77f61
[GSoC] Added Pagination to Leaderboard (#3881)
madhurgupta10 Jul 29, 2020
bc0b5c0
[GSoC] Added option to set a new avatar (#3892)
madhurgupta10 Aug 9, 2020
baee56e
[GSoC] Added Click to open user profile for leaderboard (#3887)
madhurgupta10 Aug 9, 2020
94952f1
[GSoC] Added Leaderboard Filters (#3902)
madhurgupta10 Aug 18, 2020
7823403
Merge remote-tracking branch 'upstream/master' into leaderboard
madhurgupta10 Aug 21, 2020
ef11bac
Add JavaDocs
madhurgupta10 Aug 21, 2020
b35ad7c
Added Test for Update Avatar
madhurgupta10 Aug 21, 2020
43a6615
Decreased Margin of Filter
madhurgupta10 Aug 21, 2020
a63ef00
[GSoC] Updated leaderboard string (#3897)
madhurgupta10 Aug 21, 2020
e326ef0
Merge remote-tracking branch 'upstream/leaderboard' into leaderboard
madhurgupta10 Aug 21, 2020
61db5a6
Updated Strings
madhurgupta10 Aug 21, 2020
95deb4d
Added JavaDocs for all methods and classes
madhurgupta10 Aug 21, 2020
621c803
Added JavaDocs for all methods and classes
madhurgupta10 Aug 21, 2020
fb83594
Added More JavaDocs
madhurgupta10 Aug 26, 2020
00019b5
Revert string.xml
translatewiki Aug 17, 2020
04537ce
Revert "Revert string.xml"
madhurgupta10 Aug 26, 2020
0e56a11
Added protected
madhurgupta10 Aug 26, 2020
1a1ee20
Fixed strings.xml extra changes
madhurgupta10 Aug 26, 2020
06d0522
Revert codeStyle change
madhurgupta10 Aug 26, 2020
8cd3d68
Fixed extra string change
madhurgupta10 Aug 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {
// Utils
implementation 'in.yuvi:http.fluent:1.3'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.okhttp3:okhttp:4.5.0'
implementation 'com.squareup.okhttp3:okhttp:4.8.0'
implementation 'com.squareup.okio:okio:2.2.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
Expand All @@ -42,6 +42,7 @@ dependencies {
implementation 'com.dinuscxj:circleprogressbar:1.1.1'
implementation 'com.karumi:dexter:5.0.0'
implementation "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

kapt "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION"
implementation "com.hannesdorfmann:adapterdelegates4-kotlin-dsl-layoutcontainer:$ADAPTER_DELEGATES_VERSION"
Expand All @@ -50,6 +51,7 @@ dependencies {
testImplementation "androidx.paging:paging-common-ktx:$PAGING_VERSION"
implementation "androidx.paging:paging-rxjava2-ktx:$PAGING_VERSION"
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha02"
implementation 'com.squareup.okhttp3:okhttp-ws:3.4.1'

// Logging
implementation 'ch.acra:acra-dialog:5.3.0'
Expand Down Expand Up @@ -79,7 +81,7 @@ dependencies {
testImplementation 'junit:junit:4.13'
testImplementation 'org.robolectric:robolectric:4.3'
testImplementation 'androidx.test:core:1.2.0'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.12.1'
testImplementation "com.squareup.okhttp3:mockwebserver:4.8.0"
testImplementation "org.powermock:powermock-module-junit4:2.0.0-beta.5"
testImplementation "org.powermock:powermock-api-mockito2:2.0.0-beta.5"
testImplementation 'org.mockito:mockito-core:2.23.0'
Expand All @@ -94,7 +96,7 @@ dependencies {
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.annotation:annotation:1.1.0'
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.12.1'
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.8.0'
androidTestUtil 'androidx.test:orchestrator:1.2.0'

// Debugging
Expand Down Expand Up @@ -209,8 +211,8 @@ android {

configurations.all {
resolutionStrategy.force 'androidx.annotation:annotation:1.0.2'
exclude module: 'okhttp-ws'
}

flavorDimensions 'tier'
productFlavors {
prod {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.filters.MediumTest
import androidx.test.runner.AndroidJUnit4
import fr.free.nrw.commons.achievements.AchievementsActivity
import fr.free.nrw.commons.auth.LoginActivity
import fr.free.nrw.commons.profile.ProfileActivity
import org.junit.Before
import org.junit.Rule
import org.junit.Test
Expand All @@ -32,6 +31,6 @@ class AchievementsActivityTest {
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
onView(withId(R.id.user_icon)).perform(click())

Intents.intended(hasComponent(AchievementsActivity::class.java.name))
Intents.intended(hasComponent(ProfileActivity::class.java.name))
}
}
4 changes: 2 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@
/>

<activity
android:name=".achievements.AchievementsActivity"
android:label="@string/Achievements" />
android:name=".profile.ProfileActivity"
android:label="@string/Profile" />

<activity
android:name=".bookmarks.BookmarksActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.achievements.FeedbackResponse;
import fr.free.nrw.commons.profile.achievements.FeedbackResponse;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.utils.ViewUtilWrapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.AboutActivity;
import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.achievements.AchievementsActivity;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.auth.SignupActivity;
import fr.free.nrw.commons.bookmarks.BookmarksActivity;
Expand All @@ -15,6 +14,7 @@
import fr.free.nrw.commons.explore.SearchActivity;
import fr.free.nrw.commons.explore.ExploreActivity;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.profile.ProfileActivity;
import fr.free.nrw.commons.review.ReviewActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
import fr.free.nrw.commons.upload.UploadActivity;
Expand Down Expand Up @@ -68,7 +68,7 @@ public abstract class ActivityBuilderModule {
abstract ExploreActivity bindExploreActivity();

@ContributesAndroidInjector
abstract AchievementsActivity bindAchievementsActivity();
abstract ProfileActivity bindAchievementsActivity();

@ContributesAndroidInjector
abstract BookmarksActivity bindBookmarksActivity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import fr.free.nrw.commons.media.MediaDetailFragment;
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment;
import fr.free.nrw.commons.profile.achievements.AchievementsFragment;
import fr.free.nrw.commons.profile.leaderboard.LeaderboardFragment;
import fr.free.nrw.commons.review.ReviewImageFragment;
import fr.free.nrw.commons.settings.SettingsFragment;
import fr.free.nrw.commons.upload.categories.UploadCategoriesFragment;
Expand Down Expand Up @@ -103,4 +105,10 @@ public abstract class FragmentBuilderModule {

@ContributesAndroidInjector
abstract ParentCategoriesFragment bindParentCategoriesFragment();

@ContributesAndroidInjector
abstract AchievementsFragment bindAchievementsFragment();

@ContributesAndroidInjector
abstract LeaderboardFragment bindLeaderboardFragment();
}
10 changes: 10 additions & 0 deletions app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ public HttpLoggingInterceptor provideHttpLoggingInterceptor() {
public OkHttpJsonApiClient provideOkHttpJsonApiClient(OkHttpClient okHttpClient,
DepictsClient depictsClient,
@Named("tools_forge") HttpUrl toolsForgeUrl,
@Named("test_tools_forge") HttpUrl testToolsForgeUrl,
@Named("default_preferences") JsonKvStore defaultKvStore,
Gson gson) {
return new OkHttpJsonApiClient(okHttpClient,
depictsClient,
toolsForgeUrl,
testToolsForgeUrl,
WIKIDATA_SPARQL_QUERY_URL,
BuildConfig.WIKIMEDIA_CAMPAIGNS_URL,
gson);
Expand Down Expand Up @@ -124,6 +126,14 @@ public HttpUrl provideToolsForgeUrl() {
return HttpUrl.parse(TOOLS_FORGE_URL);
}

@Provides
@Named("test_tools_forge")
@NonNull
@SuppressWarnings("ConstantConditions")
public HttpUrl provideTestToolsForgeUrl() {
return HttpUrl.parse(TEST_TOOLS_FORGE_URL);
}

@Provides
@Singleton
@Named(NAMED_COMMONS_WIKI_SITE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,34 @@
import com.google.android.material.snackbar.Snackbar;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.bookmarks.Bookmark;
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider;
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao;
import fr.free.nrw.commons.contributions.Contribution;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.utils.DownloadUtils;
import fr.free.nrw.commons.utils.ImageUtils;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.disposables.CompositeDisposable;
import java.util.Objects;
import javax.inject.Inject;
import timber.log.Timber;

public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment implements ViewPager.OnPageChangeListener {

@Inject BookmarkPicturesDao bookmarkDao;

@Inject
protected OkHttpJsonApiClient okHttpJsonApiClient;

@Inject
protected SessionManager sessionManager;

private static CompositeDisposable compositeDisposable = new CompositeDisposable();

@BindView(R.id.mediaDetailsPager) ViewPager pager;
private Boolean editable;
private boolean isFeaturedImage;
Expand Down Expand Up @@ -160,6 +172,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
// Set wallpaper
setWallpaper(m);
return true;
case R.id.menu_set_as_avatar:
// Set avatar
setAvatar(m);
return true;
default:
return super.onOptionsItemSelected(item);
}
Expand All @@ -178,6 +194,20 @@ private void setWallpaper(Media media) {
ImageUtils.setWallpaperFromImageUrl(getActivity(), Uri.parse(media.getImageUrl()));
}

/**
* Set the media as user's leaderboard avatar
* @param media
*/
private void setAvatar(Media media) {
if (media.getImageUrl() == null || media.getImageUrl().isEmpty()) {
Timber.d("Media URL not present");
return;
}
ImageUtils.setAvatarFromImageUrl(getActivity(), media.getImageUrl(),
Objects.requireNonNull(sessionManager.getCurrentAccount()).name,
okHttpJsonApiClient, compositeDisposable);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (!editable) { // Disable menu options for editable views
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package fr.free.nrw.commons.mwapi;

import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.LEADERBOARD_END_POINT;
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.UPDATE_AVATAR_END_POINT;

import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import fr.free.nrw.commons.achievements.FeaturedImages;
import fr.free.nrw.commons.achievements.FeedbackResponse;
import fr.free.nrw.commons.campaigns.CampaignResponseDTO;
import fr.free.nrw.commons.explore.depictions.DepictsClient;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.nearby.model.NearbyResponse;
import fr.free.nrw.commons.nearby.model.NearbyResultItem;
import fr.free.nrw.commons.profile.achievements.FeaturedImages;
import fr.free.nrw.commons.profile.achievements.FeedbackResponse;
import fr.free.nrw.commons.profile.leaderboard.LeaderboardResponse;
import fr.free.nrw.commons.profile.leaderboard.UpdateAvatarResponse;
import fr.free.nrw.commons.upload.FileUtils;
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
import fr.free.nrw.commons.utils.ConfigUtils;
Expand Down Expand Up @@ -40,6 +45,7 @@ public class OkHttpJsonApiClient {
private final OkHttpClient okHttpClient;
private final DepictsClient depictsClient;
private final HttpUrl wikiMediaToolforgeUrl;
private final HttpUrl wikiMediaTestToolforgeUrl;
private final String sparqlQueryUrl;
private final String campaignsUrl;
private final Gson gson;
Expand All @@ -49,17 +55,105 @@ public class OkHttpJsonApiClient {
public OkHttpJsonApiClient(OkHttpClient okHttpClient,
DepictsClient depictsClient,
HttpUrl wikiMediaToolforgeUrl,
HttpUrl wikiMediaTestToolforgeUrl,
String sparqlQueryUrl,
String campaignsUrl,
Gson gson) {
this.okHttpClient = okHttpClient;
this.depictsClient = depictsClient;
this.wikiMediaToolforgeUrl = wikiMediaToolforgeUrl;
this.wikiMediaTestToolforgeUrl = wikiMediaTestToolforgeUrl;
this.sparqlQueryUrl = sparqlQueryUrl;
this.campaignsUrl = campaignsUrl;
this.gson = gson;
}

/**
* The method will gradually calls the leaderboard API and fetches the leaderboard
* @param userName username of leaderboard user
* @param duration duration for leaderboard
* @param category category for leaderboard
* @param limit page size limit for list
* @param offset offset for the list
* @return LeaderboardResponse object
*/
@NonNull
public Observable<LeaderboardResponse> getLeaderboard(String userName, String duration, String category, String limit, String offset) {
final String fetchLeaderboardUrlTemplate = wikiMediaTestToolforgeUrl
+ LEADERBOARD_END_POINT;
String url = String.format(Locale.ENGLISH,
fetchLeaderboardUrlTemplate,
userName,
duration,
category,
limit,
offset);
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
urlBuilder.addQueryParameter("user", userName);
urlBuilder.addQueryParameter("duration", duration);
urlBuilder.addQueryParameter("category", category);
urlBuilder.addQueryParameter("limit", limit);
urlBuilder.addQueryParameter("offset", offset);
Timber.i("Url %s", urlBuilder.toString());
Request request = new Request.Builder()
.url(urlBuilder.toString())
.build();
return Observable.fromCallable(() -> {
Response response = okHttpClient.newCall(request).execute();
if (response != null && response.body() != null && response.isSuccessful()) {
String json = response.body().string();
if (json == null) {
return new LeaderboardResponse();
}
Timber.d("Response for leaderboard is %s", json);
try {
return gson.fromJson(json, LeaderboardResponse.class);
} catch (Exception e) {
return new LeaderboardResponse();
}
}
return new LeaderboardResponse();
});
}

/**
* This method will update the leaderboard user avatar
* @param username username to update
* @param avatar url of the new avatar
* @return UpdateAvatarResponse object
*/
@NonNull
public Single<UpdateAvatarResponse> setAvatar(String username, String avatar) {
final String urlTemplate = wikiMediaTestToolforgeUrl
+ UPDATE_AVATAR_END_POINT;
return Single.fromCallable(() -> {
String url = String.format(Locale.ENGLISH,
urlTemplate,
username,
avatar);
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
urlBuilder.addQueryParameter("user", username);
urlBuilder.addQueryParameter("avatar", avatar);
Timber.i("Url %s", urlBuilder.toString());
Request request = new Request.Builder()
.url(urlBuilder.toString())
.build();
Response response = okHttpClient.newCall(request).execute();
if (response != null && response.body() != null && response.isSuccessful()) {
String json = response.body().string();
if (json == null) {
return null;
}
try {
return gson.fromJson(json, UpdateAvatarResponse.class);
} catch (Exception e) {
return new UpdateAvatarResponse();
}
}
return null;
});
}

@NonNull
public Single<Integer> getUploadCount(String userName) {
HttpUrl.Builder urlBuilder = wikiMediaToolforgeUrl.newBuilder();
Expand Down Expand Up @@ -145,7 +239,6 @@ public Single<FeedbackResponse> getAchievements(String userName) {
userName);
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
urlBuilder.addQueryParameter("user", userName);
Timber.i("Url %s", urlBuilder.toString());
Request request = new Request.Builder()
.url(urlBuilder.toString())
.build();
Expand Down
Loading