Skip to content

Commit 88b21a6

Browse files
Fixes commons-app#3389 - Show User profiles (commons-app#4678)
* Fixes commons-app#3389 - Show User profiles * Don't show dummy achievements data - show data only when loaded
1 parent 7ce80aa commit 88b21a6

20 files changed

+358
-48
lines changed

app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt

+10-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class ContributionBoundaryCallback @Inject constructor(
2121
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioThreadScheduler: Scheduler
2222
) : BoundaryCallback<Contribution>() {
2323
private val compositeDisposable: CompositeDisposable = CompositeDisposable()
24+
lateinit var userName: String
25+
2426

2527
/**
2628
* 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(
5557
fun fetchContributions() {
5658
if (sessionManager.userName != null) {
5759
compositeDisposable.add(
58-
mediaClient.getMediaListForUser(sessionManager.userName!!)
60+
mediaClient.getMediaListForUser(userName!!)
5961
.map { mediaList ->
6062
mediaList.map {
6163
Contribution(media = it, state = Contribution.STATE_COMPLETED)
@@ -88,4 +90,11 @@ class ContributionBoundaryCallback @Inject constructor(
8890
}
8991
)
9092
}
93+
94+
/**
95+
* Clean up
96+
*/
97+
fun dispose() {
98+
compositeDisposable.dispose()
99+
}
91100
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java

+40-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import static fr.free.nrw.commons.di.NetworkingModule.NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE;
66

77
import android.content.Context;
8-
import android.content.Intent;
98
import android.content.res.Configuration;
109
import android.net.Uri;
1110
import android.os.Bundle;
@@ -21,6 +20,7 @@
2120
import android.widget.TextView;
2221
import androidx.annotation.NonNull;
2322
import androidx.annotation.Nullable;
23+
import androidx.appcompat.widget.AppCompatTextView;
2424
import androidx.fragment.app.FragmentManager;
2525
import androidx.recyclerview.widget.GridLayoutManager;
2626
import androidx.recyclerview.widget.RecyclerView;
@@ -35,17 +35,20 @@
3535
import fr.free.nrw.commons.Media;
3636
import fr.free.nrw.commons.R;
3737
import fr.free.nrw.commons.Utils;
38-
import fr.free.nrw.commons.customselector.ui.selector.CustomSelectorActivity;
38+
import fr.free.nrw.commons.auth.SessionManager;
3939
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
4040
import fr.free.nrw.commons.utils.DialogUtil;
4141
import fr.free.nrw.commons.media.MediaClient;
4242
import fr.free.nrw.commons.utils.SystemThemeUtils;
4343
import fr.free.nrw.commons.utils.ViewUtil;
4444
import java.util.Locale;
45+
import java.util.Objects;
4546
import javax.inject.Inject;
4647
import javax.inject.Named;
48+
import org.apache.commons.lang3.StringUtils;
4749
import org.wikipedia.dataclient.WikiSite;
48-
import timber.log.Timber;
50+
import fr.free.nrw.commons.profile.ProfileActivity;
51+
4952

5053
/**
5154
* Created by root on 01.06.2018.
@@ -56,7 +59,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
5659
WikipediaInstructionsDialogFragment.Callback {
5760

5861
private static final String RV_STATE = "rv_scroll_state";
59-
62+
6063
@BindView(R.id.contributionsList)
6164
RecyclerView rvContributionsList;
6265
@BindView(R.id.loadingContributionsProgressBar)
@@ -76,6 +79,8 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
7679

7780
@Inject
7881
SystemThemeUtils systemThemeUtils;
82+
@BindView(R.id.tv_contributions_of_user)
83+
AppCompatTextView tvContributionsOfUser;
7984

8085
@Inject
8186
ContributionController controller;
@@ -89,6 +94,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
8994
@Inject
9095
ContributionsListPresenter contributionsListPresenter;
9196

97+
@Inject
98+
SessionManager sessionManager;
99+
92100
private Animation fab_close;
93101
private Animation fab_open;
94102
private Animation rotate_forward;
@@ -105,7 +113,22 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
105113
private final int SPAN_COUNT_PORTRAIT = 1;
106114

107115
private int contributionsSize;
116+
String userName;
117+
118+
119+
@Override
120+
public void onCreate(@Nullable @org.jetbrains.annotations.Nullable final Bundle savedInstanceState) {
121+
super.onCreate(savedInstanceState);
122+
//Now that we are allowing this fragment to be started for
123+
// any userName- we expect it to be passed as an argument
124+
if (getArguments() != null) {
125+
userName = getArguments().getString(ProfileActivity.KEY_USERNAME);
126+
}
108127

128+
if (StringUtils.isEmpty(userName)) {
129+
userName = sessionManager.getUserName();
130+
}
131+
}
109132

110133
@Override
111134
public View onCreateView(
@@ -114,6 +137,16 @@ public View onCreateView(
114137
final View view = inflater.inflate(R.layout.fragment_contributions_list, container, false);
115138
ButterKnife.bind(this, view);
116139
contributionsListPresenter.onAttachView(this);
140+
141+
if (Objects.equals(sessionManager.getUserName(), userName)) {
142+
tvContributionsOfUser.setVisibility(GONE);
143+
fab_layout.setVisibility(VISIBLE);
144+
} else {
145+
tvContributionsOfUser.setVisibility(VISIBLE);
146+
tvContributionsOfUser.setText(getString(R.string.contributions_of_user, userName));
147+
fab_layout.setVisibility(GONE);
148+
}
149+
117150
initAdapter();
118151
return view;
119152
}
@@ -155,8 +188,9 @@ private void initRecyclerView() {
155188
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
156189
}
157190

158-
contributionsListPresenter.setup();
159-
contributionsListPresenter.contributionList.observe(this.getViewLifecycleOwner(), list -> {
191+
contributionsListPresenter.setup(userName,
192+
Objects.equals(sessionManager.getUserName(), userName));
193+
contributionsListPresenter.contributionList.observe(getViewLifecycleOwner(), list -> {
160194
contributionsSize = list.size();
161195
adapter.submitList(list);
162196
if (callback != null) {

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java

+35-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package fr.free.nrw.commons.contributions;
22

3+
import androidx.annotation.NonNull;
34
import androidx.lifecycle.LiveData;
5+
import androidx.paging.DataSource;
6+
import androidx.paging.DataSource.Factory;
47
import androidx.paging.LivePagedListBuilder;
58
import androidx.paging.PagedList;
69
import fr.free.nrw.commons.contributions.ContributionsListContract.UserActionListener;
@@ -20,17 +23,20 @@ public class ContributionsListPresenter implements UserActionListener {
2023
private final Scheduler ioThreadScheduler;
2124

2225
private final CompositeDisposable compositeDisposable;
26+
private final ContributionsRemoteDataSource contributionsRemoteDataSource;
2327

2428
LiveData<PagedList<Contribution>> contributionList;
2529

2630
@Inject
2731
ContributionsListPresenter(
2832
final ContributionBoundaryCallback contributionBoundaryCallback,
33+
final ContributionsRemoteDataSource contributionsRemoteDataSource,
2934
final ContributionsRepository repository,
3035
@Named(CommonsApplicationModule.IO_THREAD) final Scheduler ioThreadScheduler) {
3136
this.contributionBoundaryCallback = contributionBoundaryCallback;
3237
this.repository = repository;
3338
this.ioThreadScheduler = ioThreadScheduler;
39+
this.contributionsRemoteDataSource=contributionsRemoteDataSource;
3440
compositeDisposable = new CompositeDisposable();
3541
}
3642

@@ -43,19 +49,44 @@ public void onAttachView(final ContributionsListContract.View view) {
4349
* the live data object. This method can be tweaked to update the lazy loading behavior of the
4450
* contributions list
4551
*/
46-
void setup() {
52+
void setup(String userName, boolean isSelf) {
4753
final PagedList.Config pagedListConfig =
4854
(new PagedList.Config.Builder())
4955
.setPrefetchDistance(50)
5056
.setPageSize(10).build();
51-
contributionList = (new LivePagedListBuilder(repository.fetchContributions(),
52-
pagedListConfig)
53-
.setBoundaryCallback(contributionBoundaryCallback)).build();
57+
Factory<Integer, Contribution> factory;
58+
boolean shouldSetBoundaryCallback;
59+
if (!isSelf) {
60+
//We don't want to persist contributions for other user's, therefore
61+
// creating a new DataSource for them
62+
contributionsRemoteDataSource.setUserName(userName);
63+
factory = new Factory<Integer, Contribution>() {
64+
@NonNull
65+
@Override
66+
public DataSource<Integer, Contribution> create() {
67+
return contributionsRemoteDataSource;
68+
}
69+
};
70+
shouldSetBoundaryCallback = false;
71+
} else {
72+
contributionBoundaryCallback.setUserName(userName);
73+
shouldSetBoundaryCallback = true;
74+
factory = repository.fetchContributions();
75+
}
76+
77+
LivePagedListBuilder livePagedListBuilder = new LivePagedListBuilder(factory, pagedListConfig);
78+
if (shouldSetBoundaryCallback) {
79+
livePagedListBuilder.setBoundaryCallback(contributionBoundaryCallback);
80+
}
81+
82+
contributionList = livePagedListBuilder.build();
5483
}
5584

5685
@Override
5786
public void onDetachView() {
5887
compositeDisposable.clear();
88+
contributionsRemoteDataSource.dispose();
89+
contributionBoundaryCallback.dispose();
5990
}
6091

6192
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package fr.free.nrw.commons.contributions
2+
3+
import androidx.paging.ItemKeyedDataSource
4+
import fr.free.nrw.commons.di.CommonsApplicationModule
5+
import fr.free.nrw.commons.media.MediaClient
6+
import io.reactivex.Scheduler
7+
import io.reactivex.disposables.CompositeDisposable
8+
import timber.log.Timber
9+
import javax.inject.Inject
10+
import javax.inject.Named
11+
12+
/**
13+
* Data-Source which acts as mediator for contributions-data from the API
14+
*/
15+
class ContributionsRemoteDataSource @Inject constructor(
16+
private val mediaClient: MediaClient,
17+
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioThreadScheduler: Scheduler
18+
) : ItemKeyedDataSource<Int, Contribution>() {
19+
private val compositeDisposable: CompositeDisposable = CompositeDisposable()
20+
var userName: String? = null
21+
22+
override fun loadInitial(
23+
params: LoadInitialParams<Int>,
24+
callback: LoadInitialCallback<Contribution>
25+
) {
26+
fetchContributions(callback)
27+
}
28+
29+
override fun loadAfter(
30+
params: LoadParams<Int>,
31+
callback: LoadCallback<Contribution>
32+
) {
33+
fetchContributions(callback)
34+
}
35+
36+
override fun loadBefore(
37+
params: LoadParams<Int>,
38+
callback: LoadCallback<Contribution>
39+
) {
40+
}
41+
42+
override fun getKey(item: Contribution): Int {
43+
return item.pageId.hashCode()
44+
}
45+
46+
47+
/**
48+
* Fetches contributions using the MediaWiki API
49+
*/
50+
private fun fetchContributions(callback: LoadCallback<Contribution>) {
51+
compositeDisposable.add(
52+
mediaClient.getMediaListForUser(userName!!)
53+
.map { mediaList ->
54+
mediaList.map {
55+
Contribution(media = it, state = Contribution.STATE_COMPLETED)
56+
}
57+
}
58+
.subscribeOn(ioThreadScheduler)
59+
.subscribe({
60+
callback.onResult(it)
61+
}) { error: Throwable ->
62+
Timber.e(
63+
"Failed to fetch contributions: %s",
64+
error.message
65+
)
66+
}
67+
)
68+
}
69+
70+
fun dispose() {
71+
compositeDisposable.dispose()
72+
}
73+
}

app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java

+10
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
7676
import fr.free.nrw.commons.kvstore.JsonKvStore;
7777
import fr.free.nrw.commons.nearby.Label;
78+
import fr.free.nrw.commons.profile.ProfileActivity;
7879
import fr.free.nrw.commons.ui.widget.HtmlTextView;
7980
import fr.free.nrw.commons.utils.ViewUtilWrapper;
8081
import io.reactivex.Single;
@@ -1014,6 +1015,15 @@ public void onSeeMoreClicked(){
10141015
}
10151016
}
10161017

1018+
@OnClick(R.id.mediaDetailAuthor)
1019+
public void onAuthorViewClicked() {
1020+
if (media == null || media.getUser() == null) {
1021+
return;
1022+
}
1023+
ProfileActivity.startYourself(getActivity(), media.getUser(), !Objects
1024+
.equals(sessionManager.getUserName(), media.getUser()));
1025+
}
1026+
10171027
/**
10181028
* Enable Progress Bar and Update delete button text.
10191029
*/

app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import fr.free.nrw.commons.contributions.MainActivity;
3333
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
3434
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
35+
import fr.free.nrw.commons.profile.ProfileActivity;
3536
import fr.free.nrw.commons.theme.BaseActivity;
3637
import fr.free.nrw.commons.utils.DownloadUtils;
3738
import fr.free.nrw.commons.utils.ImageUtils;
@@ -201,6 +202,11 @@ public boolean onOptionsItemSelected(MenuItem item) {
201202
// Set avatar
202203
setAvatar(m);
203204
return true;
205+
case R.id.menu_view_user_page:
206+
if (m != null && m.getUser() != null) {
207+
ProfileActivity.startYourself(getActivity(), m.getUser(),
208+
!Objects.equals(sessionManager.getUserName(), m.getUser()));
209+
}
204210
default:
205211
return super.onOptionsItemSelected(item);
206212
}
@@ -258,7 +264,9 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
258264
menu.findItem(R.id.menu_download_current_image).setEnabled(true).setVisible(true);
259265
menu.findItem(R.id.menu_bookmark_current_image).setEnabled(true).setVisible(true);
260266
menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(true).setVisible(true);
261-
267+
if (m.getUser() != null) {
268+
menu.findItem(R.id.menu_view_user_page).setEnabled(true).setVisible(true);
269+
}
262270
// Initialize bookmark object
263271
bookmark = new Bookmark(
264272
m.getFilename(),

app/src/main/java/fr/free/nrw/commons/navtab/MoreBottomSheetFragment.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,20 @@ public void onAttach(@NonNull final Context context) {
7474
* Set the username in navigationHeader.
7575
*/
7676
private void setUserName() {
77-
AccountManager accountManager = AccountManager.get(getActivity());
78-
Account[] allAccounts = accountManager.getAccountsByType(BuildConfig.ACCOUNT_TYPE);
77+
moreProfile.setText(getUserName());
78+
}
79+
80+
private String getUserName(){
81+
final AccountManager accountManager = AccountManager.get(getActivity());
82+
final Account[] allAccounts = accountManager.getAccountsByType(BuildConfig.ACCOUNT_TYPE);
7983
if (allAccounts.length != 0) {
8084
moreProfile.setText(allAccounts[0].name);
85+
return allAccounts[0].name;
8186
}
87+
return "";
8288
}
8389

90+
8491
@OnClick(R.id.more_logout)
8592
public void onLogoutClicked() {
8693
new AlertDialog.Builder(getActivity())
@@ -136,9 +143,7 @@ public void onSettingsClicked() {
136143

137144
@OnClick(R.id.more_profile)
138145
public void onProfileClicked() {
139-
final Intent intent = new Intent(getActivity(), ProfileActivity.class);
140-
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
141-
getActivity().startActivity(intent);
146+
ProfileActivity.startYourself(getActivity(), getUserName(), false);
142147
}
143148

144149
@OnClick(R.id.more_peer_review)

0 commit comments

Comments
 (0)