Fixes #3389 - Show User profiles (#4678)

* Fixes #3389 - Show  User profiles

* Don't show dummy achievements data - show data only when loaded
This commit is contained in:
Ashish 2021-10-26 02:10:08 +05:30 committed by GitHub
parent 7ce80aa804
commit 88b21a678e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 358 additions and 48 deletions

View file

@ -21,6 +21,8 @@ class ContributionBoundaryCallback @Inject constructor(
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioThreadScheduler: Scheduler
) : BoundaryCallback<Contribution>() {
private val compositeDisposable: CompositeDisposable = CompositeDisposable()
lateinit var userName: String
/**
* It is triggered when the list has no items User's Contributions are then fetched from the
@ -55,7 +57,7 @@ class ContributionBoundaryCallback @Inject constructor(
fun fetchContributions() {
if (sessionManager.userName != null) {
compositeDisposable.add(
mediaClient.getMediaListForUser(sessionManager.userName!!)
mediaClient.getMediaListForUser(userName!!)
.map { mediaList ->
mediaList.map {
Contribution(media = it, state = Contribution.STATE_COMPLETED)
@ -88,4 +90,11 @@ class ContributionBoundaryCallback @Inject constructor(
}
)
}
/**
* Clean up
*/
fun dispose() {
compositeDisposable.dispose()
}
}

View file

@ -5,7 +5,6 @@ import static android.view.View.VISIBLE;
import static fr.free.nrw.commons.di.NetworkingModule.NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
@ -21,6 +20,7 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -35,17 +35,20 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.customselector.ui.selector.CustomSelectorActivity;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.utils.DialogUtil;
import fr.free.nrw.commons.media.MediaClient;
import fr.free.nrw.commons.utils.SystemThemeUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import java.util.Locale;
import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import org.wikipedia.dataclient.WikiSite;
import timber.log.Timber;
import fr.free.nrw.commons.profile.ProfileActivity;
/**
* Created by root on 01.06.2018.
@ -56,7 +59,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
WikipediaInstructionsDialogFragment.Callback {
private static final String RV_STATE = "rv_scroll_state";
@BindView(R.id.contributionsList)
RecyclerView rvContributionsList;
@BindView(R.id.loadingContributionsProgressBar)
@ -76,6 +79,8 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
@Inject
SystemThemeUtils systemThemeUtils;
@BindView(R.id.tv_contributions_of_user)
AppCompatTextView tvContributionsOfUser;
@Inject
ContributionController controller;
@ -89,6 +94,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
@Inject
ContributionsListPresenter contributionsListPresenter;
@Inject
SessionManager sessionManager;
private Animation fab_close;
private Animation fab_open;
private Animation rotate_forward;
@ -105,8 +113,23 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
private final int SPAN_COUNT_PORTRAIT = 1;
private int contributionsSize;
String userName;
@Override
public void onCreate(@Nullable @org.jetbrains.annotations.Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Now that we are allowing this fragment to be started for
// any userName- we expect it to be passed as an argument
if (getArguments() != null) {
userName = getArguments().getString(ProfileActivity.KEY_USERNAME);
}
if (StringUtils.isEmpty(userName)) {
userName = sessionManager.getUserName();
}
}
@Override
public View onCreateView(
final LayoutInflater inflater, @Nullable final ViewGroup container,
@ -114,6 +137,16 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
final View view = inflater.inflate(R.layout.fragment_contributions_list, container, false);
ButterKnife.bind(this, view);
contributionsListPresenter.onAttachView(this);
if (Objects.equals(sessionManager.getUserName(), userName)) {
tvContributionsOfUser.setVisibility(GONE);
fab_layout.setVisibility(VISIBLE);
} else {
tvContributionsOfUser.setVisibility(VISIBLE);
tvContributionsOfUser.setText(getString(R.string.contributions_of_user, userName));
fab_layout.setVisibility(GONE);
}
initAdapter();
return view;
}
@ -155,8 +188,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}
contributionsListPresenter.setup();
contributionsListPresenter.contributionList.observe(this.getViewLifecycleOwner(), list -> {
contributionsListPresenter.setup(userName,
Objects.equals(sessionManager.getUserName(), userName));
contributionsListPresenter.contributionList.observe(getViewLifecycleOwner(), list -> {
contributionsSize = list.size();
adapter.submitList(list);
if (callback != null) {

View file

@ -1,6 +1,9 @@
package fr.free.nrw.commons.contributions;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
import androidx.paging.DataSource.Factory;
import androidx.paging.LivePagedListBuilder;
import androidx.paging.PagedList;
import fr.free.nrw.commons.contributions.ContributionsListContract.UserActionListener;
@ -20,17 +23,20 @@ public class ContributionsListPresenter implements UserActionListener {
private final Scheduler ioThreadScheduler;
private final CompositeDisposable compositeDisposable;
private final ContributionsRemoteDataSource contributionsRemoteDataSource;
LiveData<PagedList<Contribution>> contributionList;
@Inject
ContributionsListPresenter(
final ContributionBoundaryCallback contributionBoundaryCallback,
final ContributionsRemoteDataSource contributionsRemoteDataSource,
final ContributionsRepository repository,
@Named(CommonsApplicationModule.IO_THREAD) final Scheduler ioThreadScheduler) {
this.contributionBoundaryCallback = contributionBoundaryCallback;
this.repository = repository;
this.ioThreadScheduler = ioThreadScheduler;
this.contributionsRemoteDataSource=contributionsRemoteDataSource;
compositeDisposable = new CompositeDisposable();
}
@ -43,19 +49,44 @@ public class ContributionsListPresenter implements UserActionListener {
* the live data object. This method can be tweaked to update the lazy loading behavior of the
* contributions list
*/
void setup() {
void setup(String userName, boolean isSelf) {
final PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setPrefetchDistance(50)
.setPageSize(10).build();
contributionList = (new LivePagedListBuilder(repository.fetchContributions(),
pagedListConfig)
.setBoundaryCallback(contributionBoundaryCallback)).build();
Factory<Integer, Contribution> factory;
boolean shouldSetBoundaryCallback;
if (!isSelf) {
//We don't want to persist contributions for other user's, therefore
// creating a new DataSource for them
contributionsRemoteDataSource.setUserName(userName);
factory = new Factory<Integer, Contribution>() {
@NonNull
@Override
public DataSource<Integer, Contribution> create() {
return contributionsRemoteDataSource;
}
};
shouldSetBoundaryCallback = false;
} else {
contributionBoundaryCallback.setUserName(userName);
shouldSetBoundaryCallback = true;
factory = repository.fetchContributions();
}
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(factory, pagedListConfig);
if (shouldSetBoundaryCallback) {
livePagedListBuilder.setBoundaryCallback(contributionBoundaryCallback);
}
contributionList = livePagedListBuilder.build();
}
@Override
public void onDetachView() {
compositeDisposable.clear();
contributionsRemoteDataSource.dispose();
contributionBoundaryCallback.dispose();
}
/**

View file

@ -0,0 +1,73 @@
package fr.free.nrw.commons.contributions
import androidx.paging.ItemKeyedDataSource
import fr.free.nrw.commons.di.CommonsApplicationModule
import fr.free.nrw.commons.media.MediaClient
import io.reactivex.Scheduler
import io.reactivex.disposables.CompositeDisposable
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Named
/**
* Data-Source which acts as mediator for contributions-data from the API
*/
class ContributionsRemoteDataSource @Inject constructor(
private val mediaClient: MediaClient,
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioThreadScheduler: Scheduler
) : ItemKeyedDataSource<Int, Contribution>() {
private val compositeDisposable: CompositeDisposable = CompositeDisposable()
var userName: String? = null
override fun loadInitial(
params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Contribution>
) {
fetchContributions(callback)
}
override fun loadAfter(
params: LoadParams<Int>,
callback: LoadCallback<Contribution>
) {
fetchContributions(callback)
}
override fun loadBefore(
params: LoadParams<Int>,
callback: LoadCallback<Contribution>
) {
}
override fun getKey(item: Contribution): Int {
return item.pageId.hashCode()
}
/**
* Fetches contributions using the MediaWiki API
*/
private fun fetchContributions(callback: LoadCallback<Contribution>) {
compositeDisposable.add(
mediaClient.getMediaListForUser(userName!!)
.map { mediaList ->
mediaList.map {
Contribution(media = it, state = Contribution.STATE_COMPLETED)
}
}
.subscribeOn(ioThreadScheduler)
.subscribe({
callback.onResult(it)
}) { error: Throwable ->
Timber.e(
"Failed to fetch contributions: %s",
error.message
)
}
)
}
fun dispose() {
compositeDisposable.dispose()
}
}