Skip to content

Feat: Make it smoother to switch between nearby and explore maps #6164

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
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ captures/*

# Test and other output
app/jacoco.exec
app/CommonsContributions
app/CommonsContributions
app/.*
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ private void setUpLoggedOutPager() {
private boolean loadFragment(Fragment fragment, boolean showBottom) {
//showBottom so that we do not show the bottom tray again when constructing
//from the saved instance state.

freeUpFragments();

if (fragment instanceof ContributionsFragment) {
if (activeFragment == ActiveFragment.CONTRIBUTIONS) {
// scroll to top if already on the Contributions tab
Expand Down Expand Up @@ -256,6 +259,31 @@ private boolean loadFragment(Fragment fragment, boolean showBottom) {
return false;
}

/**
* loadFragment() overload that supports passing extras to fragments
**/
private boolean loadFragment(Fragment fragment, boolean showBottom, Bundle args) {
if (fragment != null && args != null) {
fragment.setArguments(args);
}

return loadFragment(fragment, showBottom);
}

/**
* Old implementation of loadFragment() was causing memory leaks, due to MainActivity holding
* references to cleared fragments. This function frees up all fragment references.
* <p>
* Called in loadFragment() before doing the actual loading.
**/
public void freeUpFragments() {
// free all fragments except contributionsFragment because several tests depend on it.
// hence, contributionsFragment is probably still a leak
nearbyParentFragment = null;
exploreFragment = null;
bookmarkFragment = null;
}

public void hideTabs() {
binding.fragmentMainNavTabLayout.setVisibility(View.GONE);
}
Expand Down Expand Up @@ -432,6 +460,42 @@ public void onReady() {
});
}

/**
* Launch the Explore fragment from Nearby fragment. This method is called when a user clicks
* the 'Show in Explore' option in the 3-dots menu in Nearby.
*
* @param zoom current zoom of Nearby map
* @param latitude current latitude of Nearby map
* @param longitude current longitude of Nearby map
**/
public void loadExploreMapFromNearby(double zoom, double latitude, double longitude) {
Bundle bundle = new Bundle();
bundle.putDouble("prev_zoom", zoom);
bundle.putDouble("prev_latitude", latitude);
bundle.putDouble("prev_longitude", longitude);

loadFragment(ExploreFragment.newInstance(), false, bundle);
setSelectedItemId(NavTab.EXPLORE.code());
}

/**
* Launch the Nearby fragment from Explore fragment. This method is called when a user clicks
* the 'Show in Nearby' option in the 3-dots menu in Explore.
*
* @param zoom current zoom of Explore map
* @param latitude current latitude of Explore map
* @param longitude current longitude of Explore map
**/
public void loadNearbyMapFromExplore(double zoom, double latitude, double longitude) {
Bundle bundle = new Bundle();
bundle.putDouble("prev_zoom", zoom);
bundle.putDouble("prev_latitude", latitude);
bundle.putDouble("prev_longitude", longitude);

loadFragment(NearbyParentFragment.newInstance(), false, bundle);
setSelectedItemId(NavTab.NEARBY.code());
}

@Override
protected void onResume() {
super.onResume();
Expand Down
85 changes: 80 additions & 5 deletions app/src/main/java/fr/free/nrw/commons/explore/ExploreFragment.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package fr.free.nrw.commons.explore;

import static androidx.viewpager.widget.ViewPager.SCROLL_STATE_IDLE;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
Expand Down Expand Up @@ -42,9 +44,13 @@ public class ExploreFragment extends CommonsDaggerSupportFragment {
@Named("default_preferences")
public JsonKvStore applicationKvStore;

public void setScroll(boolean canScroll){
if (binding != null)
{
// Nearby map state (for if we came from Nearby fragment)
private double prevZoom;
private double prevLatitude;
private double prevLongitude;

public void setScroll(boolean canScroll) {
if (binding != null) {
binding.viewPager.setCanScroll(canScroll);
}
}
Expand All @@ -60,6 +66,7 @@ public static ExploreFragment newInstance() {
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadNearbyMapData();
binding = FragmentExploreBinding.inflate(inflater, container, false);

viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
Expand Down Expand Up @@ -89,6 +96,11 @@ public void onPageScrollStateChanged(int state) {
});
setTabs();
setHasOptionsMenu(true);

// if we came from 'Show in Explore' in Nearby, jump to Map tab
if (isCameFromNearbyMap()) {
binding.viewPager.setCurrentItem(2);
}
return binding.getRoot();
}

Expand All @@ -108,6 +120,13 @@ public void setTabs() {
Bundle mapArguments = new Bundle();
mapArguments.putString("categoryName", EXPLORE_MAP);

// if we came from 'Show in Explore' in Nearby, pass on zoom and center to Explore map root
if (isCameFromNearbyMap()) {
mapArguments.putDouble("prev_zoom", prevZoom);
mapArguments.putDouble("prev_latitude", prevLatitude);
mapArguments.putDouble("prev_longitude", prevLongitude);
}

featuredRootFragment = new ExploreListRootFragment(featuredArguments);
mobileRootFragment = new ExploreListRootFragment(mobileArguments);
mapRootFragment = new ExploreMapRootFragment(mapArguments);
Expand All @@ -120,13 +139,35 @@ public void setTabs() {
fragmentList.add(mapRootFragment);
titleList.add(getString(R.string.explore_tab_title_map).toUpperCase(Locale.ROOT));

((MainActivity)getActivity()).showTabs();
((MainActivity) getActivity()).showTabs();
((BaseActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(false);

viewPagerAdapter.setTabData(fragmentList, titleList);
viewPagerAdapter.notifyDataSetChanged();
}

/**
* Fetch Nearby map camera data from fragment arguments if any.
*/
public void loadNearbyMapData() {
// get fragment arguments
if (getArguments() != null) {
prevZoom = getArguments().getDouble("prev_zoom");
prevLatitude = getArguments().getDouble("prev_latitude");
prevLongitude = getArguments().getDouble("prev_longitude");
}
}

/**
* Checks if fragment arguments contain data from Nearby map. if present, then the user
* navigated from Nearby using 'Show in Explore'.
*
* @return true if user navigated from Nearby map
**/
public boolean isCameFromNearbyMap() {
return prevZoom != 0.0 || prevLatitude != 0.0 || prevLongitude != 0.0;
}

public boolean onBackPressed() {
if (binding.tabLayout.getSelectedTabPosition() == 0) {
if (featuredRootFragment.backPressed()) {
Expand Down Expand Up @@ -155,7 +196,38 @@ public boolean onBackPressed() {
*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_search, menu);
// if logged in 'Show in Nearby' menu item is visible
if (applicationKvStore.getBoolean("login_skipped") == false) {
inflater.inflate(R.menu.explore_fragment_menu, menu);

MenuItem others = menu.findItem(R.id.list_item_show_in_nearby);

if (binding.viewPager.getCurrentItem() == 2) {
others.setVisible(true);
}

// if on Map tab, show all menu options, else only show search
binding.viewPager.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}

@Override
public void onPageSelected(int position) {
others.setVisible((position == 2));
}

@Override
public void onPageScrollStateChanged(int state) {
if (state == SCROLL_STATE_IDLE && binding.viewPager.getCurrentItem() == 2) {
onPageSelected(2);
}
}
});
} else {
inflater.inflate(R.menu.menu_search, menu);
}
super.onCreateOptionsMenu(menu, inflater);
}

Expand All @@ -171,6 +243,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_search:
ActivityUtils.startActivityWithFlags(getActivity(), SearchActivity.class);
return true;
case R.id.list_item_show_in_nearby:
mapRootFragment.loadNearbyMapFromExplore();
return true;
default:
return super.onOptionsItemSelected(item);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,22 @@ public static ExploreMapRootFragment newInstance() {
}

public ExploreMapRootFragment(Bundle bundle) {
// get fragment arguments
String title = bundle.getString("categoryName");
double zoom = bundle.getDouble("prev_zoom");
double latitude = bundle.getDouble("prev_latitude");
double longitude = bundle.getDouble("prev_longitude");

mapFragment = new ExploreMapFragment();
Bundle featuredArguments = new Bundle();
featuredArguments.putString("categoryName", title);

// if we came from 'Show in Explore' in Nearby, pass on zoom and center
if (zoom != 0.0 || latitude != 0.0 || longitude != 0.0) {
featuredArguments.putDouble("prev_zoom", zoom);
featuredArguments.putDouble("prev_latitude", latitude);
featuredArguments.putDouble("prev_longitude", longitude);
}
mapFragment.setArguments(featuredArguments);
}

Expand Down Expand Up @@ -198,7 +210,8 @@ public boolean backPressed() {
((MainActivity) getActivity()).showTabs();
return true;

} if (mapFragment != null && mapFragment.isVisible()) {
}
if (mapFragment != null && mapFragment.isVisible()) {
if (mapFragment.backButtonClicked()) {
// Explore map fragment handled the event no further action required.
return true;
Expand All @@ -213,6 +226,10 @@ public boolean backPressed() {
return false;
}

public void loadNearbyMapFromExplore() {
mapFragment.loadNearbyMapFromExplore();
}

@Override
public void onDestroy() {
super.onDestroy();
Expand Down
Loading