mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-28 05:13:53 +01:00
Made Split to Nearby Query into a fast query for coordinates + a details query for each pin (#5731)
* Splitted the query * Made changes to the query * Improvised query * Improvised query by dividing in the batches * Fixed failing tests * Improved batches * Improved sorting * Fixes issue caused by search this area button * Fixed failing tests * Fixed unnecessary reloads on onResume * Fixed few pins not loading on changing apps * Improved zoom level and fixed the pins not loading from the center * Removed toggle chips and changed pin's color * Fixed wikidata url * Fixed unit tests * Implemented retry with delay of 5000ms * Fixed exception issue and pins issue * Added change color icon to pin * Improved pin clicking * Removed search this area button * Implemented caching of places * Fixed unit test * Factorized methods * Changed primary key from location to entity id * Fixed tests * Fixed conflicts * Fixed unit test * Fixed unit test * Fixed the bug * Fixed issue with pin loading on the first launch * Updated javadocs * Temporary commit - only for testing * Replaced Temporary commit * Temporary commit - Added jcenter * Made minor changes * Fixed unit tests * Fixed unit tests * Fixed minor bug
This commit is contained in:
parent
ba6c8fe8d0
commit
2d63f351ed
39 changed files with 1147 additions and 814 deletions
|
|
@ -46,11 +46,11 @@ public class BookmarkLocationsDao {
|
|||
ContentProviderClient db = clientProvider.get();
|
||||
try {
|
||||
cursor = db.query(
|
||||
BookmarkLocationsContentProvider.BASE_URI,
|
||||
Table.ALL_FIELDS,
|
||||
null,
|
||||
new String[]{},
|
||||
null);
|
||||
BookmarkLocationsContentProvider.BASE_URI,
|
||||
Table.ALL_FIELDS,
|
||||
null,
|
||||
new String[]{},
|
||||
null);
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
items.add(fromCursor(cursor));
|
||||
}
|
||||
|
|
@ -126,11 +126,11 @@ public class BookmarkLocationsDao {
|
|||
ContentProviderClient db = clientProvider.get();
|
||||
try {
|
||||
cursor = db.query(
|
||||
BookmarkLocationsContentProvider.BASE_URI,
|
||||
Table.ALL_FIELDS,
|
||||
Table.COLUMN_NAME + "=?",
|
||||
new String[]{bookmarkLocation.name},
|
||||
null);
|
||||
BookmarkLocationsContentProvider.BASE_URI,
|
||||
Table.ALL_FIELDS,
|
||||
Table.COLUMN_NAME + "=?",
|
||||
new String[]{bookmarkLocation.name},
|
||||
null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ public class BookmarkLocationsDao {
|
|||
@NonNull
|
||||
Place fromCursor(final Cursor cursor) {
|
||||
final LatLng location = new LatLng(cursor.getDouble(cursor.getColumnIndex(Table.COLUMN_LAT)),
|
||||
cursor.getDouble(cursor.getColumnIndex(Table.COLUMN_LONG)), 1F);
|
||||
cursor.getDouble(cursor.getColumnIndex(Table.COLUMN_LONG)), 1F);
|
||||
|
||||
final Sitelinks.Builder builder = new Sitelinks.Builder();
|
||||
builder.setWikipediaLink(cursor.getString(cursor.getColumnIndex(Table.COLUMN_WIKIPEDIA_LINK)));
|
||||
|
|
@ -207,40 +207,40 @@ public class BookmarkLocationsDao {
|
|||
|
||||
// NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES.
|
||||
public static final String[] ALL_FIELDS = {
|
||||
COLUMN_NAME,
|
||||
COLUMN_LANGUAGE,
|
||||
COLUMN_DESCRIPTION,
|
||||
COLUMN_CATEGORY,
|
||||
COLUMN_LABEL_TEXT,
|
||||
COLUMN_LABEL_ICON,
|
||||
COLUMN_LAT,
|
||||
COLUMN_LONG,
|
||||
COLUMN_IMAGE_URL,
|
||||
COLUMN_WIKIPEDIA_LINK,
|
||||
COLUMN_WIKIDATA_LINK,
|
||||
COLUMN_COMMONS_LINK,
|
||||
COLUMN_PIC,
|
||||
COLUMN_EXISTS,
|
||||
COLUMN_NAME,
|
||||
COLUMN_LANGUAGE,
|
||||
COLUMN_DESCRIPTION,
|
||||
COLUMN_CATEGORY,
|
||||
COLUMN_LABEL_TEXT,
|
||||
COLUMN_LABEL_ICON,
|
||||
COLUMN_LAT,
|
||||
COLUMN_LONG,
|
||||
COLUMN_IMAGE_URL,
|
||||
COLUMN_WIKIPEDIA_LINK,
|
||||
COLUMN_WIKIDATA_LINK,
|
||||
COLUMN_COMMONS_LINK,
|
||||
COLUMN_PIC,
|
||||
COLUMN_EXISTS,
|
||||
};
|
||||
|
||||
static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS " + TABLE_NAME;
|
||||
|
||||
static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " ("
|
||||
+ COLUMN_NAME + " STRING PRIMARY KEY,"
|
||||
+ COLUMN_LANGUAGE + " STRING,"
|
||||
+ COLUMN_DESCRIPTION + " STRING,"
|
||||
+ COLUMN_CATEGORY + " STRING,"
|
||||
+ COLUMN_LABEL_TEXT + " STRING,"
|
||||
+ COLUMN_LABEL_ICON + " INTEGER,"
|
||||
+ COLUMN_LAT + " DOUBLE,"
|
||||
+ COLUMN_LONG + " DOUBLE,"
|
||||
+ COLUMN_IMAGE_URL + " STRING,"
|
||||
+ COLUMN_WIKIPEDIA_LINK + " STRING,"
|
||||
+ COLUMN_WIKIDATA_LINK + " STRING,"
|
||||
+ COLUMN_COMMONS_LINK + " STRING,"
|
||||
+ COLUMN_PIC + " STRING,"
|
||||
+ COLUMN_EXISTS + " STRING"
|
||||
+ ");";
|
||||
+ COLUMN_NAME + " STRING PRIMARY KEY,"
|
||||
+ COLUMN_LANGUAGE + " STRING,"
|
||||
+ COLUMN_DESCRIPTION + " STRING,"
|
||||
+ COLUMN_CATEGORY + " STRING,"
|
||||
+ COLUMN_LABEL_TEXT + " STRING,"
|
||||
+ COLUMN_LABEL_ICON + " INTEGER,"
|
||||
+ COLUMN_LAT + " DOUBLE,"
|
||||
+ COLUMN_LONG + " DOUBLE,"
|
||||
+ COLUMN_IMAGE_URL + " STRING,"
|
||||
+ COLUMN_WIKIPEDIA_LINK + " STRING,"
|
||||
+ COLUMN_WIKIDATA_LINK + " STRING,"
|
||||
+ COLUMN_COMMONS_LINK + " STRING,"
|
||||
+ COLUMN_PIC + " STRING,"
|
||||
+ COLUMN_EXISTS + " STRING"
|
||||
+ ");";
|
||||
|
||||
public static void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_TABLE_STATEMENT);
|
||||
|
|
@ -308,4 +308,4 @@ public class BookmarkLocationsDao {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import androidx.room.TypeConverters
|
|||
import fr.free.nrw.commons.contributions.Contribution
|
||||
import fr.free.nrw.commons.contributions.ContributionDao
|
||||
import fr.free.nrw.commons.customselector.database.*
|
||||
import fr.free.nrw.commons.nearby.Place
|
||||
import fr.free.nrw.commons.nearby.PlaceDao
|
||||
import fr.free.nrw.commons.review.ReviewDao
|
||||
import fr.free.nrw.commons.review.ReviewEntity
|
||||
import fr.free.nrw.commons.upload.depicts.Depicts
|
||||
|
|
@ -15,10 +17,11 @@ import fr.free.nrw.commons.upload.depicts.DepictsDao
|
|||
* The database for accessing the respective DAOs
|
||||
*
|
||||
*/
|
||||
@Database(entities = [Contribution::class, Depicts::class, UploadedStatus::class, NotForUploadStatus::class, ReviewEntity::class], version = 16, exportSchema = false)
|
||||
@Database(entities = [Contribution::class, Depicts::class, UploadedStatus::class, NotForUploadStatus::class, ReviewEntity::class, Place::class], version = 18, exportSchema = false)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun contributionDao(): ContributionDao
|
||||
abstract fun PlaceDao(): PlaceDao
|
||||
abstract fun DepictsDao(): DepictsDao;
|
||||
abstract fun UploadedStatusDao(): UploadedStatusDao;
|
||||
abstract fun NotForUploadStatusDao(): NotForUploadStatusDao
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import fr.free.nrw.commons.CommonsApplication;
|
|||
import fr.free.nrw.commons.contributions.ChunkInfo;
|
||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.nearby.Sitelinks;
|
||||
import fr.free.nrw.commons.upload.WikidataPlace;
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -134,6 +136,18 @@ public class Converters {
|
|||
return readObjectWithTypeToken(depictedItems, new TypeToken<List<DepictedItem>>() {});
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static Sitelinks sitelinksFromString(String value) {
|
||||
Type type = new TypeToken<Sitelinks>() {}.getType();
|
||||
return new Gson().fromJson(value, type);
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static String fromSitelinks(Sitelinks sitelinks) {
|
||||
Gson gson = new Gson();
|
||||
return gson.toJson(sitelinks);
|
||||
}
|
||||
|
||||
private static String writeObjectToString(Object object) {
|
||||
return object == null ? null : getGson().toJson(object);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import fr.free.nrw.commons.data.DBOpenHelper;
|
|||
import fr.free.nrw.commons.db.AppDatabase;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.nearby.PlaceDao;
|
||||
import fr.free.nrw.commons.review.ReviewDao;
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
import fr.free.nrw.commons.upload.UploadController;
|
||||
|
|
@ -275,6 +276,11 @@ public class CommonsApplicationModule {
|
|||
return appDatabase.contributionDao();
|
||||
}
|
||||
|
||||
@Provides
|
||||
public PlaceDao providesPlaceDao(AppDatabase appDatabase) {
|
||||
return appDatabase.PlaceDao();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reference of DepictsDao class.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -397,6 +397,54 @@ public class OkHttpJsonApiClient {
|
|||
throw new Exception(response.message());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of places based on the provided list of places and language.
|
||||
*
|
||||
* @param placeList A list of Place objects for which to fetch information.
|
||||
* @param language The language code to use for the query.
|
||||
* @return A list of Place objects with additional information retrieved from Wikidata, or null
|
||||
* if an error occurs.
|
||||
* @throws IOException If there is an issue with reading the resource file or executing the HTTP
|
||||
* request.
|
||||
*/
|
||||
@Nullable
|
||||
public List<Place> getPlaces(
|
||||
final List<Place> 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<NearbyResultItem> bindings = nearbyResponse.getResults().getBindings();
|
||||
final List<Place> 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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -131,6 +131,17 @@ public class NearbyController extends MapController {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of places based on the provided list of places and language.
|
||||
*
|
||||
* @param placeList A list of Place objects for which to fetch information.
|
||||
* @return A list of Place objects obtained from the Wikidata query.
|
||||
* @throws Exception If an error occurs during the retrieval process.
|
||||
*/
|
||||
public List<Place> getPlaces(List<Place> placeList) throws Exception {
|
||||
return nearbyPlaces.getPlaces(placeList, Locale.getDefault().getLanguage());
|
||||
}
|
||||
|
||||
public static LatLng calculateNorthEast(double latitude, double longitude, double distance) {
|
||||
double lat1 = Math.toRadians(latitude);
|
||||
double deltaLat = distance * 0.008;
|
||||
|
|
|
|||
|
|
@ -120,6 +120,22 @@ public class NearbyPlaces {
|
|||
customQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of places based on the provided list of places and language.
|
||||
*
|
||||
* This method fetches place information from a Wikidata query using the specified language.
|
||||
*
|
||||
* @param placeList A list of Place objects for which to fetch information.
|
||||
* @param lang The language code to use for the query.
|
||||
* @return A list of Place objects obtained from the Wikidata query.
|
||||
* @throws Exception If an error occurs during the retrieval process.
|
||||
*/
|
||||
public List<Place> getPlaces(final List<Place> placeList,
|
||||
final String lang) throws Exception {
|
||||
return okHttpJsonApiClient
|
||||
.getPlaces(placeList, lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the Wikidata query to retrieve the KML String
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,34 +3,38 @@ package fr.free.nrw.commons.nearby;
|
|||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.nearby.model.NearbyResultItem;
|
||||
import fr.free.nrw.commons.utils.LocationUtils;
|
||||
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 final String language;
|
||||
public final String name;
|
||||
private final Label label;
|
||||
private final String longDescription;
|
||||
public final LatLng location;
|
||||
private final String category;
|
||||
public final String pic;
|
||||
public String language;
|
||||
public String name;
|
||||
private Label label;
|
||||
private String longDescription;
|
||||
public LatLng location;
|
||||
@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).
|
||||
public final Boolean exists;
|
||||
public Boolean exists;
|
||||
|
||||
public String distance;
|
||||
public final Sitelinks siteLinks;
|
||||
public Sitelinks siteLinks;
|
||||
private boolean isMonument;
|
||||
private String thumb;
|
||||
|
||||
|
|
@ -44,9 +48,11 @@ public class Place implements Parcelable {
|
|||
pic = null;
|
||||
exists = null;
|
||||
siteLinks = null;
|
||||
entityID = null;
|
||||
}
|
||||
|
||||
public Place(String language,String name, Label label, String longDescription, LatLng location, String category, Sitelinks siteLinks, String pic, Boolean exists) {
|
||||
public Place(String language, String name, Label label, String longDescription, LatLng location,
|
||||
String category, Sitelinks siteLinks, String pic, Boolean exists, String entityID) {
|
||||
this.language = language;
|
||||
this.name = name;
|
||||
this.label = label;
|
||||
|
|
@ -54,21 +60,37 @@ public class Place implements Parcelable {
|
|||
this.location = location;
|
||||
this.category = category;
|
||||
this.siteLinks = siteLinks;
|
||||
this.pic = (pic == null) ? "":pic;
|
||||
this.pic = (pic == null) ? "" : pic;
|
||||
this.exists = exists;
|
||||
this.entityID = entityID;
|
||||
}
|
||||
|
||||
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.label = label;
|
||||
this.longDescription = longDescription;
|
||||
this.location = location;
|
||||
this.category = category;
|
||||
this.siteLinks = siteLinks;
|
||||
this.pic = (pic == null) ? "" : pic;
|
||||
this.exists = exists;
|
||||
}
|
||||
|
||||
public Place(String name, String longDescription, LatLng location, String category, Sitelinks siteLinks, String pic, String thumb) {
|
||||
public Place(String name, String longDescription, LatLng location, String category,
|
||||
Sitelinks siteLinks, String pic, String thumb, String entityID) {
|
||||
this.name = name;
|
||||
this.longDescription = longDescription;
|
||||
this.location = location;
|
||||
this.category = category;
|
||||
this.siteLinks = siteLinks;
|
||||
this.pic = (pic == null) ? "":pic;
|
||||
this.pic = (pic == null) ? "" : pic;
|
||||
this.thumb = thumb;
|
||||
this.language = null;
|
||||
this.label = null;
|
||||
this.exists = true;
|
||||
this.entityID = entityID;
|
||||
}
|
||||
|
||||
public Place(Parcel in) {
|
||||
|
|
@ -80,19 +102,27 @@ public class Place implements Parcelable {
|
|||
this.category = in.readString();
|
||||
this.siteLinks = in.readParcelable(Sitelinks.class.getClassLoader());
|
||||
String picString = in.readString();
|
||||
this.pic = (picString == null) ? "":picString;
|
||||
this.pic = (picString == null) ? "" : picString;
|
||||
String existString = in.readString();
|
||||
this.exists = Boolean.parseBoolean(existString);
|
||||
this.isMonument = in.readInt() == 1;
|
||||
this.entityID = in.readString();
|
||||
}
|
||||
|
||||
public static Place from(NearbyResultItem item) {
|
||||
String itemClass = item.getClassName().getValue();
|
||||
String classEntityId = "";
|
||||
if(!StringUtils.isBlank(itemClass)) {
|
||||
if (!StringUtils.isBlank(itemClass)) {
|
||||
classEntityId = itemClass.replace("http://www.wikidata.org/entity/", "");
|
||||
}
|
||||
String entityId = "";
|
||||
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() : "";
|
||||
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
|
||||
|
|
@ -104,8 +134,8 @@ public class Place implements Parcelable {
|
|||
*/
|
||||
description = ((item.getLabel().getValue() != null && !item.getLabel().getValue().isEmpty())
|
||||
? item.getLabel().getValue()
|
||||
+ ((description != null && !description.isEmpty())
|
||||
? " (" + description + ")" : "")
|
||||
+ ((description != null && !description.isEmpty())
|
||||
? " (" + description + ")" : "")
|
||||
: description);
|
||||
return new Place(
|
||||
item.getLabel().getLanguage(),
|
||||
|
|
@ -121,11 +151,12 @@ public class Place implements Parcelable {
|
|||
.build(),
|
||||
item.getPic().getValue(),
|
||||
// Checking if the place exists or not
|
||||
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == ""));
|
||||
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == ""), entityId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the language of the caption ie name.
|
||||
*
|
||||
* @return language
|
||||
*/
|
||||
public String getLanguage() {
|
||||
|
|
@ -134,12 +165,27 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Gets the name of the place
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String getName() { return name; }
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/** Gets the label of the place
|
||||
* e.g. "building", "city", etc
|
||||
/**
|
||||
* 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() {
|
||||
|
|
@ -152,6 +198,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Gets the long description of the place
|
||||
*
|
||||
* @return long description
|
||||
*/
|
||||
public String getLongDescription() {
|
||||
|
|
@ -160,12 +207,16 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Gets the Commons category of the place
|
||||
*
|
||||
* @return Commons category
|
||||
*/
|
||||
public String getCategory() {return 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) {
|
||||
|
|
@ -174,6 +225,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Extracts the entity id from the wikidata link
|
||||
*
|
||||
* @return returns the entity id if wikidata link destroyed
|
||||
*/
|
||||
@Nullable
|
||||
|
|
@ -189,6 +241,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Checks if the Wikidata item has a Wikipedia page associated with it
|
||||
*
|
||||
* @return true if there is a Wikipedia link
|
||||
*/
|
||||
public boolean hasWikipediaLink() {
|
||||
|
|
@ -197,6 +250,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Checks if the Wikidata item has a Wikidata page associated with it
|
||||
*
|
||||
* @return true if there is a Wikidata link
|
||||
*/
|
||||
public boolean hasWikidataLink() {
|
||||
|
|
@ -205,6 +259,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Checks if the Wikidata item has a Commons page associated with it
|
||||
*
|
||||
* @return true if there is a Commons link
|
||||
*/
|
||||
public boolean hasCommonsLink() {
|
||||
|
|
@ -213,6 +268,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Sets that this place in nearby is a WikiData monument
|
||||
*
|
||||
* @param monument
|
||||
*/
|
||||
public void setMonument(final boolean monument) {
|
||||
|
|
@ -221,6 +277,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* Returns if this place is a WikiData monument
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isMonument() {
|
||||
|
|
@ -229,6 +286,7 @@ public class Place implements Parcelable {
|
|||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -250,17 +308,18 @@ public class Place implements Parcelable {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "Place{" +
|
||||
"name='" + name + '\'' +
|
||||
", lang='" + language + '\'' +
|
||||
", label='" + label + '\'' +
|
||||
", longDescription='" + longDescription + '\'' +
|
||||
", location='" + location + '\'' +
|
||||
", category='" + category + '\'' +
|
||||
", distance='" + distance + '\'' +
|
||||
", siteLinks='" + siteLinks.toString() + '\'' +
|
||||
", pic='" + pic + '\'' +
|
||||
", exists='" + exists.toString() + '\'' +
|
||||
'}';
|
||||
"name='" + name + '\'' +
|
||||
", lang='" + language + '\'' +
|
||||
", label='" + label + '\'' +
|
||||
", longDescription='" + longDescription + '\'' +
|
||||
", location='" + location + '\'' +
|
||||
", category='" + category + '\'' +
|
||||
", distance='" + distance + '\'' +
|
||||
", siteLinks='" + siteLinks.toString() + '\'' +
|
||||
", pic='" + pic + '\'' +
|
||||
", exists='" + exists.toString() + '\'' +
|
||||
", entityID='" + entityID + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -278,6 +337,7 @@ public class Place implements Parcelable {
|
|||
dest.writeString(category);
|
||||
dest.writeParcelable(siteLinks, 0);
|
||||
dest.writeString(pic);
|
||||
dest.writeString(entityID);
|
||||
dest.writeString(exists.toString());
|
||||
dest.writeInt(isMonument ? 1 : 0);
|
||||
}
|
||||
|
|
@ -298,7 +358,40 @@ public class Place implements Parcelable {
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
45
app/src/main/java/fr/free/nrw/commons/nearby/PlaceDao.java
Normal file
45
app/src/main/java/fr/free/nrw/commons/nearby/PlaceDao.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.OnConflictStrategy;
|
||||
import androidx.room.Query;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import io.reactivex.Completable;
|
||||
|
||||
/**
|
||||
* Data Access Object (DAO) for accessing the Place entity in the database.
|
||||
* This class provides methods for storing and retrieving Place objects,
|
||||
* utilized for the caching of places in the Nearby Map feature.
|
||||
*/
|
||||
@Dao
|
||||
public abstract class PlaceDao {
|
||||
|
||||
/**
|
||||
* Inserts a Place object into the database.
|
||||
* If a conflict occurs, the existing entry will be replaced.
|
||||
*
|
||||
* @param place The Place object to be inserted.
|
||||
*/
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
public abstract void saveSynchronous(Place place);
|
||||
|
||||
/**
|
||||
* Retrieves a Place object from the database based on the provided entity ID.
|
||||
*
|
||||
* @param entity The entity ID of the Place to be retrieved.
|
||||
* @return The Place object with the specified entity ID.
|
||||
*/
|
||||
@Query("SELECT * from place WHERE entityID=:entity")
|
||||
public abstract Place getPlace(String entity);
|
||||
|
||||
/**
|
||||
* Saves a Place object asynchronously into the database.
|
||||
*/
|
||||
public Completable save(final Place place) {
|
||||
return Completable
|
||||
.fromAction(() -> {
|
||||
saveSynchronous(place);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import io.reactivex.Completable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* The LocalDataSource class for Places
|
||||
*/
|
||||
public class PlacesLocalDataSource {
|
||||
|
||||
private final PlaceDao placeDao;
|
||||
|
||||
@Inject
|
||||
public PlacesLocalDataSource(
|
||||
final PlaceDao placeDao) {
|
||||
this.placeDao = placeDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Place object from the database based on the provided entity ID.
|
||||
*
|
||||
* @param entityID The entity ID of the Place to be retrieved.
|
||||
* @return The Place object with the specified entity ID.
|
||||
*/
|
||||
public Place fetchPlace(String entityID){
|
||||
return placeDao.getPlace(entityID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a Place object asynchronously into the database.
|
||||
*
|
||||
* @param place The Place object to be saved.
|
||||
* @return A Completable that completes once the save operation is done.
|
||||
*/
|
||||
public Completable savePlace(Place place) {
|
||||
return placeDao.save(place);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import io.reactivex.Completable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* The PlacesRepository class acts as a repository for Place entities.
|
||||
* It interacts with the PlacesLocalDataSource to perform database operations.
|
||||
*/
|
||||
public class PlacesRepository {
|
||||
|
||||
private PlacesLocalDataSource localDataSource;
|
||||
|
||||
@Inject
|
||||
public PlacesRepository(PlacesLocalDataSource localDataSource) {
|
||||
this.localDataSource = localDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a Place object asynchronously into the database.
|
||||
*
|
||||
* @param place The Place object to be saved.
|
||||
* @return A Completable that completes once the save operation is done.
|
||||
*/
|
||||
public Completable save(Place place){
|
||||
return localDataSource.savePlace(place);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Place object from the database based on the provided entity ID.
|
||||
*
|
||||
* @param entityID The entity ID of the Place to be retrieved.
|
||||
* @return The Place object with the specified entity ID.
|
||||
*/
|
||||
public Place fetchPlace(String entityID){
|
||||
return localDataSource.fetchPlace(entityID);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,10 +42,6 @@ public interface NearbyParentFragmentContract {
|
|||
|
||||
void hideBottomDetailsSheet();
|
||||
|
||||
void addSearchThisAreaButtonAction();
|
||||
|
||||
void setSearchThisAreaButtonVisibility(boolean isVisible);
|
||||
|
||||
void setProgressBarVisibility(boolean isVisible);
|
||||
|
||||
boolean isDetailsBottomSheetVisible();
|
||||
|
|
@ -76,8 +72,7 @@ public interface NearbyParentFragmentContract {
|
|||
|
||||
void filterOutAllMarkers();
|
||||
|
||||
void filterMarkersByLabels(List<Label> selectedLabels, boolean existsSelected,
|
||||
boolean needPhotoSelected, boolean wlmSelected, boolean filterForPlaceState,
|
||||
void filterMarkersByLabels(List<Label> selectedLabels, boolean filterForPlaceState,
|
||||
boolean filterForAllNoneType);
|
||||
|
||||
LatLng getCameraTarget();
|
||||
|
|
@ -97,6 +92,8 @@ public interface NearbyParentFragmentContract {
|
|||
boolean isAdvancedQueryFragmentVisible();
|
||||
|
||||
void showHideAdvancedQueryFragment(boolean shouldShow);
|
||||
|
||||
void stopQuery();
|
||||
}
|
||||
|
||||
interface NearbyListView {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ import android.location.Location;
|
|||
import android.view.View;
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import fr.free.nrw.commons.BaseMarker;
|
||||
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType;
|
||||
|
|
@ -25,9 +27,13 @@ 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.PlaceDao;
|
||||
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
|
||||
import fr.free.nrw.commons.upload.worker.WorkRequestHelper;
|
||||
import fr.free.nrw.commons.utils.LocationUtils;
|
||||
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import timber.log.Timber;
|
||||
|
|
@ -213,19 +219,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<Place> nearbyPlaces, LatLng currentLatLng,
|
||||
boolean shouldTrackPosition) {
|
||||
if (null != nearbyParentFragmentView) {
|
||||
nearbyParentFragmentView.clearAllMarkers();
|
||||
List<BaseMarker> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -278,18 +285,12 @@ public class NearbyParentFragmentPresenter
|
|||
case CHECKED:
|
||||
// Despite showing all labels NearbyFilterState still should be applied
|
||||
nearbyParentFragmentView.filterMarkersByLabels(selectedLabels,
|
||||
NearbyFilterState.getInstance().isExistsSelected(),
|
||||
NearbyFilterState.getInstance().isNeedPhotoSelected(),
|
||||
NearbyFilterState.getInstance().isWlmSelected(),
|
||||
filterForPlaceState, false);
|
||||
nearbyParentFragmentView.setRecyclerViewAdapterAllSelected();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
nearbyParentFragmentView.filterMarkersByLabels(selectedLabels,
|
||||
NearbyFilterState.getInstance().isExistsSelected(),
|
||||
NearbyFilterState.getInstance().isNeedPhotoSelected(),
|
||||
NearbyFilterState.getInstance().isWlmSelected(),
|
||||
filterForPlaceState, false);
|
||||
}
|
||||
}
|
||||
|
|
@ -327,17 +328,17 @@ public class NearbyParentFragmentPresenter
|
|||
}
|
||||
}
|
||||
|
||||
public View.OnClickListener onSearchThisAreaClicked() {
|
||||
return v -> {
|
||||
// Lock map operations during search this area operation
|
||||
// nearbyParentFragmentView.setMapCenter();
|
||||
nearbyParentFragmentView.setSearchThisAreaButtonVisibility(false);
|
||||
if (searchCloseToCurrentLocation()) {
|
||||
updateMapAndList(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||
} else {
|
||||
updateMapAndList(SEARCH_CUSTOM_AREA);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Initiates a search for places within the area. Depending on whether the search
|
||||
* is close to the current location, the map and list are updated
|
||||
* accordingly.
|
||||
*/
|
||||
public void searchInTheArea(){
|
||||
if (searchCloseToCurrentLocation()) {
|
||||
updateMapAndList(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||
} else {
|
||||
updateMapAndList(SEARCH_CUSTOM_AREA);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -368,7 +369,6 @@ public class NearbyParentFragmentPresenter
|
|||
|
||||
public void onMapReady() {
|
||||
if (null != nearbyParentFragmentView) {
|
||||
nearbyParentFragmentView.addSearchThisAreaButtonAction();
|
||||
initializeMapOperations();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ public class PlaceUtils {
|
|||
.setWikidataLink("") // we don't necessarily have them, can be fetched later
|
||||
.build(),
|
||||
media.getImageUrl(),
|
||||
media.getThumbUrl()));
|
||||
media.getThumbUrl(),
|
||||
""));
|
||||
}
|
||||
return explorePlaceList;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue