mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Compare commits
14 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b41882639e | ||
|
|
6ea6f3ebfd | ||
|
|
c973114ded | ||
|
|
74e8472d91 | ||
|
|
7deaf8dbae | ||
|
|
b47ed0546e | ||
|
|
51746934fc | ||
|
|
a98badff66 | ||
|
|
12221df75e | ||
|
|
e666e768c2 | ||
|
|
e8556a8ecd | ||
|
|
678bd33410 | ||
|
|
cba99ae5e3 | ||
|
|
bb3f8f3801 |
31 changed files with 309 additions and 280 deletions
|
|
@ -1,5 +1,8 @@
|
|||
# Wikimedia Commons for Android
|
||||
|
||||
## v3.1.0
|
||||
- Added Wiki Loves Monuments integration for WLM 2021
|
||||
|
||||
## v3.0.2
|
||||
- Fixed crash when uploading high res image
|
||||
- Fixed crash when viewing images in Explore
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ dependencies {
|
|||
implementation "com.squareup.okhttp3:okhttp-ws:$OKHTTP_VERSION"
|
||||
|
||||
// Logging
|
||||
implementation 'ch.acra:acra-dialog:5.8.1-beta11'
|
||||
implementation 'ch.acra:acra-mail:5.8.1-beta11'
|
||||
implementation 'ch.acra:acra-dialog:5.8.4'
|
||||
implementation 'ch.acra:acra-mail:5.8.4'
|
||||
implementation 'org.slf4j:slf4j-api:1.7.25'
|
||||
api('com.github.tony19:logback-android-classic:1.1.1-6') {
|
||||
exclude group: 'com.google.android', module: 'android'
|
||||
|
|
@ -150,8 +150,8 @@ android {
|
|||
defaultConfig {
|
||||
//applicationId 'fr.free.nrw.commons'
|
||||
|
||||
versionCode 1021
|
||||
versionName '3.0.2'
|
||||
versionCode 1024
|
||||
versionName '3.1.0'
|
||||
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
|
||||
|
||||
minSdkVersion 19
|
||||
|
|
@ -221,7 +221,7 @@ android {
|
|||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.force 'androidx.annotation:annotation:1.0.2'
|
||||
resolutionStrategy.force 'androidx.annotation:annotation:1.1.0'
|
||||
exclude module: 'okhttp-ws'
|
||||
}
|
||||
flavorDimensions 'tier'
|
||||
|
|
|
|||
|
|
@ -12,19 +12,19 @@ class Media constructor(
|
|||
* @return pageId for the current media object
|
||||
* Wikibase Identifier associated with media files
|
||||
*/
|
||||
val pageId: String = UUID.randomUUID().toString(),
|
||||
val thumbUrl: String? = null,
|
||||
var pageId: String = UUID.randomUUID().toString(),
|
||||
var thumbUrl: String? = null,
|
||||
|
||||
/**
|
||||
* Gets image URL
|
||||
* @return Image URL
|
||||
*/
|
||||
val imageUrl: String? = null,
|
||||
var imageUrl: String? = null,
|
||||
/**
|
||||
* Gets the name of the file.
|
||||
* @return file name as a string
|
||||
*/
|
||||
val filename: String? = null,
|
||||
var filename: String? = null,
|
||||
/**
|
||||
* Gets the file description.
|
||||
* @return file description as a string
|
||||
|
|
@ -41,7 +41,7 @@ class Media constructor(
|
|||
* Can be null.
|
||||
* @return upload date as a Date
|
||||
*/
|
||||
val dateUploaded: Date? = null,
|
||||
var dateUploaded: Date? = null,
|
||||
/**
|
||||
* Gets the license name of the file.
|
||||
* @return license as a String
|
||||
|
|
@ -52,7 +52,7 @@ class Media constructor(
|
|||
* @param license license name as a String
|
||||
*/
|
||||
var license: String? = null,
|
||||
val licenseUrl: String? = null,
|
||||
var licenseUrl: String? = null,
|
||||
/**
|
||||
* Gets the name of the creator of the file.
|
||||
* @return author name as a String
|
||||
|
|
@ -69,15 +69,15 @@ class Media constructor(
|
|||
* Gets the categories the file falls under.
|
||||
* @return file categories as an ArrayList of Strings
|
||||
*/
|
||||
val categories: List<String>? = null,
|
||||
var categories: List<String>? = null,
|
||||
/**
|
||||
* Gets the coordinates of where the file was created.
|
||||
* @return file coordinates as a LatLng
|
||||
*/
|
||||
var coordinates: LatLng? = null,
|
||||
val captions: Map<String, String> = emptyMap(),
|
||||
val descriptions: Map<String, String> = emptyMap(),
|
||||
val depictionIds: List<String> = emptyList()
|
||||
var captions: Map<String, String> = emptyMap(),
|
||||
var descriptions: Map<String, String> = emptyMap(),
|
||||
var depictionIds: List<String> = emptyList()
|
||||
) : Parcelable {
|
||||
|
||||
constructor(
|
||||
|
|
|
|||
|
|
@ -218,12 +218,11 @@ public class Utils {
|
|||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static boolean isMonumentsEnabled(final Date date, final JsonKvStore store){
|
||||
if(date.getDay()>=1 && date.getMonth()>=9 && date.getDay()<=31 && date.getMonth()<=10 ){
|
||||
public static boolean isMonumentsEnabled(final Date date) {
|
||||
if (date.getMonth() == 8) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return store.getBoolean(CAMPAIGNS_DEFAULT_PREFERENCE) || true ;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -241,7 +240,7 @@ public class Utils {
|
|||
* @return
|
||||
*/
|
||||
public static String getWLMEndDate() {
|
||||
return "31 Oct";
|
||||
return "30 Sep";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,9 +117,8 @@ public class CampaignView extends SwipableCardView {
|
|||
.parse(campaign.getStartDate());
|
||||
final Date endDate = CommonsDateUtil.getIso8601DateFormatShort()
|
||||
.parse(campaign.getEndDate());
|
||||
tvDates.setText(
|
||||
String.format("%1s - %2s", startDate,
|
||||
endDate));
|
||||
tvDates.setText(String.format("%1s - %2s", DateUtil.getExtraShortDateString(startDate),
|
||||
DateUtil.getExtraShortDateString(endDate)));
|
||||
}
|
||||
} catch (final ParseException e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ data class Contribution constructor(
|
|||
var dataLength: Long = 0,
|
||||
var dateCreated: Date? = null,
|
||||
var dateModified: Date? = null,
|
||||
var hasInvalidLocation : Int = 0
|
||||
var hasInvalidLocation : Int = 0,
|
||||
var countryCode : String? = null
|
||||
) : Parcelable {
|
||||
|
||||
fun completeWith(media: Media): Contribution {
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ public class ContributionsFragment
|
|||
private void updateClosestNearbyCardViewInfo() {
|
||||
curLatLng = locationManager.getLastLocation();
|
||||
compositeDisposable.add(Observable.fromCallable(() -> nearbyController
|
||||
.loadAttractionsFromLocation(curLatLng, curLatLng, true, false)) // thanks to boolean, it will only return closest result
|
||||
.loadAttractionsFromLocation(curLatLng, curLatLng, true, false, false)) // thanks to boolean, it will only return closest result
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::updateNearbyNotification,
|
||||
|
|
@ -528,7 +528,7 @@ public class ContributionsFragment
|
|||
* of campaigns on the campaigns card
|
||||
*/
|
||||
private void fetchCampaigns() {
|
||||
if (Utils.isMonumentsEnabled(new Date(), store)) {
|
||||
if (Utils.isMonumentsEnabled(new Date())) {
|
||||
campaignView.setCampaign(wlmCampaign);
|
||||
campaignView.setVisibility(View.VISIBLE);
|
||||
} else if (store.getBoolean(CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE, true)) {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import fr.free.nrw.commons.upload.depicts.DepictsDao
|
|||
* The database for accessing the respective DAOs
|
||||
*
|
||||
*/
|
||||
@Database(entities = [Contribution::class, Depicts::class], version = 8, exportSchema = false)
|
||||
@Database(entities = [Contribution::class, Depicts::class], version = 9, exportSchema = false)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun contributionDao(): ContributionDao
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.UPDAT
|
|||
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.gson.Gson;
|
||||
import fr.free.nrw.commons.campaigns.CampaignResponseDTO;
|
||||
import fr.free.nrw.commons.explore.depictions.DepictsClient;
|
||||
|
|
@ -264,107 +265,54 @@ public class OkHttpJsonApiClient {
|
|||
});
|
||||
}
|
||||
|
||||
public Observable<List<Place>> getNearbyPlaces(LatLng cur, String language, double radius)
|
||||
@Nullable
|
||||
public List<Place> getNearbyPlaces(final LatLng cur, final String language, final double radius,
|
||||
final boolean shouldQueryForMonuments)
|
||||
throws Exception {
|
||||
|
||||
Timber.d("Fetching nearby items at radius %s", radius);
|
||||
String wikidataQuery = FileUtils.readFromResource("/queries/nearby_query.rq");
|
||||
String query = wikidataQuery
|
||||
final String wikidataQuery;
|
||||
if (!shouldQueryForMonuments) {
|
||||
wikidataQuery = FileUtils.readFromResource("/queries/nearby_query.rq");
|
||||
} else {
|
||||
wikidataQuery = FileUtils.readFromResource("/queries/nearby_query_monuments.rq");
|
||||
}
|
||||
final String query = wikidataQuery
|
||||
.replace("${RAD}", String.format(Locale.ROOT, "%.2f", radius))
|
||||
.replace("${LAT}", String.format(Locale.ROOT, "%.4f", cur.getLatitude()))
|
||||
.replace("${LONG}", String.format(Locale.ROOT, "%.4f", cur.getLongitude()))
|
||||
.replace("${LANG}", language);
|
||||
|
||||
HttpUrl.Builder urlBuilder = HttpUrl
|
||||
final HttpUrl.Builder urlBuilder = HttpUrl
|
||||
.parse(sparqlQueryUrl)
|
||||
.newBuilder()
|
||||
.addQueryParameter("query", query)
|
||||
.addQueryParameter("format", "json");
|
||||
|
||||
Request request = new Request.Builder()
|
||||
final Request request = new Request.Builder()
|
||||
.url(urlBuilder.build())
|
||||
.build();
|
||||
|
||||
return Observable.fromCallable(() -> {
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
if (response != null && response.body() != null && response.isSuccessful()) {
|
||||
String json = response.body().string();
|
||||
if (json == null) {
|
||||
return new ArrayList<>();
|
||||
final Response response = okHttpClient.newCall(request).execute();
|
||||
if (response.body() != null && 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);
|
||||
if (shouldQueryForMonuments && item.getMonument() != null) {
|
||||
placeFromNearbyItem.setMonument(true);
|
||||
} else {
|
||||
placeFromNearbyItem.setMonument(false);
|
||||
}
|
||||
NearbyResponse nearbyResponse = gson.fromJson(json, NearbyResponse.class);
|
||||
List<NearbyResultItem> bindings = nearbyResponse.getResults().getBindings();
|
||||
List<Place> places = new ArrayList<>();
|
||||
for (NearbyResultItem item : bindings) {
|
||||
places.add(Place.from(item));
|
||||
}
|
||||
return places;
|
||||
places.add(placeFromNearbyItem);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
});
|
||||
return places;
|
||||
}
|
||||
throw new Exception(response.message());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wikidata query to fetch monuments
|
||||
*
|
||||
* @param cur : The current location coordinates
|
||||
* @param language : The language
|
||||
* @param radius : The radius around the current location within which we expect the results
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public Observable<List<Place>> getNearbyMonuments(LatLng cur, String language, final double radius){
|
||||
Timber.d("Fetching monuments at radius %s", radius);
|
||||
final String wikidataQuery;
|
||||
try {
|
||||
wikidataQuery = FileUtils.readFromResource("/queries/monuments_query.rq");
|
||||
if (TextUtils.isEmpty(language)) {
|
||||
language = "en";
|
||||
}
|
||||
String query = wikidataQuery
|
||||
.replace("${RAD}", String.format(Locale.ROOT, "%.2f", radius))
|
||||
.replace("${LAT}", String.format(Locale.ROOT, "%.4f", cur.getLatitude()))
|
||||
.replace("${LONG}", String.format(Locale.ROOT, "%.4f", cur.getLongitude()))
|
||||
.replace("${LANG}", language);
|
||||
|
||||
HttpUrl.Builder urlBuilder = HttpUrl
|
||||
.parse(sparqlQueryUrl)
|
||||
.newBuilder()
|
||||
.addQueryParameter("query", query)
|
||||
.addQueryParameter("format", "json");
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(urlBuilder.build())
|
||||
.build();
|
||||
|
||||
Timber.d("Monuments URL: %s", request.url().toString());
|
||||
|
||||
return Observable.fromCallable(() -> {
|
||||
final Response response = okHttpClient.newCall(request).execute();
|
||||
if (response != null && response.body() != null && response.isSuccessful()) {
|
||||
final String json = response.body().string();
|
||||
if (json == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
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 place = Place.from(item);
|
||||
place.setMonument(true);
|
||||
places.add(place);
|
||||
}
|
||||
return places;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
});
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
return Observable.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the QIDs of all Wikidata items that are subclasses of the given Wikidata item. Example:
|
||||
* bridge -> suspended bridge, aqueduct, etc
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ public class NearbyController {
|
|||
* @return NearbyPlacesInfo a variable holds Place list without distance information
|
||||
* and boundary coordinates of current Place List
|
||||
*/
|
||||
public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng, LatLng searchLatLng, boolean returnClosestResult, boolean checkingAroundCurrentLocation) throws IOException {
|
||||
public NearbyPlacesInfo loadAttractionsFromLocation(final LatLng curLatLng, final LatLng searchLatLng,
|
||||
final boolean returnClosestResult, final boolean checkingAroundCurrentLocation,
|
||||
final boolean shouldQueryForMonuments) throws Exception {
|
||||
|
||||
Timber.d("Loading attractions near %s", searchLatLng);
|
||||
NearbyPlacesInfo nearbyPlacesInfo = new NearbyPlacesInfo();
|
||||
|
|
@ -66,7 +68,9 @@ public class NearbyController {
|
|||
Timber.d("Loading attractions nearby, but curLatLng is null");
|
||||
return null;
|
||||
}
|
||||
List<Place> places = nearbyPlaces.radiusExpander(searchLatLng, Locale.getDefault().getLanguage(), returnClosestResult);
|
||||
List<Place> places = nearbyPlaces
|
||||
.radiusExpander(searchLatLng, Locale.getDefault().getLanguage(), returnClosestResult,
|
||||
shouldQueryForMonuments);
|
||||
|
||||
if (null != places && places.size() > 0) {
|
||||
LatLng[] boundaryCoordinates = {places.get(0).location, // south
|
||||
|
|
@ -128,11 +132,6 @@ public class NearbyController {
|
|||
}
|
||||
}
|
||||
|
||||
public Observable<List<Place>> queryWikiDataForMonuments(
|
||||
final LatLng latLng, final String language) {
|
||||
return nearbyPlaces.queryWikiDataForMonuments(latLng, language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads attractions from location for list view, we need to return Place data type.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -19,8 +17,8 @@ import timber.log.Timber;
|
|||
@Singleton
|
||||
public class NearbyPlaces {
|
||||
|
||||
private static final double INITIAL_RADIUS = 1.0; // in kilometers
|
||||
private static final double RADIUS_MULTIPLIER = 1.618;
|
||||
private static final double INITIAL_RADIUS = 0.3; // in kilometers
|
||||
private static final double RADIUS_MULTIPLIER = 2.0;
|
||||
public double radius = INITIAL_RADIUS;
|
||||
|
||||
private final OkHttpJsonApiClient okHttpJsonApiClient;
|
||||
|
|
@ -41,12 +39,12 @@ public class NearbyPlaces {
|
|||
* @param lang user's language
|
||||
* @param returnClosestResult true if only the nearest point is desired
|
||||
* @return list of places obtained
|
||||
* @throws IOException if query fails
|
||||
*/
|
||||
List<Place> radiusExpander(LatLng curLatLng, String lang, boolean returnClosestResult) throws IOException {
|
||||
List<Place> radiusExpander(final LatLng curLatLng, final String lang, final boolean returnClosestResult
|
||||
, final boolean shouldQueryForMonuments) throws Exception {
|
||||
|
||||
int minResults;
|
||||
double maxRadius;
|
||||
final int minResults;
|
||||
final double maxRadius;
|
||||
|
||||
List<Place> places = Collections.emptyList();
|
||||
|
||||
|
|
@ -57,19 +55,14 @@ public class NearbyPlaces {
|
|||
maxRadius = 5; // Return places only in 5 km area
|
||||
radius = INITIAL_RADIUS; // refresh radius again, otherwise increased radius is grater than MAX_RADIUS, thus returns null
|
||||
} else {
|
||||
minResults = 40;
|
||||
minResults = 20;
|
||||
maxRadius = 300.0; // in kilometers
|
||||
radius = INITIAL_RADIUS;
|
||||
}
|
||||
|
||||
// Increase the radius gradually to find a satisfactory number of nearby places
|
||||
while (radius <= maxRadius) {
|
||||
try {
|
||||
places = getFromWikidataQuery(curLatLng, lang, radius);
|
||||
} catch (final Exception e) {
|
||||
Timber.e(e, "Exception in fetching nearby places");
|
||||
break;
|
||||
}
|
||||
places = getFromWikidataQuery(curLatLng, lang, radius, shouldQueryForMonuments);
|
||||
Timber.d("%d results at radius: %f", places.size(), radius);
|
||||
if (places.size() >= minResults) {
|
||||
break;
|
||||
|
|
@ -89,16 +82,12 @@ public class NearbyPlaces {
|
|||
* @param cur coordinates of search location
|
||||
* @param lang user's language
|
||||
* @param radius radius for search, as determined by radiusExpander()
|
||||
* @param shouldQueryForMonuments should the query include properites for monuments
|
||||
* @return list of places obtained
|
||||
* @throws IOException if query fails
|
||||
*/
|
||||
public List<Place> getFromWikidataQuery(LatLng cur, String lang, double radius) throws Exception {
|
||||
return okHttpJsonApiClient.getNearbyPlaces(cur, lang, radius).blockingSingle();
|
||||
}
|
||||
|
||||
public Observable<List<Place>> queryWikiDataForMonuments(
|
||||
LatLng latLng, String language) {
|
||||
return okHttpJsonApiClient
|
||||
.getNearbyMonuments(latLng, language, radius);
|
||||
public List<Place> getFromWikidataQuery(final LatLng cur, final String lang,
|
||||
final double radius, final boolean shouldQueryForMonuments) throws Exception {
|
||||
return okHttpJsonApiClient.getNearbyPlaces(cur, lang, radius, shouldQueryForMonuments);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
isDarkTheme = systemThemeUtils.isDeviceInNightMode();
|
||||
if (Utils.isMonumentsEnabled(new Date(), applicationKvStore)) {
|
||||
if (Utils.isMonumentsEnabled(new Date())) {
|
||||
rlContainerWLMMonthMessage.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
rlContainerWLMMonthMessage.setVisibility(View.GONE);
|
||||
|
|
@ -513,7 +513,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
setBottomSheetCallbacks();
|
||||
decideButtonVisibilities();
|
||||
addActionToTitle();
|
||||
if(!Utils.isMonumentsEnabled(new Date(), applicationKvStore)){
|
||||
if (!Utils.isMonumentsEnabled(new Date())) {
|
||||
chipWlm.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -883,29 +883,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
|
||||
final Observable<NearbyPlacesInfo> nearbyPlacesInfoObservable = Observable
|
||||
.fromCallable(() -> nearbyController
|
||||
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, true));
|
||||
.loadAttractionsFromLocation(curlatLng, searchLatLng,
|
||||
false, true, Utils.isMonumentsEnabled(new Date())));
|
||||
|
||||
Observable<List<Place>> observableWikidataMonuments = Observable.empty();
|
||||
if(Utils.isMonumentsEnabled(new Date(), applicationKvStore)){
|
||||
observableWikidataMonuments =
|
||||
nearbyController
|
||||
.queryWikiDataForMonuments(searchLatLng, Locale.getDefault().getLanguage());
|
||||
|
||||
}
|
||||
|
||||
compositeDisposable.add(Observable.zip(nearbyPlacesInfoObservable
|
||||
, observableWikidataMonuments.onErrorReturn(throwable -> {
|
||||
showErrorMessage(getString(R.string.error_fetching_nearby_monuments) + throwable
|
||||
.getLocalizedMessage());
|
||||
return new ArrayList<>();
|
||||
}),
|
||||
(nearbyPlacesInfo, monuments) -> {
|
||||
final List<Place> places = mergeNearbyPlacesAndMonuments(nearbyPlacesInfo.placeList,
|
||||
monuments);
|
||||
nearbyPlacesInfo.placeList.clear();
|
||||
nearbyPlacesInfo.placeList.addAll(places);
|
||||
return nearbyPlacesInfo;
|
||||
}).subscribeOn(Schedulers.io())
|
||||
compositeDisposable.add(nearbyPlacesInfoObservable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(nearbyPlacesInfo -> {
|
||||
updateMapMarkers(nearbyPlacesInfo, true);
|
||||
|
|
@ -925,28 +907,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
|
||||
final Observable<NearbyPlacesInfo> nearbyPlacesInfoObservable = Observable
|
||||
.fromCallable(() -> nearbyController
|
||||
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, false));
|
||||
.loadAttractionsFromLocation(curlatLng, searchLatLng,
|
||||
false, true, Utils.isMonumentsEnabled(new Date())));
|
||||
|
||||
Observable<List<Place>> observableWikidataMonuments = Observable.empty();
|
||||
if (Utils.isMonumentsEnabled(new Date(), applicationKvStore)) {
|
||||
observableWikidataMonuments = nearbyController
|
||||
.queryWikiDataForMonuments(searchLatLng, Locale.getDefault().getLanguage());
|
||||
|
||||
}
|
||||
|
||||
compositeDisposable.add(Observable.zip(nearbyPlacesInfoObservable
|
||||
, observableWikidataMonuments.onErrorReturn(throwable -> {
|
||||
showErrorMessage(getString(R.string.error_fetching_nearby_monuments) + throwable
|
||||
.getLocalizedMessage());
|
||||
return new ArrayList<>();
|
||||
}),
|
||||
(nearbyPlacesInfo, monuments) -> {
|
||||
final List<Place> places = mergeNearbyPlacesAndMonuments(nearbyPlacesInfo.placeList,
|
||||
monuments);
|
||||
nearbyPlacesInfo.placeList.clear();
|
||||
nearbyPlacesInfo.placeList.addAll(places);
|
||||
return nearbyPlacesInfo;
|
||||
}).subscribeOn(Schedulers.io())
|
||||
compositeDisposable.add(nearbyPlacesInfoObservable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(nearbyPlacesInfo -> {
|
||||
updateMapMarkers(nearbyPlacesInfo, false);
|
||||
|
|
@ -961,25 +926,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* If a nearby place happens to be a monument as well, don't make the Pin's overlap, instead
|
||||
* show it as a monument
|
||||
*
|
||||
* @param nearbyPlaces
|
||||
* @param monuments
|
||||
* @return
|
||||
*/
|
||||
private List<Place> mergeNearbyPlacesAndMonuments(List<Place> nearbyPlaces, List<Place> monuments){
|
||||
List<Place> allPlaces= new ArrayList<>();
|
||||
allPlaces.addAll(monuments);
|
||||
for (Place place : nearbyPlaces){
|
||||
if(!allPlaces.contains(place)){
|
||||
allPlaces.add(place);
|
||||
}
|
||||
}
|
||||
return allPlaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates places for your location, should be used for finding nearby places around a
|
||||
* location where you are.
|
||||
|
|
@ -1248,8 +1194,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
.position(new LatLng(curLatLng.getLatitude(),
|
||||
curLatLng.getLongitude()));
|
||||
currentLocationMarkerOptions.setIcon(icon); // Set custom icon
|
||||
mapView.post(() -> currentLocationMarker = mapBox.addMarker(currentLocationMarkerOptions));
|
||||
|
||||
mapView.post(
|
||||
() -> currentLocationMarker = mapBox.addMarker(currentLocationMarkerOptions));
|
||||
|
||||
final List<LatLng> circle = UiUtils
|
||||
.createCircleArray(curLatLng.getLatitude(), curLatLng.getLongitude(),
|
||||
|
|
@ -1259,8 +1205,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
.addAll(circle)
|
||||
.strokeColor(getResources().getColor(R.color.current_marker_stroke))
|
||||
.fillColor(getResources().getColor(R.color.current_marker_fill));
|
||||
mapView.post(() -> currentLocationPolygon = mapBox.addPolygon(currentLocationPolygonOptions));
|
||||
|
||||
mapView.post(
|
||||
() -> currentLocationPolygon = mapBox
|
||||
.addPolygon(currentLocationPolygonOptions));
|
||||
});
|
||||
} else {
|
||||
Timber.d("not adding current location marker..current location is null");
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ class NearbyResultItem(private val item: ResultTuple?,
|
|||
@field:SerializedName("pic") private val pic: ResultTuple?,
|
||||
@field:SerializedName("destroyed") private val destroyed: ResultTuple?,
|
||||
@field:SerializedName("description") private val description: ResultTuple?,
|
||||
@field:SerializedName("endTime") private val endTime: ResultTuple?) {
|
||||
@field:SerializedName("endTime") private val endTime: ResultTuple?,
|
||||
@field:SerializedName("monument") private val monument: ResultTuple?) {
|
||||
|
||||
fun getItem(): ResultTuple {
|
||||
return item ?: ResultTuple()
|
||||
|
|
@ -71,4 +72,8 @@ class NearbyResultItem(private val item: ResultTuple?,
|
|||
fun getAddress(): String {
|
||||
return address?.value?:""
|
||||
}
|
||||
|
||||
fun getMonument():ResultTuple?{
|
||||
return monument
|
||||
}
|
||||
}
|
||||
|
|
@ -283,13 +283,14 @@ public class UploadRepository {
|
|||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public Place checkNearbyPlaces(double decLatitude, double decLongitude) {
|
||||
public Place checkNearbyPlaces(final double decLatitude, final double decLongitude) {
|
||||
try {
|
||||
List<Place> fromWikidataQuery = nearbyPlaces.getFromWikidataQuery(new LatLng(
|
||||
final List<Place> fromWikidataQuery = nearbyPlaces.getFromWikidataQuery(new LatLng(
|
||||
decLatitude, decLongitude, 0.0f),
|
||||
Locale.getDefault().getLanguage(),
|
||||
NEARBY_RADIUS_IN_KILO_METERS);
|
||||
return fromWikidataQuery.size() > 0 ? fromWikidataQuery.get(0) : null;
|
||||
NEARBY_RADIUS_IN_KILO_METERS, false);
|
||||
return (fromWikidataQuery != null && fromWikidataQuery.size() > 0) ? fromWikidataQuery
|
||||
.get(0) : null;
|
||||
}catch (final Exception e) {
|
||||
Timber.e("Error fetching nearby places: %s", e.getMessage());
|
||||
return null;
|
||||
|
|
@ -299,4 +300,8 @@ public class UploadRepository {
|
|||
public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) {
|
||||
uploadModel.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex);
|
||||
}
|
||||
|
||||
public boolean isWMLSupportedForThisPlace() {
|
||||
return uploadModel.getItems().get(0).isWLMUpload();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ public class Prefs {
|
|||
public static final String DEFAULT_LICENSE = "defaultLicense";
|
||||
public static final String UPLOADS_SHOWING = "uploadsshowing";
|
||||
public static final String MANAGED_EXIF_TAGS = "managed_exif_tags";
|
||||
public static final String DESCRIPTION_LANGUAGE = "descriptionLanguage";
|
||||
public static final String DESCRIPTION_LANGUAGE = "languageDescription";
|
||||
public static final String APP_UI_LANGUAGE = "appUiLanguage";
|
||||
public static final String KEY_THEME_VALUE = "appThemePref";
|
||||
public static final String TELEMETRY_PREFERENCE = "telemetryPref";
|
||||
|
|
|
|||
|
|
@ -199,11 +199,14 @@ class FileProcessor @Inject constructor(
|
|||
private fun suggestNearbyDepictions(imageCoordinates: ImageCoordinates): Disposable {
|
||||
return Observable.fromIterable(radiiProgressionInMetres.map { it / 1000.0 })
|
||||
.concatMap {
|
||||
okHttpJsonApiClient.getNearbyPlaces(
|
||||
imageCoordinates.latLng,
|
||||
Locale.getDefault().language,
|
||||
it
|
||||
)
|
||||
Observable.fromCallable {
|
||||
okHttpJsonApiClient.getNearbyPlaces(
|
||||
imageCoordinates.latLng,
|
||||
Locale.getDefault().language,
|
||||
it,
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.filter { it.size >= MIN_NEARBY_RESULTS }
|
||||
|
|
|
|||
|
|
@ -26,24 +26,28 @@ class PageContentsCreator {
|
|||
private final Context context;
|
||||
|
||||
@Inject
|
||||
public PageContentsCreator(Context context) {
|
||||
public PageContentsCreator(final Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public String createFrom(Contribution contribution, String countryCode) {
|
||||
public String createFrom(final Contribution contribution) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
final Media media = contribution.getMedia();
|
||||
buffer
|
||||
.append("== {{int:filedesc}} ==\n")
|
||||
.append("{{Information\n")
|
||||
.append("|description=").append(media.getFallbackDescription())
|
||||
.append("{{ on Wikidata|").append(contribution.getWikidataPlace().getId()).append("}}")
|
||||
.append("|description=").append(media.getFallbackDescription()).append("\n");
|
||||
if (contribution.getWikidataPlace() != null) {
|
||||
buffer.append("{{ on Wikidata|").append(contribution.getWikidataPlace().getId())
|
||||
.append("}}");
|
||||
}
|
||||
buffer
|
||||
.append("\n")
|
||||
.append("|source=").append("{{own}}\n")
|
||||
.append("|author=[[User:").append(media.getAuthor()).append("|")
|
||||
.append(media.getAuthor()).append("]]\n");
|
||||
|
||||
String templatizedCreatedDate = getTemplatizedCreatedDate(
|
||||
final String templatizedCreatedDate = getTemplatizedCreatedDate(
|
||||
contribution.getDateCreated(), contribution.getDateCreatedSource());
|
||||
if (!StringUtils.isBlank(templatizedCreatedDate)) {
|
||||
buffer.append("|date=").append(templatizedCreatedDate);
|
||||
|
|
@ -51,18 +55,18 @@ class PageContentsCreator {
|
|||
|
||||
buffer.append("}}").append("\n");
|
||||
|
||||
if (contribution.getWikidataPlace()!=null && contribution.getWikidataPlace().isMonumentUpload()) {
|
||||
buffer.append("{{Wiki Loves Monuments 2021|1= ")
|
||||
.append(countryCode)
|
||||
.append("}}").append("\n");
|
||||
}
|
||||
|
||||
//Only add Location template (e.g. {{Location|37.51136|-77.602615}} ) if coords is not null
|
||||
final String decimalCoords = contribution.getDecimalCoords();
|
||||
if (decimalCoords != null) {
|
||||
buffer.append("{{Location|").append(decimalCoords).append("}}").append("\n");
|
||||
}
|
||||
|
||||
if (contribution.getWikidataPlace()!=null && contribution.getWikidataPlace().isMonumentUpload()) {
|
||||
buffer.append("{{Wiki Loves Monuments 2021|1= ")
|
||||
.append(contribution.getCountryCode())
|
||||
.append("}}").append("\n");
|
||||
}
|
||||
|
||||
buffer.append("== {{int:license-header}} ==\n")
|
||||
.append(licenseTemplateFor(media.getLicense())).append("\n\n")
|
||||
.append("{{Uploaded from Mobile|platform=Android|version=")
|
||||
|
|
|
|||
|
|
@ -210,11 +210,11 @@ public class UploadClient {
|
|||
public Observable<UploadResult> uploadFileFromStash(
|
||||
final Contribution contribution,
|
||||
final String uniqueFileName,
|
||||
final String fileKey, @Nullable String countryCode) {
|
||||
final String fileKey) {
|
||||
try {
|
||||
return uploadInterface
|
||||
.uploadFileFromStash(csrfTokenClient.getTokenBlocking(),
|
||||
pageContentsCreator.createFrom(contribution, countryCode),
|
||||
pageContentsCreator.createFrom(contribution),
|
||||
CommonsApplication.DEFAULT_EDIT_SUMMARY,
|
||||
uniqueFileName,
|
||||
fileKey).map(uploadResponse -> {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ public class UploadItem {
|
|||
private final String createdTimestampSource;
|
||||
private final BehaviorSubject<Integer> imageQuality;
|
||||
private boolean hasInvalidLocation;
|
||||
private boolean isWLMUpload = false;
|
||||
private String countryCode;
|
||||
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
|
|
@ -87,6 +89,14 @@ public class UploadItem {
|
|||
this.uploadMediaDetails = uploadMediaDetails;
|
||||
}
|
||||
|
||||
public void setWLMUpload(final boolean WLMUpload) {
|
||||
isWLMUpload = WLMUpload;
|
||||
}
|
||||
|
||||
public boolean isWLMUpload() {
|
||||
return isWLMUpload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object obj) {
|
||||
if (!(obj instanceof UploadItem)) {
|
||||
|
|
@ -121,4 +131,13 @@ public class UploadItem {
|
|||
public boolean hasInvalidLocation() {
|
||||
return hasInvalidLocation;
|
||||
}
|
||||
|
||||
public void setCountryCode(final String countryCode) {
|
||||
this.countryCode = countryCode;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCountryCode() {
|
||||
return countryCode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,6 +154,15 @@ public class UploadModel {
|
|||
contribution.setDateCreatedSource(item.getCreatedTimestampSource());
|
||||
//Set the date only if you have it, else the upload service is gonna try it the other way
|
||||
}
|
||||
|
||||
if (contribution.getWikidataPlace() != null) {
|
||||
if (item.isWLMUpload()) {
|
||||
contribution.getWikidataPlace().setMonumentUpload(true);
|
||||
} else {
|
||||
contribution.getWikidataPlace().setMonumentUpload(false);
|
||||
}
|
||||
}
|
||||
contribution.setCountryCode(item.getCountryCode());
|
||||
return contribution;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ data class WikidataPlace(
|
|||
val imageValue: String?,
|
||||
val wikipediaArticle: String?,
|
||||
val location: LatLng? = null,
|
||||
val isMonumentUpload : Boolean =false
|
||||
var isMonumentUpload : Boolean =false
|
||||
) :
|
||||
WikidataItem, Parcelable {
|
||||
constructor(place: Place) : this(
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ public interface MediaLicenseContract {
|
|||
void getLicenses();
|
||||
|
||||
void selectLicense(String licenseName);
|
||||
|
||||
boolean isWLMSupportedForThisPlace();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,16 +90,11 @@ public class MediaLicenseFragment extends UploadBaseFragment implements MediaLic
|
|||
initPresenter();
|
||||
initLicenseSpinner();
|
||||
presenter.getLicenses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the wlm info message if the upload is a WLM upload
|
||||
*/
|
||||
if(callback.isWLMUpload()){
|
||||
//TODO : Update the info message logo
|
||||
llInfoMonumentUpload.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
llInfoMonumentUpload.setVisibility(View.GONE);
|
||||
}
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -229,4 +224,16 @@ public class MediaLicenseFragment extends UploadBaseFragment implements MediaLic
|
|||
callback.onNextButtonClicked(callback.getIndexInViewFlipper(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBecameVisible() {
|
||||
super.onBecameVisible();
|
||||
/**
|
||||
* Show the wlm info message if the upload is a WLM upload
|
||||
*/
|
||||
if(callback.isWLMUpload() && presenter.isWLMSupportedForThisPlace()){
|
||||
llInfoMonumentUpload.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
llInfoMonumentUpload.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,4 +74,9 @@ public class MediaLicensePresenter implements MediaLicenseContract.UserActionLis
|
|||
repository.setSelectedLicense(licenseName);
|
||||
view.updateLicenseSummary(repository.getSelectedLicense(), repository.getCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWLMSupportedForThisPlace() {
|
||||
return repository.isWMLSupportedForThisPlace();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,14 @@ import static fr.free.nrw.commons.utils.ImageUtils.FILE_NAME_EXISTS;
|
|||
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_KEEP;
|
||||
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
|
||||
|
||||
import android.location.Address;
|
||||
import android.location.Geocoder;
|
||||
import androidx.annotation.Nullable;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.filepicker.UploadableFile;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
import fr.free.nrw.commons.repository.UploadRepository;
|
||||
import fr.free.nrw.commons.upload.ImageCoordinates;
|
||||
|
|
@ -22,10 +27,13 @@ import io.reactivex.Maybe;
|
|||
import io.reactivex.Scheduler;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
@ -48,6 +56,8 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
|||
private Scheduler ioScheduler;
|
||||
private Scheduler mainThreadScheduler;
|
||||
|
||||
private final List<String> WLM_SUPPORTED_COUNTRIES= Arrays.asList("am","at","az","br","hr","sv","fi","fr","de","gh","in","ie","il","mk","my","mt","pk","pe","pl","ru","rw","si","es","se","tw","ug","ua","us");
|
||||
|
||||
@Inject
|
||||
public UploadMediaPresenter(UploadRepository uploadRepository,
|
||||
@Named("default_preferences") JsonKvStore defaultKVStore,
|
||||
|
|
@ -77,18 +87,31 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
|||
* @param place
|
||||
*/
|
||||
@Override
|
||||
public void receiveImage(UploadableFile uploadableFile, Place place) {
|
||||
public void receiveImage(final UploadableFile uploadableFile, final Place place) {
|
||||
view.showProgress(true);
|
||||
compositeDisposable.add(
|
||||
repository
|
||||
.preProcessImage(uploadableFile, place, this)
|
||||
.map(uploadItem -> {
|
||||
if(place!=null && place.isMonument()){
|
||||
if (place.location != null) {
|
||||
final String countryCode = reverseGeoCode(place.location);
|
||||
if (countryCode != null && WLM_SUPPORTED_COUNTRIES
|
||||
.contains(countryCode.toLowerCase())) {
|
||||
uploadItem.setWLMUpload(true);
|
||||
uploadItem.setCountryCode(countryCode.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
return uploadItem;
|
||||
})
|
||||
.subscribeOn(ioScheduler)
|
||||
.observeOn(mainThreadScheduler)
|
||||
.subscribe(uploadItem ->
|
||||
{
|
||||
view.onImageProcessed(uploadItem, place);
|
||||
view.updateMediaDetails(uploadItem.getUploadMediaDetails());
|
||||
ImageCoordinates gpsCoords = uploadItem.getGpsCoords();
|
||||
final ImageCoordinates gpsCoords = uploadItem.getGpsCoords();
|
||||
final boolean hasImageCoordinates =
|
||||
gpsCoords != null && gpsCoords.getImageCoordsExists();
|
||||
view.showMapWithImageCoordinates(hasImageCoordinates);
|
||||
|
|
@ -100,12 +123,32 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
|||
throwable -> Timber.e(throwable, "Error occurred in processing images")));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String reverseGeoCode(final LatLng latLng){
|
||||
final Geocoder geocoder = new Geocoder(
|
||||
CommonsApplication.getInstance().getApplicationContext(), Locale
|
||||
.getDefault());
|
||||
try {
|
||||
final List<Address> addresses = geocoder
|
||||
.getFromLocation(latLng.getLatitude(), latLng.getLongitude(), 1);
|
||||
for (final Address address : addresses) {
|
||||
if (address != null && address.getCountryCode() != null) {
|
||||
String countryCode = address.getCountryCode();
|
||||
return countryCode;
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks for the nearest location that needs images and suggests it to the user.
|
||||
* @param uploadItem
|
||||
*/
|
||||
private void checkNearbyPlaces(UploadItem uploadItem) {
|
||||
Disposable checkNearbyPlaces = Maybe.fromCallable(() -> repository
|
||||
private void checkNearbyPlaces(final UploadItem uploadItem) {
|
||||
final Disposable checkNearbyPlaces = Maybe.fromCallable(() -> repository
|
||||
.checkNearbyPlaces(uploadItem.getGpsCoords().getDecLatitude(),
|
||||
uploadItem.getGpsCoords().getDecLongitude()))
|
||||
.subscribeOn(ioScheduler)
|
||||
|
|
|
|||
|
|
@ -274,19 +274,10 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
|||
Timber.d("Ensure uniqueness of filename");
|
||||
val uniqueFileName = findUniqueFileName(filename!!)
|
||||
|
||||
|
||||
try {
|
||||
//Upload the file from stash
|
||||
var countryCode: String? =null
|
||||
with(contribution.wikidataPlace?.location){
|
||||
if(contribution.wikidataPlace?.isMonumentUpload!!) {
|
||||
countryCode =
|
||||
reverseGeoCode(contribution.wikidataPlace?.location!!)?.toLowerCase()
|
||||
}
|
||||
|
||||
}
|
||||
val uploadResult = uploadClient.uploadFileFromStash(
|
||||
contribution, uniqueFileName, stashUploadResult.fileKey, countryCode
|
||||
contribution, uniqueFileName, stashUploadResult.fileKey
|
||||
).blockingSingle()
|
||||
|
||||
if (uploadResult.isSuccessful()) {
|
||||
|
|
@ -301,13 +292,13 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
|||
"WikiDataEdit not required, upload success"
|
||||
)
|
||||
saveCompletedContribution(contribution,uploadResult)
|
||||
showSuccessNotification(contribution)
|
||||
}else{
|
||||
Timber.d(
|
||||
"WikiDataEdit not required, making wikidata edit"
|
||||
)
|
||||
makeWikiDataEdit(uploadResult, contribution)
|
||||
}
|
||||
showSuccessNotification(contribution)
|
||||
|
||||
} else {
|
||||
Timber.e("Stash Upload failed")
|
||||
|
|
@ -349,26 +340,6 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
|||
}
|
||||
}
|
||||
|
||||
private fun reverseGeoCode(latLng: LatLng): String? {
|
||||
|
||||
val geocoder = Geocoder(
|
||||
CommonsApplication.getInstance().applicationContext, Locale
|
||||
.getDefault()
|
||||
)
|
||||
try {
|
||||
val addresses =
|
||||
geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1)
|
||||
for (address in addresses) {
|
||||
if (address != null && address.locale.isO3Country != null) {
|
||||
return address.locale.country
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun clearChunks(contribution: Contribution) {
|
||||
contribution.chunkInfo=null
|
||||
contributionDao.saveSynchronous(contribution)
|
||||
|
|
|
|||
|
|
@ -640,7 +640,7 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="image_location">Image Location</string>
|
||||
<string name="check_whether_location_is_correct">Check whether location is correct</string>
|
||||
<string name="place_state_wlm">WLM</string>
|
||||
<string name="wlm_upload_info">You are contributing to Wiki Loves Monuments Campaign. Related templates will be added accordingly.</string>
|
||||
<string name="wlm_upload_info">This image will be entered into the Wiki Loves Monuments 2021 contest</string>
|
||||
<string name="display_monuments">Display monuments</string>
|
||||
<string name="wlm_month_message">It\'s Wiki Loves Monuments month!</string>
|
||||
<string name="learn_more">LEARN MORE</string>
|
||||
|
|
|
|||
71
app/src/main/resources/queries/nearby_query_monuments.rq
Normal file
71
app/src/main/resources/queries/nearby_query_monuments.rq
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
SELECT
|
||||
(SAMPLE(?location) as ?location)
|
||||
?item
|
||||
(SAMPLE(COALESCE(?itemLabelPreferredLanguage, ?itemLabelAnyLanguage)) as ?label)
|
||||
(SAMPLE(COALESCE(?itemDescriptionPreferredLanguage, ?itemDescriptionAnyLanguage, "?")) as ?description)
|
||||
(SAMPLE(?classId) as ?class)
|
||||
(SAMPLE(COALESCE(?classLabelPreferredLanguage, ?classLabelAnyLanguage, "?")) as ?classLabel)
|
||||
(SAMPLE(COALESCE(?icon0, ?icon1)) as ?icon)
|
||||
?wikipediaArticle
|
||||
?commonsArticle
|
||||
(SAMPLE(?commonsCategory) as ?commonsCategory)
|
||||
(SAMPLE(?pic) as ?pic)
|
||||
(SAMPLE(?destroyed) as ?destroyed)
|
||||
(SAMPLE(?endTime) as ?endTime)
|
||||
(SAMPLE(?monument) as ?monument)
|
||||
WHERE {
|
||||
# Around given location...
|
||||
SERVICE wikibase:around {
|
||||
?item wdt:P625 ?location.
|
||||
bd:serviceParam wikibase:center "Point(${LONG} ${LAT})"^^geo:wktLiteral.
|
||||
bd:serviceParam wikibase:radius "${RAD}" . # Radius in kilometers.
|
||||
}
|
||||
|
||||
OPTIONAL {
|
||||
{ ?item p:P1435 ?monument } UNION { ?item p:P2186 ?monument } UNION { ?item p:P1459 ?monument } UNION { ?item p:P1460 ?monument } UNION { ?item p:P1216 ?monument } UNION { ?item p:P709 ?monument } UNION { ?item p:P718 ?monument } UNION { ?item p:P5694 ?monument }
|
||||
}
|
||||
|
||||
# Get the label in the preferred language of the user, or any other language if no label is available in that language.
|
||||
OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage. FILTER (lang(?itemLabelPreferredLanguage) = "${LANG}")}
|
||||
OPTIONAL {?item rdfs:label ?itemLabelAnyLanguage}
|
||||
|
||||
# Get the description in the preferred language of the user, or any other language if no description is available in that language.
|
||||
OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage. FILTER (lang(?itemDescriptionPreferredLanguage) = "${LANG}")}
|
||||
OPTIONAL {?item schema:description ?itemDescriptionAnyLanguage }
|
||||
|
||||
# Get Commons category (P373)
|
||||
OPTIONAL { ?item wdt:P373 ?commonsCategory. }
|
||||
|
||||
# Get (P18)
|
||||
OPTIONAL { ?item wdt:P18 ?pic. }
|
||||
|
||||
# Get (P576)
|
||||
OPTIONAL { ?item wdt:P576 ?destroyed. }
|
||||
|
||||
# Get (P582)
|
||||
OPTIONAL { ?item wdt:P582 ?endTime. }
|
||||
|
||||
# Get the class label in the preferred language of the user, or any other language if no label is available in that language.
|
||||
OPTIONAL {
|
||||
?item p:P31/ps:P31 ?classId.
|
||||
OPTIONAL {?classId rdfs:label ?classLabelPreferredLanguage. FILTER (lang(?classLabelPreferredLanguage) = "${LANG}")}
|
||||
OPTIONAL {?classId rdfs:label ?classLabelAnyLanguage}
|
||||
|
||||
OPTIONAL {
|
||||
?wikipediaArticle schema:about ?item ;
|
||||
schema:isPartOf <https://${LANG}.wikipedia.org/> .
|
||||
}
|
||||
OPTIONAL {
|
||||
?wikipediaArticle schema:about ?item ;
|
||||
schema:isPartOf <https://en.wikipedia.org/> .
|
||||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
|
||||
}
|
||||
|
||||
OPTIONAL {
|
||||
?commonsArticle schema:about ?item ;
|
||||
schema:isPartOf <https://commons.wikimedia.org/> .
|
||||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
|
||||
}
|
||||
}
|
||||
}
|
||||
GROUP BY ?item ?wikipediaArticle ?commonsArticle
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.3.31'
|
||||
ext.kotlin_version = '1.5.10'
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableBuildCache=true
|
||||
|
||||
KOTLIN_VERSION=1.3.72
|
||||
KOTLIN_VERSION=1.5.10
|
||||
BUTTERKNIFE_VERSION=10.1.0
|
||||
LEAK_CANARY_VERSION=1.6.2
|
||||
DAGGER_VERSION=2.23
|
||||
ROOM_VERSION=2.2.3
|
||||
ROOM_VERSION=2.3.0
|
||||
PREFERENCE_VERSION=1.1.0
|
||||
CORE_KTX_VERSION=1.2.0
|
||||
ADAPTER_DELEGATES_VERSION=4.3.0
|
||||
|
|
|
|||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
|
||||
distributionUrl=https://services.gradle.org/distributions/gradle-6.9-all.zip
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue