Skip to content

Commit 677e009

Browse files
neslihanturanmisaochan
authored andcommitted
Search this area (commons-app#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
1 parent b907a0a commit 677e009

File tree

9 files changed

+283
-32
lines changed

9 files changed

+283
-32
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ private void updateClosestNearbyCardViewInfo() {
622622
curLatLng = locationManager.getLastLocation();
623623

624624
placesDisposable = Observable.fromCallable(() -> nearbyController
625-
.loadAttractionsFromLocation(curLatLng, true)) // thanks to boolean, it will only return closest result
625+
.loadAttractionsFromLocation(curLatLng, curLatLng, true, false)) // thanks to boolean, it will only return closest result
626626
.subscribeOn(Schedulers.io())
627627
.observeOn(AndroidSchedulers.mainThread())
628628
.subscribe(this::updateNearbyNotification,

app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java

+15-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import android.content.res.Resources;
66
import android.graphics.Bitmap;
77
import android.support.graphics.drawable.VectorDrawableCompat;
8+
import android.util.Log;
89

910
import com.mapbox.mapboxsdk.annotations.IconFactory;
1011

@@ -31,6 +32,8 @@ public class NearbyController {
3132
private static final int MAX_RESULTS = 1000;
3233
private final NearbyPlaces nearbyPlaces;
3334
private final SharedPreferences prefs;
35+
public static double searchedRadius = 10.0; //in kilometers
36+
public static LatLng currentLocation;
3437

3538
@Inject
3639
public NearbyController(NearbyPlaces nearbyPlaces,
@@ -44,18 +47,21 @@ public NearbyController(NearbyPlaces nearbyPlaces,
4447
* Prepares Place list to make their distance information update later.
4548
*
4649
* @param curLatLng current location for user
50+
* @param latLangToSearchAround the location user wants to search around
51+
* @param returnClosestResult if this search is done to find closest result or all results
4752
* @return NearbyPlacesInfo a variable holds Place list without distance information
4853
* and boundary coordinates of current Place List
4954
*/
50-
public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng, boolean returnClosestResult) throws IOException {
51-
Timber.d("Loading attractions near %s", curLatLng);
55+
public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng, LatLng latLangToSearchAround, boolean returnClosestResult, boolean checkingAroundCurrentLocation) throws IOException {
56+
57+
Timber.d("Loading attractions near %s", latLangToSearchAround);
5258
NearbyPlacesInfo nearbyPlacesInfo = new NearbyPlacesInfo();
5359

54-
if (curLatLng == null) {
60+
if (latLangToSearchAround == null) {
5561
Timber.d("Loading attractions neari, but curLatLng is null");
5662
return null;
5763
}
58-
List<Place> places = nearbyPlaces.getFromWikidataQuery(curLatLng, Locale.getDefault().getLanguage(), returnClosestResult);
64+
List<Place> places = nearbyPlaces.getFromWikidataQuery(latLangToSearchAround, Locale.getDefault().getLanguage(), returnClosestResult);
5965

6066
if (null != places && places.size() > 0) {
6167
LatLng[] boundaryCoordinates = {places.get(0).location, // south
@@ -93,6 +99,11 @@ public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng, boolean re
9399
}
94100
nearbyPlacesInfo.placeList = places;
95101
nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates;
102+
if (!returnClosestResult && checkingAroundCurrentLocation) {
103+
// Do not update searched radius, if controller is used for nearby card notification
104+
searchedRadius = nearbyPlaces.radius;
105+
currentLocation = curLatLng;
106+
}
96107
return nearbyPlacesInfo;
97108
}
98109
else {

app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java

+99-15
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import android.support.design.widget.Snackbar;
1515
import android.support.v4.app.FragmentTransaction;
1616
import android.support.v7.app.AlertDialog;
17+
import android.util.Log;
1718
import android.view.LayoutInflater;
1819

1920
import android.view.View;
@@ -64,8 +65,6 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
6465
LinearLayout bottomSheetDetails;
6566
@BindView(R.id.transparentView)
6667
View transparentView;
67-
@BindView(R.id.fab_recenter)
68-
View fabRecenter;
6968

7069
@Inject
7170
LocationServiceManager locationManager;
@@ -87,16 +86,19 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
8786

8887
private LatLng curLatLng;
8988
private Disposable placesDisposable;
89+
private Disposable placesDisposableCustom;
9090
private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed
9191
public View view;
9292
private Snackbar snackbar;
9393

9494
private LatLng lastKnownLocation;
95+
private LatLng customLatLng;
9596

9697
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
9798
private BroadcastReceiver broadcastReceiver;
9899

99100
private boolean onOrientationChanged = false;
101+
private boolean populateForCurrentLocation = false;
100102

101103
@Override
102104
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -216,32 +218,35 @@ public void prepareViewsForSheetPosition(int bottomSheetState) {
216218

217219
@Override
218220
public void onLocationChangedSignificantly(LatLng latLng) {
219-
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
221+
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
220222
}
221223

222224
@Override
223225
public void onLocationChangedSlightly(LatLng latLng) {
224-
refreshView(LOCATION_SLIGHTLY_CHANGED);
226+
refreshView(LOCATION_SLIGHTLY_CHANGED);
225227
}
226228

227229

228230
@Override
229231
public void onLocationChangedMedium(LatLng latLng) {
230232
// For nearby map actions, there are no differences between 500 meter location change (aka medium change) and slight change
231-
refreshView(LOCATION_SLIGHTLY_CHANGED);
233+
refreshView(LOCATION_SLIGHTLY_CHANGED);
232234
}
233235

234236
@Override
235237
public void onWikidataEditSuccessful() {
236-
refreshView(MAP_UPDATED);
238+
// Do not refresh nearby map if we are checking other areas with search this area button
239+
if (!nearbyMapFragment.searchThisAreaModeOn) {
240+
refreshView(MAP_UPDATED);
241+
}
237242
}
238243

239244
/**
240245
* This method should be the single point to load/refresh nearby places
241246
*
242247
* @param locationChangeType defines if location shanged significantly or slightly
243248
*/
244-
private void refreshView(LocationServiceManager.LocationChangeType locationChangeType) {
249+
public void refreshView(LocationServiceManager.LocationChangeType locationChangeType) {
245250
Timber.d("Refreshing nearby places");
246251
if (lockNearbyView) {
247252
return;
@@ -257,9 +262,11 @@ private void refreshView(LocationServiceManager.LocationChangeType locationChang
257262

258263
if (curLatLng != null && curLatLng.equals(lastLocation)
259264
&& !locationChangeType.equals(MAP_UPDATED)) { //refresh view only if location has changed
265+
// Two exceptional cases to refresh nearby map manually.
260266
if (!onOrientationChanged) {
261267
return;
262268
}
269+
263270
}
264271
curLatLng = lastLocation;
265272

@@ -292,7 +299,7 @@ private void refreshView(LocationServiceManager.LocationChangeType locationChang
292299
bundle.putString("CurLatLng", gsonCurLatLng);
293300

294301
placesDisposable = Observable.fromCallable(() -> nearbyController
295-
.loadAttractionsFromLocation(curLatLng, false))
302+
.loadAttractionsFromLocation(curLatLng, curLatLng, false, true))
296303
.subscribeOn(Schedulers.io())
297304
.observeOn(AndroidSchedulers.mainThread())
298305
.subscribe(this::populatePlaces,
@@ -301,14 +308,70 @@ private void refreshView(LocationServiceManager.LocationChangeType locationChang
301308
showErrorMessage(getString(R.string.error_fetching_nearby_places));
302309
progressBar.setVisibility(View.GONE);
303310
});
311+
304312
} else if (locationChangeType
305313
.equals(LOCATION_SLIGHTLY_CHANGED)) {
306314
Gson gson = new GsonBuilder()
307315
.registerTypeAdapter(Uri.class, new UriSerializer())
308316
.create();
309317
String gsonCurLatLng = gson.toJson(curLatLng);
310318
bundle.putString("CurLatLng", gsonCurLatLng);
311-
updateMapFragment(true);
319+
updateMapFragment(false,true, null, null);
320+
}
321+
322+
if (nearbyMapFragment != null) {
323+
nearbyMapFragment.searchThisAreaButton.setVisibility(View.GONE);
324+
}
325+
}
326+
327+
/**
328+
* This method should be used with "Search this are button". This method will search nearby
329+
* points around any custom location (target location when user clicked on search this area)
330+
* button. It populates places for custom location.
331+
* @param customLatLng Custom area which we will search around
332+
*/
333+
public void refreshViewForCustomLocation(LatLng customLatLng, boolean refreshForCurrentLocation) {
334+
335+
if (customLatLng == null) {
336+
// If null, return
337+
return;
338+
}
339+
340+
populateForCurrentLocation = refreshForCurrentLocation;
341+
this.customLatLng = customLatLng;
342+
placesDisposableCustom = Observable.fromCallable(() -> nearbyController
343+
.loadAttractionsFromLocation(curLatLng, customLatLng, false, populateForCurrentLocation))
344+
.subscribeOn(Schedulers.io())
345+
.observeOn(AndroidSchedulers.mainThread())
346+
.subscribe(this::populatePlacesFromCustomLocation,
347+
throwable -> {
348+
Timber.d(throwable);
349+
showErrorMessage(getString(R.string.error_fetching_nearby_places));
350+
});
351+
352+
if (nearbyMapFragment != null) {
353+
nearbyMapFragment.searchThisAreaButton.setVisibility(View.GONE);
354+
}
355+
}
356+
357+
/**
358+
* Populates places for custom location, should be used for finding nearby places around a
359+
* location where you are not at.
360+
* @param nearbyPlacesInfo This variable has place list information and distances.
361+
*/
362+
private void populatePlacesFromCustomLocation(NearbyController.NearbyPlacesInfo nearbyPlacesInfo) {
363+
//NearbyMapFragment nearbyMapFragment = getMapFragment();
364+
if (nearbyMapFragment != null) {
365+
nearbyMapFragment.searchThisAreaButtonProgressBar.setVisibility(View.GONE);
366+
}
367+
368+
if (nearbyMapFragment != null && curLatLng != null) {
369+
if (!populateForCurrentLocation) {
370+
nearbyMapFragment.updateMapSignificantlyForCustomLocation(customLatLng, nearbyPlacesInfo.placeList);
371+
} else {
372+
updateMapFragment(true,true, customLatLng, nearbyPlacesInfo);
373+
}
374+
updateListFragmentForCustomLocation(nearbyPlacesInfo.placeList);
312375
}
313376
}
314377

@@ -342,7 +405,7 @@ private void populatePlaces(NearbyController.NearbyPlacesInfo nearbyPlacesInfo)
342405
} else {
343406
// There are fragments, just update the map and list
344407
Timber.d("Map fragment already exists, just update the map and list");
345-
updateMapFragment(false);
408+
updateMapFragment(false,false, null, null);
346409
updateListFragment();
347410
}
348411
}
@@ -364,7 +427,11 @@ private void lockNearbyView(boolean lock) {
364427
}
365428
}
366429

367-
private void updateMapFragment(boolean isSlightUpdate) {
430+
private void updateMapFragment(boolean updateViaButton, boolean isSlightUpdate, @Nullable LatLng customLatLng, @Nullable NearbyController.NearbyPlacesInfo nearbyPlacesInfo) {
431+
432+
if (nearbyMapFragment.searchThisAreaModeOn) {
433+
return;
434+
}
368435
/*
369436
Significant update means updating nearby place markers. Slightly update means only
370437
updating current location marker and camera target.
@@ -380,14 +447,14 @@ private void updateMapFragment(boolean isSlightUpdate) {
380447
* If we are close to nearby places boundaries, we need a significant update to
381448
* get new nearby places. Check order is south, north, west, east
382449
* */
383-
if (nearbyMapFragment.boundaryCoordinates != null
450+
if (nearbyMapFragment.boundaryCoordinates != null && !nearbyMapFragment.searchThisAreaModeOn
384451
&& (curLatLng.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude()
385452
|| curLatLng.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude()
386453
|| curLatLng.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude()
387454
|| curLatLng.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) {
388455
// populate places
389456
placesDisposable = Observable.fromCallable(() -> nearbyController
390-
.loadAttractionsFromLocation(curLatLng, false))
457+
.loadAttractionsFromLocation(curLatLng, curLatLng, false, updateViaButton))
391458
.subscribeOn(Schedulers.io())
392459
.observeOn(AndroidSchedulers.mainThread())
393460
.subscribe(this::populatePlaces,
@@ -397,11 +464,16 @@ private void updateMapFragment(boolean isSlightUpdate) {
397464
progressBar.setVisibility(View.GONE);
398465
});
399466
nearbyMapFragment.setBundleForUpdtes(bundle);
400-
nearbyMapFragment.updateMapSignificantly();
467+
nearbyMapFragment.updateMapSignificantlyForCurrentLocation();
401468
updateListFragment();
402469
return;
403470
}
404471

472+
if (updateViaButton) {
473+
nearbyMapFragment.updateMapSignificantlyForCustomLocation(customLatLng, nearbyPlacesInfo.placeList);
474+
return;
475+
}
476+
405477
/*
406478
If this is the map update just after orientation change, then it is not a slight update
407479
anymore. We want to significantly update map after each orientation change
@@ -416,7 +488,7 @@ private void updateMapFragment(boolean isSlightUpdate) {
416488
nearbyMapFragment.updateMapSlightly();
417489
} else {
418490
nearbyMapFragment.setBundleForUpdtes(bundle);
419-
nearbyMapFragment.updateMapSignificantly();
491+
nearbyMapFragment.updateMapSignificantlyForCurrentLocation();
420492
updateListFragment();
421493
}
422494
} else {
@@ -433,6 +505,15 @@ private void updateListFragment() {
433505
nearbyListFragment.updateNearbyListSignificantly();
434506
}
435507

508+
/**
509+
* Updates nearby list for custom location, will be used with search this area method. When you
510+
* want to search for a place where you are not at.
511+
* @param placeList List of places around your manually chosen target location from map.
512+
*/
513+
private void updateListFragmentForCustomLocation(List<Place> placeList) {
514+
nearbyListFragment.updateNearbyListSignificantlyForCustomLocation(placeList);
515+
}
516+
436517
/**
437518
* Calls fragment for map view.
438519
*/
@@ -650,6 +731,9 @@ public void onDestroy() {
650731
if (placesDisposable != null) {
651732
placesDisposable.dispose();
652733
}
734+
if (placesDisposableCustom != null) {
735+
placesDisposableCustom.dispose();
736+
}
653737
}
654738

655739
@Override

app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java

+13
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ public void updateNearbyListSignificantly() {
9898
}
9999
}
100100

101+
/**
102+
* While nearby updates for current location held with bundle, automatically, custom updates are
103+
* done by calling this methods, triddered by search this are button input from user.
104+
* @param placeList
105+
*/
106+
public void updateNearbyListSignificantlyForCustomLocation(List<Place> placeList) {
107+
try {
108+
adapterFactory.updateAdapterData(placeList, (RVRendererAdapter<Place>) recyclerView.getAdapter());
109+
} catch (NullPointerException e) {
110+
Timber.e("Null pointer exception from calling recyclerView.getAdapter()");
111+
}
112+
}
113+
101114
private List<Place> getPlaceListFromBundle(Bundle bundle) {
102115
List<Place> placeList = Collections.emptyList();
103116

0 commit comments

Comments
 (0)