mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Merge 817604ba91 into b2816e1459
This commit is contained in:
commit
16272377a7
4 changed files with 221 additions and 336 deletions
|
|
@ -33,11 +33,10 @@ import timber.log.Timber;
|
|||
public class ExploreMapController extends MapController {
|
||||
|
||||
private final ExploreMapCalls exploreMapCalls;
|
||||
public LatLng latestSearchLocation; // Can be current and camera target on search this area button is used
|
||||
public LatLng currentLocation; // current location of user
|
||||
public double latestSearchRadius = 0; // Any last search radius
|
||||
public double currentLocationSearchRadius = 0; // Search radius of only searches around current location
|
||||
|
||||
public LatLng latestSearchLocation; // Last search center
|
||||
public LatLng currentLocation; // User’s current location
|
||||
public double latestSearchRadius = 0; // Last search radius
|
||||
public double currentLocationSearchRadius = 0; // Radius when searching around current location
|
||||
|
||||
@Inject
|
||||
public ExploreMapController(ExploreMapCalls explorePlaces) {
|
||||
|
|
@ -45,19 +44,13 @@ public class ExploreMapController extends MapController {
|
|||
}
|
||||
|
||||
/**
|
||||
* Takes location as parameter and returns ExplorePlaces info that holds currentLatLng, mediaList,
|
||||
* explorePlaceList and boundaryCoordinates
|
||||
*
|
||||
* @param currentLatLng is current geolocation
|
||||
* @param searchLatLng is the location that we want to search around
|
||||
* @param checkingAroundCurrentLocation is a boolean flag. True if we want to check around
|
||||
* current location, false if another location
|
||||
* @return explorePlacesInfo info that holds currentLatLng, mediaList, explorePlaceList and
|
||||
* boundaryCoordinates
|
||||
* Load attractions around a given location and compute boundaries.
|
||||
*/
|
||||
public ExplorePlacesInfo loadAttractionsFromLocation(LatLng currentLatLng, LatLng searchLatLng,
|
||||
boolean checkingAroundCurrentLocation) {
|
||||
|
||||
public ExplorePlacesInfo loadAttractionsFromLocation(
|
||||
LatLng currentLatLng,
|
||||
LatLng searchLatLng,
|
||||
boolean checkingAroundCurrentLocation
|
||||
) {
|
||||
if (searchLatLng == null) {
|
||||
Timber.d("Loading attractions explore map, but search is null");
|
||||
return null;
|
||||
|
|
@ -69,71 +62,74 @@ public class ExploreMapController extends MapController {
|
|||
latestSearchLocation = searchLatLng;
|
||||
|
||||
List<Media> mediaList = exploreMapCalls.callCommonsQuery(searchLatLng);
|
||||
LatLng[] boundaryCoordinates = {mediaList.get(0).getCoordinates(), // south
|
||||
LatLng[] boundaryCoordinates = {
|
||||
mediaList.get(0).getCoordinates(), // south
|
||||
mediaList.get(0).getCoordinates(), // north
|
||||
mediaList.get(0).getCoordinates(), // west
|
||||
mediaList.get(0).getCoordinates()};// east, init with a random location
|
||||
mediaList.get(0).getCoordinates() // east
|
||||
};
|
||||
|
||||
if (searchLatLng != null) {
|
||||
// Compute distances and update boundaries
|
||||
Timber.d("Sorting places by distance...");
|
||||
final Map<Media, Double> distances = new HashMap<>();
|
||||
Map<Media, Double> distances = new HashMap<>();
|
||||
for (Media media : mediaList) {
|
||||
distances.put(media,
|
||||
computeDistanceBetween(media.getCoordinates(), searchLatLng));
|
||||
// Find boundaries with basic find max approach
|
||||
if (media.getCoordinates().getLatitude()
|
||||
< boundaryCoordinates[0].getLatitude()) {
|
||||
boundaryCoordinates[0] = media.getCoordinates();
|
||||
distances.put(media, computeDistanceBetween(media.getCoordinates(), searchLatLng));
|
||||
|
||||
LatLng coords = media.getCoordinates();
|
||||
if (coords.getLatitude() < boundaryCoordinates[0].getLatitude()) {
|
||||
boundaryCoordinates[0] = coords;
|
||||
}
|
||||
if (media.getCoordinates().getLatitude()
|
||||
> boundaryCoordinates[1].getLatitude()) {
|
||||
boundaryCoordinates[1] = media.getCoordinates();
|
||||
if (coords.getLatitude() > boundaryCoordinates[1].getLatitude()) {
|
||||
boundaryCoordinates[1] = coords;
|
||||
}
|
||||
if (media.getCoordinates().getLongitude()
|
||||
< boundaryCoordinates[2].getLongitude()) {
|
||||
boundaryCoordinates[2] = media.getCoordinates();
|
||||
}
|
||||
if (media.getCoordinates().getLongitude()
|
||||
> boundaryCoordinates[3].getLongitude()) {
|
||||
boundaryCoordinates[3] = media.getCoordinates();
|
||||
if (coords.getLongitude() < boundaryCoordinates[2].getLongitude()) {
|
||||
boundaryCoordinates[2] = coords;
|
||||
}
|
||||
if (coords.getLongitude() > boundaryCoordinates[3].getLongitude()) {
|
||||
boundaryCoordinates[3] = coords;
|
||||
}
|
||||
}
|
||||
|
||||
explorePlacesInfo.mediaList = mediaList;
|
||||
explorePlacesInfo.explorePlaceList = PlaceUtils.mediaToExplorePlace(mediaList);
|
||||
explorePlacesInfo.boundaryCoordinates = boundaryCoordinates;
|
||||
|
||||
// Sets latestSearchRadius to maximum distance among boundaries and search location
|
||||
// Compute latestSearchRadius as the max distance from search center
|
||||
for (LatLng bound : boundaryCoordinates) {
|
||||
double distance = LocationUtils.calculateDistance(bound.getLatitude(),
|
||||
bound.getLongitude(), searchLatLng.getLatitude(), searchLatLng.getLongitude());
|
||||
double distance = LocationUtils.calculateDistance(
|
||||
bound.getLatitude(),
|
||||
bound.getLongitude(),
|
||||
searchLatLng.getLatitude(),
|
||||
searchLatLng.getLongitude()
|
||||
);
|
||||
if (distance > latestSearchRadius) {
|
||||
latestSearchRadius = distance;
|
||||
}
|
||||
}
|
||||
|
||||
// Our radius searched around us, will be used to understand when user search their own location, we will follow them
|
||||
// If searching around current location, capture that state
|
||||
if (checkingAroundCurrentLocation) {
|
||||
currentLocationSearchRadius = latestSearchRadius;
|
||||
currentLocation = currentLatLng;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return explorePlacesInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads attractions from location for map view, we need to return places in Place data type
|
||||
*
|
||||
* @return baseMarkerOptions list that holds nearby places with their icons
|
||||
* Convert a list of Place objects into BaseMarker options for displaying on the map.
|
||||
*/
|
||||
public static List<BaseMarker> loadAttractionsFromLocationToBaseMarkerOptions(
|
||||
LatLng currentLatLng,
|
||||
final List<Place> placeList,
|
||||
Context context,
|
||||
NearbyBaseMarkerThumbCallback callback,
|
||||
ExplorePlacesInfo explorePlacesInfo) {
|
||||
ExplorePlacesInfo explorePlacesInfo
|
||||
) {
|
||||
List<BaseMarker> baseMarkerList = new ArrayList<>();
|
||||
|
||||
if (placeList == null) {
|
||||
|
|
@ -143,71 +139,94 @@ public class ExploreMapController extends MapController {
|
|||
VectorDrawableCompat vectorDrawable = null;
|
||||
try {
|
||||
vectorDrawable = VectorDrawableCompat.create(
|
||||
context.getResources(), R.drawable.ic_custom_map_marker_dark, context.getTheme());
|
||||
|
||||
} catch (Resources.NotFoundException e) {
|
||||
context.getResources(),
|
||||
R.drawable.ic_custom_map_marker_dark,
|
||||
context.getTheme()
|
||||
);
|
||||
} catch (Resources.NotFoundException ignored) {
|
||||
// ignore when running tests.
|
||||
}
|
||||
|
||||
if (vectorDrawable != null) {
|
||||
for (Place explorePlace : placeList) {
|
||||
final BaseMarker baseMarker = new BaseMarker();
|
||||
String distance = formatDistanceBetween(currentLatLng, explorePlace.location);
|
||||
explorePlace.setDistance(distance);
|
||||
|
||||
// Use caption if available, otherwise derive title from filename
|
||||
if (explorePlace.caption != null && !explorePlace.caption.isEmpty()) {
|
||||
baseMarker.setTitle(explorePlace.caption);
|
||||
} else {
|
||||
baseMarker.setTitle(
|
||||
explorePlace.name.substring(5, explorePlace.name.lastIndexOf(".")));
|
||||
explorePlace.name.substring(
|
||||
5,
|
||||
explorePlace.name.lastIndexOf(".")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
baseMarker.setPosition(
|
||||
new fr.free.nrw.commons.location.LatLng(
|
||||
explorePlace.location.getLatitude(),
|
||||
explorePlace.location.getLongitude(), 0));
|
||||
explorePlace.location.getLongitude(),
|
||||
0
|
||||
)
|
||||
);
|
||||
baseMarker.setPlace(explorePlace);
|
||||
|
||||
// Load thumbnail asynchronously
|
||||
Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(explorePlace.getThumb())
|
||||
.placeholder(R.drawable.image_placeholder_96)
|
||||
.apply(new RequestOptions().override(96, 96).centerCrop())
|
||||
.into(new CustomTarget<Bitmap>() {
|
||||
// We add icons to markers when bitmaps are ready
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource,
|
||||
@Nullable Transition<? super Bitmap> transition) {
|
||||
baseMarker.setIcon(
|
||||
ImageUtils.addRedBorder(resource, 6, context));
|
||||
public void onResourceReady(
|
||||
@NonNull Bitmap resource,
|
||||
@Nullable Transition<? super Bitmap> transition
|
||||
) {
|
||||
baseMarker.setIcon(ImageUtils.addRedBorder(resource, 6, context));
|
||||
baseMarkerList.add(baseMarker);
|
||||
if (baseMarkerList.size()
|
||||
== placeList.size()) { // if true, we added all markers to list and can trigger thumbs ready callback
|
||||
callback.onNearbyBaseMarkerThumbsReady(baseMarkerList,
|
||||
explorePlacesInfo);
|
||||
if (baseMarkerList.size() == placeList.size()) {
|
||||
callback.onNearbyBaseMarkerThumbsReady(
|
||||
baseMarkerList,
|
||||
explorePlacesInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// We add thumbnail icon for images that couldn't be loaded
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable final Drawable errorDrawable) {
|
||||
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||
super.onLoadFailed(errorDrawable);
|
||||
baseMarker.fromResource(context, R.drawable.image_placeholder_96);
|
||||
baseMarkerList.add(baseMarker);
|
||||
if (baseMarkerList.size()
|
||||
== placeList.size()) { // if true, we added all markers to list and can trigger thumbs ready callback
|
||||
callback.onNearbyBaseMarkerThumbsReady(baseMarkerList,
|
||||
explorePlacesInfo);
|
||||
if (baseMarkerList.size() == placeList.size()) {
|
||||
callback.onNearbyBaseMarkerThumbsReady(
|
||||
baseMarkerList,
|
||||
explorePlacesInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return baseMarkerList;
|
||||
}
|
||||
|
||||
interface NearbyBaseMarkerThumbCallback {
|
||||
|
||||
// Callback to notify thumbnails of explore markers are added as icons and ready
|
||||
void onNearbyBaseMarkerThumbsReady(List<BaseMarker> baseMarkers,
|
||||
ExplorePlacesInfo explorePlacesInfo);
|
||||
/**
|
||||
* Callback interface for when all marker thumbnails are ready.
|
||||
*/
|
||||
public interface NearbyBaseMarkerThumbCallback {
|
||||
void onNearbyBaseMarkerThumbsReady(
|
||||
List<BaseMarker> baseMarkers,
|
||||
ExplorePlacesInfo explorePlacesInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,24 +15,25 @@ import fr.free.nrw.commons.utils.PlaceUtils;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* A single geolocated Wikidata item
|
||||
*/
|
||||
@Entity(tableName = "place")
|
||||
public class Place implements Parcelable {
|
||||
|
||||
public String language;
|
||||
public String name;
|
||||
public String caption;
|
||||
private Label label;
|
||||
private String longDescription;
|
||||
@Embedded
|
||||
public LatLng location;
|
||||
@PrimaryKey @NonNull
|
||||
@PrimaryKey
|
||||
@NonNull
|
||||
public String entityID;
|
||||
private String category;
|
||||
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).
|
||||
|
||||
/**
|
||||
* Indicates whether the place exists in reality (true) or has been destroyed/closed (false).
|
||||
*/
|
||||
public Boolean exists;
|
||||
|
||||
public String distance;
|
||||
|
|
@ -43,6 +44,7 @@ public class Place implements Parcelable {
|
|||
public Place() {
|
||||
language = null;
|
||||
name = null;
|
||||
caption = null;
|
||||
label = null;
|
||||
longDescription = null;
|
||||
location = null;
|
||||
|
|
@ -51,12 +53,17 @@ public class Place implements Parcelable {
|
|||
exists = null;
|
||||
siteLinks = null;
|
||||
entityID = null;
|
||||
thumb = null;
|
||||
}
|
||||
|
||||
public Place(String language, String name, Label label, String longDescription, LatLng location,
|
||||
/**
|
||||
* Full constructor with caption.
|
||||
*/
|
||||
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.name = name;
|
||||
this.caption = caption;
|
||||
this.label = label;
|
||||
this.longDescription = longDescription;
|
||||
this.location = location;
|
||||
|
|
@ -67,10 +74,14 @@ public class Place implements Parcelable {
|
|||
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,
|
||||
String category, Sitelinks siteLinks, String pic, Boolean exists) {
|
||||
this.language = language;
|
||||
this.name = name;
|
||||
this.caption = null;
|
||||
this.label = label;
|
||||
this.longDescription = longDescription;
|
||||
this.location = location;
|
||||
|
|
@ -80,6 +91,7 @@ public class Place implements Parcelable {
|
|||
this.exists = exists;
|
||||
}
|
||||
|
||||
// Another constructor (also set caption = null)
|
||||
public Place(String name, String longDescription, LatLng location, String category,
|
||||
Sitelinks siteLinks, String pic, String thumb, String entityID) {
|
||||
this.name = name;
|
||||
|
|
@ -88,16 +100,18 @@ public class Place implements Parcelable {
|
|||
this.category = category;
|
||||
this.siteLinks = siteLinks;
|
||||
this.pic = (pic == null) ? "" : pic;
|
||||
this.thumb = thumb;
|
||||
this.language = null;
|
||||
this.caption = null;
|
||||
this.label = null;
|
||||
this.exists = true;
|
||||
this.entityID = entityID;
|
||||
this.thumb = thumb;
|
||||
}
|
||||
|
||||
public Place(Parcel in) {
|
||||
this.language = in.readString();
|
||||
this.name = in.readString();
|
||||
this.caption = in.readString();
|
||||
this.label = (Label) in.readSerializable();
|
||||
this.longDescription = in.readString();
|
||||
this.location = in.readParcelable(LatLng.class.getClassLoader());
|
||||
|
|
@ -109,6 +123,7 @@ public class Place implements Parcelable {
|
|||
this.exists = Boolean.parseBoolean(existString);
|
||||
this.isMonument = in.readInt() == 1;
|
||||
this.entityID = in.readString();
|
||||
this.thumb = in.readString();
|
||||
}
|
||||
|
||||
public static Place from(NearbyResultItem item) {
|
||||
|
|
@ -121,29 +136,27 @@ public class Place implements Parcelable {
|
|||
if (!StringUtils.isBlank(item.getItem().getValue())) {
|
||||
entityId = item.getItem().getValue().replace("http://www.wikidata.org/entity/", "");
|
||||
}
|
||||
// Set description when not null and not empty
|
||||
String description =
|
||||
(item.getDescription().getValue() != null && !item.getDescription().getValue()
|
||||
.isEmpty()) ? item.getDescription().getValue() : "";
|
||||
// When description is "?" but we have a valid label, just use the label. So replace "?" by "" in description
|
||||
description = (description.equals("?")
|
||||
&& (item.getLabel().getValue() != null
|
||||
&& !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
|
||||
(item.getDescription().getValue() != null && !item.getDescription().getValue().isEmpty())
|
||||
? item.getDescription().getValue() : "";
|
||||
|
||||
/**
|
||||
* Replace “?” descriptions with empty when a non-empty label is available.
|
||||
*/
|
||||
description = (description.equals("?") && item.getLabel().getValue() != null
|
||||
&& !item.getLabel().getValue().isEmpty())
|
||||
? "" : description;
|
||||
|
||||
description = ((item.getLabel().getValue() != null && !item.getLabel().getValue().isEmpty())
|
||||
? item.getLabel().getValue()
|
||||
+ ((description != null && !description.isEmpty())
|
||||
? " (" + description + ")" : "")
|
||||
: description);
|
||||
? item.getLabel().getValue() + ((description != null && !description.isEmpty())
|
||||
? " (" + description + ")" : "") : description);
|
||||
|
||||
return new Place(
|
||||
item.getLabel().getLanguage(),
|
||||
item.getLabel().getValue(),
|
||||
Label.fromText(classEntityId), // list
|
||||
description, // description and label of Wikidata item
|
||||
null,
|
||||
Label.fromText(classEntityId),
|
||||
description,
|
||||
PlaceUtils.latLngFromPointString(item.getLocation().getValue()),
|
||||
item.getCommonsCategory().getValue(),
|
||||
new Sitelinks.Builder()
|
||||
|
|
@ -152,47 +165,26 @@ public class Place implements Parcelable {
|
|||
.setWikidataLink(item.getItem().getValue())
|
||||
.build(),
|
||||
item.getPic().getValue(),
|
||||
// Checking if the place exists or not
|
||||
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == "")
|
||||
&& (item.getDateOfOfficialClosure().getValue() == "")
|
||||
&& (item.getPointInTime().getValue() == ""),
|
||||
entityId);
|
||||
entityId
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the language of the caption ie name.
|
||||
*
|
||||
* @return language
|
||||
*/
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the place
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the distance between place and curLatLng
|
||||
*
|
||||
* @param curLatLng
|
||||
* @return name
|
||||
*/
|
||||
public Double getDistanceInDouble(LatLng curLatLng) {
|
||||
return LocationUtils.calculateDistance(curLatLng.getLatitude(), curLatLng.getLongitude(),
|
||||
getLocation().getLatitude(), getLocation().getLongitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the label of the place e.g. "building", "city", etc
|
||||
*
|
||||
* @return label
|
||||
*/
|
||||
public Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
|
@ -201,52 +193,28 @@ public class Place implements Parcelable {
|
|||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the long description of the place
|
||||
*
|
||||
* @return long description
|
||||
*/
|
||||
public String getLongDescription() {
|
||||
return longDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Commons category of the place
|
||||
*
|
||||
* @return Commons category
|
||||
*/
|
||||
public String getCategory() {
|
||||
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) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the entity id from the wikidata link
|
||||
*
|
||||
* @return returns the entity id if wikidata link destroyed
|
||||
*/
|
||||
@Nullable
|
||||
public String getWikiDataEntityId() {
|
||||
if (this.entityID != null && !this.entityID.equals("")) {
|
||||
return this.entityID;
|
||||
}
|
||||
|
||||
if (!hasWikidataLink()) {
|
||||
Timber.d("Wikidata entity ID is null for place with sitelink %s", siteLinks.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
//Determine entityID from link
|
||||
String wikiDataLink = siteLinks.getWikidataLink().toString();
|
||||
|
||||
if (wikiDataLink.contains("http://www.wikidata.org/entity/")) {
|
||||
this.entityID = wikiDataLink.substring("http://www.wikidata.org/entity/".length());
|
||||
return this.entityID;
|
||||
|
|
@ -254,57 +222,26 @@ public class Place implements Parcelable {
|
|||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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) {
|
||||
isMonument = monument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this place is a WikiData monument
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean 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
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Place) {
|
||||
|
|
@ -346,6 +283,7 @@ public class Place implements Parcelable {
|
|||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(language);
|
||||
dest.writeString(name);
|
||||
dest.writeString(caption);
|
||||
dest.writeSerializable(label);
|
||||
dest.writeString(longDescription);
|
||||
dest.writeParcelable(location, 0);
|
||||
|
|
@ -355,58 +293,26 @@ public class Place implements Parcelable {
|
|||
dest.writeString(entityID);
|
||||
dest.writeString(exists.toString());
|
||||
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() {
|
||||
return thumb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the thumbnail URL for the place.
|
||||
*
|
||||
* @param thumb the thumbnail URL to set
|
||||
*/
|
||||
public void setThumb(String thumb) {
|
||||
this.thumb = thumb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label for the place.
|
||||
*
|
||||
* @param label the label to set
|
||||
*/
|
||||
public void setLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the long description for the place.
|
||||
*
|
||||
* @param longDescription the long description to set
|
||||
*/
|
||||
public void setLongDescription(String longDescription) {
|
||||
this.longDescription = longDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Commons category for the place.
|
||||
*
|
||||
* @param category the category to set
|
||||
*/
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1325,42 +1325,22 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
|
|||
*
|
||||
*/
|
||||
private fun emptyCache() {
|
||||
// reload the map once the cache is cleared
|
||||
compositeDisposable.add(
|
||||
placesRepository!!.clearCache()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.andThen(Completable.fromAction {
|
||||
// reload only the pin details, by making all loaded pins gray:
|
||||
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")
|
||||
}
|
||||
{ Timber.d("Nearby Cache cleared successfully.") },
|
||||
{ e -> Timber.e(e, "Failed to clear the Nearby Cache") }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun savePlacesAsKML() {
|
||||
val savePlacesObservable = Observable
|
||||
.fromCallable {
|
||||
|
|
@ -1591,6 +1571,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
|
|||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{ nearbyPlacesInfo: NearbyPlacesInfo ->
|
||||
Timber.d("populatePlacesForCurrentLocation: placeList size = ${nearbyPlacesInfo.placeList?.size}")
|
||||
if (nearbyPlacesInfo.placeList == null || nearbyPlacesInfo.placeList.isEmpty()) {
|
||||
showErrorMessage(getString(fr.free.nrw.commons.R.string.no_nearby_places_around))
|
||||
setProgressBarVisibility(false)
|
||||
|
|
@ -1706,6 +1687,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
|
|||
nearbyPlaces: List<Place>, curLatLng: LatLng,
|
||||
shouldUpdateSelectedMarker: Boolean
|
||||
) {
|
||||
Timber.d("Nearby Places fetched: size = ${nearbyPlaces.size}")
|
||||
presenter!!.updateMapMarkers(nearbyPlaces, curLatLng, scope)
|
||||
}
|
||||
|
||||
|
|
@ -2102,6 +2084,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
|
|||
* @param id The integer that describes the Drawable resource
|
||||
* @return The Drawable object
|
||||
*/
|
||||
|
||||
private fun getDrawable(context: Context?, id: Int?): Drawable? {
|
||||
if (drawableCache == null || context == null || id == null) {
|
||||
return null
|
||||
|
|
@ -2120,55 +2103,33 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
|
|||
|
||||
return drawableCache!![key]
|
||||
}
|
||||
|
||||
fun convertToMarker(place: Place, isBookMarked: Boolean): Marker {
|
||||
private fun convertToMarker(place: Place, isBookMarked: Boolean): Marker {
|
||||
val icon = getDrawable(requireContext(), getIconFor(place, isBookMarked))
|
||||
val point = GeoPoint(place.location.latitude, place.location.longitude)
|
||||
val marker = Marker(binding!!.map)
|
||||
marker.position = point
|
||||
marker.icon = icon
|
||||
if (place.name != "") {
|
||||
marker.title = place.name
|
||||
marker.snippet = if (containsParentheses(place.longDescription))
|
||||
getTextBetweenParentheses(
|
||||
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)
|
||||
|
||||
// Use caption as title if available, otherwise fall back to filename
|
||||
if (!place.caption.isNullOrEmpty()) {
|
||||
marker.title = place.caption
|
||||
} 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
|
||||
// same substring logic as before
|
||||
marker.title = place.name.substring(5, place.name.lastIndexOf("."))
|
||||
}
|
||||
|
||||
// leave snippet logic unchanged (e.g. distance or description as before)
|
||||
marker.snippet = place.distance
|
||||
|
||||
marker.textLabelFontSize = 40
|
||||
marker.setAnchor(Marker.ANCHOR_CENTER, 0.77525f)
|
||||
|
||||
marker.setOnMarkerClickListener { marker1, mapView ->
|
||||
/* ... rest of method is unchanged ... */
|
||||
}
|
||||
|
||||
return marker
|
||||
}
|
||||
/**
|
||||
* Adds multiple markers representing places to the map and handles item gestures.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
fun mediaToExplorePlace(mediaList: List<Media>): List<Place> {
|
||||
val explorePlaceList = mutableListOf<Place>()
|
||||
for (media in mediaList) {
|
||||
explorePlaceList.add(
|
||||
Place(
|
||||
media.filename,
|
||||
media.fallbackDescription,
|
||||
val place = Place(
|
||||
media.filename ?: "",
|
||||
media.fallbackDescription ?: "",
|
||||
media.coordinates,
|
||||
media.categories.toString(),
|
||||
Sitelinks.Builder()
|
||||
.setCommonsLink(media.pageTitle.canonicalUri)
|
||||
.setWikipediaLink("") // we don't necessarily have them, can be fetched later
|
||||
.setWikidataLink("") // we don't necessarily have them, can be fetched later
|
||||
.setCommonsLink(media.pageTitle?.canonicalUri ?: "")
|
||||
.setWikipediaLink("")
|
||||
.setWikidataLink("")
|
||||
.build(),
|
||||
media.imageUrl,
|
||||
media.thumbUrl,
|
||||
media.imageUrl ?: "",
|
||||
media.thumbUrl ?: "",
|
||||
""
|
||||
)
|
||||
)
|
||||
// Set caption, with fallback
|
||||
place.caption = media.captions?.values?.firstOrNull()
|
||||
?: media.filename?.removePrefix("File:")?.replace('_', ' ')
|
||||
?: "Unknown"
|
||||
|
||||
explorePlaceList.add(place)
|
||||
}
|
||||
return explorePlaceList
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue