Fixes #545 - Add support for campaigns (#4423)

* Integrate WLM
- Show monuments in maps along with nearby

* BugFix in Monuments
1. Single preference for monuments and campaigns
2. Expand collapse chips container in nearby
3. Typo fix in Monuments card in Nearby
4. If a nearby place is a monument as well - do not show them separately, show it as a monument instead
5. Bug fix, monument radius, use the same one as that of nearby

* More bug fixes
1. Possible NPE in nearby
2. Added column location_address in BookmarkLocationDao
3. Bug Fix - Display Date in WLM card
4. WLM card on click takes to nearby

* Use lowercase country code in WLM uploads

* Bug-Fix, WLM Campaign Icon

* 1. Updated monuments query to use any of the following properties for monuments - [P1435, P2186, P1459, P1460, P1216, P709, P718, P5694] 2. Append WikiData QID to descriptions template

* Updated WLM Banner String, Handle NPE in contributions callback

* Added nearby-monuments query log lines

* Handle WLM Query exception : - if an exception is thrown in WLM query, continue showing the nearby items if that succeeds

* Fix BookmarkLocationDaoTest

* Added Column Address in BookmarkLocationDaoTest

* Use fallback description as usual nearby pins even for WLM pins, instead of relying on P6375

* Test fix in BookmarkLocationDao

* Updated template for WLM, removed redundant feilds

* Fixed WLM template

* Removed categories from WLM template

* Fixed BookmarkControllerTest

* Fixed BookmarkLocationFragmentUnitTest

* fix ModelFunctions

* Fixed BookmarksDaoLocationTest

* Fixed WLM template
This commit is contained in:
Ashish 2021-08-18 13:57:26 +05:30 committed by GitHub
parent 67f5b6c271
commit 6588a6fd0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 2906 additions and 185 deletions

View file

@ -8,14 +8,17 @@ import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import java.util.Objects;
public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBaseMarker> {
public static final Parcelable.Creator<NearbyBaseMarker> CREATOR = new Parcelable.Creator<NearbyBaseMarker>() {
@Override
public NearbyBaseMarker createFromParcel(Parcel in) {
return new NearbyBaseMarker(in);
}
@Override
public NearbyBaseMarker[] newArray(int size) {
return new NearbyBaseMarker[size];
}
@ -70,4 +73,21 @@ public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBase
dest.writeString(title);
dest.writeParcelable(place, 0);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final NearbyBaseMarker that = (NearbyBaseMarker) o;
return Objects.equals(place.location, that.place.location);
}
@Override
public int hashCode() {
return Objects.hash(place);
}
}

View file

@ -10,6 +10,7 @@ import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.Marker;
import io.reactivex.Observable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@ -127,6 +128,11 @@ 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.
*
@ -168,6 +174,7 @@ public class NearbyController {
VectorDrawableCompat vectorDrawable = null;
VectorDrawableCompat vectorDrawableGreen = null;
VectorDrawableCompat vectorDrawableGrey = null;
VectorDrawableCompat vectorDrawableMonuments = null;
vectorDrawable = null;
try {
vectorDrawable = VectorDrawableCompat.create(
@ -176,6 +183,9 @@ public class NearbyController {
context.getResources(), R.drawable.ic_custom_map_marker_green, context.getTheme());
vectorDrawableGrey = VectorDrawableCompat.create(
context.getResources(), R.drawable.ic_custom_map_marker_grey, context.getTheme());
vectorDrawableMonuments = VectorDrawableCompat
.create(context.getResources(), R.drawable.ic_custom_map_marker_monuments,
context.getTheme());
} catch (Resources.NotFoundException e) {
// ignore when running tests.
}
@ -183,34 +193,39 @@ public class NearbyController {
Bitmap icon = UiUtils.getBitmap(vectorDrawable);
Bitmap iconGreen = UiUtils.getBitmap(vectorDrawableGreen);
Bitmap iconGrey = UiUtils.getBitmap(vectorDrawableGrey);
Bitmap iconMonuments = UiUtils.getBitmap(vectorDrawableMonuments);
for (Place place : placeList) {
NearbyBaseMarker nearbyBaseMarker = new NearbyBaseMarker();
String distance = formatDistanceBetween(curLatLng, place.location);
place.setDistance(distance);
NearbyBaseMarker nearbyBaseMarker = new NearbyBaseMarker();
nearbyBaseMarker.title(place.name);
nearbyBaseMarker.position(
new com.mapbox.mapboxsdk.geometry.LatLng(
place.location.getLatitude(),
place.location.getLongitude()));
new com.mapbox.mapboxsdk.geometry.LatLng(
place.location.getLatitude(),
place.location.getLongitude()));
nearbyBaseMarker.place(place);
// Check if string is only spaces or empty, if so place doesn't have any picture
if (!place.pic.trim().isEmpty()) {
if (place.isMonument()) {
nearbyBaseMarker.icon(IconFactory.getInstance(context)
.fromBitmap(iconMonuments));
}
else if (!place.pic.trim().isEmpty()) {
if (iconGreen != null) {
nearbyBaseMarker.icon(IconFactory.getInstance(context)
.fromBitmap(iconGreen));
.fromBitmap(iconGreen));
}
} else if (!place.exists) { // Means that the topic of the Wikidata item does not exist in the real world anymore, for instance it is a past event, or a place that was destroyed
if (iconGrey != null) {
nearbyBaseMarker.icon(IconFactory.getInstance(context)
.fromBitmap(iconGrey));
.fromBitmap(iconGrey));
}
} else {
nearbyBaseMarker.icon(IconFactory.getInstance(context)
.fromBitmap(icon));
.fromBitmap(icon));
}
baseMarkerOptions.add(nearbyBaseMarker);
}
}

View file

@ -5,6 +5,7 @@ import java.util.ArrayList;
public class NearbyFilterState {
private boolean existsSelected;
private boolean needPhotoSelected;
private boolean wlmSelected;
private int checkBoxTriState;
private ArrayList<Label> selectedLabels;
@ -16,6 +17,7 @@ public class NearbyFilterState {
private NearbyFilterState() {
existsSelected = false;
needPhotoSelected = true;
wlmSelected = true;
checkBoxTriState = -1; // Unknown
selectedLabels = new ArrayList<>(); // Initially empty
}
@ -39,6 +41,14 @@ public class NearbyFilterState {
getInstance().needPhotoSelected = needPhotoSelected;
}
public static void setWlmSelected(final boolean wlmSelected) {
getInstance().wlmSelected = wlmSelected;
}
public boolean isWlmSelected() {
return wlmSelected;
}
public boolean isExistsSelected() {
return existsSelected;
}

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.nearby;
import io.reactivex.Observable;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Collections;
@ -65,9 +66,9 @@ public class NearbyPlaces {
while (radius <= maxRadius) {
try {
places = getFromWikidataQuery(curLatLng, lang, radius);
} catch (InterruptedIOException e) {
Timber.e(e, "exception in fetching nearby places");
return places;
} catch (final Exception e) {
Timber.e(e, "Exception in fetching nearby places");
break;
}
Timber.d("%d results at radius: %f", places.size(), radius);
if (places.size() >= minResults) {
@ -91,7 +92,13 @@ public class NearbyPlaces {
* @return list of places obtained
* @throws IOException if query fails
*/
public List<Place> getFromWikidataQuery(LatLng cur, String lang, double radius) throws IOException {
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);
}
}

View file

@ -4,8 +4,10 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import fr.free.nrw.commons.nearby.NearbyController.NearbyPlacesInfo;
import org.apache.commons.lang3.StringUtils;
import fr.free.nrw.commons.location.LatLng;
@ -31,6 +33,7 @@ public class Place implements Parcelable {
public String distance;
public final Sitelinks siteLinks;
private boolean isMonument;
public Place(String language,String name, Label label, String longDescription, LatLng location, String category, Sitelinks siteLinks, String pic, Boolean exists) {
@ -56,6 +59,7 @@ public class Place implements Parcelable {
this.pic = (picString == null) ? "":picString;
String existString = in.readString();
this.exists = Boolean.parseBoolean(existString);
this.isMonument = in.readInt() == 1;
}
public static Place from(NearbyResultItem item) {
String itemClass = item.getClassName().getValue();
@ -80,20 +84,20 @@ public class Place implements Parcelable {
? " (" + description + ")" : "")
: description);
return new Place(
item.getLabel().getLanguage(),
item.getLabel().getValue(),
Label.fromText(classEntityId), // list
description, // description and label of Wikidata item
PlaceUtils.latLngFromPointString(item.getLocation().getValue()),
item.getCommonsCategory().getValue(),
new Sitelinks.Builder()
.setWikipediaLink(item.getWikipediaArticle().getValue())
.setCommonsLink(item.getCommonsArticle().getValue())
.setWikidataLink(item.getItem().getValue())
.build(),
item.getPic().getValue(),
// Checking if the place exists or not
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == ""));
item.getLabel().getLanguage(),
item.getLabel().getValue(),
Label.fromText(classEntityId), // list
description, // description and label of Wikidata item
PlaceUtils.latLngFromPointString(item.getLocation().getValue()),
item.getCommonsCategory().getValue(),
new Sitelinks.Builder()
.setWikipediaLink(item.getWikipediaArticle().getValue())
.setCommonsLink(item.getCommonsArticle().getValue())
.setWikidataLink(item.getItem().getValue())
.build(),
item.getPic().getValue(),
// Checking if the place exists or not
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == ""));
}
/**
@ -126,7 +130,9 @@ public class Place implements Parcelable {
* Gets the long description of the place
* @return long description
*/
public String getLongDescription() { return longDescription; }
public String getLongDescription() {
return longDescription;
}
/**
* Gets the Commons category of the place
@ -181,6 +187,22 @@ public class Place implements Parcelable {
return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getCommonsLink()));
}
/**
* Sets that this place in nearby is a WikiData monument
* @param monument
*/
public void setMonument(final boolean monument) {
isMonument = monument;
}
/**
* Returns if this place is a WikiData monument
* @return
*/
public boolean isMonument() {
return isMonument;
}
/**
* Check if we already have the exact same Place
* @param o Place being tested
@ -233,6 +255,7 @@ public class Place implements Parcelable {
dest.writeParcelable(siteLinks, 0);
dest.writeString(pic);
dest.writeString(exists.toString());
dest.writeInt(isMonument ? 1 : 0);
}
public static final Creator<Place> CREATOR = new Creator<Place>() {

View file

@ -3,7 +3,6 @@ package fr.free.nrw.commons.nearby.contract;
import android.content.Context;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import java.util.List;
@ -13,7 +12,6 @@ import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.nearby.Label;
import fr.free.nrw.commons.nearby.NearbyBaseMarker;
import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter;
public interface NearbyParentFragmentContract {
@ -60,7 +58,7 @@ public interface NearbyParentFragmentContract {
void displayAllMarkers();
void filterMarkersByLabels(List<Label> selectedLabels, boolean existsSelected, boolean needPhotoSelected, boolean filterForPlaceState, boolean filterForAllNoneType);
void filterMarkersByLabels(List<Label> selectedLabels, boolean existsSelected, boolean needPhotoSelected, boolean wlmSelected, boolean filterForPlaceState, boolean filterForAllNoneType);
LatLng getCameraTarget();

View file

@ -3,7 +3,6 @@ package fr.free.nrw.commons.nearby.fragments;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.MAP_UPDATED;
import static fr.free.nrw.commons.nearby.Label.TEXT_TO_DESCRIPTION;
import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween;
import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT;
@ -16,8 +15,8 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.drawable.VectorDrawable;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Html;
@ -45,8 +44,8 @@ import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.SearchView;
import androidx.fragment.app.Fragment;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -54,6 +53,7 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;
@ -83,26 +83,24 @@ import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.contributions.ContributionsFragment;
import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.contributions.MainActivity.ActiveFragment;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.location.LocationUpdateListener;
import fr.free.nrw.commons.navtab.NavTab;
import fr.free.nrw.commons.nearby.CheckBoxTriStates;
import fr.free.nrw.commons.nearby.Label;
import fr.free.nrw.commons.nearby.MarkerPlaceGroup;
import fr.free.nrw.commons.nearby.NearbyBaseMarker;
import fr.free.nrw.commons.nearby.NearbyController;
import fr.free.nrw.commons.nearby.NearbyController.NearbyPlacesInfo;
import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter;
import fr.free.nrw.commons.nearby.NearbyFilterState;
import fr.free.nrw.commons.nearby.NearbyMarker;
import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.utils.DialogUtil;
import fr.free.nrw.commons.utils.ExecutorUtils;
import fr.free.nrw.commons.utils.LayoutUtils;
@ -116,14 +114,18 @@ import fr.free.nrw.commons.utils.ViewUtil;
import fr.free.nrw.commons.wikidata.WikidataEditListener;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import timber.log.Timber;
@ -155,6 +157,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@BindView(R.id.search_this_area_button) Button searchThisAreaButton;
@BindView(R.id.map_progress_bar) ProgressBar progressBar;
@BindView(R.id.choice_chip_exists) Chip chipExists;
@BindView(R.id.choice_chip_wlm) Chip chipWlm;
@BindView(R.id.choice_chip_needs_photo) Chip chipNeedsPhoto;
@BindView(R.id.choice_chip_group) ChipGroup choiceChipGroup;
@BindView(R.id.search_view) SearchView searchView;
@ -168,6 +171,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@BindView(R.id.no_results_message) TextView noResultsView;
@BindView(R.id.tv_attribution)
AppCompatTextView tvAttribution;
@BindView(R.id.rl_container_wlm_month_message)
RelativeLayout rlContainerWLMMonthMessage;
@BindView(R.id.tv_learn_more)
AppCompatTextView tvLearnMore;
@BindView(R.id.iv_toggle_chips)
AppCompatImageView ivToggleChips;
@BindView(R.id.chip_view)
View llContainerChips;
@Inject LocationServiceManager locationManager;
@Inject NearbyController nearbyController;
@ -229,7 +240,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
/**
* Holds all the markers
*/
private List<NearbyBaseMarker> allMarkers;
private List<NearbyBaseMarker> allMarkers =new ArrayList<>();
/**
* WLM URL
*/
public static final String WLM_URL = "https://www.wikilovesmonuments.org/";
@NonNull
public static NearbyParentFragment newInstance() {
@ -268,6 +284,12 @@ 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)) {
rlContainerWLMMonthMessage.setVisibility(View.VISIBLE);
} else {
rlContainerWLMMonthMessage.setVisibility(View.GONE);
}
cameraMoveListener= () -> presenter.onCameraMove(mapBox.getCameraPosition().target);
addCheckBoxCallback();
presenter.attachView(this);
@ -491,6 +513,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
setBottomSheetCallbacks();
decideButtonVisibilities();
addActionToTitle();
if(!Utils.isMonumentsEnabled(new Date(), applicationKvStore)){
chipWlm.setVisibility(View.GONE);
}
}
/**
@ -598,6 +623,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
Log.d("deneme5","setfilterState");
chipNeedsPhoto.setChecked(NearbyFilterState.getInstance().isNeedPhotoSelected());
chipExists.setChecked(NearbyFilterState.getInstance().isExistsSelected());
chipWlm.setChecked(NearbyFilterState.getInstance().isWlmSelected());
if (NearbyController.currentLocation != null) {
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
}
@ -608,13 +634,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
chipNeedsPhoto.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (NearbyController.currentLocation != null) {
checkBoxTriStates.setState(CheckBoxTriStates.UNKNOWN);
if (isChecked) {
NearbyFilterState.setNeedPhotoSelected(true);
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
} else {
NearbyFilterState.setNeedPhotoSelected(false);
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
}
NearbyFilterState.setNeedPhotoSelected(isChecked);
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
} else {
chipNeedsPhoto.setChecked(!isChecked);
}
@ -624,17 +645,23 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
chipExists.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (NearbyController.currentLocation != null) {
checkBoxTriStates.setState(CheckBoxTriStates.UNKNOWN);
if (isChecked) {
NearbyFilterState.setExistsSelected(true);
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
} else {
NearbyFilterState.setExistsSelected(false);
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
}
NearbyFilterState.setExistsSelected(isChecked);
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
} else {
chipExists.setChecked(!isChecked);
}
});
chipWlm.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(NearbyController.currentLocation!=null){
checkBoxTriStates.setState(CheckBoxTriStates.UNKNOWN);
NearbyFilterState.setWlmSelected(isChecked);
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
}else{
chipWlm.setChecked(!isChecked);
}
});
}
/**
@ -852,40 +879,105 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
}
private void populatePlacesForCurrentLocation(final fr.free.nrw.commons.location.LatLng curlatLng,
final fr.free.nrw.commons.location.LatLng searchLatLng) {
compositeDisposable.add(Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, true))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(nearbyPlacesInfo -> {
updateMapMarkers(nearbyPlacesInfo, true);
lastFocusLocation=searchLatLng;
},
throwable -> {
Timber.d(throwable);
showErrorMessage(getString(R.string.error_fetching_nearby_places)+throwable.getLocalizedMessage());
setProgressBarVisibility(false);
presenter.lockUnlockNearby(false);
setFilterState();
}));
final fr.free.nrw.commons.location.LatLng searchLatLng){
final Observable<NearbyPlacesInfo> nearbyPlacesInfoObservable = Observable
.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, true));
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())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(nearbyPlacesInfo -> {
updateMapMarkers(nearbyPlacesInfo, true);
lastFocusLocation=searchLatLng;
},
throwable -> {
Timber.d(throwable);
showErrorMessage(getString(R.string.error_fetching_nearby_places)+throwable.getLocalizedMessage());
setProgressBarVisibility(false);
presenter.lockUnlockNearby(false);
setFilterState();
}));
}
private void populatePlacesForAnotherLocation(final fr.free.nrw.commons.location.LatLng curlatLng,
final fr.free.nrw.commons.location.LatLng searchLatLng) {
compositeDisposable.add(Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, false))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(nearbyPlacesInfo -> {
updateMapMarkers(nearbyPlacesInfo, false);
lastFocusLocation=searchLatLng;
},
throwable -> {
Timber.d(throwable);
showErrorMessage(getString(R.string.error_fetching_nearby_places)+throwable.getLocalizedMessage());
setProgressBarVisibility(false);
presenter.lockUnlockNearby(false);
}));
final fr.free.nrw.commons.location.LatLng searchLatLng){
final Observable<NearbyPlacesInfo> nearbyPlacesInfoObservable = Observable
.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, false));
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())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(nearbyPlacesInfo -> {
updateMapMarkers(nearbyPlacesInfo, false);
lastFocusLocation=searchLatLng;
},
throwable -> {
Timber.e(throwable);
showErrorMessage(getString(R.string.error_fetching_nearby_places)+throwable.getLocalizedMessage());
setProgressBarVisibility(false);
presenter.lockUnlockNearby(false);
setFilterState();
}));
}
/**
* 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;
}
/**
@ -1178,7 +1270,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private void removeCurrentLocationMarker() {
if (currentLocationMarker != null && mapBox!=null) {
mapBox.removeMarker(currentLocationMarker);
mapBox.removePolygon(currentLocationPolygon);
if (currentLocationPolygon != null) {
mapBox.removePolygon(currentLocationPolygon);
}
}
}
@ -1244,6 +1338,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
public void filterMarkersByLabels(final List<Label> selectedLabels,
final boolean displayExists,
final boolean displayNeedsPhoto,
final boolean displayWlm,
final boolean filterForPlaceState,
final boolean filterForAllNoneType) {
@ -1263,23 +1358,36 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
continue;
}
if (displayExists && displayNeedsPhoto) {
if (!displayWlm && place.isMonument()) {
continue;
}
boolean shouldUpdateMarker=false;
if (displayWlm && place.isMonument()) {
shouldUpdateMarker=true;
}
else if (displayExists && displayNeedsPhoto) {
// Exists and needs photo
if (place.exists && place.pic.trim().isEmpty()) {
updateMarker(markerPlaceGroup.getIsBookmarked(), place, NearbyController.currentLocation);
shouldUpdateMarker=true;
}
} else if (displayExists && !displayNeedsPhoto) {
// Exists and all included needs and doesn't needs photo
if (place.exists) {
updateMarker(markerPlaceGroup.getIsBookmarked(), place, NearbyController.currentLocation);
shouldUpdateMarker=true;
}
} else if (!displayExists && displayNeedsPhoto) {
// All and only needs photo
if (place.pic.trim().isEmpty()) {
updateMarker(markerPlaceGroup.getIsBookmarked(), place, NearbyController.currentLocation);
shouldUpdateMarker=true;
}
} else if (!displayExists && !displayNeedsPhoto) {
// all
shouldUpdateMarker=true;
}
if(shouldUpdateMarker){
updateMarker(markerPlaceGroup.getIsBookmarked(), place, NearbyController.currentLocation);
}
}
@ -1337,7 +1445,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
}
private @DrawableRes int getIconFor(Place place, Boolean isBookmarked) {
if (!place.pic.trim().isEmpty()) {
if(place.isMonument()){
return R.drawable.ic_custom_map_marker_monuments;
}
else if (!place.pic.trim().isEmpty()) {
return (isBookmarked ?
R.drawable.ic_custom_map_marker_green_bookmarked :
R.drawable.ic_custom_map_marker_green);
@ -1397,7 +1508,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
}
@Override
public void recenterMap(final fr.free.nrw.commons.location.LatLng curLatLng) {
public void recenterMap(fr.free.nrw.commons.location.LatLng curLatLng) {
if (isPermissionDenied || curLatLng == null) {
recenterToUserLocation = true;
checkPermissionsAndPerformAction();
@ -1667,4 +1778,21 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
rlBottomSheetLayoutParams.height = getActivity().getWindowManager().getDefaultDisplay().getHeight() / 16 * 9;
rlBottomSheet.setLayoutParams(rlBottomSheetLayoutParams);
}
@OnClick(R.id.tv_learn_more)
public void onLearnMoreClicked() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(WLM_URL));
startActivity(intent);
}
@OnClick(R.id.iv_toggle_chips)
public void onToggleChipsClicked() {
if (llContainerChips.getVisibility() == View.VISIBLE) {
llContainerChips.setVisibility(View.GONE);
} else {
llContainerChips.setVisibility(View.VISIBLE);
}
ivToggleChips.setRotation(ivToggleChips.getRotation() + 180);
}
}

View file

@ -7,6 +7,7 @@ class NearbyResultItem(private val item: ResultTuple?,
private val commonsArticle: ResultTuple?,
private val location: ResultTuple?,
private val label: ResultTuple?,
@field:SerializedName("streetAddress") private val address: ResultTuple?,
private val icon: ResultTuple?, @field:SerializedName("class") private val className: ResultTuple?,
@field:SerializedName("classLabel") private val classLabel: ResultTuple?,
@field:SerializedName("commonsCategory") private val commonsCategory: ResultTuple?,
@ -66,4 +67,8 @@ class NearbyResultItem(private val item: ResultTuple?,
fun getEndTime(): ResultTuple {
return endTime ?: ResultTuple()
}
fun getAddress(): String {
return address?.value?:""
}
}

View file

@ -1,6 +1,5 @@
package fr.free.nrw.commons.nearby.presenter;
import android.util.Log;
import android.view.View;
import androidx.annotation.MainThread;
@ -297,6 +296,7 @@ public class NearbyParentFragmentPresenter
nearbyParentFragmentView.filterMarkersByLabels(selectedLabels,
NearbyFilterState.getInstance().isExistsSelected(),
NearbyFilterState.getInstance().isNeedPhotoSelected(),
NearbyFilterState.getInstance().isWlmSelected(),
filterForPlaceState, false);
nearbyParentFragmentView.setRecyclerViewAdapterAllSelected();
break;
@ -305,6 +305,7 @@ public class NearbyParentFragmentPresenter
nearbyParentFragmentView.filterMarkersByLabels(selectedLabels,
NearbyFilterState.getInstance().isExistsSelected(),
NearbyFilterState.getInstance().isNeedPhotoSelected(),
NearbyFilterState.getInstance().isWlmSelected(),
filterForPlaceState, false);
}
}