Fix: Show captions instead of filenames in Explore > Map (Fixes #6294)

This commit is contained in:
Rajas 2025-04-28 17:11:59 -04:00
parent d0f6c16878
commit 7dfec6be99
4 changed files with 147 additions and 246 deletions

View file

@ -154,8 +154,12 @@ public class ExploreMapController extends MapController {
String distance = formatDistanceBetween(currentLatLng, explorePlace.location); String distance = formatDistanceBetween(currentLatLng, explorePlace.location);
explorePlace.setDistance(distance); explorePlace.setDistance(distance);
baseMarker.setTitle( if (explorePlace.caption != null && !explorePlace.caption.isEmpty()) {
explorePlace.name.substring(5, explorePlace.name.lastIndexOf("."))); baseMarker.setTitle(explorePlace.caption);
} else {
baseMarker.setTitle(
explorePlace.name.substring(5, explorePlace.name.lastIndexOf(".")));
}
baseMarker.setPosition( baseMarker.setPosition(
new fr.free.nrw.commons.location.LatLng( new fr.free.nrw.commons.location.LatLng(
explorePlace.location.getLatitude(), explorePlace.location.getLatitude(),

View file

@ -15,26 +15,22 @@ import fr.free.nrw.commons.utils.PlaceUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import timber.log.Timber; import timber.log.Timber;
/**
* A single geolocated Wikidata item
*/
@Entity(tableName = "place") @Entity(tableName = "place")
public class Place implements Parcelable { public class Place implements Parcelable {
public String language; public String language;
public String name; public String name;
public String caption;
private Label label; private Label label;
private String longDescription; private String longDescription;
@Embedded @Embedded
public LatLng location; public LatLng location;
@PrimaryKey @NonNull @PrimaryKey
@NonNull
public String entityID; public String entityID;
private String category; private String category;
public String pic; public String pic;
// exists boolean will tell whether the place exists or not,
// For a place to be existing both destroyed and endTime property should be null but it is also not necessary for a non-existing place to have both properties either one property is enough (in such case that not given property will be considered as null).
public Boolean exists; public Boolean exists;
public String distance; public String distance;
public Sitelinks siteLinks; public Sitelinks siteLinks;
private boolean isMonument; private boolean isMonument;
@ -43,6 +39,7 @@ public class Place implements Parcelable {
public Place() { public Place() {
language = null; language = null;
name = null; name = null;
caption = null;
label = null; label = null;
longDescription = null; longDescription = null;
location = null; location = null;
@ -51,12 +48,15 @@ public class Place implements Parcelable {
exists = null; exists = null;
siteLinks = null; siteLinks = null;
entityID = null; entityID = null;
thumb = null;
} }
public Place(String language, String name, Label label, String longDescription, LatLng location, // New full constructor with caption
String category, Sitelinks siteLinks, String pic, Boolean exists, String entityID) { public Place(String language, String name, String caption, Label label, String longDescription, LatLng location,
String category, Sitelinks siteLinks, String pic, Boolean exists, String entityID) {
this.language = language; this.language = language;
this.name = name; this.name = name;
this.caption = caption;
this.label = label; this.label = label;
this.longDescription = longDescription; this.longDescription = longDescription;
this.location = location; this.location = location;
@ -67,10 +67,12 @@ public class Place implements Parcelable {
this.entityID = entityID; this.entityID = entityID;
} }
// Old constructor still kept (used elsewhere) sets caption to null
public Place(String language, String name, Label label, String longDescription, LatLng location, public Place(String language, String name, Label label, String longDescription, LatLng location,
String category, Sitelinks siteLinks, String pic, Boolean exists) { String category, Sitelinks siteLinks, String pic, Boolean exists) {
this.language = language; this.language = language;
this.name = name; this.name = name;
this.caption = null;
this.label = label; this.label = label;
this.longDescription = longDescription; this.longDescription = longDescription;
this.location = location; this.location = location;
@ -80,8 +82,9 @@ public class Place implements Parcelable {
this.exists = exists; this.exists = exists;
} }
// Another constructor (also set caption = null)
public Place(String name, String longDescription, LatLng location, String category, public Place(String name, String longDescription, LatLng location, String category,
Sitelinks siteLinks, String pic, String thumb, String entityID) { Sitelinks siteLinks, String pic, String thumb, String entityID) {
this.name = name; this.name = name;
this.longDescription = longDescription; this.longDescription = longDescription;
this.location = location; this.location = location;
@ -90,6 +93,7 @@ public class Place implements Parcelable {
this.pic = (pic == null) ? "" : pic; this.pic = (pic == null) ? "" : pic;
this.thumb = thumb; this.thumb = thumb;
this.language = null; this.language = null;
this.caption = null;
this.label = null; this.label = null;
this.exists = true; this.exists = true;
this.entityID = entityID; this.entityID = entityID;
@ -98,6 +102,7 @@ public class Place implements Parcelable {
public Place(Parcel in) { public Place(Parcel in) {
this.language = in.readString(); this.language = in.readString();
this.name = in.readString(); this.name = in.readString();
this.caption = in.readString();
this.label = (Label) in.readSerializable(); this.label = (Label) in.readSerializable();
this.longDescription = in.readString(); this.longDescription = in.readString();
this.location = in.readParcelable(LatLng.class.getClassLoader()); this.location = in.readParcelable(LatLng.class.getClassLoader());
@ -109,6 +114,7 @@ public class Place implements Parcelable {
this.exists = Boolean.parseBoolean(existString); this.exists = Boolean.parseBoolean(existString);
this.isMonument = in.readInt() == 1; this.isMonument = in.readInt() == 1;
this.entityID = in.readString(); this.entityID = in.readString();
this.thumb = in.readString();
} }
public static Place from(NearbyResultItem item) { public static Place from(NearbyResultItem item) {
@ -118,32 +124,26 @@ public class Place implements Parcelable {
classEntityId = itemClass.replace("http://www.wikidata.org/entity/", ""); classEntityId = itemClass.replace("http://www.wikidata.org/entity/", "");
} }
String entityId = ""; String entityId = "";
if (!StringUtils.isBlank(item.getItem().getValue())){ if (!StringUtils.isBlank(item.getItem().getValue())) {
entityId = item.getItem().getValue().replace("http://www.wikidata.org/entity/", ""); entityId = item.getItem().getValue().replace("http://www.wikidata.org/entity/", "");
} }
// Set description when not null and not empty
String description = String description =
(item.getDescription().getValue() != null && !item.getDescription().getValue() (item.getDescription().getValue() != null && !item.getDescription().getValue().isEmpty())
.isEmpty()) ? item.getDescription().getValue() : ""; ? item.getDescription().getValue() : "";
// When description is "?" but we have a valid label, just use the label. So replace "?" by "" in description
description = (description.equals("?") description = (description.equals("?") && (item.getLabel().getValue() != null
&& (item.getLabel().getValue() != null && !item.getLabel().getValue().isEmpty())) ? "" : description;
&& !item.getLabel().getValue().isEmpty()) ? "" : description);
/*
* If we have a valid label
* - If have a valid label add the description at the end of the string with parenthesis
* - If we don't have a valid label, string will include only the description. So add it without paranthesis
*/
description = ((item.getLabel().getValue() != null && !item.getLabel().getValue().isEmpty()) description = ((item.getLabel().getValue() != null && !item.getLabel().getValue().isEmpty())
? item.getLabel().getValue() ? item.getLabel().getValue() + ((description != null && !description.isEmpty())
+ ((description != null && !description.isEmpty()) ? " (" + description + ")" : "") : description);
? " (" + description + ")" : "")
: description);
return new Place( return new Place(
item.getLabel().getLanguage(), item.getLabel().getLanguage(),
item.getLabel().getValue(), item.getLabel().getValue(),
Label.fromText(classEntityId), // list null,
description, // description and label of Wikidata item Label.fromText(classEntityId),
description,
PlaceUtils.latLngFromPointString(item.getLocation().getValue()), PlaceUtils.latLngFromPointString(item.getLocation().getValue()),
item.getCommonsCategory().getValue(), item.getCommonsCategory().getValue(),
new Sitelinks.Builder() new Sitelinks.Builder()
@ -152,47 +152,26 @@ public class Place implements Parcelable {
.setWikidataLink(item.getItem().getValue()) .setWikidataLink(item.getItem().getValue())
.build(), .build(),
item.getPic().getValue(), item.getPic().getValue(),
// Checking if the place exists or not
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == "") (item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == "")
&& (item.getDateOfOfficialClosure().getValue() == "") && (item.getDateOfOfficialClosure().getValue() == "")
&& (item.getPointInTime().getValue()==""), && (item.getPointInTime().getValue() == ""),
entityId); entityId
);
} }
/**
* Gets the language of the caption ie name.
*
* @return language
*/
public String getLanguage() { public String getLanguage() {
return language; return language;
} }
/**
* Gets the name of the place
*
* @return name
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Gets the distance between place and curLatLng
*
* @param curLatLng
* @return name
*/
public Double getDistanceInDouble(LatLng curLatLng) { public Double getDistanceInDouble(LatLng curLatLng) {
return LocationUtils.calculateDistance(curLatLng.getLatitude(), curLatLng.getLongitude(), return LocationUtils.calculateDistance(curLatLng.getLatitude(), curLatLng.getLongitude(),
getLocation().getLatitude(), getLocation().getLongitude()); getLocation().getLatitude(), getLocation().getLongitude());
} }
/**
* Gets the label of the place e.g. "building", "city", etc
*
* @return label
*/
public Label getLabel() { public Label getLabel() {
return label; return label;
} }
@ -201,52 +180,28 @@ public class Place implements Parcelable {
return location; return location;
} }
/**
* Gets the long description of the place
*
* @return long description
*/
public String getLongDescription() { public String getLongDescription() {
return longDescription; return longDescription;
} }
/**
* Gets the Commons category of the place
*
* @return Commons category
*/
public String getCategory() { public String getCategory() {
return category; return category;
} }
/**
* Sets the distance of the place from the user's location
*
* @param distance distance of place from user's location
*/
public void setDistance(String distance) { public void setDistance(String distance) {
this.distance = distance; this.distance = distance;
} }
/**
* Extracts the entity id from the wikidata link
*
* @return returns the entity id if wikidata link destroyed
*/
@Nullable @Nullable
public String getWikiDataEntityId() { public String getWikiDataEntityId() {
if (this.entityID != null && !this.entityID.equals("")) { if (this.entityID != null && !this.entityID.equals("")) {
return this.entityID; return this.entityID;
} }
if (!hasWikidataLink()) { if (!hasWikidataLink()) {
Timber.d("Wikidata entity ID is null for place with sitelink %s", siteLinks.toString()); Timber.d("Wikidata entity ID is null for place with sitelink %s", siteLinks.toString());
return null; return null;
} }
//Determine entityID from link
String wikiDataLink = siteLinks.getWikidataLink().toString(); String wikiDataLink = siteLinks.getWikidataLink().toString();
if (wikiDataLink.contains("http://www.wikidata.org/entity/")) { if (wikiDataLink.contains("http://www.wikidata.org/entity/")) {
this.entityID = wikiDataLink.substring("http://www.wikidata.org/entity/".length()); this.entityID = wikiDataLink.substring("http://www.wikidata.org/entity/".length());
return this.entityID; return this.entityID;
@ -254,57 +209,26 @@ public class Place implements Parcelable {
return null; return null;
} }
/**
* Checks if the Wikidata item has a Wikipedia page associated with it
*
* @return true if there is a Wikipedia link
*/
public boolean hasWikipediaLink() { public boolean hasWikipediaLink() {
return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getWikipediaLink())); return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getWikipediaLink()));
} }
/**
* Checks if the Wikidata item has a Wikidata page associated with it
*
* @return true if there is a Wikidata link
*/
public boolean hasWikidataLink() { public boolean hasWikidataLink() {
return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getWikidataLink())); return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getWikidataLink()));
} }
/**
* Checks if the Wikidata item has a Commons page associated with it
*
* @return true if there is a Commons link
*/
public boolean hasCommonsLink() { public boolean hasCommonsLink() {
return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getCommonsLink())); return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getCommonsLink()));
} }
/**
* Sets that this place in nearby is a WikiData monument
*
* @param monument
*/
public void setMonument(final boolean monument) { public void setMonument(final boolean monument) {
isMonument = monument; isMonument = monument;
} }
/**
* Returns if this place is a WikiData monument
*
* @return
*/
public boolean isMonument() { public boolean isMonument() {
return isMonument; return isMonument;
} }
/**
* Check if we already have the exact same Place
*
* @param o Place being tested
* @return true if name and location of Place is exactly the same
*/
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof Place) { if (o instanceof Place) {
@ -346,6 +270,7 @@ public class Place implements Parcelable {
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(language); dest.writeString(language);
dest.writeString(name); dest.writeString(name);
dest.writeString(caption);
dest.writeSerializable(label); dest.writeSerializable(label);
dest.writeString(longDescription); dest.writeString(longDescription);
dest.writeParcelable(location, 0); dest.writeParcelable(location, 0);
@ -355,58 +280,26 @@ public class Place implements Parcelable {
dest.writeString(entityID); dest.writeString(entityID);
dest.writeString(exists.toString()); dest.writeString(exists.toString());
dest.writeInt(isMonument ? 1 : 0); dest.writeInt(isMonument ? 1 : 0);
dest.writeString(thumb);
} }
public static final Creator<Place> CREATOR = new Creator<Place>() {
@Override
public Place createFromParcel(Parcel in) {
return new Place(in);
}
@Override
public Place[] newArray(int size) {
return new Place[size];
}
};
public String getThumb() { public String getThumb() {
return thumb; return thumb;
} }
/**
* Sets the thumbnail URL for the place.
*
* @param thumb the thumbnail URL to set
*/
public void setThumb(String thumb) { public void setThumb(String thumb) {
this.thumb = thumb; this.thumb = thumb;
} }
/**
* Sets the label for the place.
*
* @param label the label to set
*/
public void setLabel(Label label) { public void setLabel(Label label) {
this.label = label; this.label = label;
} }
/**
* Sets the long description for the place.
*
* @param longDescription the long description to set
*/
public void setLongDescription(String longDescription) { public void setLongDescription(String longDescription) {
this.longDescription = longDescription; this.longDescription = longDescription;
} }
/**
* Sets the Commons category for the place.
*
* @param category the category to set
*/
public void setCategory(String category) { public void setCategory(String category) {
this.category = category; this.category = category;
} }
} }

View file

@ -1319,43 +1319,46 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
* Clears the Nearby local cache and then calls for pin details to be fetched afresh. * Clears the Nearby local cache and then calls for pin details to be fetched afresh.
* *
*/ */
private fun emptyCache() { private fun emptyCache() {
// reload the map once the cache is cleared compositeDisposable.add(
compositeDisposable.add( placesRepository!!.clearCache()
placesRepository!!.clearCache() .subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread()) .andThen(Completable.fromAction {
.andThen(Completable.fromAction { val newPlaceGroups = ArrayList<MarkerPlaceGroup>(
// reload only the pin details, by making all loaded pins gray: NearbyController.markerLabelList.size
val newPlaceGroups = ArrayList<MarkerPlaceGroup>(
NearbyController.markerLabelList.size
)
for (placeGroup in NearbyController.markerLabelList) {
val place = Place(
"", "", placeGroup.place.label, "",
placeGroup.place.getLocation(), "",
placeGroup.place.siteLinks, "", placeGroup.place.exists,
placeGroup.place.entityID
)
place.setDistance(placeGroup.place.distance)
place.isMonument = placeGroup.place.isMonument
newPlaceGroups.add(
MarkerPlaceGroup(placeGroup.isBookmarked, place)
)
}
presenter!!.loadPlacesDataAsync(newPlaceGroups, scope)
})
.subscribe(
{
Timber.d("Nearby Cache cleared successfully.")
},
{ throwable: Throwable? ->
Timber.e(throwable, "Failed to clear the Nearby Cache")
}
) )
) for (placeGroup in NearbyController.markerLabelList) {
} val old = placeGroup.place
// 11-arg constructor: (language, name, caption, label, longDesc,
// location, category, siteLinks, pic, exists, entityID)
val place = Place(
"", // language unused here
old.name, // name
"", // caption
old.label, // Label
old.longDescription, // longDescription
old.location, // location
old.category, // category
old.siteLinks, // siteLinks
old.pic, // pic
old.exists, // exists
old.entityID // entityID
)
place.setDistance(old.distance)
place.isMonument = old.isMonument
newPlaceGroups.add(
MarkerPlaceGroup(placeGroup.isBookmarked, place)
)
}
presenter!!.loadPlacesDataAsync(newPlaceGroups, scope)
})
.subscribe(
{ Timber.d("Nearby Cache cleared successfully.") },
{ e -> Timber.e(e, "Failed to clear the Nearby Cache") }
)
)
}
private fun savePlacesAsKML() { private fun savePlacesAsKML() {
val savePlacesObservable = Observable val savePlacesObservable = Observable
.fromCallable { .fromCallable {
@ -1586,6 +1589,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(
{ nearbyPlacesInfo: NearbyPlacesInfo -> { nearbyPlacesInfo: NearbyPlacesInfo ->
Timber.d("populatePlacesForCurrentLocation: placeList size = ${nearbyPlacesInfo.placeList?.size}")
if (nearbyPlacesInfo.placeList == null || nearbyPlacesInfo.placeList.isEmpty()) { if (nearbyPlacesInfo.placeList == null || nearbyPlacesInfo.placeList.isEmpty()) {
showErrorMessage(getString(fr.free.nrw.commons.R.string.no_nearby_places_around)) showErrorMessage(getString(fr.free.nrw.commons.R.string.no_nearby_places_around))
setProgressBarVisibility(false) setProgressBarVisibility(false)
@ -1701,6 +1705,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
nearbyPlaces: List<Place>, curLatLng: LatLng, nearbyPlaces: List<Place>, curLatLng: LatLng,
shouldUpdateSelectedMarker: Boolean shouldUpdateSelectedMarker: Boolean
) { ) {
Timber.d("Nearby Places fetched: size = ${nearbyPlaces.size}")
presenter!!.updateMapMarkers(nearbyPlaces, curLatLng, scope) presenter!!.updateMapMarkers(nearbyPlaces, curLatLng, scope)
} }
@ -2114,53 +2119,53 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
return drawableCache!![key] return drawableCache!![key]
} }
fun convertToMarker(place: Place, isBookMarked: Boolean): Marker { fun convertToMarker(place: Place, isBookMarked: Boolean): Marker {
val icon = getDrawable(requireContext(), getIconFor(place, isBookMarked)) val icon = getDrawable(requireContext(), getIconFor(place, isBookMarked))
val point = GeoPoint(place.location.latitude, place.location.longitude) val point = GeoPoint(place.location.latitude, place.location.longitude)
val marker = Marker(binding!!.map) val marker = Marker(binding!!.map)
marker.position = point marker.position = point
marker.icon = icon marker.icon = icon
if (place.name != "") { if (place.name != "") {
marker.title = place.name marker.title = place.name
marker.snippet = if (containsParentheses(place.longDescription)) marker.snippet = if (containsParentheses(place.longDescription))
getTextBetweenParentheses( getTextBetweenParentheses(place.longDescription)
place.longDescription else
) place.longDescription
else
place.longDescription
}
marker.textLabelFontSize = 40
// anchorV is 21.707/28.0 as icon height is 28dp while the pin base is at 21.707dp from top
marker.setAnchor(Marker.ANCHOR_CENTER, 0.77525f)
marker.setOnMarkerClickListener { marker1: Marker, mapView: MapView? ->
if (clickedMarker != null) {
clickedMarker!!.closeInfoWindow()
}
clickedMarker = marker1
if (!isNetworkErrorOccurred) {
binding!!.bottomSheetDetails.dataCircularProgress.visibility =
View.VISIBLE
binding!!.bottomSheetDetails.icon.visibility = View.GONE
binding!!.bottomSheetDetails.wikiDataLl.visibility = View.GONE
if (place.name == "") {
getPlaceData(place.wikiDataEntityId, place, marker1, isBookMarked)
} else {
marker.showInfoWindow()
binding!!.bottomSheetDetails.dataCircularProgress.visibility =
View.GONE
binding!!.bottomSheetDetails.icon.visibility = View.VISIBLE
binding!!.bottomSheetDetails.wikiDataLl.visibility = View.VISIBLE
passInfoToSheet(place)
hideBottomSheet()
}
bottomSheetDetailsBehavior!!.setState(BottomSheetBehavior.STATE_COLLAPSED)
} else {
marker.showInfoWindow()
}
true
}
return marker
} }
marker.textLabelFontSize = 40
marker.setAnchor(Marker.ANCHOR_CENTER, 0.77525f)
marker.setOnMarkerClickListener { marker1, mapView ->
if (clickedMarker != null) {
clickedMarker!!.closeInfoWindow()
}
clickedMarker = marker1
if (!isNetworkErrorOccurred) {
binding!!.bottomSheetDetails.dataCircularProgress.visibility = View.VISIBLE
binding!!.bottomSheetDetails.icon.visibility = View.GONE
binding!!.bottomSheetDetails.wikiDataLl.visibility = View.GONE
if (place.wikiDataEntityId.isNullOrEmpty()) {
marker.showInfoWindow()
binding!!.bottomSheetDetails.dataCircularProgress.visibility = View.GONE
binding!!.bottomSheetDetails.icon.visibility = View.VISIBLE
binding!!.bottomSheetDetails.wikiDataLl.visibility = View.VISIBLE
passInfoToSheet(place)
hideBottomSheet()
} else {
getPlaceData(place.wikiDataEntityId, place, marker1, isBookMarked)
}
bottomSheetDetailsBehavior!!.setState(BottomSheetBehavior.STATE_COLLAPSED)
} else {
marker.showInfoWindow()
}
true
}
return marker
}
/** /**
* Adds multiple markers representing places to the map and handles item gestures. * Adds multiple markers representing places to the map and handles item gestures.

View file

@ -19,31 +19,30 @@ object PlaceUtils {
} }
} }
/**
* Turns a Media list to a Place list by creating a new list in Place type
* @param mediaList
* @return
*/
@JvmStatic @JvmStatic
fun mediaToExplorePlace(mediaList: List<Media>): List<Place> { fun mediaToExplorePlace(mediaList: List<Media>): List<Place> {
val explorePlaceList = mutableListOf<Place>() val explorePlaceList = mutableListOf<Place>()
for (media in mediaList) { for (media in mediaList) {
explorePlaceList.add( val place = Place(
Place( media.filename ?: "",
media.filename, media.fallbackDescription ?: "",
media.fallbackDescription, media.coordinates,
media.coordinates, media.categories.toString(),
media.categories.toString(), Sitelinks.Builder()
Sitelinks.Builder() .setCommonsLink(media.pageTitle?.canonicalUri ?: "")
.setCommonsLink(media.pageTitle.canonicalUri) .setWikipediaLink("")
.setWikipediaLink("") // we don't necessarily have them, can be fetched later .setWikidataLink("")
.setWikidataLink("") // we don't necessarily have them, can be fetched later .build(),
.build(), media.imageUrl ?: "",
media.imageUrl, media.thumbUrl ?: "",
media.thumbUrl, ""
""
)
) )
// Set caption, with fallback
place.caption = media.captions?.values?.firstOrNull()
?: media.filename?.removePrefix("File:")?.replace('_', ' ')
?: "Unknown"
explorePlaceList.add(place)
} }
return explorePlaceList return explorePlaceList
} }