mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Search this area (#2051)
* Recognize user is moving on the map and show a button * Use variable from strings xml instead of hardcoded string * Change search this area button location in xml file * Add location util file to convert mapbox LatLng to commons Latlng and viceversa * Populate places around searched area * Update narby map according to new points came from searched area * Add searchThisAreaMode boolean to stop nearby map updated when we try to search nearby areas. * Lock auto nearby operations during serch this area mode, with a more modular method and decrease code repetition * Add an if clausse to prevent multiple refresh view calls, while map is moving * Disable map gestures during search this area operation, re-eable them on operation is done * Add progress bar during search this area operation * Make sure you locked the map during search nearby map process * Implement recenter map view button * Fix logic problem and make sure you refreshed the view on coming back to previous position * Use custom refresh method instead * Use latest updated location from location manager isntead * Update ListFragment accordingly too * Do not update camera target according to bottom sheet status or do not follow users location with camera, if search this area mode is on * Add javadocs, sorry forgotten previously * Remove unused method * Threat both or search this area and regular search in same way * Make sure distances are correct * Seperate cutom location updates and current location updates from each other to continue other operations * Remove all logs, and make sure search this are button is not visible for no reason while around of current location is already loaded * Notify load attractions from location method about search status, current location of custom location * Make sure we calculate searched area and display search this area button when we are out of 3/4 of total searched area
This commit is contained in:
parent
b907a0a8f1
commit
677e0099af
9 changed files with 283 additions and 32 deletions
|
|
@ -622,7 +622,7 @@ public class ContributionsFragment
|
||||||
curLatLng = locationManager.getLastLocation();
|
curLatLng = locationManager.getLastLocation();
|
||||||
|
|
||||||
placesDisposable = Observable.fromCallable(() -> nearbyController
|
placesDisposable = Observable.fromCallable(() -> nearbyController
|
||||||
.loadAttractionsFromLocation(curLatLng, true)) // thanks to boolean, it will only return closest result
|
.loadAttractionsFromLocation(curLatLng, curLatLng, true, false)) // thanks to boolean, it will only return closest result
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(this::updateNearbyNotification,
|
.subscribe(this::updateNearbyNotification,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.support.graphics.drawable.VectorDrawableCompat;
|
import android.support.graphics.drawable.VectorDrawableCompat;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.mapbox.mapboxsdk.annotations.IconFactory;
|
import com.mapbox.mapboxsdk.annotations.IconFactory;
|
||||||
|
|
||||||
|
|
@ -31,6 +32,8 @@ public class NearbyController {
|
||||||
private static final int MAX_RESULTS = 1000;
|
private static final int MAX_RESULTS = 1000;
|
||||||
private final NearbyPlaces nearbyPlaces;
|
private final NearbyPlaces nearbyPlaces;
|
||||||
private final SharedPreferences prefs;
|
private final SharedPreferences prefs;
|
||||||
|
public static double searchedRadius = 10.0; //in kilometers
|
||||||
|
public static LatLng currentLocation;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public NearbyController(NearbyPlaces nearbyPlaces,
|
public NearbyController(NearbyPlaces nearbyPlaces,
|
||||||
|
|
@ -44,18 +47,21 @@ public class NearbyController {
|
||||||
* Prepares Place list to make their distance information update later.
|
* Prepares Place list to make their distance information update later.
|
||||||
*
|
*
|
||||||
* @param curLatLng current location for user
|
* @param curLatLng current location for user
|
||||||
|
* @param latLangToSearchAround the location user wants to search around
|
||||||
|
* @param returnClosestResult if this search is done to find closest result or all results
|
||||||
* @return NearbyPlacesInfo a variable holds Place list without distance information
|
* @return NearbyPlacesInfo a variable holds Place list without distance information
|
||||||
* and boundary coordinates of current Place List
|
* and boundary coordinates of current Place List
|
||||||
*/
|
*/
|
||||||
public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng, boolean returnClosestResult) throws IOException {
|
public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng, LatLng latLangToSearchAround, boolean returnClosestResult, boolean checkingAroundCurrentLocation) throws IOException {
|
||||||
Timber.d("Loading attractions near %s", curLatLng);
|
|
||||||
|
Timber.d("Loading attractions near %s", latLangToSearchAround);
|
||||||
NearbyPlacesInfo nearbyPlacesInfo = new NearbyPlacesInfo();
|
NearbyPlacesInfo nearbyPlacesInfo = new NearbyPlacesInfo();
|
||||||
|
|
||||||
if (curLatLng == null) {
|
if (latLangToSearchAround == null) {
|
||||||
Timber.d("Loading attractions neari, but curLatLng is null");
|
Timber.d("Loading attractions neari, but curLatLng is null");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<Place> places = nearbyPlaces.getFromWikidataQuery(curLatLng, Locale.getDefault().getLanguage(), returnClosestResult);
|
List<Place> places = nearbyPlaces.getFromWikidataQuery(latLangToSearchAround, Locale.getDefault().getLanguage(), returnClosestResult);
|
||||||
|
|
||||||
if (null != places && places.size() > 0) {
|
if (null != places && places.size() > 0) {
|
||||||
LatLng[] boundaryCoordinates = {places.get(0).location, // south
|
LatLng[] boundaryCoordinates = {places.get(0).location, // south
|
||||||
|
|
@ -93,6 +99,11 @@ public class NearbyController {
|
||||||
}
|
}
|
||||||
nearbyPlacesInfo.placeList = places;
|
nearbyPlacesInfo.placeList = places;
|
||||||
nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates;
|
nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates;
|
||||||
|
if (!returnClosestResult && checkingAroundCurrentLocation) {
|
||||||
|
// Do not update searched radius, if controller is used for nearby card notification
|
||||||
|
searchedRadius = nearbyPlaces.radius;
|
||||||
|
currentLocation = curLatLng;
|
||||||
|
}
|
||||||
return nearbyPlacesInfo;
|
return nearbyPlacesInfo;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import android.support.design.widget.BottomSheetBehavior;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -64,8 +65,6 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
LinearLayout bottomSheetDetails;
|
LinearLayout bottomSheetDetails;
|
||||||
@BindView(R.id.transparentView)
|
@BindView(R.id.transparentView)
|
||||||
View transparentView;
|
View transparentView;
|
||||||
@BindView(R.id.fab_recenter)
|
|
||||||
View fabRecenter;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
LocationServiceManager locationManager;
|
LocationServiceManager locationManager;
|
||||||
|
|
@ -87,16 +86,19 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
|
|
||||||
private LatLng curLatLng;
|
private LatLng curLatLng;
|
||||||
private Disposable placesDisposable;
|
private Disposable placesDisposable;
|
||||||
|
private Disposable placesDisposableCustom;
|
||||||
private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed
|
private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed
|
||||||
public View view;
|
public View view;
|
||||||
private Snackbar snackbar;
|
private Snackbar snackbar;
|
||||||
|
|
||||||
private LatLng lastKnownLocation;
|
private LatLng lastKnownLocation;
|
||||||
|
private LatLng customLatLng;
|
||||||
|
|
||||||
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
|
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
|
||||||
private BroadcastReceiver broadcastReceiver;
|
private BroadcastReceiver broadcastReceiver;
|
||||||
|
|
||||||
private boolean onOrientationChanged = false;
|
private boolean onOrientationChanged = false;
|
||||||
|
private boolean populateForCurrentLocation = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
|
@ -216,24 +218,27 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChangedSignificantly(LatLng latLng) {
|
public void onLocationChangedSignificantly(LatLng latLng) {
|
||||||
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
|
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChangedSlightly(LatLng latLng) {
|
public void onLocationChangedSlightly(LatLng latLng) {
|
||||||
refreshView(LOCATION_SLIGHTLY_CHANGED);
|
refreshView(LOCATION_SLIGHTLY_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChangedMedium(LatLng latLng) {
|
public void onLocationChangedMedium(LatLng latLng) {
|
||||||
// For nearby map actions, there are no differences between 500 meter location change (aka medium change) and slight change
|
// For nearby map actions, there are no differences between 500 meter location change (aka medium change) and slight change
|
||||||
refreshView(LOCATION_SLIGHTLY_CHANGED);
|
refreshView(LOCATION_SLIGHTLY_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWikidataEditSuccessful() {
|
public void onWikidataEditSuccessful() {
|
||||||
refreshView(MAP_UPDATED);
|
// Do not refresh nearby map if we are checking other areas with search this area button
|
||||||
|
if (!nearbyMapFragment.searchThisAreaModeOn) {
|
||||||
|
refreshView(MAP_UPDATED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -241,7 +246,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
*
|
*
|
||||||
* @param locationChangeType defines if location shanged significantly or slightly
|
* @param locationChangeType defines if location shanged significantly or slightly
|
||||||
*/
|
*/
|
||||||
private void refreshView(LocationServiceManager.LocationChangeType locationChangeType) {
|
public void refreshView(LocationServiceManager.LocationChangeType locationChangeType) {
|
||||||
Timber.d("Refreshing nearby places");
|
Timber.d("Refreshing nearby places");
|
||||||
if (lockNearbyView) {
|
if (lockNearbyView) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -257,9 +262,11 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
|
|
||||||
if (curLatLng != null && curLatLng.equals(lastLocation)
|
if (curLatLng != null && curLatLng.equals(lastLocation)
|
||||||
&& !locationChangeType.equals(MAP_UPDATED)) { //refresh view only if location has changed
|
&& !locationChangeType.equals(MAP_UPDATED)) { //refresh view only if location has changed
|
||||||
|
// Two exceptional cases to refresh nearby map manually.
|
||||||
if (!onOrientationChanged) {
|
if (!onOrientationChanged) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
curLatLng = lastLocation;
|
curLatLng = lastLocation;
|
||||||
|
|
||||||
|
|
@ -292,7 +299,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
bundle.putString("CurLatLng", gsonCurLatLng);
|
bundle.putString("CurLatLng", gsonCurLatLng);
|
||||||
|
|
||||||
placesDisposable = Observable.fromCallable(() -> nearbyController
|
placesDisposable = Observable.fromCallable(() -> nearbyController
|
||||||
.loadAttractionsFromLocation(curLatLng, false))
|
.loadAttractionsFromLocation(curLatLng, curLatLng, false, true))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(this::populatePlaces,
|
.subscribe(this::populatePlaces,
|
||||||
|
|
@ -301,6 +308,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
showErrorMessage(getString(R.string.error_fetching_nearby_places));
|
showErrorMessage(getString(R.string.error_fetching_nearby_places));
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (locationChangeType
|
} else if (locationChangeType
|
||||||
.equals(LOCATION_SLIGHTLY_CHANGED)) {
|
.equals(LOCATION_SLIGHTLY_CHANGED)) {
|
||||||
Gson gson = new GsonBuilder()
|
Gson gson = new GsonBuilder()
|
||||||
|
|
@ -308,7 +316,62 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
.create();
|
.create();
|
||||||
String gsonCurLatLng = gson.toJson(curLatLng);
|
String gsonCurLatLng = gson.toJson(curLatLng);
|
||||||
bundle.putString("CurLatLng", gsonCurLatLng);
|
bundle.putString("CurLatLng", gsonCurLatLng);
|
||||||
updateMapFragment(true);
|
updateMapFragment(false,true, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nearbyMapFragment != null) {
|
||||||
|
nearbyMapFragment.searchThisAreaButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should be used with "Search this are button". This method will search nearby
|
||||||
|
* points around any custom location (target location when user clicked on search this area)
|
||||||
|
* button. It populates places for custom location.
|
||||||
|
* @param customLatLng Custom area which we will search around
|
||||||
|
*/
|
||||||
|
public void refreshViewForCustomLocation(LatLng customLatLng, boolean refreshForCurrentLocation) {
|
||||||
|
|
||||||
|
if (customLatLng == null) {
|
||||||
|
// If null, return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
populateForCurrentLocation = refreshForCurrentLocation;
|
||||||
|
this.customLatLng = customLatLng;
|
||||||
|
placesDisposableCustom = Observable.fromCallable(() -> nearbyController
|
||||||
|
.loadAttractionsFromLocation(curLatLng, customLatLng, false, populateForCurrentLocation))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(this::populatePlacesFromCustomLocation,
|
||||||
|
throwable -> {
|
||||||
|
Timber.d(throwable);
|
||||||
|
showErrorMessage(getString(R.string.error_fetching_nearby_places));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (nearbyMapFragment != null) {
|
||||||
|
nearbyMapFragment.searchThisAreaButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates places for custom location, should be used for finding nearby places around a
|
||||||
|
* location where you are not at.
|
||||||
|
* @param nearbyPlacesInfo This variable has place list information and distances.
|
||||||
|
*/
|
||||||
|
private void populatePlacesFromCustomLocation(NearbyController.NearbyPlacesInfo nearbyPlacesInfo) {
|
||||||
|
//NearbyMapFragment nearbyMapFragment = getMapFragment();
|
||||||
|
if (nearbyMapFragment != null) {
|
||||||
|
nearbyMapFragment.searchThisAreaButtonProgressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nearbyMapFragment != null && curLatLng != null) {
|
||||||
|
if (!populateForCurrentLocation) {
|
||||||
|
nearbyMapFragment.updateMapSignificantlyForCustomLocation(customLatLng, nearbyPlacesInfo.placeList);
|
||||||
|
} else {
|
||||||
|
updateMapFragment(true,true, customLatLng, nearbyPlacesInfo);
|
||||||
|
}
|
||||||
|
updateListFragmentForCustomLocation(nearbyPlacesInfo.placeList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -342,7 +405,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
} else {
|
} else {
|
||||||
// There are fragments, just update the map and list
|
// There are fragments, just update the map and list
|
||||||
Timber.d("Map fragment already exists, just update the map and list");
|
Timber.d("Map fragment already exists, just update the map and list");
|
||||||
updateMapFragment(false);
|
updateMapFragment(false,false, null, null);
|
||||||
updateListFragment();
|
updateListFragment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -364,7 +427,11 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateMapFragment(boolean isSlightUpdate) {
|
private void updateMapFragment(boolean updateViaButton, boolean isSlightUpdate, @Nullable LatLng customLatLng, @Nullable NearbyController.NearbyPlacesInfo nearbyPlacesInfo) {
|
||||||
|
|
||||||
|
if (nearbyMapFragment.searchThisAreaModeOn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Significant update means updating nearby place markers. Slightly update means only
|
Significant update means updating nearby place markers. Slightly update means only
|
||||||
updating current location marker and camera target.
|
updating current location marker and camera target.
|
||||||
|
|
@ -380,14 +447,14 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
* If we are close to nearby places boundaries, we need a significant update to
|
* If we are close to nearby places boundaries, we need a significant update to
|
||||||
* get new nearby places. Check order is south, north, west, east
|
* get new nearby places. Check order is south, north, west, east
|
||||||
* */
|
* */
|
||||||
if (nearbyMapFragment.boundaryCoordinates != null
|
if (nearbyMapFragment.boundaryCoordinates != null && !nearbyMapFragment.searchThisAreaModeOn
|
||||||
&& (curLatLng.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude()
|
&& (curLatLng.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude()
|
||||||
|| curLatLng.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude()
|
|| curLatLng.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude()
|
||||||
|| curLatLng.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude()
|
|| curLatLng.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude()
|
||||||
|| curLatLng.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) {
|
|| curLatLng.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) {
|
||||||
// populate places
|
// populate places
|
||||||
placesDisposable = Observable.fromCallable(() -> nearbyController
|
placesDisposable = Observable.fromCallable(() -> nearbyController
|
||||||
.loadAttractionsFromLocation(curLatLng, false))
|
.loadAttractionsFromLocation(curLatLng, curLatLng, false, updateViaButton))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(this::populatePlaces,
|
.subscribe(this::populatePlaces,
|
||||||
|
|
@ -397,11 +464,16 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
nearbyMapFragment.setBundleForUpdtes(bundle);
|
nearbyMapFragment.setBundleForUpdtes(bundle);
|
||||||
nearbyMapFragment.updateMapSignificantly();
|
nearbyMapFragment.updateMapSignificantlyForCurrentLocation();
|
||||||
updateListFragment();
|
updateListFragment();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updateViaButton) {
|
||||||
|
nearbyMapFragment.updateMapSignificantlyForCustomLocation(customLatLng, nearbyPlacesInfo.placeList);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If this is the map update just after orientation change, then it is not a slight update
|
If this is the map update just after orientation change, then it is not a slight update
|
||||||
anymore. We want to significantly update map after each orientation change
|
anymore. We want to significantly update map after each orientation change
|
||||||
|
|
@ -416,7 +488,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
nearbyMapFragment.updateMapSlightly();
|
nearbyMapFragment.updateMapSlightly();
|
||||||
} else {
|
} else {
|
||||||
nearbyMapFragment.setBundleForUpdtes(bundle);
|
nearbyMapFragment.setBundleForUpdtes(bundle);
|
||||||
nearbyMapFragment.updateMapSignificantly();
|
nearbyMapFragment.updateMapSignificantlyForCurrentLocation();
|
||||||
updateListFragment();
|
updateListFragment();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -433,6 +505,15 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
nearbyListFragment.updateNearbyListSignificantly();
|
nearbyListFragment.updateNearbyListSignificantly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates nearby list for custom location, will be used with search this area method. When you
|
||||||
|
* want to search for a place where you are not at.
|
||||||
|
* @param placeList List of places around your manually chosen target location from map.
|
||||||
|
*/
|
||||||
|
private void updateListFragmentForCustomLocation(List<Place> placeList) {
|
||||||
|
nearbyListFragment.updateNearbyListSignificantlyForCustomLocation(placeList);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls fragment for map view.
|
* Calls fragment for map view.
|
||||||
*/
|
*/
|
||||||
|
|
@ -650,6 +731,9 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
if (placesDisposable != null) {
|
if (placesDisposable != null) {
|
||||||
placesDisposable.dispose();
|
placesDisposable.dispose();
|
||||||
}
|
}
|
||||||
|
if (placesDisposableCustom != null) {
|
||||||
|
placesDisposableCustom.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,19 @@ public class NearbyListFragment extends DaggerFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* While nearby updates for current location held with bundle, automatically, custom updates are
|
||||||
|
* done by calling this methods, triddered by search this are button input from user.
|
||||||
|
* @param placeList
|
||||||
|
*/
|
||||||
|
public void updateNearbyListSignificantlyForCustomLocation(List<Place> placeList) {
|
||||||
|
try {
|
||||||
|
adapterFactory.updateAdapterData(placeList, (RVRendererAdapter<Place>) recyclerView.getAdapter());
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
Timber.e("Null pointer exception from calling recyclerView.getAdapter()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<Place> getPlaceListFromBundle(Bundle bundle) {
|
private List<Place> getPlaceListFromBundle(Bundle bundle) {
|
||||||
List<Place> placeList = Collections.emptyList();
|
List<Place> placeList = Collections.emptyList();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,10 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
@ -60,10 +62,11 @@ import fr.free.nrw.commons.Utils;
|
||||||
import fr.free.nrw.commons.auth.LoginActivity;
|
import fr.free.nrw.commons.auth.LoginActivity;
|
||||||
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
|
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
|
||||||
import fr.free.nrw.commons.contributions.ContributionController;
|
import fr.free.nrw.commons.contributions.ContributionController;
|
||||||
|
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||||
|
import fr.free.nrw.commons.utils.LocationUtils;
|
||||||
import fr.free.nrw.commons.utils.UriDeserializer;
|
import fr.free.nrw.commons.utils.UriDeserializer;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView;
|
|
||||||
|
|
||||||
import static android.app.Activity.RESULT_OK;
|
import static android.app.Activity.RESULT_OK;
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
@ -115,16 +118,21 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
private Place place;
|
private Place place;
|
||||||
private Marker selected;
|
private Marker selected;
|
||||||
private Marker currentLocationMarker;
|
private Marker currentLocationMarker;
|
||||||
private MapboxMap mapboxMap;
|
public MapboxMap mapboxMap;
|
||||||
private PolygonOptions currentLocationPolygonOptions;
|
private PolygonOptions currentLocationPolygonOptions;
|
||||||
|
|
||||||
|
public Button searchThisAreaButton;
|
||||||
|
public ProgressBar searchThisAreaButtonProgressBar;
|
||||||
|
|
||||||
private boolean isBottomListSheetExpanded;
|
private boolean isBottomListSheetExpanded;
|
||||||
private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.06;
|
private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.06;
|
||||||
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.04;
|
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.04;
|
||||||
|
|
||||||
private boolean isMapReady;
|
private boolean isMapReady;
|
||||||
|
public boolean searchThisAreaModeOn = false;
|
||||||
|
|
||||||
private Bundle bundleForUpdtes;// Carry information from activity about changed nearby places and current location
|
private Bundle bundleForUpdtes;// Carry information from activity about changed nearby places and current location
|
||||||
|
private boolean searchedAroundCurrentLocation = true;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Named("prefs")
|
@Named("prefs")
|
||||||
|
|
@ -246,8 +254,8 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
* called when user is out of boundaries (south, north, east or west) of markers drawn by
|
* called when user is out of boundaries (south, north, east or west) of markers drawn by
|
||||||
* previous nearby call.
|
* previous nearby call.
|
||||||
*/
|
*/
|
||||||
public void updateMapSignificantly() {
|
public void updateMapSignificantlyForCurrentLocation() {
|
||||||
Timber.d("updateMapSignificantly called, bundle is:"+bundleForUpdtes);
|
Timber.d("updateMapSignificantlyForCurrentLocation called, bundle is:"+bundleForUpdtes);
|
||||||
if (mapboxMap != null) {
|
if (mapboxMap != null) {
|
||||||
if (bundleForUpdtes != null) {
|
if (bundleForUpdtes != null) {
|
||||||
Gson gson = new GsonBuilder()
|
Gson gson = new GsonBuilder()
|
||||||
|
|
@ -271,10 +279,32 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
mapboxMap.clear();
|
mapboxMap.clear();
|
||||||
addCurrentLocationMarker(mapboxMap);
|
addCurrentLocationMarker(mapboxMap);
|
||||||
updateMapToTrackPosition();
|
updateMapToTrackPosition();
|
||||||
addNearbyMarkerstoMapBoxMap();
|
// We are trying to find nearby places around our current location, thus custom parameter is nullified
|
||||||
|
addNearbyMarkerstoMapBoxMap(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be used for map vew updates for custom locations (ie. with search this area method).
|
||||||
|
* Clears the map, adds current location marker, adds nearby markers around custom location,
|
||||||
|
* re-enables map gestures which was locked during place load, remove progress bar.
|
||||||
|
* @param customLatLng custom location that we will search around
|
||||||
|
* @param placeList places around of custom location
|
||||||
|
*/
|
||||||
|
public void updateMapSignificantlyForCustomLocation(fr.free.nrw.commons.location.LatLng customLatLng, List<Place> placeList) {
|
||||||
|
List<NearbyBaseMarker> customBaseMarkerOptions = NearbyController
|
||||||
|
.loadAttractionsFromLocationToBaseMarkerOptions(curLatLng, // Curlatlang will be used to calculate distances
|
||||||
|
placeList,
|
||||||
|
getActivity());
|
||||||
|
mapboxMap.clear();
|
||||||
|
// We are trying to find nearby places around our custom searched area, thus custom parameter is nonnull
|
||||||
|
addNearbyMarkerstoMapBoxMap(customBaseMarkerOptions);
|
||||||
|
addCurrentLocationMarker(mapboxMap);
|
||||||
|
// Re-enable mapbox gestures on custom location markers load
|
||||||
|
mapboxMap.getUiSettings().setAllGesturesEnabled(true);
|
||||||
|
searchThisAreaButtonProgressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
// Only update current position marker and camera view
|
// Only update current position marker and camera view
|
||||||
private void updateMapToTrackPosition() {
|
private void updateMapToTrackPosition() {
|
||||||
|
|
||||||
|
|
@ -299,6 +329,9 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
|
|
||||||
// Make camera to follow user on location change
|
// Make camera to follow user on location change
|
||||||
CameraPosition position ;
|
CameraPosition position ;
|
||||||
|
|
||||||
|
// Do not update camera position is search this area mode on
|
||||||
|
if (!searchThisAreaModeOn) {
|
||||||
if (ViewUtil.isPortrait(getActivity())){
|
if (ViewUtil.isPortrait(getActivity())){
|
||||||
position = new CameraPosition.Builder()
|
position = new CameraPosition.Builder()
|
||||||
.target(isBottomListSheetExpanded ?
|
.target(isBottomListSheetExpanded ?
|
||||||
|
|
@ -323,10 +356,10 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
|
|
||||||
mapboxMap.animateCamera(CameraUpdateFactory
|
mapboxMap.animateCamera(CameraUpdateFactory
|
||||||
.newCameraPosition(position), 1000);
|
.newCameraPosition(position), 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initViews() {
|
private void initViews() {
|
||||||
Timber.d("initViews called");
|
Timber.d("initViews called");
|
||||||
bottomSheetList = ((NearbyFragment)getParentFragment()).view.findViewById(R.id.bottom_sheet);
|
bottomSheetList = ((NearbyFragment)getParentFragment()).view.findViewById(R.id.bottom_sheet);
|
||||||
|
|
@ -366,6 +399,9 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
bookmarkButton = getActivity().findViewById(R.id.bookmarkButton);
|
bookmarkButton = getActivity().findViewById(R.id.bookmarkButton);
|
||||||
bookmarkButtonImage = getActivity().findViewById(R.id.bookmarkButtonImage);
|
bookmarkButtonImage = getActivity().findViewById(R.id.bookmarkButtonImage);
|
||||||
|
|
||||||
|
searchThisAreaButton = ((NearbyFragment)getParentFragment()).view.findViewById(R.id.search_this_area_button);
|
||||||
|
searchThisAreaButtonProgressBar = ((NearbyFragment)getParentFragment()).view.findViewById(R.id.search_this_area_button_progres_bar);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setListeners() {
|
private void setListeners() {
|
||||||
|
|
@ -495,13 +531,77 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onMapReady(MapboxMap mapboxMap) {
|
public void onMapReady(MapboxMap mapboxMap) {
|
||||||
NearbyMapFragment.this.mapboxMap = mapboxMap;
|
NearbyMapFragment.this.mapboxMap = mapboxMap;
|
||||||
updateMapSignificantly();
|
addMapMovementListeners();
|
||||||
|
updateMapSignificantlyForCurrentLocation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mapView.setStyleUrl("asset://mapstyle.json");
|
mapView.setStyleUrl("asset://mapstyle.json");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addMapMovementListeners() {
|
||||||
|
|
||||||
|
mapboxMap.addOnCameraMoveListener(new MapboxMap.OnCameraMoveListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraMove() {
|
||||||
|
|
||||||
|
if (NearbyController.currentLocation != null) { // If our nearby markers are calculated at least once
|
||||||
|
|
||||||
|
if (searchThisAreaButton.getVisibility() == View.GONE) {
|
||||||
|
searchThisAreaButton.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
double distance = mapboxMap.getCameraPosition().target
|
||||||
|
.distanceTo(new LatLng(NearbyController.currentLocation.getLatitude()
|
||||||
|
, NearbyController.currentLocation.getLongitude()));
|
||||||
|
|
||||||
|
if (distance > NearbyController.searchedRadius*1000*3/4) { //Convert to meter, and compare if our distance is bigger than 3/4 or our searched area
|
||||||
|
if (!searchThisAreaModeOn) { // If we are changing mode, then change click action
|
||||||
|
searchThisAreaModeOn = true;
|
||||||
|
searchThisAreaButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
searchThisAreaModeOn = true;
|
||||||
|
// Lock map operations during search this area operation
|
||||||
|
mapboxMap.getUiSettings().setAllGesturesEnabled(false);
|
||||||
|
searchThisAreaButtonProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
searchThisAreaButton.setVisibility(View.GONE);
|
||||||
|
searchedAroundCurrentLocation = false;
|
||||||
|
((NearbyFragment)getParentFragment())
|
||||||
|
.refreshViewForCustomLocation(LocationUtils
|
||||||
|
.mapBoxLatLngToCommonsLatLng(mapboxMap.getCameraPosition().target), false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (searchThisAreaModeOn) {
|
||||||
|
searchThisAreaModeOn = false; // This flag will help us to understand should we folor users location or not
|
||||||
|
searchThisAreaButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
searchThisAreaModeOn = true;
|
||||||
|
// Lock map operations during search this area operation
|
||||||
|
mapboxMap.getUiSettings().setAllGesturesEnabled(false);
|
||||||
|
searchThisAreaButtonProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
fabRecenter.callOnClick();
|
||||||
|
searchThisAreaButton.setVisibility(View.GONE);
|
||||||
|
searchedAroundCurrentLocation = true;
|
||||||
|
((NearbyFragment)getParentFragment())
|
||||||
|
.refreshViewForCustomLocation(LocationUtils
|
||||||
|
.mapBoxLatLngToCommonsLatLng(mapboxMap.getCameraPosition().target), true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (searchedAroundCurrentLocation) {
|
||||||
|
searchThisAreaButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* onLogoutComplete is called after shared preferences and data stored in local database are cleared.
|
* onLogoutComplete is called after shared preferences and data stored in local database are cleared.
|
||||||
*/
|
*/
|
||||||
|
|
@ -554,10 +654,17 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
/**
|
/**
|
||||||
* Adds markers for nearby places to mapbox map
|
* Adds markers for nearby places to mapbox map
|
||||||
*/
|
*/
|
||||||
private void addNearbyMarkerstoMapBoxMap() {
|
private void addNearbyMarkerstoMapBoxMap(@Nullable List<NearbyBaseMarker> customNearbyBaseMarker) {
|
||||||
|
List<NearbyBaseMarker> baseMarkerOptions;
|
||||||
Timber.d("addNearbyMarkerstoMapBoxMap is called");
|
Timber.d("addNearbyMarkerstoMapBoxMap is called");
|
||||||
|
if (customNearbyBaseMarker != null) {
|
||||||
|
// If we try to update nearby points for a custom location choosen from map (we are not there)
|
||||||
|
baseMarkerOptions = customNearbyBaseMarker;
|
||||||
|
} else {
|
||||||
|
// If we try to display nearby markers around our curret location
|
||||||
|
baseMarkerOptions = this.baseMarkerOptions;
|
||||||
|
}
|
||||||
mapboxMap.addMarkers(baseMarkerOptions);
|
mapboxMap.addMarkers(baseMarkerOptions);
|
||||||
|
|
||||||
mapboxMap.setOnInfoWindowCloseListener(marker -> {
|
mapboxMap.setOnInfoWindowCloseListener(marker -> {
|
||||||
if (marker == selected) {
|
if (marker == selected) {
|
||||||
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public class NearbyPlaces {
|
||||||
private static final Uri WIKIDATA_QUERY_URL = Uri.parse("https://query.wikidata.org/sparql");
|
private static final Uri WIKIDATA_QUERY_URL = Uri.parse("https://query.wikidata.org/sparql");
|
||||||
private static final Uri WIKIDATA_QUERY_UI_URL = Uri.parse("https://query.wikidata.org/");
|
private static final Uri WIKIDATA_QUERY_UI_URL = Uri.parse("https://query.wikidata.org/");
|
||||||
private final String wikidataQuery;
|
private final String wikidataQuery;
|
||||||
private double radius = INITIAL_RADIUS;
|
public double radius = INITIAL_RADIUS;
|
||||||
|
|
||||||
public NearbyPlaces() {
|
public NearbyPlaces() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -55,6 +55,7 @@ public class NearbyPlaces {
|
||||||
} else {
|
} else {
|
||||||
MIN_RESULTS = 40;
|
MIN_RESULTS = 40;
|
||||||
MAX_RADIUS = 300.0; // in kilometers
|
MAX_RADIUS = 300.0; // in kilometers
|
||||||
|
radius = INITIAL_RADIUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase the radius gradually to find a satisfactory number of nearby places
|
// increase the radius gradually to find a satisfactory number of nearby places
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package fr.free.nrw.commons.utils;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.location.LatLng;
|
||||||
|
|
||||||
|
public class LocationUtils {
|
||||||
|
public static LatLng mapBoxLatLngToCommonsLatLng(com.mapbox.mapboxsdk.geometry.LatLng mapBoxLatLng) {
|
||||||
|
return new LatLng(mapBoxLatLng.getLatitude(), mapBoxLatLng.getLongitude(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static com.mapbox.mapboxsdk.geometry.LatLng comonsLatLngToMapBoxLatLng(LatLng commonsLatLng) {
|
||||||
|
return new com.mapbox.mapboxsdk.geometry.LatLng(commonsLatLng.getLatitude(), commonsLatLng.getLongitude());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -70,6 +69,28 @@
|
||||||
android:id="@+id/bottom_sheet_details"
|
android:id="@+id/bottom_sheet_details"
|
||||||
layout="@layout/bottom_sheet_details" />
|
layout="@layout/bottom_sheet_details" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/search_this_area_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:elevation="6dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:textColor="@color/status_bar_blue"
|
||||||
|
android:text="@string/search_this_area" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/search_this_area_button_progres_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
/>
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<android.support.design.widget.FloatingActionButton
|
||||||
android:id="@+id/fab_plus"
|
android:id="@+id/fab_plus"
|
||||||
|
|
|
||||||
|
|
@ -425,6 +425,7 @@ Upload your first media by touching the camera or gallery icon above.</string>
|
||||||
<string name="no_go_back">No, Go Back</string>
|
<string name="no_go_back">No, Go Back</string>
|
||||||
|
|
||||||
<string name="upload_flow_all_images_in_set">(For all images in set)</string>
|
<string name="upload_flow_all_images_in_set">(For all images in set)</string>
|
||||||
|
<string name="search_this_area">Search this area</string>
|
||||||
<string name="nearby_card_permission_title">Permission Request</string>
|
<string name="nearby_card_permission_title">Permission Request</string>
|
||||||
<string name="nearby_card_permission_explanation">Would you like us to use your current location to display the nearest place that needs pictures?</string>
|
<string name="nearby_card_permission_explanation">Would you like us to use your current location to display the nearest place that needs pictures?</string>
|
||||||
<string name="unable_to_display_nearest_place">Unable to display nearest place that needs pictures without location permissions</string>
|
<string name="unable_to_display_nearest_place">Unable to display nearest place that needs pictures without location permissions</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue