mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
[GSoC] Added Leaderboard Filters (#3902)
* Attempt to add filters * Basic Filter Working * Filter Improved * Filter Completed
This commit is contained in:
parent
baee56e392
commit
94952f1820
8 changed files with 222 additions and 23 deletions
|
|
@ -2,8 +2,6 @@ package fr.free.nrw.commons.profile.leaderboard;
|
|||
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.LOADED;
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.LOADING;
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.PAGE_SIZE;
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.START_OFFSET;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
|
@ -20,10 +18,19 @@ public class DataSourceClass extends PageKeyedDataSource<Integer, LeaderboardLis
|
|||
private SessionManager sessionManager;
|
||||
private MutableLiveData<String> progressLiveStatus;
|
||||
private CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
private String duration;
|
||||
private String category;
|
||||
private int limit;
|
||||
private int offset;
|
||||
|
||||
public DataSourceClass(OkHttpJsonApiClient okHttpJsonApiClient,SessionManager sessionManager) {
|
||||
public DataSourceClass(OkHttpJsonApiClient okHttpJsonApiClient,SessionManager sessionManager,
|
||||
String duration, String category, int limit, int offset) {
|
||||
this.okHttpJsonApiClient = okHttpJsonApiClient;
|
||||
this.sessionManager = sessionManager;
|
||||
this.duration = duration;
|
||||
this.category = category;
|
||||
this.limit = limit;
|
||||
this.offset = offset;
|
||||
progressLiveStatus = new MutableLiveData<>();
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +45,7 @@ public class DataSourceClass extends PageKeyedDataSource<Integer, LeaderboardLis
|
|||
|
||||
compositeDisposable.add(okHttpJsonApiClient
|
||||
.getLeaderboard(Objects.requireNonNull(sessionManager.getCurrentAccount()).name,
|
||||
"all_time", "upload", String.valueOf(PAGE_SIZE), String.valueOf(START_OFFSET))
|
||||
duration, category, String.valueOf(limit), String.valueOf(offset))
|
||||
.doOnSubscribe(disposable -> {
|
||||
compositeDisposable.add(disposable);
|
||||
progressLiveStatus.postValue(LOADING);
|
||||
|
|
@ -68,7 +75,7 @@ public class DataSourceClass extends PageKeyedDataSource<Integer, LeaderboardLis
|
|||
@NonNull LoadCallback<Integer, LeaderboardList> callback) {
|
||||
compositeDisposable.add(okHttpJsonApiClient
|
||||
.getLeaderboard(Objects.requireNonNull(sessionManager.getCurrentAccount()).name,
|
||||
"all_time", "upload", String.valueOf(PAGE_SIZE), String.valueOf(params.key))
|
||||
duration, category, String.valueOf(limit), String.valueOf(params.key))
|
||||
.doOnSubscribe(disposable -> {
|
||||
compositeDisposable.add(disposable);
|
||||
progressLiveStatus.postValue(LOADING);
|
||||
|
|
@ -76,7 +83,7 @@ public class DataSourceClass extends PageKeyedDataSource<Integer, LeaderboardLis
|
|||
response -> {
|
||||
if (response != null && response.getStatus() == 200) {
|
||||
progressLiveStatus.postValue(LOADED);
|
||||
callback.onResult(response.getLeaderboardList(), params.key + PAGE_SIZE);
|
||||
callback.onResult(response.getLeaderboardList(), params.key + limit);
|
||||
}
|
||||
},
|
||||
t -> {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,42 @@ public class DataSourceFactory extends DataSource.Factory<Integer, LeaderboardLi
|
|||
private OkHttpJsonApiClient okHttpJsonApiClient;
|
||||
private CompositeDisposable compositeDisposable;
|
||||
private SessionManager sessionManager;
|
||||
private String duration;
|
||||
private String category;
|
||||
private int limit;
|
||||
private int offset;
|
||||
|
||||
public String getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(final String duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(final String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public void setLimit(final int limit) {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public void setOffset(final int offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public DataSourceFactory(OkHttpJsonApiClient okHttpJsonApiClient, CompositeDisposable compositeDisposable,
|
||||
SessionManager sessionManager) {
|
||||
|
|
@ -27,7 +63,7 @@ public class DataSourceFactory extends DataSource.Factory<Integer, LeaderboardLi
|
|||
|
||||
@Override
|
||||
public DataSource<Integer, LeaderboardList> create() {
|
||||
DataSourceClass dataSourceClass = new DataSourceClass(okHttpJsonApiClient, sessionManager);
|
||||
DataSourceClass dataSourceClass = new DataSourceClass(okHttpJsonApiClient, sessionManager, duration, category, limit, offset);
|
||||
liveData.postValue(dataSourceClass);
|
||||
return dataSourceClass;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,19 @@ package fr.free.nrw.commons.profile.leaderboard;
|
|||
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.LOADED;
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.LOADING;
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.PAGE_SIZE;
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.START_OFFSET;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Spinner;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.MergeAdapter;
|
||||
|
|
@ -35,6 +41,12 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment {
|
|||
@BindView(R.id.progressBar)
|
||||
ProgressBar progressBar;
|
||||
|
||||
@BindView(R.id.category_spinner)
|
||||
Spinner categorySpinner;
|
||||
|
||||
@BindView(R.id.duration_spinner)
|
||||
Spinner durationSpinner;
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
|
||||
|
|
@ -48,32 +60,91 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment {
|
|||
|
||||
private CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
String duration;
|
||||
String category;
|
||||
int limit = PAGE_SIZE;
|
||||
int offset = START_OFFSET;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_leaderboard, container, false);
|
||||
ButterKnife.bind(this, rootView);
|
||||
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
hideLayouts();
|
||||
setLeaderboard();
|
||||
setSpinners();
|
||||
|
||||
String[] durationValues = getContext().getResources().getStringArray(R.array.leaderboard_duration_values);
|
||||
String[] categoryValues = getContext().getResources().getStringArray(R.array.leaderboard_category_values);
|
||||
|
||||
duration = durationValues[0];
|
||||
category = categoryValues[0];
|
||||
|
||||
setLeaderboard(duration, category, limit, offset);
|
||||
|
||||
durationSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
|
||||
duration = durationValues[durationSpinner.getSelectedItemPosition()];
|
||||
refreshLeaderboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
}
|
||||
});
|
||||
|
||||
categorySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
category = categoryValues[categorySpinner.getSelectedItemPosition()];
|
||||
refreshLeaderboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
}
|
||||
});
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void refreshLeaderboard() {
|
||||
if (viewModel != null) {
|
||||
viewModel.refresh(duration, category, limit, offset);
|
||||
setLeaderboard(duration, category, limit, offset);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSpinners() {
|
||||
ArrayAdapter<CharSequence> categoryAdapter = ArrayAdapter.createFromResource(getContext(),
|
||||
R.array.leaderboard_categories, android.R.layout.simple_spinner_item);
|
||||
categoryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
categorySpinner.setAdapter(categoryAdapter);
|
||||
|
||||
ArrayAdapter<CharSequence> durationAdapter = ArrayAdapter.createFromResource(getContext(),
|
||||
R.array.leaderboard_durations, android.R.layout.simple_spinner_item);
|
||||
durationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
durationSpinner.setAdapter(durationAdapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* To call the API to get results
|
||||
* which then sets the views using setLeaderboardUser method
|
||||
*/
|
||||
private void setLeaderboard() {
|
||||
private void setLeaderboard(String duration, String category, int limit, int offset) {
|
||||
if (checkAccount()) {
|
||||
try {
|
||||
compositeDisposable.add(okHttpJsonApiClient
|
||||
.getLeaderboard(Objects.requireNonNull(sessionManager.getCurrentAccount()).name,
|
||||
"all_time", "upload", null, null)
|
||||
duration, category, null, null)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
response -> {
|
||||
if (response != null && response.getStatus() == 200) {
|
||||
setViews(response);
|
||||
setViews(response, duration, category, limit, offset);
|
||||
}
|
||||
},
|
||||
t -> {
|
||||
|
|
@ -92,15 +163,15 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment {
|
|||
* Set the views
|
||||
* @param response Leaderboard Response Object
|
||||
*/
|
||||
private void setViews(LeaderboardResponse response) {
|
||||
private void setViews(LeaderboardResponse response, String duration, String category, int limit, int offset) {
|
||||
viewModel = new ViewModelProvider(this, viewModelFactory).get(LeaderboardListViewModel.class);
|
||||
viewModel.setParams(duration, category, limit, offset);
|
||||
LeaderboardListAdapter leaderboardListAdapter = new LeaderboardListAdapter();
|
||||
UserDetailAdapter userDetailAdapter= new UserDetailAdapter(response);
|
||||
MergeAdapter mergeAdapter = new MergeAdapter(userDetailAdapter, leaderboardListAdapter);
|
||||
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
|
||||
leaderboardListRecyclerView.setLayoutManager(linearLayoutManager);
|
||||
leaderboardListRecyclerView.setAdapter(mergeAdapter);
|
||||
|
||||
viewModel.getListLiveData().observe(getViewLifecycleOwner(), leaderboardListAdapter::submitList);
|
||||
viewModel.getProgressLoadStatus().observe(getViewLifecycleOwner(), status -> {
|
||||
if (Objects.requireNonNull(status).equalsIgnoreCase(LOADING)) {
|
||||
|
|
@ -117,6 +188,8 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment {
|
|||
private void hideProgressBar() {
|
||||
if (progressBar != null) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
categorySpinner.setVisibility(View.VISIBLE);
|
||||
durationSpinner.setVisibility(View.VISIBLE);
|
||||
leaderboardListRecyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
|
@ -134,6 +207,8 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment {
|
|||
* used to hide the layouts while fetching results from api
|
||||
*/
|
||||
private void hideLayouts(){
|
||||
categorySpinner.setVisibility(View.INVISIBLE);
|
||||
durationSpinner.setVisibility(View.INVISIBLE);
|
||||
leaderboardListRecyclerView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,13 @@ public class LeaderboardListViewModel extends ViewModel {
|
|||
private DataSourceFactory dataSourceFactory;
|
||||
private LiveData<PagedList<LeaderboardList>> listLiveData;
|
||||
private CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
private LiveData<String> progressLoadStatus = new MutableLiveData<>();
|
||||
|
||||
public LeaderboardListViewModel(OkHttpJsonApiClient okHttpJsonApiClient, SessionManager sessionManager) {
|
||||
dataSourceFactory = new DataSourceFactory(okHttpJsonApiClient, compositeDisposable, sessionManager);
|
||||
public LeaderboardListViewModel(OkHttpJsonApiClient okHttpJsonApiClient, SessionManager
|
||||
sessionManager) {
|
||||
|
||||
dataSourceFactory = new DataSourceFactory(okHttpJsonApiClient,
|
||||
compositeDisposable, sessionManager);
|
||||
initializePaging();
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +44,21 @@ public class LeaderboardListViewModel extends ViewModel {
|
|||
|
||||
}
|
||||
|
||||
public void refresh(String duration, String category, int limit, int offset) {
|
||||
dataSourceFactory.setDuration(duration);
|
||||
dataSourceFactory.setCategory(category);
|
||||
dataSourceFactory.setLimit(limit);
|
||||
dataSourceFactory.setOffset(offset);
|
||||
dataSourceFactory.getMutableLiveData().getValue().invalidate();
|
||||
}
|
||||
|
||||
public void setParams(String duration, String category, int limit, int offset) {
|
||||
dataSourceFactory.setDuration(duration);
|
||||
dataSourceFactory.setCategory(category);
|
||||
dataSourceFactory.setLimit(limit);
|
||||
dataSourceFactory.setOffset(offset);
|
||||
}
|
||||
|
||||
public LiveData<String> getProgressLoadStatus() {
|
||||
return progressLoadStatus;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ public class ViewModelFactory implements ViewModelProvider.Factory {
|
|||
private OkHttpJsonApiClient okHttpJsonApiClient;
|
||||
private SessionManager sessionManager;
|
||||
|
||||
|
||||
@Inject
|
||||
public ViewModelFactory(OkHttpJsonApiClient okHttpJsonApiClient, SessionManager sessionManager) {
|
||||
this.okHttpJsonApiClient = okHttpJsonApiClient;
|
||||
|
|
|
|||
|
|
@ -4,12 +4,44 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/filters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="1"
|
||||
android:layout_margin="20dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Spinner
|
||||
android:layout_marginStart="60dp"
|
||||
android:id="@+id/duration_spinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="0.5"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<Spinner
|
||||
android:layout_marginEnd="60dp"
|
||||
android:id="@+id/category_spinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="0.5"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/leaderboard_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/filters" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
|
|
|
|||
|
|
@ -46,4 +46,29 @@
|
|||
<item>1</item>
|
||||
<item>0</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="leaderboard_categories">
|
||||
<item>@string/leaderboard_upload</item>
|
||||
<item>@string/leaderboard_used</item>
|
||||
<item>@string/leaderboard_nearby</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="leaderboard_category_values">
|
||||
<item>upload</item>
|
||||
<item>used</item>
|
||||
<item>nearby</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="leaderboard_durations">
|
||||
<item>@string/leaderboard_weekly</item>
|
||||
<item>@string/leaderboard_yearly</item>
|
||||
<item>@string/leaderboard_all_time</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="leaderboard_duration_values">
|
||||
<item>weekly</item>
|
||||
<item>yearly</item>
|
||||
<item>all_time</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
|
@ -666,4 +666,10 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="avatar_set_successfully">Avatar Set Successfully</string>
|
||||
<string name="avatar_set_unsuccessfully">Error setting new avatar, please try again</string>
|
||||
<string name="menu_set_avatar">Set as avatar</string>
|
||||
<string name="leaderboard_yearly">Yearly</string>
|
||||
<string name="leaderboard_weekly">Weekly</string>
|
||||
<string name="leaderboard_all_time">All Time</string>
|
||||
<string name="leaderboard_upload">Upload</string>
|
||||
<string name="leaderboard_nearby">Nearby</string>
|
||||
<string name="leaderboard_used">Used</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue