mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Merge changes from 3.1-release (#4629)
* Cherry-Picked NPE fix from master (#4569) * Fix notification bug #4547 (#4570) * Make Single Query for Nearby and WLM pins (#4573) * Merge nearby and monument queries * Bug Fix- query resource path change on shouldQueryForMonuments * Bug Fixes 1. Propagate exceptions for nearby API calls to caller 2. Fix too much work on main thread exception in NearbyParentFragment * Modify parameters for Nearby query * Bug fix- current location marker (#4580) * Move WLM template below geolocation template (#4582) * Modify string for WLM upload notice * Fix bug #4583 (#4591) * Fix bug #4585 by updating kotlin and acra version (#4592) * Fixes #4554 - only use WLM2021 template for countries that are included in it (#4574) * Fixes #4554 1. For WLM uploads reverse geo code and see if the country code is supported -only then is the WLM upload flow triggered, otherwise usual nearby uploads happen 2. Bug Fix - Current Location marker and area * Fixed compile error added after rebasing * Bug fix for country code in reverse geo code * Update WLM camaign dates [Do not merge now, merge only after alpha release] (#4584) * Updates dates for WML campaign * Bug fix- campaign dates * Fixed logic for WLM enablement - stick to the month of September * Add countries supported by WLM2021 template, except Italy * Versioning for v3.1.0 * Update changelog.md * Fix empty default lang bug (#4608) * Fix bug #4583 * Fix empty default lang bug * Fixes #4595 - Updated nearby query (#4622) * Fixes #4595 - Updated nearby query * Removed logic to replace local language in nearby query - that might acccidentally replace other strings * Fetch property location in usual nearby query * Remove duplicate line (#4626) * Change "learn more" link to new wiki * Add Sweden's P3426 to property filter * Fixes #4601 - 1. Handle possible exceptions in upload file from stash 2. Modify MWException, as error is nullable, update getTitle and getMessage to rever that (#4627) * Versioning for v3.1.1 * Update changelog.md * Updated DB version to rever integrity Co-authored-by: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com> Co-authored-by: Josephine Lim <josephinelim86@gmail.com>
This commit is contained in:
parent
b91222329e
commit
7476b0a24d
38 changed files with 383 additions and 409 deletions
|
|
@ -1,5 +1,14 @@
|
|||
# Wikimedia Commons for Android
|
||||
|
||||
## v3.1.1
|
||||
- Optimized Nearby query
|
||||
- Added Sweden's property for WLM 2021
|
||||
- Added link to wiki explaining how to contribute to WLM through app
|
||||
- Fixed various bugs and crashes
|
||||
|
||||
## 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'
|
||||
|
|
@ -155,8 +155,8 @@ android {
|
|||
defaultConfig {
|
||||
//applicationId 'fr.free.nrw.commons'
|
||||
|
||||
versionCode 1021
|
||||
versionName '3.0.2'
|
||||
versionCode 1025
|
||||
versionName '3.1.1'
|
||||
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
|
||||
|
||||
minSdkVersion 19
|
||||
|
|
@ -226,7 +226,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();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ data class Contribution constructor(
|
|||
var dateCreated: Date? = null,
|
||||
var dateModified: Date? = null,
|
||||
var hasInvalidLocation : Int = 0,
|
||||
var contentUri: Uri? = null
|
||||
var contentUri: Uri? = null,
|
||||
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)) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import fr.free.nrw.commons.explore.recentsearches.RecentSearchesDao;
|
|||
public class DBOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final String DATABASE_NAME = "commons.db";
|
||||
private static final int DATABASE_VERSION = 18;
|
||||
private static final int DATABASE_VERSION = 19;
|
||||
public static final String CONTRIBUTIONS_TABLE = "contributions";
|
||||
private final String DROP_TABLE_STATEMENT="DROP TABLE IF EXISTS %s";
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import fr.free.nrw.commons.upload.depicts.DepictsDao
|
|||
* The database for accessing the respective DAOs
|
||||
*
|
||||
*/
|
||||
@Database(entities = [Contribution::class, Depicts::class, UploadedStatus::class], version = 9, exportSchema = false)
|
||||
@Database(entities = [Contribution::class, Depicts::class, UploadedStatus::class], version = 10, exportSchema = false)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun contributionDao(): ContributionDao
|
||||
|
|
|
|||
|
|
@ -373,8 +373,6 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
|||
media = getArguments().getParcelable("media");
|
||||
}
|
||||
|
||||
media = detailProvider.getMediaAtPosition(index);
|
||||
|
||||
if(media != null && applicationKvStore.getBoolean(String.format(NOMINATING_FOR_DELETION_MEDIA, media.getImageUrl()), false)) {
|
||||
enableProgressBar();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,105 +265,52 @@ 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
|
||||
.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();
|
||||
|
||||
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<>();
|
||||
}
|
||||
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;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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";
|
||||
if (!shouldQueryForMonuments) {
|
||||
wikidataQuery = FileUtils.readFromResource("/queries/nearby_query.rq");
|
||||
} else {
|
||||
wikidataQuery = FileUtils.readFromResource("/queries/nearby_query_monuments.rq");
|
||||
}
|
||||
String query = wikidataQuery
|
||||
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();
|
||||
|
||||
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()) {
|
||||
if (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);
|
||||
final Place placeFromNearbyItem = Place.from(item);
|
||||
if (shouldQueryForMonuments && item.getMonument() != null) {
|
||||
placeFromNearbyItem.setMonument(true);
|
||||
} else {
|
||||
placeFromNearbyItem.setMonument(false);
|
||||
}
|
||||
places.add(placeFromNearbyItem);
|
||||
}
|
||||
return places;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
});
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
return Observable.error(e);
|
||||
}
|
||||
throw new Exception(response.message());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
/**
|
||||
* WLM URL
|
||||
*/
|
||||
public static final String WLM_URL = "https://www.wikilovesmonuments.org/";
|
||||
public static final String WLM_URL = "https://commons.wikimedia.org/wiki/Commons:Mobile_app/Contributing_to_WLM_using_the_app";
|
||||
|
||||
@NonNull
|
||||
public static NearbyParentFragment newInstance() {
|
||||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -229,7 +229,10 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
/**
|
||||
* Changing the default app language with selected one and save it to SharedPreferences
|
||||
*/
|
||||
public void setLocale(final Activity activity, final String userSelectedValue) {
|
||||
public void setLocale(final Activity activity, String userSelectedValue) {
|
||||
if (userSelectedValue.equals("")) {
|
||||
userSelectedValue = Locale.getDefault().getLanguage();
|
||||
}
|
||||
final Locale locale = new Locale(userSelectedValue);
|
||||
Locale.setDefault(locale);
|
||||
final Configuration configuration = new Configuration();
|
||||
|
|
|
|||
|
|
@ -199,12 +199,15 @@ class FileProcessor @Inject constructor(
|
|||
private fun suggestNearbyDepictions(imageCoordinates: ImageCoordinates): Disposable {
|
||||
return Observable.fromIterable(radiiProgressionInMetres.map { it / 1000.0 })
|
||||
.concatMap {
|
||||
Observable.fromCallable {
|
||||
okHttpJsonApiClient.getNearbyPlaces(
|
||||
imageCoordinates.latLng,
|
||||
Locale.getDefault().language,
|
||||
it
|
||||
it,
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.filter { it.size >= MIN_NEARBY_RESULTS }
|
||||
.take(1)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class PageContentsCreator {
|
|||
this.context = context;
|
||||
}
|
||||
|
||||
public String createFrom(final Contribution contribution, final String countryCode) {
|
||||
public String createFrom(final Contribution contribution) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
final Media media = contribution.getMedia();
|
||||
buffer
|
||||
|
|
@ -55,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,21 +210,21 @@ 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 -> {
|
||||
UploadResponse uploadResult = gson
|
||||
final UploadResponse uploadResult = gson
|
||||
.fromJson(uploadResponse, UploadResponse.class);
|
||||
if (uploadResult.getUpload() == null) {
|
||||
final MwException exception = gson
|
||||
.fromJson(uploadResponse, MwException.class);
|
||||
Timber.e(exception, "Error in uploading file from stash");
|
||||
throw new RuntimeException(exception.getErrorCode());
|
||||
throw new Exception(exception.getErrorCode());
|
||||
}
|
||||
return uploadResult.getUpload();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* Uri of uploadItem
|
||||
|
|
@ -102,6 +104,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)) {
|
||||
|
|
@ -136,4 +146,13 @@ public class UploadItem {
|
|||
public boolean hasInvalidLocation() {
|
||||
return hasInvalidLocation;
|
||||
}
|
||||
|
||||
public void setCountryCode(final String countryCode) {
|
||||
this.countryCode = countryCode;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCountryCode() {
|
||||
return countryCode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,6 +155,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;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
class UploadResponse(val upload: UploadResult)
|
||||
class UploadResponse(val upload: UploadResult?)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import fr.free.nrw.commons.customselector.database.UploadedStatusDao
|
|||
import fr.free.nrw.commons.di.ApplicationlessInjection
|
||||
import fr.free.nrw.commons.location.LatLng
|
||||
import fr.free.nrw.commons.media.MediaClient
|
||||
import fr.free.nrw.commons.upload.StashUploadResult
|
||||
import fr.free.nrw.commons.upload.FileUtilsWrapper
|
||||
import fr.free.nrw.commons.upload.StashUploadState
|
||||
import fr.free.nrw.commons.upload.UploadClient
|
||||
|
|
@ -276,7 +277,9 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
|||
//Upload the file to stash
|
||||
val stashUploadResult = uploadClient.uploadFileToStash(
|
||||
appContext, filename, contribution, notificationProgressUpdater
|
||||
).blockingSingle()
|
||||
).onErrorReturn{
|
||||
return@onErrorReturn StashUploadResult(StashUploadState.FAILED,fileKey = null)
|
||||
}.blockingSingle()
|
||||
|
||||
when (stashUploadResult.state) {
|
||||
StashUploadState.SUCCESS -> {
|
||||
|
|
@ -285,22 +288,15 @@ 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 == true) {
|
||||
countryCode =
|
||||
reverseGeoCode(contribution.wikidataPlace?.location!!)?.toLowerCase()
|
||||
}
|
||||
|
||||
}
|
||||
val uploadResult = uploadClient.uploadFileFromStash(
|
||||
contribution, uniqueFileName, stashUploadResult.fileKey, countryCode
|
||||
).blockingSingle()
|
||||
contribution, uniqueFileName, stashUploadResult.fileKey
|
||||
).onErrorReturn {
|
||||
return@onErrorReturn null
|
||||
}.blockingSingle()
|
||||
|
||||
if (uploadResult.isSuccessful()) {
|
||||
if (null != uploadResult && uploadResult.isSuccessful()) {
|
||||
Timber.d(
|
||||
"Stash Upload success..proceeding to make wikidata edit"
|
||||
)
|
||||
|
|
@ -312,13 +308,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")
|
||||
|
|
@ -333,6 +329,7 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
|||
Timber.e("Upload from stash failed for contribution : $filename")
|
||||
showFailedNotification(contribution)
|
||||
contribution.state=Contribution.STATE_FAILED
|
||||
contributionDao.saveSynchronous(contribution)
|
||||
if (STASH_ERROR_CODES.contains(exception.message)) {
|
||||
clearChunks(contribution)
|
||||
}
|
||||
|
|
@ -360,26 +357,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)
|
||||
|
|
|
|||
|
|
@ -650,7 +650,7 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="welcome_custom_selector_ok">Awesome</string>
|
||||
<string name="custom_selector_already_uploaded_image_text">This image has already been uploaded to Commons.</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>
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
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)
|
||||
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.
|
||||
}
|
||||
|
||||
{ ?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 Commons category (P373)
|
||||
OPTIONAL { ?item wdt:P373 ?commonsCategory. }
|
||||
|
||||
# Get (P18)
|
||||
OPTIONAL { ?item wdt:P18 ?pic. }
|
||||
|
||||
# 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 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) = "")}
|
||||
OPTIONAL {?classId rdfs:label ?classLabelAnyLanguage}
|
||||
|
||||
OPTIONAL {
|
||||
?wikipediaArticle schema:about ?item ;
|
||||
schema:isPartOf <https://.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,66 +1,56 @@
|
|||
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)
|
||||
WHERE {
|
||||
# Around given location...
|
||||
(SAMPLE(?location) as ?location)
|
||||
(SAMPLE(?label) AS ?label)
|
||||
(SAMPLE(?description) AS ?description)
|
||||
(SAMPLE(?class) AS ?class)
|
||||
(SAMPLE(?classLabel) AS ?classLabel)
|
||||
(SAMPLE(?pic) AS ?pic)
|
||||
(SAMPLE(?destroyed) AS ?destroyed)
|
||||
(SAMPLE(?endTime) AS ?endTime)
|
||||
(SAMPLE(?wikipediaArticle) AS ?wikipediaArticle)
|
||||
(SAMPLE(?commonsArticle) AS ?commonsArticle)
|
||||
(SAMPLE(?commonsCategory) AS ?commonsCategory)
|
||||
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.
|
||||
}
|
||||
|
||||
# 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" }
|
||||
bd:serviceParam wikibase:center "Point(${LONG} ${LAT})"^^geo:wktLiteral. # Longitude latitude
|
||||
bd:serviceParam wikibase:radius "${RAD}". # Radius in kilometers.
|
||||
}
|
||||
|
||||
OPTIONAL {
|
||||
?commonsArticle schema:about ?item ;
|
||||
schema:isPartOf <https://commons.wikimedia.org/> .
|
||||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
|
||||
?item p:P31/ps:P31 ?class.
|
||||
}
|
||||
|
||||
# Get picture
|
||||
OPTIONAL {?item wdt:P18 ?pic}
|
||||
|
||||
# Get existence
|
||||
OPTIONAL {?item wdt:P576 ?destroyed}
|
||||
OPTIONAL {?item wdt:P582 ?endTime}
|
||||
|
||||
# Get Commons category
|
||||
OPTIONAL {?item wdt:P373 ?commonsCategory}
|
||||
|
||||
# Get Wikipedia article
|
||||
OPTIONAL {
|
||||
?wikipediaArticle schema:about ?item.
|
||||
?wikipediaArticle schema:isPartOf <https://${LANG}.wikipedia.org/>.
|
||||
}
|
||||
|
||||
# Get Commons article
|
||||
OPTIONAL {
|
||||
?commonsArticle schema:about ?item.
|
||||
?commonsArticle schema:isPartOf <https://commons.wikimedia.org/>.
|
||||
}
|
||||
GROUP BY ?item ?wikipediaArticle ?commonsArticle
|
||||
|
||||
# Labels and descriptions
|
||||
SERVICE wikibase:label {
|
||||
bd:serviceParam wikibase:language "${LANG},en,fr,de,es,ja,ru,it,zh,pt,ar,fa,pl,nl,id,uk,he,sv,cs,ko,vi,ca,no,fi,hu,tr,th,hi,bn,ceb,ro,sw,kk,da,eo,sr,lt,sk,bg,sl,eu,et,hr,ms,el,arz,ur,ta,te,nn,gl,az,af,bs,be,ml,ka,is,sq,uz,la,br,mk,lv,azb,mr,sh,tl,cy,ckb,ast,be-tarask,zh-yue,hy,pa,as,my,kn,ne,si,tt,ha,war,zh-min-nan,vo,min,lmo,ht,lb,gu,tg,sco,ku,new,bpy,nds,io,pms,su,oc,jv,nap,ba,scn,wa,bar,an,ksh,szl,fy,frr,als,ia,ga,yi,mg,gd,vec,ce,sa,mai,xmf,sd,wuu,mrj,mhr,km,roa-tara,am,roa-rup,map-bms,bh,mnw,shn,bcl,co,cv,dv,nds-nl,fo,hif,fur,gan,glk,hak,ilo,pam,csb,avk,lij,li,gv,mi,mt,nah,nrm,se,nov,qu,os,pi,pag,ps,pdc,rm,bat-smg,sc,to,tk,hsb,fiu-vro,vls,yo,diq,zh-classical,frp,lad,kw,mn,haw,ang,ln,ie,wo,tpi,ty,crh,nv,jbo,ay,pcd,zea,eml,ky,ig,or,cbk-zam,kg,arc,rmy,ab,gn,so,kab,ug,stq,udm,ext,mzn,pap,cu,sah,tet,sn,lo,pnb,iu,na,got,bo,dsb,chr,cdo,om,sm,ee,ti,av,bm,zu,pnt,cr,pih,ss,ve,bi,rw,ch,xh,kl,ik,bug,dz,ts,tn,kv,tum,xal,st,tw,bxr,ak,ny,fj,lbe,za,ks,ff,lg,sg,rn,chy,mwl,lez,bjn,gom,tyv,vep,nso,kbd,ltg,rue,pfl,gag,koi,krc,ace,olo,kaa,mdf,myv,srn,ady,jam,tcy,dty,atj,kbp,din,lfn,gor,inh,sat,hyw,nqo,ban,szy,awa,ary,lld,smn,skr,mad,dag,shi,nia,ki,gcr".
|
||||
?item rdfs:label ?label.
|
||||
?item schema:description ?description.
|
||||
?class rdfs:label ?classLabel.
|
||||
}
|
||||
}
|
||||
GROUP BY ?item
|
||||
68
app/src/main/resources/queries/nearby_query_monuments.rq
Normal file
68
app/src/main/resources/queries/nearby_query_monuments.rq
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
SELECT
|
||||
?item
|
||||
(SAMPLE(?location) as ?location)
|
||||
(SAMPLE(?label) AS ?label)
|
||||
(SAMPLE(?description) AS ?description)
|
||||
(SAMPLE(?class) AS ?class)
|
||||
(SAMPLE(?classLabel) AS ?classLabel)
|
||||
(SAMPLE(?pic) AS ?pic)
|
||||
(SAMPLE(?destroyed) AS ?destroyed)
|
||||
(SAMPLE(?endTime) AS ?endTime)
|
||||
(SAMPLE(?wikipediaArticle) AS ?wikipediaArticle)
|
||||
(SAMPLE(?commonsArticle) AS ?commonsArticle)
|
||||
(SAMPLE(?commonsCategory) AS ?commonsCategory)
|
||||
(SAMPLE(?monument) AS ?monument)
|
||||
WHERE {
|
||||
# Around given location
|
||||
SERVICE wikibase:around {
|
||||
?item wdt:P625 ?location.
|
||||
bd:serviceParam wikibase:center "Point(${LONG} ${LAT})"^^geo:wktLiteral. # Longitude latitude
|
||||
bd:serviceParam wikibase:radius "${RAD}". # Radius in kilometers.
|
||||
}
|
||||
|
||||
OPTIONAL {
|
||||
?item p:P31/ps:P31 ?class.
|
||||
}
|
||||
|
||||
# Get picture
|
||||
OPTIONAL {?item wdt:P18 ?pic}
|
||||
|
||||
# Get existence
|
||||
OPTIONAL {?item wdt:P576 ?destroyed}
|
||||
OPTIONAL {?item wdt:P582 ?endTime}
|
||||
|
||||
# Get Commons category
|
||||
OPTIONAL {?item wdt:P373 ?commonsCategory}
|
||||
|
||||
# Get Wikipedia article
|
||||
OPTIONAL {
|
||||
?wikipediaArticle schema:about ?item.
|
||||
?wikipediaArticle schema:isPartOf <https://${LANG}.wikipedia.org/>.
|
||||
}
|
||||
|
||||
# Get Commons article
|
||||
OPTIONAL {
|
||||
?commonsArticle schema:about ?item.
|
||||
?commonsArticle schema:isPartOf <https://commons.wikimedia.org/>.
|
||||
}
|
||||
|
||||
# Wiki Loves Monuments
|
||||
OPTIONAL {?item p:P1435 ?monument}
|
||||
OPTIONAL {?item p:P2186 ?monument}
|
||||
OPTIONAL {?item p:P1459 ?monument}
|
||||
OPTIONAL {?item p:P1460 ?monument}
|
||||
OPTIONAL {?item p:P1216 ?monument}
|
||||
OPTIONAL {?item p:P709 ?monument}
|
||||
OPTIONAL {?item p:P718 ?monument}
|
||||
OPTIONAL {?item p:P5694 ?monument}
|
||||
OPTIONAL {?item p:P3426 ?monument}
|
||||
|
||||
# Labels and descriptions
|
||||
SERVICE wikibase:label {
|
||||
bd:serviceParam wikibase:language "${LANG},en,fr,de,es,ja,ru,it,zh,pt,ar,fa,pl,nl,id,uk,he,sv,cs,ko,vi,ca,no,fi,hu,tr,th,hi,bn,ceb,ro,sw,kk,da,eo,sr,lt,sk,bg,sl,eu,et,hr,ms,el,arz,ur,ta,te,nn,gl,az,af,bs,be,ml,ka,is,sq,uz,la,br,mk,lv,azb,mr,sh,tl,cy,ckb,ast,be-tarask,zh-yue,hy,pa,as,my,kn,ne,si,tt,ha,war,zh-min-nan,vo,min,lmo,ht,lb,gu,tg,sco,ku,new,bpy,nds,io,pms,su,oc,jv,nap,ba,scn,wa,bar,an,ksh,szl,fy,frr,als,ia,ga,yi,mg,gd,vec,ce,sa,mai,xmf,sd,wuu,mrj,mhr,km,roa-tara,am,roa-rup,map-bms,bh,mnw,shn,bcl,co,cv,dv,nds-nl,fo,hif,fur,gan,glk,hak,ilo,pam,csb,avk,lij,li,gv,mi,mt,nah,nrm,se,nov,qu,os,pi,pag,ps,pdc,rm,bat-smg,sc,to,tk,hsb,fiu-vro,vls,yo,diq,zh-classical,frp,lad,kw,mn,haw,ang,ln,ie,wo,tpi,ty,crh,nv,jbo,ay,pcd,zea,eml,ky,ig,or,cbk-zam,kg,arc,rmy,ab,gn,so,kab,ug,stq,udm,ext,mzn,pap,cu,sah,tet,sn,lo,pnb,iu,na,got,bo,dsb,chr,cdo,om,sm,ee,ti,av,bm,zu,pnt,cr,pih,ss,ve,bi,rw,ch,xh,kl,ik,bug,dz,ts,tn,kv,tum,xal,st,tw,bxr,ak,ny,fj,lbe,za,ks,ff,lg,sg,rn,chy,mwl,lez,bjn,gom,tyv,vep,nso,kbd,ltg,rue,pfl,gag,koi,krc,ace,olo,kaa,mdf,myv,srn,ady,jam,tcy,dty,atj,kbp,din,lfn,gor,inh,sat,hyw,nqo,ban,szy,awa,ary,lld,smn,skr,mad,dag,shi,nia,ki,gcr".
|
||||
?item rdfs:label ?label.
|
||||
?item schema:description ?description.
|
||||
?class rdfs:label ?classLabel.
|
||||
}
|
||||
}
|
||||
GROUP BY ?item
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.3.31'
|
||||
ext.kotlin_version = '1.5.10'
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
|
|
|
|||
|
|
@ -31,11 +31,20 @@ public class MwException extends RuntimeException {
|
|||
return error;
|
||||
}
|
||||
|
||||
@Nullable public String getTitle() {
|
||||
@Nullable
|
||||
public String getTitle() {
|
||||
if (error != null) {
|
||||
return error.getTitle();
|
||||
}
|
||||
return errors != null ? errors.get(0).getTitle() : null;
|
||||
}
|
||||
|
||||
@Override @Nullable public String getMessage() {
|
||||
@Override
|
||||
@Nullable
|
||||
public String getMessage() {
|
||||
if (error != null) {
|
||||
return error.getDetails();
|
||||
}
|
||||
return errors != null ? errors.get(0).getDetails() : null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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