mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
* 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:
parent
67f5b6c271
commit
6588a6fd0e
39 changed files with 2906 additions and 185 deletions
|
|
@ -17,6 +17,8 @@ import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
|||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import java.util.Date;
|
||||
import org.wikipedia.dataclient.WikiSite;
|
||||
import org.wikipedia.page.PageTitle;
|
||||
|
||||
|
|
@ -29,6 +31,7 @@ import fr.free.nrw.commons.utils.ViewUtil;
|
|||
import timber.log.Timber;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static fr.free.nrw.commons.campaigns.CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE;
|
||||
|
||||
public class Utils {
|
||||
|
||||
|
|
@ -210,4 +213,35 @@ public class Utils {
|
|||
textView.setText(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* For now we are enabling the monuments only when the date lies between 1 Sept & 31 OCt
|
||||
* @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 ){
|
||||
return true;
|
||||
}
|
||||
|
||||
return store.getBoolean(CAMPAIGNS_DEFAULT_PREFERENCE) || true ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Util function to get the start date of wlm monument
|
||||
* For this release we are hardcoding it to be 1st September
|
||||
* @return
|
||||
*/
|
||||
public static String getWLMStartDate() {
|
||||
return "1 Sep";
|
||||
}
|
||||
|
||||
/***
|
||||
* Util function to get the end date of wlm monument
|
||||
* For this release we are hardcoding it to be 31st October
|
||||
* @return
|
||||
*/
|
||||
public static String getWLMEndDate() {
|
||||
return "31 Oct";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,11 +147,11 @@ public class BookmarkLocationsDao {
|
|||
}
|
||||
|
||||
@NonNull
|
||||
Place fromCursor(Cursor cursor) {
|
||||
LatLng location = new LatLng(cursor.getDouble(cursor.getColumnIndex(Table.COLUMN_LAT)),
|
||||
Place fromCursor(final Cursor cursor) {
|
||||
final LatLng location = new LatLng(cursor.getDouble(cursor.getColumnIndex(Table.COLUMN_LAT)),
|
||||
cursor.getDouble(cursor.getColumnIndex(Table.COLUMN_LONG)), 1F);
|
||||
|
||||
Sitelinks.Builder builder = new Sitelinks.Builder();
|
||||
final Sitelinks.Builder builder = new Sitelinks.Builder();
|
||||
builder.setWikipediaLink(cursor.getString(cursor.getColumnIndex(Table.COLUMN_WIKIPEDIA_LINK)));
|
||||
builder.setWikidataLink(cursor.getString(cursor.getColumnIndex(Table.COLUMN_WIKIDATA_LINK)));
|
||||
builder.setCommonsLink(cursor.getString(cursor.getColumnIndex(Table.COLUMN_COMMONS_LINK)));
|
||||
|
|
@ -220,7 +220,7 @@ public class BookmarkLocationsDao {
|
|||
COLUMN_WIKIDATA_LINK,
|
||||
COLUMN_COMMONS_LINK,
|
||||
COLUMN_PIC,
|
||||
COLUMN_EXISTS
|
||||
COLUMN_EXISTS,
|
||||
};
|
||||
|
||||
static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS " + TABLE_NAME;
|
||||
|
|
@ -251,7 +251,7 @@ public class BookmarkLocationsDao {
|
|||
onCreate(db);
|
||||
}
|
||||
|
||||
public static void onUpdate(SQLiteDatabase db, int from, int to) {
|
||||
public static void onUpdate(final SQLiteDatabase db, int from, final int to) {
|
||||
Timber.d("bookmarksLocations db is updated from:"+from+", to:"+to);
|
||||
if (from == to) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@ data class Campaign(var title: String? = null,
|
|||
var description: String? = null,
|
||||
var startDate: String? = null,
|
||||
var endDate: String? = null,
|
||||
var link: String? = null)
|
||||
var link: String? = null,
|
||||
var isWLMCampaign: Boolean = false)
|
||||
|
|
@ -4,11 +4,13 @@ import android.content.Context;
|
|||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import fr.free.nrw.commons.theme.BaseActivity;
|
||||
import org.wikipedia.util.DateUtil;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
|
@ -27,9 +29,14 @@ import fr.free.nrw.commons.utils.ViewUtil;
|
|||
* A view which represents a single campaign
|
||||
*/
|
||||
public class CampaignView extends SwipableCardView {
|
||||
Campaign campaign = null;
|
||||
Campaign campaign;
|
||||
private ViewHolder viewHolder;
|
||||
|
||||
public static final String CAMPAIGNS_DEFAULT_PREFERENCE = "displayCampaignsCardView";
|
||||
public static final String WLM_CARD_PREFERENCE = "displayWLMCardView";
|
||||
|
||||
private String campaignPreference = CAMPAIGNS_DEFAULT_PREFERENCE;
|
||||
|
||||
public CampaignView(@NonNull Context context) {
|
||||
super(context);
|
||||
init();
|
||||
|
|
@ -45,37 +52,46 @@ public class CampaignView extends SwipableCardView {
|
|||
init();
|
||||
}
|
||||
|
||||
public void setCampaign(Campaign campaign) {
|
||||
public void setCampaign(final Campaign campaign) {
|
||||
this.campaign = campaign;
|
||||
if (campaign != null) {
|
||||
this.setVisibility(View.VISIBLE);
|
||||
if (campaign.isWLMCampaign()) {
|
||||
campaignPreference = WLM_CARD_PREFERENCE;
|
||||
}
|
||||
setVisibility(View.VISIBLE);
|
||||
viewHolder.init();
|
||||
} else {
|
||||
this.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean onSwipe(View view) {
|
||||
@Override public boolean onSwipe(final View view) {
|
||||
view.setVisibility(View.GONE);
|
||||
((MainActivity) getContext()).defaultKvStore
|
||||
.putBoolean("displayCampaignsCardView", false);
|
||||
((BaseActivity) getContext()).defaultKvStore
|
||||
.putBoolean(campaignPreference, false);
|
||||
ViewUtil.showLongToast(getContext(),
|
||||
getResources().getString(R.string.nearby_campaign_dismiss_message));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
View rootView = inflate(getContext(), R.layout.layout_campagin, this);
|
||||
final View rootView = inflate(getContext(), R.layout.layout_campagin, this);
|
||||
viewHolder = new ViewHolder(rootView);
|
||||
setOnClickListener(view -> {
|
||||
if (campaign != null) {
|
||||
if (campaign.isWLMCampaign()) {
|
||||
((MainActivity)(getContext())).showNearby();
|
||||
} else {
|
||||
Utils.handleWebUrl(getContext(), Uri.parse(campaign.getLink()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public class ViewHolder {
|
||||
|
||||
@BindView(R.id.iv_campaign)
|
||||
ImageView ivCampaign;
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.tv_description) TextView tvDescription;
|
||||
@BindView(R.id.tv_dates) TextView tvDates;
|
||||
|
|
@ -86,14 +102,26 @@ public class CampaignView extends SwipableCardView {
|
|||
|
||||
public void init() {
|
||||
if (campaign != null) {
|
||||
ivCampaign.setImageDrawable(
|
||||
getResources().getDrawable(R.drawable.ic_campaign));
|
||||
|
||||
tvTitle.setText(campaign.getTitle());
|
||||
tvDescription.setText(campaign.getDescription());
|
||||
try {
|
||||
Date startDate = CommonsDateUtil.getIso8601DateFormatShort().parse(campaign.getStartDate());
|
||||
Date endDate = CommonsDateUtil.getIso8601DateFormatShort().parse(campaign.getEndDate());
|
||||
tvDates.setText(String.format("%1s - %2s", DateUtil.getExtraShortDateString(startDate),
|
||||
DateUtil.getExtraShortDateString(endDate)));
|
||||
} catch (ParseException e) {
|
||||
if (campaign.isWLMCampaign()) {
|
||||
tvDates.setText(
|
||||
String.format("%1s - %2s", campaign.getStartDate(),
|
||||
campaign.getEndDate()));
|
||||
} else {
|
||||
final Date startDate = CommonsDateUtil.getIso8601DateFormatShort()
|
||||
.parse(campaign.getStartDate());
|
||||
final Date endDate = CommonsDateUtil.getIso8601DateFormatShort()
|
||||
.parse(campaign.getEndDate());
|
||||
tvDates.setText(
|
||||
String.format("%1s - %2s", startDate,
|
||||
endDate));
|
||||
}
|
||||
} catch (final ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@ package fr.free.nrw.commons.contributions;
|
|||
|
||||
import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.STATE_PAUSED;
|
||||
import static fr.free.nrw.commons.nearby.fragments.NearbyParentFragment.WLM_URL;
|
||||
import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
|
|
@ -27,21 +26,21 @@ import androidx.fragment.app.Fragment;
|
|||
import androidx.fragment.app.FragmentManager.OnBackStackChangedListener;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.notification.Notification;
|
||||
import fr.free.nrw.commons.notification.NotificationController;
|
||||
import fr.free.nrw.commons.theme.BaseActivity;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import androidx.work.WorkInfo;
|
||||
import androidx.work.WorkManager;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.Media;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.campaigns.Campaign;
|
||||
import fr.free.nrw.commons.campaigns.CampaignView;
|
||||
import fr.free.nrw.commons.campaigns.CampaignsPresenter;
|
||||
|
|
@ -59,10 +58,7 @@ import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
|
|||
import fr.free.nrw.commons.nearby.NearbyController;
|
||||
import fr.free.nrw.commons.nearby.NearbyNotificationCardView;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
import fr.free.nrw.commons.notification.Notification;
|
||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||
import fr.free.nrw.commons.notification.NotificationController;
|
||||
import fr.free.nrw.commons.theme.BaseActivity;
|
||||
import fr.free.nrw.commons.upload.worker.UploadWorker;
|
||||
import fr.free.nrw.commons.utils.ConfigUtils;
|
||||
import fr.free.nrw.commons.utils.DialogUtil;
|
||||
|
|
@ -73,9 +69,6 @@ import io.reactivex.Observable;
|
|||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class ContributionsFragment
|
||||
|
|
@ -118,6 +111,8 @@ public class ContributionsFragment
|
|||
|
||||
public TextView notificationCount;
|
||||
|
||||
private Campaign wlmCampaign;
|
||||
|
||||
@NonNull
|
||||
public static ContributionsFragment newInstance() {
|
||||
ContributionsFragment fragment = new ContributionsFragment();
|
||||
|
|
@ -137,6 +132,7 @@ public class ContributionsFragment
|
|||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_contributions, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
initWLMCampaign();
|
||||
presenter.onAttachView(this);
|
||||
contributionsPresenter.onAttachView(this);
|
||||
campaignView.setVisibility(View.GONE);
|
||||
|
|
@ -177,6 +173,15 @@ public class ContributionsFragment
|
|||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the campaign object for WML
|
||||
*/
|
||||
private void initWLMCampaign() {
|
||||
wlmCampaign = new Campaign(getString(R.string.wlm_campaign_title),
|
||||
getString(R.string.wlm_campaign_description), Utils.getWLMStartDate().toString(),
|
||||
Utils.getWLMEndDate().toString(), WLM_URL, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.contribution_activity_notification_menu, menu);
|
||||
|
|
@ -518,13 +523,17 @@ public class ContributionsFragment
|
|||
}
|
||||
|
||||
/**
|
||||
* ask the presenter to fetch the campaigns only if user has not manually disabled it
|
||||
* As the home screen has limited space, we have choosen to show either campaigns or WLM card.
|
||||
* The WLM Card gets the priority over monuments, so if the WLM is going on we show that instead
|
||||
* of campaigns on the campaigns card
|
||||
*/
|
||||
private void fetchCampaigns() {
|
||||
if (store.getBoolean("displayCampaignsCardView", true)) {
|
||||
if (Utils.isMonumentsEnabled(new Date(), store)) {
|
||||
campaignView.setCampaign(wlmCampaign);
|
||||
campaignView.setVisibility(View.VISIBLE);
|
||||
} else if (store.getBoolean(CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE, true)) {
|
||||
presenter.getCampaigns();
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
campaignView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
|
|||
|
||||
private ContributionsListAdapter adapter;
|
||||
|
||||
private Callback callback;
|
||||
@Nullable private Callback callback;
|
||||
|
||||
private final int SPAN_COUNT_LANDSCAPE = 3;
|
||||
private final int SPAN_COUNT_PORTRAIT = 1;
|
||||
|
|
@ -150,7 +150,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
|
|||
contributionsListPresenter.contributionList.observe(this.getViewLifecycleOwner(), list -> {
|
||||
contributionsSize = list.size();
|
||||
adapter.submitList(list);
|
||||
if (callback != null) {
|
||||
callback.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
rvContributionsList.setAdapter(adapter);
|
||||
adapter.registerAdapterDataObserver(new AdapterDataObserver() {
|
||||
|
|
@ -172,8 +174,10 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
|
|||
@Override
|
||||
public void onItemRangeChanged(final int positionStart, final int itemCount) {
|
||||
super.onItemRangeChanged(positionStart, itemCount);
|
||||
if (callback != null) {
|
||||
callback.viewPagerNotifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Fab close on touch outside (Scrolling or taping on item triggers this action).
|
||||
|
|
|
|||
|
|
@ -373,6 +373,13 @@ public class MainActivity extends BaseActivity
|
|||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method to show nearby from the reference of this.
|
||||
*/
|
||||
public void showNearby() {
|
||||
tabLayout.setSelectedItemId(NavTab.NEARBY.code());
|
||||
}
|
||||
|
||||
public enum ActiveFragment {
|
||||
CONTRIBUTIONS,
|
||||
NEARBY,
|
||||
|
|
|
|||
|
|
@ -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 = 15;
|
||||
private static final int DATABASE_VERSION = 17;
|
||||
public static final String CONTRIBUTIONS_TABLE = "contributions";
|
||||
private final String DROP_TABLE_STATEMENT="DROP TABLE IF EXISTS %s";
|
||||
|
||||
|
|
|
|||
|
|
@ -265,7 +265,9 @@ public class OkHttpJsonApiClient {
|
|||
}
|
||||
|
||||
public Observable<List<Place>> getNearbyPlaces(LatLng cur, String language, double radius)
|
||||
throws IOException {
|
||||
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))
|
||||
|
|
@ -302,6 +304,67 @@ public class OkHttpJsonApiClient {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wikidata query to fetch monuments
|
||||
*
|
||||
* @param cur : The current location coordinates
|
||||
* @param language : The language
|
||||
* @param radius : The radius around the current location within which we expect the results
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public Observable<List<Place>> getNearbyMonuments(LatLng cur, String language, final double radius){
|
||||
Timber.d("Fetching monuments at radius %s", radius);
|
||||
final String wikidataQuery;
|
||||
try {
|
||||
wikidataQuery = FileUtils.readFromResource("/queries/monuments_query.rq");
|
||||
if (TextUtils.isEmpty(language)) {
|
||||
language = "en";
|
||||
}
|
||||
String query = wikidataQuery
|
||||
.replace("${RAD}", String.format(Locale.ROOT, "%.2f", radius))
|
||||
.replace("${LAT}", String.format(Locale.ROOT, "%.4f", cur.getLatitude()))
|
||||
.replace("${LONG}", String.format(Locale.ROOT, "%.4f", cur.getLongitude()))
|
||||
.replace("${LANG}", language);
|
||||
|
||||
HttpUrl.Builder urlBuilder = HttpUrl
|
||||
.parse(sparqlQueryUrl)
|
||||
.newBuilder()
|
||||
.addQueryParameter("query", query)
|
||||
.addQueryParameter("format", "json");
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(urlBuilder.build())
|
||||
.build();
|
||||
|
||||
Timber.d("Monuments URL: %s", request.url().toString());
|
||||
|
||||
return Observable.fromCallable(() -> {
|
||||
final Response response = okHttpClient.newCall(request).execute();
|
||||
if (response != null && response.body() != null && response.isSuccessful()) {
|
||||
final String json = response.body().string();
|
||||
if (json == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
final NearbyResponse nearbyResponse = gson.fromJson(json, NearbyResponse.class);
|
||||
final List<NearbyResultItem> bindings = nearbyResponse.getResults().getBindings();
|
||||
final List<Place> places = new ArrayList<>();
|
||||
for (final NearbyResultItem item : bindings) {
|
||||
final Place place = Place.from(item);
|
||||
place.setMonument(true);
|
||||
places.add(place);
|
||||
}
|
||||
return places;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
});
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
return Observable.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the QIDs of all Wikidata items that are subclasses of the given Wikidata item. Example:
|
||||
* bridge -> suspended bridge, aqueduct, etc
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,12 +193,13 @@ 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(
|
||||
|
|
@ -196,7 +207,12 @@ public class NearbyController {
|
|||
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));
|
||||
|
|
@ -210,7 +226,6 @@ public class NearbyController {
|
|||
nearbyBaseMarker.icon(IconFactory.getInstance(context)
|
||||
.fromBitmap(icon));
|
||||
}
|
||||
|
||||
baseMarkerOptions.add(nearbyBaseMarker);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -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>() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
NearbyFilterState.setNeedPhotoSelected(isChecked);
|
||||
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
|
||||
} else {
|
||||
NearbyFilterState.setNeedPhotoSelected(false);
|
||||
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);
|
||||
NearbyFilterState.setExistsSelected(isChecked);
|
||||
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels, checkBoxTriStates.getState(), true, false);
|
||||
} else {
|
||||
NearbyFilterState.setExistsSelected(false);
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -853,9 +880,32 @@ 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())
|
||||
|
||||
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);
|
||||
|
|
@ -872,22 +922,64 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
|
||||
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())
|
||||
|
||||
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.d(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates places for your location, should be used for finding nearby places around a
|
||||
* location where you are.
|
||||
|
|
@ -1178,9 +1270,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
private void removeCurrentLocationMarker() {
|
||||
if (currentLocationMarker != null && mapBox!=null) {
|
||||
mapBox.removeMarker(currentLocationMarker);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?:""
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package fr.free.nrw.commons.repository;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import fr.free.nrw.commons.category.CategoriesModel;
|
||||
import fr.free.nrw.commons.category.CategoryItem;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
|
|
@ -26,6 +27,7 @@ import java.util.Locale;
|
|||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* The repository class for UploadActivity
|
||||
|
|
@ -280,6 +282,7 @@ public class UploadRepository {
|
|||
* @param decLongitude
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public Place checkNearbyPlaces(double decLatitude, double decLongitude) {
|
||||
try {
|
||||
List<Place> fromWikidataQuery = nearbyPlaces.getFromWikidataQuery(new LatLng(
|
||||
|
|
@ -287,7 +290,8 @@ public class UploadRepository {
|
|||
Locale.getDefault().getLanguage(),
|
||||
NEARBY_RADIUS_IN_KILO_METERS);
|
||||
return fromWikidataQuery.size() > 0 ? fromWikidataQuery.get(0) : null;
|
||||
} catch (IOException e) {
|
||||
}catch (final Exception e) {
|
||||
Timber.e("Error fetching nearby places: %s", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.MultiSelectListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceGroupAdapter;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
|
@ -25,6 +27,7 @@ import com.mapbox.mapboxsdk.Mapbox;
|
|||
import com.mapbox.mapboxsdk.maps.TelemetryDefinition;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.campaigns.CampaignView;
|
||||
import fr.free.nrw.commons.contributions.MainActivity;
|
||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
|
|
@ -104,7 +107,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
findPreference("displayNearbyCardView").setEnabled(false);
|
||||
findPreference("descriptionDefaultLanguagePref").setEnabled(false);
|
||||
findPreference("displayLocationPermissionForCardView").setEnabled(false);
|
||||
findPreference("displayCampaignsCardView").setEnabled(false);
|
||||
findPreference(CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE).setEnabled(false);
|
||||
}
|
||||
|
||||
findPreference("telemetryOptOut").setOnPreferenceChangeListener(
|
||||
|
|
@ -127,7 +130,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
||||
protected Adapter onCreateAdapter(final PreferenceScreen preferenceScreen) {
|
||||
return new PreferenceGroupAdapter(preferenceScreen) {
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import javax.inject.Inject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
class PageContentsCreator {
|
||||
|
||||
|
|
@ -29,13 +30,15 @@ class PageContentsCreator {
|
|||
this.context = context;
|
||||
}
|
||||
|
||||
public String createFrom(Contribution contribution) {
|
||||
public String createFrom(Contribution contribution, String countryCode) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
final Media media = contribution.getMedia();
|
||||
buffer
|
||||
.append("== {{int:filedesc}} ==\n")
|
||||
.append("{{Information\n")
|
||||
.append("|description=").append(media.getFallbackDescription()).append("\n")
|
||||
.append("|description=").append(media.getFallbackDescription())
|
||||
.append("{{ on Wikidata|").append(contribution.getWikidataPlace().getId()).append("}}")
|
||||
.append("\n")
|
||||
.append("|source=").append("{{own}}\n")
|
||||
.append("|author=[[User:").append(media.getAuthor()).append("|")
|
||||
.append(media.getAuthor()).append("]]\n");
|
||||
|
|
@ -48,6 +51,12 @@ 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) {
|
||||
|
|
@ -66,6 +75,7 @@ class PageContentsCreator {
|
|||
} else {
|
||||
buffer.append("{{subst:unc}}");
|
||||
}
|
||||
Timber.d("Template: %s", buffer.toString());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -261,6 +261,11 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
|
|||
return fragments.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWLMUpload() {
|
||||
return place!=null && place.isMonument();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(int messageResourceId) {
|
||||
ViewUtil.showLongToast(this, messageResourceId);
|
||||
|
|
@ -372,6 +377,11 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
|
|||
public int getTotalNumberOfSteps() {
|
||||
return fragments.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWLMUpload() {
|
||||
return place!=null && place.isMonument();
|
||||
}
|
||||
});
|
||||
fragments.add(uploadMediaDetailFragment);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ public class UploadBaseFragment extends CommonsDaggerSupportFragment {
|
|||
|
||||
int getTotalNumberOfSteps();
|
||||
|
||||
boolean isWLMUpload();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
|
@ -212,11 +210,11 @@ public class UploadClient {
|
|||
public Observable<UploadResult> uploadFileFromStash(
|
||||
final Contribution contribution,
|
||||
final String uniqueFileName,
|
||||
final String fileKey) {
|
||||
final String fileKey, @Nullable String countryCode) {
|
||||
try {
|
||||
return uploadInterface
|
||||
.uploadFileFromStash(csrfTokenClient.getTokenBlocking(),
|
||||
pageContentsCreator.createFrom(contribution),
|
||||
pageContentsCreator.createFrom(contribution, countryCode),
|
||||
CommonsApplication.DEFAULT_EDIT_SUMMARY,
|
||||
uniqueFileName,
|
||||
fileKey).map(uploadResponse -> {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import android.os.Parcelable
|
||||
import fr.free.nrw.commons.location.LatLng
|
||||
import fr.free.nrw.commons.nearby.Place
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
|
|
@ -9,14 +10,18 @@ data class WikidataPlace(
|
|||
override val id: String,
|
||||
override val name: String,
|
||||
val imageValue: String?,
|
||||
val wikipediaArticle: String?
|
||||
val wikipediaArticle: String?,
|
||||
val location: LatLng? = null,
|
||||
val isMonumentUpload : Boolean =false
|
||||
) :
|
||||
WikidataItem, Parcelable {
|
||||
constructor(place: Place) : this(
|
||||
place.wikiDataEntityId!!,
|
||||
place.name,
|
||||
place.pic.takeIf { it.isNotBlank() },
|
||||
place.siteLinks.wikipediaLink?.toString() ?: ""
|
||||
place.siteLinks.wikipediaLink?.toString() ?: "",
|
||||
place.location,
|
||||
isMonumentUpload=place.isMonument
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
|
|
@ -48,6 +49,8 @@ public class MediaLicenseFragment extends UploadBaseFragment implements MediaLic
|
|||
TextView tvShareLicenseSummary;
|
||||
@BindView(R.id.tooltip)
|
||||
ImageView tooltip;
|
||||
@BindView(R.id.ll_info_monument_upload)
|
||||
LinearLayout llInfoMonumentUpload;
|
||||
|
||||
@Inject
|
||||
MediaLicenseContract.UserActionListener presenter;
|
||||
|
|
@ -87,6 +90,16 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ package fr.free.nrw.commons.upload.worker
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import android.location.Geocoder
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.Data
|
||||
import androidx.work.WorkerParameters
|
||||
import com.google.gson.Gson
|
||||
import com.mapbox.mapboxsdk.plugins.localization.BuildConfig
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import fr.free.nrw.commons.CommonsApplication
|
||||
|
|
@ -19,6 +19,7 @@ import fr.free.nrw.commons.contributions.ChunkInfo
|
|||
import fr.free.nrw.commons.contributions.Contribution
|
||||
import fr.free.nrw.commons.contributions.ContributionDao
|
||||
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.StashUploadState
|
||||
import fr.free.nrw.commons.upload.UploadClient
|
||||
|
|
@ -30,6 +31,7 @@ import kotlinx.coroutines.flow.collect
|
|||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
import javax.inject.Inject
|
||||
|
|
@ -275,8 +277,16 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
|||
|
||||
try {
|
||||
//Upload the file from stash
|
||||
var countryCode: String? =null
|
||||
with(contribution.wikidataPlace?.location){
|
||||
if(contribution.wikidataPlace?.isMonumentUpload!!) {
|
||||
countryCode =
|
||||
reverseGeoCode(contribution.wikidataPlace?.location!!)?.toLowerCase()
|
||||
}
|
||||
|
||||
}
|
||||
val uploadResult = uploadClient.uploadFileFromStash(
|
||||
contribution, uniqueFileName, stashUploadResult.fileKey
|
||||
contribution, uniqueFileName, stashUploadResult.fileKey, countryCode
|
||||
).blockingSingle()
|
||||
|
||||
if (uploadResult.isSuccessful()) {
|
||||
|
|
@ -339,6 +349,26 @@ 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)
|
||||
|
|
|
|||
2117
app/src/main/res/drawable/ic_custom_map_marker_monuments.xml
Normal file
2117
app/src/main/res/drawable/ic_custom_map_marker_monuments.xml
Normal file
File diff suppressed because it is too large
Load diff
BIN
app/src/main/res/drawable/wlm_banner.png
Normal file
BIN
app/src/main/res/drawable/wlm_banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
|
|
@ -37,6 +37,14 @@
|
|||
app:chipBackgroundColor="@color/bg_chip_state"
|
||||
android:text="@string/place_state_needs_photo"/>
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/choice_chip_wlm"
|
||||
style="@style/Widget.MaterialComponents.Chip.Filter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:chipBackgroundColor="@color/bg_chip_state"
|
||||
android:text="@string/place_state_wlm"/>
|
||||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
||||
android:padding="@dimen/standard_gap"
|
||||
>
|
||||
android:padding="@dimen/standard_gap">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
|
@ -67,8 +67,29 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:padding="10dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_info_monument_upload"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
app:srcCompat="@drawable/ic_custom_map_marker_monuments"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/wlm_upload_info"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
<fr.free.nrw.commons.ui.widget.HtmlTextView
|
||||
android:id="@+id/tv_media_upload_policy"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
|
@ -15,6 +16,35 @@
|
|||
layout="@layout/nearby_filter_all_items"
|
||||
android:id="@+id/nearby_filter"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:gravity="center"
|
||||
android:id="@+id/rl_container_wlm_month_message"
|
||||
android:background="@color/white"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone"
|
||||
android:layout_below="@id/nearby_filter">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toStartOf="@id/tv_learn_more"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/secondaryTextColor"
|
||||
android:text="@string/wlm_month_message"/>
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tv_learn_more"
|
||||
android:textColor="@color/status_bar_blue"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:text="@string/learn_more"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</androidx.appcompat.widget.AppCompatTextView>
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/nearby_filter_list"
|
||||
android:id="@+id/nearby_filter_list"
|
||||
android:layout_below="@id/nearby_filter"
|
||||
|
|
@ -28,7 +58,7 @@
|
|||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/nearby_filter">
|
||||
android:layout_below="@id/rl_container_wlm_month_message">
|
||||
|
||||
<com.mapbox.mapboxsdk.maps.MapView
|
||||
android:id="@+id/map_view"
|
||||
|
|
@ -69,7 +99,8 @@
|
|||
android:textColor="@color/status_bar_blue"
|
||||
android:visibility="gone"
|
||||
app:elevation="@dimen/dimen_6"
|
||||
android:layout_below="@id/nearby_filter"/>
|
||||
android:layout_below="@id/rl_container_wlm_month_message"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:id="@+id/transparentView"
|
||||
|
|
@ -88,7 +119,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/nearby_filter"
|
||||
android:layout_below="@id/rl_container_wlm_month_message"
|
||||
android:clickable="true"
|
||||
android:visibility="visible"
|
||||
app:backgroundTint="@color/main_background_light"
|
||||
|
|
|
|||
|
|
@ -1,22 +1,35 @@
|
|||
<LinearLayout android:layout_width="match_parent"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="vertical"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@color/status_bar_blue">
|
||||
|
||||
<include
|
||||
android:layout_toStartOf="@+id/iv_toggle_chips"
|
||||
android:id="@+id/chip_view"
|
||||
layout="@layout/filter_chip_view"
|
||||
android:background="@color/deleteRed"
|
||||
/>
|
||||
|
||||
<include android:id="@+id/search_view_layout" layout="@layout/filter_search_view_layout" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/search_view_layout"
|
||||
android:background="@color/status_bar_blue">
|
||||
</RelativeLayout>
|
||||
android:background="@color/deleteRed" />
|
||||
|
||||
</LinearLayout>
|
||||
<include
|
||||
android:layout_toStartOf="@+id/iv_toggle_chips"
|
||||
android:id="@+id/search_view_layout"
|
||||
layout="@layout/filter_search_view_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/chip_view" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/iv_toggle_chips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/ic_expand_less_black_24dp"
|
||||
android:tint="@color/white"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
@ -323,6 +323,7 @@
|
|||
<string name="share_app_title">Share App</string>
|
||||
|
||||
<string name="error_fetching_nearby_places">Error fetching nearby places.</string>
|
||||
<string name="error_fetching_nearby_monuments">Error fetching nearby monuments.</string>
|
||||
<string name="no_recent_searches">No recent searches</string>
|
||||
<string name="delete_recent_searches_dialog">Are you sure you want to clear your search history?</string>
|
||||
<string name="delete_search_dialog">Do you want to delete this search?</string>
|
||||
|
|
@ -638,5 +639,12 @@ Upload your first media by tapping on the add button.</string>
|
|||
The shadow of the image view of the location picker</string>
|
||||
<string name="image_location">Image Location</string>
|
||||
<string name="check_whether_location_is_correct">Check whether location is correct</string>
|
||||
<string name="place_state_wlm">WLM</string>
|
||||
<string name="wlm_upload_info">You are contributing to Wiki Loves Monuments Campaign. Related templates will be added accordingly.</string>
|
||||
<string name="display_monuments">Display monuments</string>
|
||||
<string name="wlm_month_message">It\'s Wiki Loves Monuments month!</string>
|
||||
<string name="learn_more">LEARN MORE</string>
|
||||
<string name="wlm_campaign_title">Wiki Loves Monuments</string>
|
||||
<string name="wlm_campaign_description">Wiki Loves Monuments is an international photo contest for monuments organised by Wikimedia</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@
|
|||
app:singleLineTitle="false"
|
||||
android:summary="@string/display_campaigns_explanation"
|
||||
android:title="@string/display_campaigns" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
|
|
|||
60
app/src/main/resources/queries/monuments_query.rq
Normal file
60
app/src/main/resources/queries/monuments_query.rq
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
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,9 +1,6 @@
|
|||
package fr.free.nrw.commons.bookmarks.locations
|
||||
|
||||
import android.net.Uri
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import fr.free.nrw.commons.bookmarks.Bookmark
|
||||
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao
|
||||
import fr.free.nrw.commons.nearby.Place
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
|
|
@ -33,8 +30,23 @@ class BookmarkLocationControllerTest {
|
|||
private val mockBookmarkList: List<Place>
|
||||
private get() {
|
||||
val list = ArrayList<Place>()
|
||||
list.add(Place("en","a place",null,"a description",null,"a cat",null,null,true))
|
||||
list.add(Place("en","another place",null,"another description",null,"another cat",null,null,true))
|
||||
list.add(
|
||||
Place(
|
||||
"en", "a place", null, "a description", null, "a cat", null, null, true)
|
||||
)
|
||||
list.add(
|
||||
Place(
|
||||
"en",
|
||||
"another place",
|
||||
null,
|
||||
"another description",
|
||||
null,
|
||||
"another cat",
|
||||
null,
|
||||
null,
|
||||
true
|
||||
)
|
||||
)
|
||||
return list
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,18 @@ class BookmarkLocationFragmentUnitTests {
|
|||
private val mockBookmarkList: List<Place>
|
||||
private get() {
|
||||
val list = ArrayList<Place>()
|
||||
list.add(Place("en","a place",null,"a description",null,"a cat",null,null,true))
|
||||
list.add(
|
||||
Place(
|
||||
"en",
|
||||
"a place",
|
||||
null,
|
||||
"a description",
|
||||
null,
|
||||
"a cat",
|
||||
null,
|
||||
null,
|
||||
true)
|
||||
)
|
||||
return list
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,7 +265,14 @@ class NearbyParentFragmentPresenterTest {
|
|||
fun testFilterByMarkerTypeMultiSelectCHECKED() {
|
||||
val state = CheckBoxTriStates.CHECKED
|
||||
nearbyPresenter.filterByMarkerType(selectedLabels, state, false,true)
|
||||
verify(nearbyParentFragmentView).filterMarkersByLabels(ArgumentMatchers.anyList(),ArgumentMatchers.anyBoolean(),ArgumentMatchers.anyBoolean(),ArgumentMatchers.anyBoolean(),ArgumentMatchers.anyBoolean());
|
||||
verify(nearbyParentFragmentView).filterMarkersByLabels(
|
||||
ArgumentMatchers.anyList(),
|
||||
ArgumentMatchers.anyBoolean(),
|
||||
ArgumentMatchers.anyBoolean(),
|
||||
ArgumentMatchers.anyBoolean(),
|
||||
ArgumentMatchers.anyBoolean(),
|
||||
ArgumentMatchers.anyBoolean()
|
||||
);
|
||||
verify(nearbyParentFragmentView).setRecyclerViewAdapterAllSelected()
|
||||
verifyNoMoreInteractions(nearbyParentFragmentView)
|
||||
}
|
||||
|
|
@ -276,7 +283,14 @@ class NearbyParentFragmentPresenterTest {
|
|||
@Test
|
||||
fun testFilterByMarkerTypeSingleSelect() {
|
||||
nearbyPresenter.filterByMarkerType(selectedLabels, 0, true,false)
|
||||
verify(nearbyParentFragmentView).filterMarkersByLabels(any(), any(), any(), any(), any());
|
||||
verify(nearbyParentFragmentView).filterMarkersByLabels(
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any()
|
||||
);
|
||||
verifyNoMoreInteractions(nearbyParentFragmentView)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue