diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java index 567dd6af4..d5f385e2c 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java @@ -27,6 +27,7 @@ import io.reactivex.Observable; import io.reactivex.Single; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.regex.Matcher; @@ -35,6 +36,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; +import okhttp3.Protocol; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; @@ -411,7 +413,7 @@ public class OkHttpJsonApiClient { throws Exception { final String wikidataQuery = FileUtils.readFromResource("/queries/query_for_item.rq"); final String query = wikidataQuery - .replace("${ENTITY}", entityId) + .replace("${ENTITY}", "wd:"+entityId) .replace("${LANG}", language); final HttpUrl.Builder urlBuilder = HttpUrl .parse(sparqlQueryUrl) @@ -435,6 +437,44 @@ public class OkHttpJsonApiClient { throw new Exception(response.message()); } + @Nullable + public List getNearbyPlacesFromQID( + final List placeList, final String language) throws IOException { + final String wikidataQuery = FileUtils.readFromResource("/queries/query_for_item.rq"); + String qids = ""; + for (final Place place : placeList) { + qids += "\n" + ("wd:" + place.getWikiDataEntityId()); + } + final String query = wikidataQuery + .replace("${ENTITY}", qids) + .replace("${LANG}", language); + final HttpUrl.Builder urlBuilder = HttpUrl + .parse(sparqlQueryUrl) + .newBuilder() + .addQueryParameter("query", query) + .addQueryParameter("format", "json"); + + final Request request = new Request.Builder() + .url(urlBuilder.build()) + .build(); + + try (Response response = okHttpClient.newCall(request).execute()) { + if (response.isSuccessful()) { + final String json = response.body().string(); + final NearbyResponse nearbyResponse = gson.fromJson(json, NearbyResponse.class); + final List bindings = nearbyResponse.getResults().getBindings(); + final List places = new ArrayList<>(); + for (final NearbyResultItem item : bindings) { + final Place placeFromNearbyItem = Place.from(item); + places.add(placeFromNearbyItem); + } + return places; + } else { + throw new IOException("Unexpected response code: " + response.code()); + } + } + } + /** * Make API Call to get Places * diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java index a5d139291..d6d80aafd 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java @@ -131,6 +131,10 @@ public class NearbyController extends MapController { ); } + public List getPlacesFromQID(List placeList) throws Exception { + return nearbyPlaces.getPlacesFromQID(placeList, Locale.getDefault().getLanguage()); + } + public Place getNearbyPlace(String entity) throws Exception { return nearbyPlaces.getPlaceFromWikidataQuery( entity, diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java index 8e87c9683..ccfc9e5fc 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java @@ -134,6 +134,12 @@ public class NearbyPlaces { .getNearbyPlace(entityId, lang); } + public List getPlacesFromQID(final List placeList, + final String lang) throws Exception { + return okHttpJsonApiClient + .getNearbyPlacesFromQID(placeList, lang); + } + /** * Runs the Wikidata query to retrieve the KML String * diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java index e78341395..d93dd7033 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java @@ -66,6 +66,7 @@ import fr.free.nrw.commons.contributions.MainActivity.ActiveFragment; import fr.free.nrw.commons.databinding.FragmentNearbyParentBinding; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.kvstore.JsonKvStore; +import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LocationPermissionsHelper; import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback; import fr.free.nrw.commons.location.LocationServiceManager; @@ -103,6 +104,8 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; @@ -1326,10 +1329,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment if (nearbyPlacesInfo.placeList == null || nearbyPlacesInfo.placeList.isEmpty()) { showErrorMessage(getString(R.string.no_nearby_places_around)); } else { - updateMapMarkers(nearbyPlacesInfo, true); + updateMapMarkers(nearbyPlacesInfo.placeList, nearbyPlacesInfo.currentLatLng, + true); lastFocusLocation = searchLatLng; lastMapFocus = new GeoPoint(searchLatLng.getLatitude(), searchLatLng.getLongitude()); + loadPlacesDataAsync(nearbyPlacesInfo.placeList, nearbyPlacesInfo.currentLatLng); } }, throwable -> { @@ -1364,9 +1369,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment // Updating last searched location applicationKvStore.putString("LastLocation", searchLatLng.getLatitude() + "," + searchLatLng.getLongitude()); - updateMapMarkers(nearbyPlacesInfo, false); + updateMapMarkers(nearbyPlacesInfo.placeList, nearbyPlacesInfo.currentLatLng, + false); lastMapFocus = new GeoPoint(searchLatLng.getLatitude(), searchLatLng.getLongitude()); + loadPlacesDataAsync(nearbyPlacesInfo.placeList, nearbyPlacesInfo.currentLatLng); } }, throwable -> { @@ -1379,15 +1386,48 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment })); } + public void loadPlacesDataAsync(List placeList, LatLng curLatLng) { + final Observable> nearbyPlacesInfoObservable = Observable + .fromCallable(() -> nearbyController + .getPlacesFromQID(placeList)); + compositeDisposable.add(nearbyPlacesInfoObservable + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(p -> { + List places = p; + if (places == null || places.isEmpty()) { + showErrorMessage(getString(R.string.no_nearby_places_around)); + } else { + for (Place place : places) { + for (Place foundPlace : placeList) { + if (place.siteLinks.getWikidataLink().equals(foundPlace.siteLinks.getWikidataLink())) { + place.location = foundPlace.location; + place.distance = foundPlace.distance; + place.setMonument(foundPlace.isMonument()); + break; + } + } + } + updateMapMarkers(places, curLatLng, false); + } + }, + throwable -> { + Timber.e(throwable); + showErrorMessage(getString(R.string.error_fetching_nearby_places) + + throwable.getLocalizedMessage()); + setFilterState(); + })); + } + /** * Populates places for your location, should be used for finding nearby places around a * location where you are. * - * @param nearbyPlacesInfo This variable has place list information and distances. + * @param nearbyPlaces This variable has place list information and distances. */ - private void updateMapMarkers(final NearbyController.NearbyPlacesInfo nearbyPlacesInfo, + private void updateMapMarkers(final List nearbyPlaces, final LatLng curLatLng, final boolean shouldUpdateSelectedMarker) { - presenter.updateMapMarkers(nearbyPlacesInfo, shouldUpdateSelectedMarker); + presenter.updateMapMarkers(nearbyPlaces, curLatLng, shouldUpdateSelectedMarker); setFilterState(); } @@ -1774,7 +1814,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment return (isBookmarked ? R.drawable.ic_custom_map_marker_green_bookmarked : R.drawable.ic_custom_map_marker_green); - } else if (!place.exists) { // Means that the topic of the Wikidata item does not exist in the real world anymore, for instance it is a past event, or a place that was destroyed + } else if (!place.exists || (place.name == "")) { // Means that the topic of the Wikidata item does not exist in the real world anymore, for instance it is a past event, or a place that was destroyed return (isBookmarked ? R.drawable.ic_custom_map_marker_grey_bookmarked : R.drawable.ic_custom_map_marker_grey); @@ -1797,6 +1837,13 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment Marker marker = new Marker(binding.map); marker.setPosition(point); marker.setIcon(icon); + if (!Objects.equals(place.name, "")){ + marker.setTitle(place.name); + marker.setSnippet( + containsParentheses(place.getLongDescription()) + ? getTextBetweenParentheses( + place.getLongDescription()) : place.getLongDescription()); + } marker.setTextLabelFontSize(40); marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_TOP); marker.setOnMarkerClickListener((marker1, mapView) -> { @@ -1807,7 +1854,16 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment binding.bottomSheetDetails.dataCircularProgress.setVisibility(View.VISIBLE); binding.bottomSheetDetails.icon.setVisibility(View.GONE); binding.bottomSheetDetails.wikiDataLl.setVisibility(View.GONE); - getPlaceData(place.getWikiDataEntityId(), place, marker1); + if (Objects.equals(place.name, "")){ + getPlaceData(place.getWikiDataEntityId(), place, marker1); + }else { + marker.showInfoWindow(); + binding.bottomSheetDetails.dataCircularProgress.setVisibility(View.GONE); + binding.bottomSheetDetails.icon.setVisibility(View.VISIBLE); + binding.bottomSheetDetails.wikiDataLl.setVisibility(View.VISIBLE); + passInfoToSheet(place); + hideBottomSheet(); + } bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); return true; }); @@ -1830,6 +1886,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment Marker marker = new Marker(binding.map); marker.setPosition(point); marker.setIcon(icon); + Place place = nearbyBaseMarkers.get(i).getPlace(); + if (!Objects.equals(place.name, "")){ + marker.setTitle(place.name); + marker.setSnippet( + containsParentheses(place.getLongDescription()) + ? getTextBetweenParentheses( + place.getLongDescription()) : place.getLongDescription()); + } marker.setTextLabelFontSize(40); marker.setId(String.valueOf(i)); marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_TOP); @@ -1840,11 +1904,20 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment } clickedMarker = marker1; int index = Integer.parseInt(marker1.getId()); - Place place = nearbyBaseMarkers.get(index).getPlace(); + Place updatedPlace = nearbyBaseMarkers.get(index).getPlace(); binding.bottomSheetDetails.dataCircularProgress.setVisibility(View.VISIBLE); binding.bottomSheetDetails.icon.setVisibility(View.GONE); binding.bottomSheetDetails.wikiDataLl.setVisibility(View.GONE); - getPlaceData(place.getWikiDataEntityId(), place, marker1); + if (Objects.equals(updatedPlace.name, "")){ + getPlaceData(updatedPlace.getWikiDataEntityId(), updatedPlace, marker1); + }else { + marker.showInfoWindow(); + binding.bottomSheetDetails.dataCircularProgress.setVisibility(View.GONE); + binding.bottomSheetDetails.icon.setVisibility(View.VISIBLE); + binding.bottomSheetDetails.wikiDataLl.setVisibility(View.VISIBLE); + passInfoToSheet(place); + hideBottomSheet(); + } bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); return true; }); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/model/ResultTuple.kt b/app/src/main/java/fr/free/nrw/commons/nearby/model/ResultTuple.kt index eedcf2e29..161b0c07f 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/model/ResultTuple.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/model/ResultTuple.kt @@ -6,7 +6,7 @@ class ResultTuple { @SerializedName("xml:lang") val language: String val type: String - val value: String + var value: String constructor(lang: String, type: String, value: String) { this.language = lang diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.java b/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.java index 440cb5638..06d2e0066 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.java @@ -25,6 +25,7 @@ import fr.free.nrw.commons.nearby.Label; import fr.free.nrw.commons.nearby.MarkerPlaceGroup; import fr.free.nrw.commons.nearby.NearbyController; import fr.free.nrw.commons.nearby.NearbyFilterState; +import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract; import fr.free.nrw.commons.utils.LocationUtils; import fr.free.nrw.commons.wikidata.WikidataEditListener; @@ -213,19 +214,20 @@ public class NearbyParentFragmentPresenter * 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 placeToCenter list information and distances. + * @param nearbyPlaces This variable has placeToCenter list information and distances. */ - public void updateMapMarkers(NearbyController.NearbyPlacesInfo nearbyPlacesInfo, boolean shouldTrackPosition) { + public void updateMapMarkers(List nearbyPlaces, LatLng currentLatLng, + boolean shouldTrackPosition) { if (null != nearbyParentFragmentView) { nearbyParentFragmentView.clearAllMarkers(); List baseMarkers = NearbyController - .loadAttractionsFromLocationToBaseMarkerOptions(nearbyPlacesInfo.currentLatLng, + .loadAttractionsFromLocationToBaseMarkerOptions(currentLatLng, // Curlatlang will be used to calculate distances - nearbyPlacesInfo.placeList); + nearbyPlaces); nearbyParentFragmentView.updateMapMarkers(baseMarkers); lockUnlockNearby(false); // So that new location updates wont come nearbyParentFragmentView.setProgressBarVisibility(false); - nearbyParentFragmentView.updateListFragment(nearbyPlacesInfo.placeList); + nearbyParentFragmentView.updateListFragment(nearbyPlaces); } } diff --git a/app/src/main/resources/queries/query_for_item.rq b/app/src/main/resources/queries/query_for_item.rq index 31e9087e0..1a5210e04 100644 --- a/app/src/main/resources/queries/query_for_item.rq +++ b/app/src/main/resources/queries/query_for_item.rq @@ -13,7 +13,7 @@ SELECT WHERE { SERVICE { values ?item { - wd:${ENTITY} + ${ENTITY} } }