diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt index bf6d42ac27..16d89f8fcd 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt @@ -21,6 +21,8 @@ class ContributionBoundaryCallback @Inject constructor( @param:Named(CommonsApplicationModule.IO_THREAD) private val ioThreadScheduler: Scheduler ) : BoundaryCallback() { 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() + } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index 1cb1116184..86ab4f016c 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -5,7 +5,6 @@ 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.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 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,7 +113,22 @@ 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( @@ -114,6 +137,16 @@ public View onCreateView( 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 @@ private void initRecyclerView() { ((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) { diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java index 26aa3ea994..320ba88a2d 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java @@ -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> 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 void onAttachView(final ContributionsListContract.View view) { * 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 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() { + @NonNull + @Override + public DataSource 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(); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRemoteDataSource.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRemoteDataSource.kt new file mode 100644 index 0000000000..777bb8a21e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRemoteDataSource.kt @@ -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() { + private val compositeDisposable: CompositeDisposable = CompositeDisposable() + var userName: String? = null + + override fun loadInitial( + params: LoadInitialParams, + callback: LoadInitialCallback + ) { + fetchContributions(callback) + } + + override fun loadAfter( + params: LoadParams, + callback: LoadCallback + ) { + fetchContributions(callback) + } + + override fun loadBefore( + params: LoadParams, + callback: LoadCallback + ) { + } + + override fun getKey(item: Contribution): Int { + return item.pageId.hashCode() + } + + + /** + * Fetches contributions using the MediaWiki API + */ + private fun fetchContributions(callback: LoadCallback) { + 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() + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java index 7684d739dd..17e9581ce9 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java @@ -75,6 +75,7 @@ import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity; import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.nearby.Label; +import fr.free.nrw.commons.profile.ProfileActivity; import fr.free.nrw.commons.ui.widget.HtmlTextView; import fr.free.nrw.commons.utils.ViewUtilWrapper; import io.reactivex.Single; @@ -1014,6 +1015,15 @@ public void onSeeMoreClicked(){ } } + @OnClick(R.id.mediaDetailAuthor) + public void onAuthorViewClicked() { + if (media == null || media.getUser() == null) { + return; + } + ProfileActivity.startYourself(getActivity(), media.getUser(), !Objects + .equals(sessionManager.getUserName(), media.getUser())); + } + /** * Enable Progress Bar and Update delete button text. */ diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index ce6585b525..49b776178f 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -32,6 +32,7 @@ import fr.free.nrw.commons.contributions.MainActivity; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; +import fr.free.nrw.commons.profile.ProfileActivity; import fr.free.nrw.commons.theme.BaseActivity; import fr.free.nrw.commons.utils.DownloadUtils; import fr.free.nrw.commons.utils.ImageUtils; @@ -201,6 +202,11 @@ public boolean onOptionsItemSelected(MenuItem item) { // Set avatar setAvatar(m); return true; + case R.id.menu_view_user_page: + if (m != null && m.getUser() != null) { + ProfileActivity.startYourself(getActivity(), m.getUser(), + !Objects.equals(sessionManager.getUserName(), m.getUser())); + } default: return super.onOptionsItemSelected(item); } @@ -258,7 +264,9 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { menu.findItem(R.id.menu_download_current_image).setEnabled(true).setVisible(true); menu.findItem(R.id.menu_bookmark_current_image).setEnabled(true).setVisible(true); menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(true).setVisible(true); - + if (m.getUser() != null) { + menu.findItem(R.id.menu_view_user_page).setEnabled(true).setVisible(true); + } // Initialize bookmark object bookmark = new Bookmark( m.getFilename(), diff --git a/app/src/main/java/fr/free/nrw/commons/navtab/MoreBottomSheetFragment.java b/app/src/main/java/fr/free/nrw/commons/navtab/MoreBottomSheetFragment.java index 2bd22666f4..24e6d25f07 100644 --- a/app/src/main/java/fr/free/nrw/commons/navtab/MoreBottomSheetFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/navtab/MoreBottomSheetFragment.java @@ -74,13 +74,20 @@ public void onAttach(@NonNull final Context context) { * Set the username in navigationHeader. */ private void setUserName() { - AccountManager accountManager = AccountManager.get(getActivity()); - Account[] allAccounts = accountManager.getAccountsByType(BuildConfig.ACCOUNT_TYPE); + moreProfile.setText(getUserName()); + } + + private String getUserName(){ + final AccountManager accountManager = AccountManager.get(getActivity()); + final Account[] allAccounts = accountManager.getAccountsByType(BuildConfig.ACCOUNT_TYPE); if (allAccounts.length != 0) { moreProfile.setText(allAccounts[0].name); + return allAccounts[0].name; } + return ""; } + @OnClick(R.id.more_logout) public void onLogoutClicked() { new AlertDialog.Builder(getActivity()) @@ -136,9 +143,7 @@ public void onSettingsClicked() { @OnClick(R.id.more_profile) public void onProfileClicked() { - final Intent intent = new Intent(getActivity(), ProfileActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); - getActivity().startActivity(intent); + ProfileActivity.startYourself(getActivity(), getUserName(), false); } @OnClick(R.id.more_peer_review) diff --git a/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.java b/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.java index 2e0f6c2610..71703e0d77 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.java @@ -13,6 +13,7 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.widget.Toolbar; import androidx.core.content.FileProvider; import androidx.fragment.app.Fragment; @@ -25,6 +26,7 @@ import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.ViewPagerAdapter; import fr.free.nrw.commons.auth.SessionManager; +import fr.free.nrw.commons.contributions.ContributionsListFragment; import fr.free.nrw.commons.profile.achievements.AchievementsFragment; import fr.free.nrw.commons.profile.leaderboard.LeaderboardFragment; import fr.free.nrw.commons.theme.BaseActivity; @@ -49,9 +51,6 @@ public class ProfileActivity extends BaseActivity { @BindView(R.id.tab_layout) TabLayout tabLayout; - @BindView(R.id.toolbar) - Toolbar toolbar; - @Inject SessionManager sessionManager; @@ -59,15 +58,32 @@ public class ProfileActivity extends BaseActivity { private AchievementsFragment achievementsFragment; private LeaderboardFragment leaderboardFragment; + public static final String KEY_USERNAME ="username"; + public static final String KEY_SHOULD_SHOW_CONTRIBUTIONS ="shouldShowContributions"; + + String userName; + private boolean shouldShowContributions; + + @Override + protected void onRestoreInstanceState(final Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + if (savedInstanceState != null) { + userName = savedInstanceState.getString(KEY_USERNAME); + shouldShowContributions = savedInstanceState.getBoolean(KEY_SHOULD_SHOW_CONTRIBUTIONS); + } + } + + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); ButterKnife.bind(this); - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); setTitle(sessionManager.getUserName()); + userName = getIntent().getStringExtra(KEY_USERNAME); + shouldShowContributions = getIntent().getBooleanExtra(KEY_SHOULD_SHOW_CONTRIBUTIONS, false); + supportFragmentManager = getSupportFragmentManager(); viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(viewPagerAdapter); @@ -87,11 +103,15 @@ public boolean onSupportNavigateUp() { /** * Creates a way to change current activity to AchievementActivity + * * @param context */ - public static void startYourself(Context context) { + public static void startYourself(final Context context, final String userName, + final boolean shouldShowContributions) { Intent intent = new Intent(context, ProfileActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(KEY_USERNAME, userName); + intent.putExtra(KEY_SHOULD_SHOW_CONTRIBUTIONS, shouldShowContributions); context.startActivity(intent); } @@ -102,11 +122,28 @@ private void setTabs() { List fragmentList = new ArrayList<>(); List titleList = new ArrayList<>(); achievementsFragment = new AchievementsFragment(); + Bundle achievementsBundle = new Bundle(); + achievementsBundle.putString(KEY_USERNAME, userName); + achievementsFragment.setArguments(achievementsBundle); fragmentList.add(achievementsFragment); + titleList.add(getResources().getString(R.string.achievements_tab_title).toUpperCase()); leaderboardFragment = new LeaderboardFragment(); + Bundle leaderBoardBundle = new Bundle(); + leaderBoardBundle.putString(KEY_USERNAME, userName); + leaderboardFragment.setArguments(leaderBoardBundle); + fragmentList.add(leaderboardFragment); titleList.add(getResources().getString(R.string.leaderboard_tab_title).toUpperCase()); + + if (shouldShowContributions) { + ContributionsListFragment contributionsListFragment = new ContributionsListFragment(); + Bundle contributionsListBundle = new Bundle(); + contributionsListBundle.putString(KEY_USERNAME, userName); + contributionsListFragment.setArguments(contributionsListBundle); + fragmentList.add(contributionsListFragment); + titleList.add(getString(R.string.contributions_fragment).toUpperCase()); + } viewPagerAdapter.setTabData(fragmentList, titleList); viewPagerAdapter.notifyDataSetChanged(); @@ -191,4 +228,10 @@ void shareScreen(final Bitmap bitmap) { e.printStackTrace(); } } + + @Override + protected void onSaveInstanceState(@NonNull final Bundle outState) { + outState.putString(KEY_USERNAME, userName); + super.onSaveInstanceState(outState); + } } \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java index fd28643985..7f4b10c69a 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java @@ -15,7 +15,9 @@ import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.annotation.Nullable; import androidx.appcompat.view.ContextThemeWrapper; +import androidx.appcompat.widget.AppCompatTextView; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; import butterknife.BindView; @@ -28,6 +30,7 @@ import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; import fr.free.nrw.commons.utils.ViewUtil; +import fr.free.nrw.commons.profile.ProfileActivity; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; @@ -114,6 +117,9 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment { @BindView(R.id.wikidata_edits) TextView wikidataEditsText; + @BindView(R.id.tv_achievements_of_user) + AppCompatTextView tvAchievementsOfUser; + @Inject SessionManager sessionManager; @@ -128,6 +134,16 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment { // menu item for action bar private MenuItem item; + private String userName; + + @Override + public void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + userName = getArguments().getString(ProfileActivity.KEY_USERNAME); + } + } + /** * This method helps in the creation Achievement screen and * dynamically set the size of imageView @@ -157,6 +173,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa // Set the initial value of WikiData edits to 0 wikidataEditsText.setText("0"); + if(sessionManager.getUserName().equals(userName)){ + tvAchievementsOfUser.setVisibility(View.GONE); + }else{ + tvAchievementsOfUser.setVisibility(View.VISIBLE); + tvAchievementsOfUser.setText(getString(R.string.achievements_of_user,userName)); + } setWikidataEditCount(); setAchievements(); return rootView; @@ -182,7 +204,7 @@ private void setAchievements() { try{ compositeDisposable.add(okHttpJsonApiClient - .getAchievements(Objects.requireNonNull(sessionManager.getCurrentAccount()).name) + .getAchievements(Objects.requireNonNull(userName)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( @@ -225,7 +247,6 @@ private void setAchievements() { * in the form of JavaRx Single object */ private void setWikidataEditCount() { - String userName = sessionManager.getUserName(); if (StringUtils.isBlank(userName)) { return; } @@ -274,7 +295,7 @@ private void onError() { private void setUploadCount(Achievements achievements) { if (checkAccount()) { compositeDisposable.add(okHttpJsonApiClient - .getUploadCount(Objects.requireNonNull(sessionManager.getCurrentAccount()).name) + .getUploadCount(Objects.requireNonNull(userName)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( @@ -304,7 +325,7 @@ private void setUploadProgress(int uploadCount){ if (uploadCount==0){ setZeroAchievements(); }else { - + imagesUploadedProgressbar.setVisibility(View.VISIBLE); imagesUploadedProgressbar.setProgress (100*uploadCount/levelInfo.getMaxUploadCount()); imagesUploadedProgressbar.setProgressTextFormatPattern @@ -314,10 +335,14 @@ private void setUploadProgress(int uploadCount){ } private void setZeroAchievements() { - AlertDialog.Builder builder=new AlertDialog.Builder(getActivity()) - .setMessage(getString(R.string.no_achievements_yet)) - .setPositiveButton(getString(R.string.ok), (dialog, which) -> { - }); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) + .setMessage( + !Objects.equals(sessionManager.getUserName(), userName) ? + getString(R.string.no_achievements_yet, userName) : + getString(R.string.you_have_no_achievements_yet) + ) + .setPositiveButton(getString(R.string.ok), (dialog, which) -> { + }); AlertDialog dialog = builder.create(); dialog.show(); imagesUploadedProgressbar.setVisibility(View.INVISIBLE); @@ -336,6 +361,7 @@ private void setZeroAchievements() { * @param notRevertPercentage */ private void setImageRevertPercentage(int notRevertPercentage){ + imageRevertsProgressbar.setVisibility(View.VISIBLE); imageRevertsProgressbar.setProgress(notRevertPercentage); String revertPercentage = Integer.toString(notRevertPercentage); imageRevertsProgressbar.setProgressTextFormatPattern(revertPercentage + "%%"); @@ -348,6 +374,7 @@ private void setImageRevertPercentage(int notRevertPercentage){ * @param achievements */ private void inflateAchievements(Achievements achievements) { + imagesUsedByWikiProgressBar.setVisibility(View.VISIBLE); thanksReceived.setText(String.valueOf(achievements.getThanksReceived())); imagesUsedByWikiProgressBar.setProgress (100 * achievements.getUniqueUsedImages() / levelInfo.getMaxUniqueImages()); @@ -481,5 +508,4 @@ private boolean checkAccount(){ } return true; } - } diff --git a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java index 4c43c9159f..0cd6f41d3e 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java @@ -17,6 +17,7 @@ import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.Toast; +import androidx.annotation.Nullable; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.MergeAdapter; @@ -27,6 +28,7 @@ import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; +import fr.free.nrw.commons.profile.ProfileActivity; import fr.free.nrw.commons.utils.ViewUtil; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; @@ -104,6 +106,16 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment { */ private boolean scrollToRank; + private String userName; + + @Override + public void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + userName = getArguments().getString(ProfileActivity.KEY_USERNAME); + } + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_leaderboard, container, false); @@ -220,7 +232,7 @@ private void setLeaderboard(String duration, String category, int limit, int off if (checkAccount()) { try { compositeDisposable.add(okHttpJsonApiClient - .getLeaderboard(Objects.requireNonNull(sessionManager.getCurrentAccount()).name, + .getLeaderboard(Objects.requireNonNull(userName), duration, category, null, null) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java index acf065330a..4931def7a1 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java @@ -1,7 +1,7 @@ package fr.free.nrw.commons.profile.leaderboard; -import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.USER_LINK_PREFIX; +import android.app.Activity; import android.content.Context; import android.net.Uri; import android.view.LayoutInflater; @@ -14,6 +14,7 @@ import com.facebook.drawee.view.SimpleDraweeView; import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; +import fr.free.nrw.commons.profile.ProfileActivity; /** * This class extends RecyclerView.Adapter and creates the List section of the leaderboard @@ -81,9 +82,13 @@ public void onBindViewHolder(@NonNull LeaderboardListAdapter.ListViewHolder hold count.setText(getItem(position).getCategoryCount().toString()); /* - Open the user profile in a webview when a username is clicked on leaderboard + Now that we have our in app profile-section, lets take the user there */ - holder.itemView.setOnClickListener(view -> Utils.handleWebUrl(holder.getContext(), Uri.parse( - String.format("%s%s", USER_LINK_PREFIX, getItem(position).getUsername())))); + holder.itemView.setOnClickListener(view -> { + if (view.getContext() instanceof ProfileActivity) { + ((Activity) (view.getContext())).finish(); + } + ProfileActivity.startYourself(view.getContext(), getItem(position).getUsername(), true); + }); } } diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml index 64cc0f7a9f..47e24da276 100644 --- a/app/src/main/res/layout/activity_profile.xml +++ b/app/src/main/res/layout/activity_profile.xml @@ -15,8 +15,6 @@ android:layout_height="wrap_content" android:background="?attr/mainBackground"> - - + + @@ -203,6 +212,7 @@ android:layout_marginRight="@dimen/large_gap" android:layout_marginEnd="@dimen/large_gap" android:progress="50" + android:visibility="gone" android:id="@+id/image_reverts_progressbar" app:progress_end_color="#8C8B98" app:progress_start_color="#3A3381" @@ -270,6 +280,7 @@ app:progress_end_color="#8C8B98" app:progress_start_color="#3A3381" app:progress_stroke_width="2.5dp" + android:visibility="gone" app:progress_text_color="@color/secondaryColor" app:progress_text_format_pattern="12/24" app:style="solid_line" /> diff --git a/app/src/main/res/layout/fragment_contributions_list.xml b/app/src/main/res/layout/fragment_contributions_list.xml index 923cc83431..410c24c821 100644 --- a/app/src/main/res/layout/fragment_contributions_list.xml +++ b/app/src/main/res/layout/fragment_contributions_list.xml @@ -1,6 +1,7 @@ - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2acf08b8f7..8419506970 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -527,7 +527,8 @@ Upload your first media by tapping on the add button. Unable to get coordinates. Share image via - You haven\'t made any contributions yet + You haven\'t made any contributions yet + %s has not made any contributions yet Account created! Text copied to clipboard Notification marked as read @@ -656,4 +657,7 @@ Upload your first media by tapping on the add button. LEARN MORE Wiki Loves Monuments Wiki Loves Monuments is an international photo contest for monuments organised by Wikimedia + Contributions of User: %s + Achievements of User: %s + View user page diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt index 30060a5ee1..a6ed43a179 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt @@ -49,7 +49,8 @@ class ContributionBoundaryCallbackTest { MockitoAnnotations.initMocks(this) scheduler = Schedulers.trampoline() contributionBoundaryCallback = - ContributionBoundaryCallback(repository, sessionManager, mediaClient, scheduler); + ContributionBoundaryCallback(repository, sessionManager, mediaClient, scheduler) + contributionBoundaryCallback.userName = "test" } @Test diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsListPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsListPresenterTest.kt index 7e9b723a79..a8cde3ebaa 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsListPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsListPresenterTest.kt @@ -32,6 +32,9 @@ class ContributionsListPresenterTest { @Mock internal lateinit var repository: ContributionsRepository + @Mock + internal lateinit var remoteDataSource: ContributionsRemoteDataSource + @Rule @JvmField var instantTaskExecutorRule = InstantTaskExecutorRule() @@ -49,7 +52,12 @@ class ContributionsListPresenterTest { MockitoAnnotations.initMocks(this) scheduler = Schedulers.trampoline() contributionsListPresenter = - ContributionsListPresenter(contributionBoundaryCallback, repository, scheduler); + ContributionsListPresenter( + contributionBoundaryCallback, + remoteDataSource, + repository, + scheduler + ); } @Test diff --git a/app/src/test/kotlin/fr/free/nrw/commons/profile/ProfileActivityTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/profile/ProfileActivityTest.kt index 2671f69f6d..ee8cafa19f 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/profile/ProfileActivityTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/profile/ProfileActivityTest.kt @@ -80,7 +80,7 @@ class ProfileActivityTest { @Test @Throws(Exception::class) fun testStartYourself() { - ProfileActivity.startYourself(activity) + ProfileActivity.startYourself(activity, "test", false) } @Test diff --git a/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt index bf3e576db0..96d99061c0 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt @@ -11,12 +11,14 @@ import androidx.fragment.app.FragmentTransaction import com.dinuscxj.progressbar.CircleProgressBar import fr.free.nrw.commons.TestAppAdapter import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.profile.ProfileActivity import org.junit.Assert import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.powermock.reflect.Whitebox import org.robolectric.Robolectric @@ -85,6 +87,9 @@ class AchievementsFragmentUnitTests { @Mock private lateinit var progressBar: ProgressBar + @Mock + private lateinit var sessionManager: SessionManager + @Before fun setUp() { MockitoAnnotations.initMocks(this) @@ -131,6 +136,10 @@ class AchievementsFragmentUnitTests { Whitebox.setInternalState(fragment, "progressBar", progressBar) Whitebox.setInternalState(fragment, "imagesRevertLimitText", imagesRevertLimitText) Whitebox.setInternalState(fragment, "item", menuItem) + Whitebox.setInternalState(fragment, "sessionManager", sessionManager) + + Mockito.`when`(sessionManager.userName).thenReturn("Test") + } @Test