#3468 Switch from RvRenderer to AdapterDelegates - replace PlaceRenderer

This commit is contained in:
Sean Mac Gillicuddy 2020-05-14 07:23:37 +01:00
parent 456b86454e
commit 3b422963a4
16 changed files with 430 additions and 599 deletions

View file

@ -35,7 +35,6 @@ dependencies {
// UI // UI
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar'
implementation 'com.github.chrisbanes:PhotoView:2.0.0' implementation 'com.github.chrisbanes:PhotoView:2.0.0'
implementation 'com.github.pedrovgs:renderers:3.3.3'
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:8.6.2' implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:8.6.2'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-localization-v8:0.11.0' implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-localization-v8:0.11.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-scalebar-v9:0.4.0' implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-scalebar-v9:0.4.0'
@ -105,6 +104,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "androidx.exifinterface:exifinterface:1.0.0" implementation "androidx.exifinterface:exifinterface:1.0.0"
implementation "androidx.core:core-ktx:$CORE_KTX_VERSION" implementation "androidx.core:core-ktx:$CORE_KTX_VERSION"
implementation "androidx.multidex:multidex:2.0.1"
//swipe_layout //swipe_layout
implementation 'com.daimajia.swipelayout:library:1.2.0@aar' implementation 'com.daimajia.swipelayout:library:1.2.0@aar'
@ -143,7 +143,7 @@ android {
testOptions { testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR' execution 'ANDROIDX_TEST_ORCHESTRATOR'
} }
multiDexEnabled true
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }

View file

@ -9,7 +9,6 @@ import static org.acra.ReportField.STACK_TRACE;
import static org.acra.ReportField.USER_COMMENT; import static org.acra.ReportField.USER_COMMENT;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Application;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
@ -18,13 +17,13 @@ import android.os.Build;
import android.os.Process; import android.os.Process;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.multidex.MultiDexApplication;
import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.core.ImagePipeline; import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.Mapbox;
import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher; import com.squareup.leakcanary.RefWatcher;
import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao; import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao;
@ -77,7 +76,7 @@ import timber.log.Timber;
resCommentPrompt = R.string.crash_dialog_comment_prompt resCommentPrompt = R.string.crash_dialog_comment_prompt
) )
public class CommonsApplication extends Application { public class CommonsApplication extends MultiDexApplication {
@Inject SessionManager sessionManager; @Inject SessionManager sessionManager;
@Inject DBOpenHelper dbOpenHelper; @Inject DBOpenHelper dbOpenHelper;

View file

@ -8,26 +8,21 @@ import android.view.ViewGroup;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.pedrogomez.renderers.RVRendererAdapter;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import dagger.android.support.DaggerFragment; import dagger.android.support.DaggerFragment;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.nearby.NearbyAdapterFactory;
import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.nearby.fragments.CommonPlaceClickActions;
import fr.free.nrw.commons.nearby.fragments.PlaceAdapter;
import java.util.List;
import javax.inject.Inject;
import kotlin.Unit;
public class BookmarkLocationsFragment extends DaggerFragment { public class BookmarkLocationsFragment extends DaggerFragment {
@ -37,8 +32,10 @@ public class BookmarkLocationsFragment extends DaggerFragment {
@BindView(R.id.parentLayout) RelativeLayout parentLayout; @BindView(R.id.parentLayout) RelativeLayout parentLayout;
@Inject BookmarkLocationsController controller; @Inject BookmarkLocationsController controller;
private NearbyAdapterFactory adapterFactory;
@Inject ContributionController contributionController; @Inject ContributionController contributionController;
@Inject BookmarkLocationsDao bookmarkLocationDao;
@Inject CommonPlaceClickActions commonPlaceClickActions;
private PlaceAdapter adapter;
/** /**
* Create an instance of the fragment with the right bundle parameters * Create an instance of the fragment with the right bundle parameters
@ -56,7 +53,6 @@ public class BookmarkLocationsFragment extends DaggerFragment {
) { ) {
View v = inflater.inflate(R.layout.fragment_bookmarks_locations, container, false); View v = inflater.inflate(R.layout.fragment_bookmarks_locations, container, false);
ButterKnife.bind(this, v); ButterKnife.bind(this, v);
adapterFactory = new NearbyAdapterFactory(this, contributionController);
return v; return v;
} }
@ -65,7 +61,15 @@ public class BookmarkLocationsFragment extends DaggerFragment {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapterFactory.create(new ArrayList<>(), this::initList)); adapter = new PlaceAdapter(bookmarkLocationDao,
place -> Unit.INSTANCE,
(place, isBookmarked) -> {
adapter.remove(place);
return Unit.INSTANCE;
},
commonPlaceClickActions
);
recyclerView.setAdapter(adapter);
} }
@Override @Override
@ -79,7 +83,7 @@ public class BookmarkLocationsFragment extends DaggerFragment {
*/ */
private void initList() { private void initList() {
List<Place> places = controller.loadFavoritesLocations(); List<Place> places = controller.loadFavoritesLocations();
adapterFactory.updateAdapterData(places, (RVRendererAdapter<Place>) recyclerView.getAdapter()); adapter.setItems(places);
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
if (places.size() <= 0) { if (places.size() <= 0) {
statusTextView.setText(R.string.bookmark_empty); statusTextView.setText(R.string.bookmark_empty);

View file

@ -0,0 +1,12 @@
package fr.free.nrw.commons.di
import android.app.Activity
import dagger.Module
import dagger.Provides
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsFragment
@Module
class BookmarkLocationsFragmentModule {
@Provides
fun BookmarkLocationsFragment.providesActivity(): Activity = activity!!
}

View file

@ -10,11 +10,9 @@ import dagger.android.AndroidInjector;
import dagger.android.support.AndroidSupportInjectionModule; import dagger.android.support.AndroidSupportInjectionModule;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.auth.LoginActivity; import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.contributions.ContributionViewHolder;
import fr.free.nrw.commons.contributions.ContributionsModule; import fr.free.nrw.commons.contributions.ContributionsModule;
import fr.free.nrw.commons.depictions.DepictionModule; import fr.free.nrw.commons.depictions.DepictionModule;
import fr.free.nrw.commons.explore.SearchModule; import fr.free.nrw.commons.explore.SearchModule;
import fr.free.nrw.commons.nearby.PlaceRenderer;
import fr.free.nrw.commons.review.ReviewController; import fr.free.nrw.commons.review.ReviewController;
import fr.free.nrw.commons.settings.SettingsFragment; import fr.free.nrw.commons.settings.SettingsFragment;
import fr.free.nrw.commons.upload.FileProcessor; import fr.free.nrw.commons.upload.FileProcessor;
@ -49,8 +47,6 @@ public interface CommonsApplicationComponent extends AndroidInjector<Application
@Override @Override
void inject(ApplicationlessInjection instance); void inject(ApplicationlessInjection instance);
void inject(PlaceRenderer placeRenderer);
void inject(FileProcessor fileProcessor); void inject(FileProcessor fileProcessor);
void inject(PicOfDayAppWidget picOfDayAppWidget); void inject(PicOfDayAppWidget picOfDayAppWidget);

View file

@ -72,13 +72,13 @@ public abstract class FragmentBuilderModule {
@ContributesAndroidInjector @ContributesAndroidInjector
abstract ContributionsFragment bindContributionsFragment(); abstract ContributionsFragment bindContributionsFragment();
@ContributesAndroidInjector @ContributesAndroidInjector(modules = NearbyParentFragmentModule.class)
abstract NearbyParentFragment bindNearbyParentFragment(); abstract NearbyParentFragment bindNearbyParentFragment();
@ContributesAndroidInjector @ContributesAndroidInjector
abstract BookmarkPicturesFragment bindBookmarkPictureListFragment(); abstract BookmarkPicturesFragment bindBookmarkPictureListFragment();
@ContributesAndroidInjector @ContributesAndroidInjector(modules = BookmarkLocationsFragmentModule.class)
abstract BookmarkLocationsFragment bindBookmarkLocationListFragment(); abstract BookmarkLocationsFragment bindBookmarkLocationListFragment();
@ContributesAndroidInjector @ContributesAndroidInjector

View file

@ -0,0 +1,13 @@
package fr.free.nrw.commons.di
import android.app.Activity
import dagger.Module
import dagger.Provides
import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment
@Module
class NearbyParentFragmentModule{
@Provides
fun NearbyParentFragment.providesActivity(): Activity = activity!!
}

View file

@ -1,57 +0,0 @@
package fr.free.nrw.commons.nearby;
import androidx.fragment.app.Fragment;
import com.pedrogomez.renderers.ListAdapteeCollection;
import com.pedrogomez.renderers.RVRendererAdapter;
import com.pedrogomez.renderers.RendererBuilder;
import java.util.Collections;
import java.util.List;
import fr.free.nrw.commons.contributions.ContributionController;
public class NearbyAdapterFactory {
private Fragment fragment;
private ContributionController controller;
public NearbyAdapterFactory(Fragment fragment, ContributionController controller) {
this.fragment = fragment;
this.controller = controller;
}
public RVRendererAdapter<Place> create(List<Place> placeList) {
return create(placeList, null);
}
public RVRendererAdapter<Place> create(
List<Place> placeList,
PlaceRenderer.OnBookmarkClick onBookmarkClick
) {
RendererBuilder<Place> builder = new RendererBuilder<Place>()
.bind(Place.class, new PlaceRenderer(fragment, controller, onBookmarkClick));
ListAdapteeCollection<Place> collection = new ListAdapteeCollection<>(
placeList != null ? placeList : Collections.emptyList());
return new RVRendererAdapter<>(builder, collection);
}
public void updateAdapterData(List<Place> newPlaceList, RVRendererAdapter<Place> rendererAdapter) {
rendererAdapter.notifyDataSetChanged();
rendererAdapter.diffUpdate(newPlaceList);
}
public void clear(RVRendererAdapter<Place> rendererAdapter){
rendererAdapter.clear();
}
public void add(Place place, RVRendererAdapter<Place> rendererAdapter){
rendererAdapter.add(place);
}
public void update(RVRendererAdapter<Place> rendererAdapter){
rendererAdapter.notifyDataSetChanged();
}
}

View file

@ -0,0 +1,84 @@
package fr.free.nrw.commons.nearby
import android.view.View
import android.view.View.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager
import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateLayoutContainerViewHolder
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer
import fr.free.nrw.commons.R
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao
import kotlinx.android.synthetic.main.item_place.*
import kotlinx.android.synthetic.main.nearby_row_button.*
fun placeAdapterDelegate(
bookmarkLocationDao: BookmarkLocationsDao,
onItemClick: ((Place) -> Unit)? = null,
onCameraClicked: (Place) -> Unit,
onGalleryClicked: (Place) -> Unit,
onBookmarkClicked: (Place, Boolean) -> Unit,
onOverflowIconClicked: (Place, View) -> Unit,
onDirectionsClicked: (Place) -> Unit
) =
adapterDelegateLayoutContainer<Place, Place>(R.layout.item_place) {
containerView.setOnClickListener { _: View? ->
showOrHideAndScrollToIfLast()
onItemClick?.invoke(item)
}
containerView.setOnFocusChangeListener { view1: View?, hasFocus: Boolean ->
if (!hasFocus && buttonLayout.isShown) {
buttonLayout.visibility = GONE
} else if (hasFocus && !buttonLayout.isShown) {
showOrHideAndScrollToIfLast()
onItemClick?.invoke(item)
}
}
cameraButton.setOnClickListener { onCameraClicked(item) }
galleryButton.setOnClickListener { onGalleryClicked(item) }
bookmarkRowButton.setOnClickListener {
val isBookmarked = bookmarkLocationDao.updateBookmarkLocation(item)
bookmarkRowButtonImage.setImageResource(if (isBookmarked) R.drawable.ic_round_star_filled_24px else R.drawable.ic_round_star_border_24px)
onBookmarkClicked(item, isBookmarked)
}
iconOverflow.setOnClickListener { onOverflowIconClicked(item, it) }
directionsButton.setOnClickListener { onDirectionsClicked(item) }
bind {
tvName.text = item.name
val descriptionText: String = item.longDescription
if (descriptionText == "?") {
tvDesc.setText(R.string.no_description_found)
tvDesc.visibility = INVISIBLE
} else {
tvDesc.text = descriptionText
}
distance.text = item.distance
icon.setImageResource(item.label.icon)
iconOverflow.visibility =
if (item.hasCommonsLink() || item.hasWikidataLink()) VISIBLE
else GONE
bookmarkRowButtonImage.setImageResource(
if (bookmarkLocationDao.findBookmarkLocation(item))
R.drawable.ic_round_star_filled_24px
else
R.drawable.ic_round_star_border_24px
)
}
}
private fun AdapterDelegateLayoutContainerViewHolder<Place>.showOrHideAndScrollToIfLast() {
TransitionManager.beginDelayedTransition(buttonLayout)
if (buttonLayout.isShown) {
buttonLayout.visibility = GONE
} else {
buttonLayout.visibility = VISIBLE
val recyclerView = containerView.parent as RecyclerView
val lastPosition = recyclerView.adapter!!.itemCount - 1
if (recyclerView.getChildLayoutPosition(containerView) == lastPosition) {
(recyclerView.layoutManager as LinearLayoutManager?)
?.scrollToPositionWithOffset(lastPosition, buttonLayout.height)
}
}
}

View file

@ -1,292 +0,0 @@
package fr.free.nrw.commons.nearby;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.transition.TransitionManager;
import com.facebook.drawee.view.SimpleDraweeView;
import com.pedrogomez.renderers.Renderer;
import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
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.di.ApplicationlessInjection;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment;
import timber.log.Timber;
import static fr.free.nrw.commons.theme.NavigationBaseActivity.startActivityWithFlags;
import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT;
public class PlaceRenderer extends Renderer<Place> {
@BindView(R.id.tvName) TextView tvName;
@BindView(R.id.tvDesc) TextView tvDesc;
@BindView(R.id.distance) TextView distance;
@BindView(R.id.icon) SimpleDraweeView icon;
@BindView(R.id.buttonLayout) LinearLayout buttonLayout;
@BindView(R.id.cameraButton) LinearLayout cameraButton;
@BindView(R.id.galleryButton) LinearLayout galleryButton;
@BindView(R.id.directionsButton) LinearLayout directionsButton;
@BindView(R.id.iconOverflow) LinearLayout iconOverflow;
@BindView(R.id.cameraButtonText) TextView cameraButtonText;
@BindView(R.id.galleryButtonText) TextView galleryButtonText;
@BindView(R.id.bookmarkRowButton) LinearLayout bookmarkButton;
@BindView(R.id.bookmarkButtonText) TextView bookmarkButtonText;
@BindView(R.id.bookmarkRowButtonImage) ImageView bookmarkButtonImage;
@BindView(R.id.directionsButtonText) TextView directionsButtonText;
@BindView(R.id.iconOverflowText) TextView iconOverflowText;
private View view;
private static ArrayList<LinearLayout> openedItems;
private Place place;
private Fragment fragment;
private ContributionController controller;
private OnBookmarkClick onBookmarkClick;
@Inject BookmarkLocationsDao bookmarkLocationDao;
@Inject
@Named("default_preferences")
JsonKvStore applicationKvStore;
public PlaceRenderer(){
openedItems = new ArrayList<>();
}
public PlaceRenderer(
Fragment fragment,
ContributionController controller,
OnBookmarkClick onBookmarkClick
) {
this.fragment = fragment;
this.controller = controller;
openedItems = new ArrayList<>();
this.onBookmarkClick = onBookmarkClick;
}
@Override
protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) {
view = layoutInflater.inflate(R.layout.item_place, viewGroup, false);
return view;
}
@Override
protected void setUpView(View view) {
ButterKnife.bind(this, view);
closeLayout(buttonLayout);
}
@Override
protected void hookListeners(View view) {
final View.OnClickListener listener = view12 -> {
Timber.d("Renderer clicked");
TransitionManager.beginDelayedTransition(buttonLayout);
if (buttonLayout.isShown()) {
closeLayout(buttonLayout);
} else {
openLayout(buttonLayout);
RecyclerView recyclerView = (RecyclerView) view.getParent();
int lastPosition = recyclerView.getAdapter().getItemCount() - 1;
if (recyclerView.getChildLayoutPosition(view) == lastPosition) {
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(lastPosition, buttonLayout.getHeight());
}
}
if (onBookmarkClick == null) {
((NearbyParentFragment) fragment).centerMapToPlace(place);
}
};
view.setOnClickListener(listener);
view.requestFocus();
view.setOnFocusChangeListener((view1, hasFocus) -> {
if (!hasFocus && buttonLayout.isShown()) {
closeLayout(buttonLayout);
} else if (hasFocus && !buttonLayout.isShown()) {
listener.onClick(view1);
}
});
cameraButton.setOnClickListener(view2 -> {
if (applicationKvStore.getBoolean("login_skipped", false)) {
// prompt the user to login
new AlertDialog.Builder(getContext())
.setMessage(R.string.login_alert_message)
.setPositiveButton(R.string.login, (dialog, which) -> {
startActivityWithFlags( getContext(), LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
Intent.FLAG_ACTIVITY_SINGLE_TOP);
applicationKvStore.putBoolean("login_skipped", false);
fragment.getActivity().finish();
})
.show();
} else {
Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
storeSharedPrefs();
controller.initiateCameraPick(fragment.getActivity());
}
});
galleryButton.setOnClickListener(view3 -> {
if (applicationKvStore.getBoolean("login_skipped", false)) {
// prompt the user to login
new AlertDialog.Builder(getContext())
.setMessage(R.string.login_alert_message)
.setPositiveButton(R.string.login, (dialog, which) -> {
startActivityWithFlags( getContext(), LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
Intent.FLAG_ACTIVITY_SINGLE_TOP);
applicationKvStore.putBoolean("login_skipped", false);
fragment.getActivity().finish();
})
.show();
}else {
Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
storeSharedPrefs();
controller.initiateGalleryPick(fragment.getActivity(), false);
}
});
bookmarkButton.setOnClickListener(view4 -> {
if (applicationKvStore.getBoolean("login_skipped", false)) {
// prompt the user to login
new AlertDialog.Builder(getContext())
.setMessage(R.string.login_alert_message)
.setPositiveButton(R.string.login, (dialog, which) -> {
startActivityWithFlags( getContext(), LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
Intent.FLAG_ACTIVITY_SINGLE_TOP);
applicationKvStore.putBoolean("login_skipped", false);
fragment.getActivity().finish();
})
.show();
} else {
boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(place);
int icon = isBookmarked ? R.drawable.ic_round_star_filled_24px : R.drawable.ic_round_star_border_24px;
bookmarkButtonImage.setImageResource(icon);
if (onBookmarkClick != null) {
onBookmarkClick.onClick();
}
else {
((NearbyParentFragment) (fragment.getParentFragment())).
updateMarker(isBookmarked, place, null);
}
}
});
}
private void storeSharedPrefs() {
Timber.d("Store place object %s", place.toString());
applicationKvStore.putJson(PLACE_OBJECT, place);
}
private void closeLayout(LinearLayout buttonLayout){
buttonLayout.setVisibility(View.GONE);
}
private void openLayout(LinearLayout buttonLayout){
buttonLayout.setVisibility(View.VISIBLE);
}
@Override
public void render() {
ApplicationlessInjection.getInstance(getContext().getApplicationContext())
.getCommonsApplicationComponent().inject(this);
place = getContent();
tvName.setText(place.name);
String descriptionText = place.getLongDescription();
if (descriptionText.equals("?")) {
descriptionText = getContext().getString(R.string.no_description_found);
tvDesc.setVisibility(View.INVISIBLE);
}
tvDesc.setText(descriptionText);
distance.setText(place.distance);
icon.setImageResource(place.getLabel().getIcon());
directionsButton.setOnClickListener(view -> Utils.handleGeoCoordinates(getContext(), this.place.getLocation()));
iconOverflow.setVisibility(showMenu() ? View.VISIBLE : View.GONE);
iconOverflow.setOnClickListener(v -> popupMenuListener());
int icon;
if (bookmarkLocationDao.findBookmarkLocation(place)) {
icon = R.drawable.ic_round_star_filled_24px;
} else {
icon = R.drawable.ic_round_star_border_24px;
}
bookmarkButtonImage.setImageResource(icon);
}
private void popupMenuListener() {
PopupMenu popupMenu = new PopupMenu(view.getContext(), iconOverflow);
popupMenu.inflate(R.menu.nearby_info_dialog_options);
MenuItem commonsArticle = popupMenu.getMenu()
.findItem(R.id.nearby_info_menu_commons_article);
MenuItem wikiDataArticle = popupMenu.getMenu()
.findItem(R.id.nearby_info_menu_wikidata_article);
MenuItem wikipediaArticle = popupMenu.getMenu()
.findItem(R.id.nearby_info_menu_wikipedia_article);
commonsArticle.setEnabled(place.hasCommonsLink());
wikiDataArticle.setEnabled(place.hasWikidataLink());
wikipediaArticle.setEnabled(place.hasWikipediaLink());
popupMenu.setOnMenuItemClickListener(item -> {
switch (item.getItemId()) {
case R.id.nearby_info_menu_commons_article:
openWebView(place.siteLinks.getCommonsLink());
return true;
case R.id.nearby_info_menu_wikidata_article:
openWebView(place.siteLinks.getWikidataLink());
return true;
case R.id.nearby_info_menu_wikipedia_article:
openWebView(place.siteLinks.getWikipediaLink());
return true;
default:
break;
}
return false;
});
popupMenu.show();
}
private void openWebView(Uri link) {
Utils.handleWebUrl(getContext(), link);
}
private boolean showMenu() {
return place.hasCommonsLink() || place.hasWikidataLink();
}
public interface OnBookmarkClick {
void onClick();
}
}

View file

@ -0,0 +1,99 @@
package fr.free.nrw.commons.nearby.fragments
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.PopupMenu
import fr.free.nrw.commons.R
import fr.free.nrw.commons.Utils
import fr.free.nrw.commons.auth.LoginActivity
import fr.free.nrw.commons.contributions.ContributionController
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.theme.NavigationBaseActivity
import fr.free.nrw.commons.wikidata.WikidataConstants
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Named
class CommonPlaceClickActions @Inject constructor(
@Named("default_preferences") private val applicationKvStore: JsonKvStore,
private val activity: Activity,
private val contributionController: ContributionController
) {
fun onCameraClicked(): (Place) -> Unit = {
if (applicationKvStore.getBoolean("login_skipped", false)) {
showLoginDialog()
} else {
Timber.d("Camera button tapped. Image title: ${it.getName()}Image desc: ${it.longDescription}")
storeSharedPrefs(it)
contributionController.initiateCameraPick(activity)
}
}
fun onGalleryClicked(): (Place) -> Unit = {
if (applicationKvStore.getBoolean("login_skipped", false)) {
showLoginDialog()
} else {
Timber.d("Gallery button tapped. Image title: ${it.getName()}Image desc: ${it.getLongDescription()}")
storeSharedPrefs(it)
contributionController.initiateGalleryPick(activity, false)
}
}
fun onOverflowClicked(): (Place, View) -> Unit = { place, view ->
PopupMenu(view.context, view).apply {
inflate(R.menu.nearby_info_dialog_options)
enableBy(R.id.nearby_info_menu_commons_article, place.hasCommonsLink())
enableBy(R.id.nearby_info_menu_wikidata_article, place.hasWikidataLink())
enableBy(R.id.nearby_info_menu_wikipedia_article, place.hasWikipediaLink())
setOnMenuItemClickListener { item: MenuItem ->
when (item.itemId) {
R.id.nearby_info_menu_commons_article -> openWebView(place.siteLinks.commonsLink)
R.id.nearby_info_menu_wikidata_article -> openWebView(place.siteLinks.wikidataLink)
R.id.nearby_info_menu_wikipedia_article -> openWebView(place.siteLinks.wikipediaLink)
else -> false
}
}
}.show()
}
fun onDirectionsClicked(): (Place) -> Unit = {
Utils.handleGeoCoordinates(activity, it.getLocation())
}
private fun storeSharedPrefs(selectedPlace: Place) {
Timber.d("Store place object %s", selectedPlace.toString())
applicationKvStore.putJson(WikidataConstants.PLACE_OBJECT, selectedPlace)
}
private fun openWebView(link: Uri): Boolean {
Utils.handleWebUrl(activity, link)
return true;
}
private fun PopupMenu.enableBy(menuId: Int, hasLink: Boolean) {
menu.findItem(menuId).isEnabled = hasLink
}
private fun showLoginDialog() {
AlertDialog.Builder(activity)
.setMessage(R.string.login_alert_message)
.setPositiveButton(R.string.login) { dialog, which ->
NavigationBaseActivity.startActivityWithFlags(
activity,
LoginActivity::class.java,
Intent.FLAG_ACTIVITY_CLEAR_TOP,
Intent.FLAG_ACTIVITY_SINGLE_TOP
)
applicationKvStore.putBoolean("login_skipped", false)
activity.finish()
}
.show()
}
}

View file

@ -1,7 +1,14 @@
package fr.free.nrw.commons.nearby.fragments; package fr.free.nrw.commons.nearby.fragments;
import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION;
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;
import android.Manifest; import android.Manifest;
import android.app.AlertDialog;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -26,14 +33,16 @@ import android.widget.RelativeLayout;
import android.widget.SearchView; import android.widget.SearchView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.chip.Chip; import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup; import com.google.android.material.chip.ChipGroup;
@ -57,18 +66,6 @@ import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.maps.UiSettings; import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.pluginscalebar.ScaleBarOptions; import com.mapbox.pluginscalebar.ScaleBarOptions;
import com.mapbox.pluginscalebar.ScaleBarPlugin; import com.mapbox.pluginscalebar.ScaleBarPlugin;
import com.pedrogomez.renderers.RVRendererAdapter;
import fr.free.nrw.commons.utils.DialogUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
@ -76,6 +73,7 @@ import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao; import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.contributions.MainActivity; import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.location.LocationServiceManager;
@ -83,7 +81,6 @@ import fr.free.nrw.commons.location.LocationUpdateListener;
import fr.free.nrw.commons.nearby.CheckBoxTriStates; import fr.free.nrw.commons.nearby.CheckBoxTriStates;
import fr.free.nrw.commons.nearby.Label; import fr.free.nrw.commons.nearby.Label;
import fr.free.nrw.commons.nearby.MarkerPlaceGroup; import fr.free.nrw.commons.nearby.MarkerPlaceGroup;
import fr.free.nrw.commons.nearby.NearbyAdapterFactory;
import fr.free.nrw.commons.nearby.NearbyBaseMarker; import fr.free.nrw.commons.nearby.NearbyBaseMarker;
import fr.free.nrw.commons.nearby.NearbyController; import fr.free.nrw.commons.nearby.NearbyController;
import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter; import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter;
@ -92,6 +89,7 @@ import fr.free.nrw.commons.nearby.NearbyMarker;
import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract; import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter; import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter;
import fr.free.nrw.commons.utils.DialogUtil;
import fr.free.nrw.commons.utils.ExecutorUtils; import fr.free.nrw.commons.utils.ExecutorUtils;
import fr.free.nrw.commons.utils.LayoutUtils; import fr.free.nrw.commons.utils.LayoutUtils;
import fr.free.nrw.commons.utils.LocationUtils; import fr.free.nrw.commons.utils.LocationUtils;
@ -104,17 +102,16 @@ import fr.free.nrw.commons.utils.ViewUtil;
import fr.free.nrw.commons.wikidata.WikidataEditListener; import fr.free.nrw.commons.wikidata.WikidataEditListener;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import kotlin.Unit;
import timber.log.Timber; import timber.log.Timber;
import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION;
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;
public class NearbyParentFragment extends CommonsDaggerSupportFragment public class NearbyParentFragment extends CommonsDaggerSupportFragment
implements NearbyParentFragmentContract.View, implements NearbyParentFragmentContract.View,
@ -164,6 +161,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@Inject @Inject
SystemThemeUtils systemThemeUtils; SystemThemeUtils systemThemeUtils;
@Inject
CommonPlaceClickActions commonPlaceClickActions;
private NearbyFilterSearchRecyclerViewAdapter nearbyFilterSearchRecyclerViewAdapter; private NearbyFilterSearchRecyclerViewAdapter nearbyFilterSearchRecyclerViewAdapter;
@ -177,7 +176,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private static final float ZOOM_LEVEL = 14f; private static final float ZOOM_LEVEL = 14f;
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
private BroadcastReceiver broadcastReceiver; private BroadcastReceiver broadcastReceiver;
private boolean isNetworkErrorOccurred = false; private boolean isNetworkErrorOccurred;
private Snackbar snackbar; private Snackbar snackbar;
private View view; private View view;
private NearbyParentFragmentPresenter presenter; private NearbyParentFragmentPresenter presenter;
@ -189,25 +188,22 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.005; private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.005;
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.004; private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.004;
private boolean isMapBoxReady=false; private boolean isMapBoxReady;
private MapboxMap mapBox; private MapboxMap mapBox;
IntentFilter intentFilter = new IntentFilter(NETWORK_INTENT_ACTION); IntentFilter intentFilter = new IntentFilter(NETWORK_INTENT_ACTION);
private Marker currentLocationMarker; private Marker currentLocationMarker;
private Polygon currentLocationPolygon; private Polygon currentLocationPolygon;
private Place lastPlaceToCenter; private Place lastPlaceToCenter;
private fr.free.nrw.commons.location.LatLng lastKnownLocation; private fr.free.nrw.commons.location.LatLng lastKnownLocation;
private fr.free.nrw.commons.location.LatLng currentLocation=null;
private NearbyController.NearbyPlacesInfo nearbyPlacesInfo;
private NearbyAdapterFactory adapterFactory;
private boolean isVisibleToUser; private boolean isVisibleToUser;
private MapboxMap.OnCameraMoveListener cameraMoveListener; private MapboxMap.OnCameraMoveListener cameraMoveListener;
private fr.free.nrw.commons.location.LatLng lastFocusLocation; private fr.free.nrw.commons.location.LatLng lastFocusLocation;
private LatLngBounds latLngBounds; private LatLngBounds latLngBounds;
private PlaceAdapter adapter;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) { final Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_nearby_parent, container, false); view = inflater.inflate(R.layout.fragment_nearby_parent, container, false);
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
initNetworkBroadCastReceiver(); initNetworkBroadCastReceiver();
@ -218,7 +214,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
isDarkTheme = systemThemeUtils.isDeviceInNightMode(); isDarkTheme = systemThemeUtils.isDeviceInNightMode();
cameraMoveListener= () -> presenter.onCameraMove(mapBox.getCameraPosition().target); cameraMoveListener= () -> presenter.onCameraMove(mapBox.getCameraPosition().target);
@ -228,28 +224,28 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
initThemePreferences(); initThemePreferences();
mapView.onCreate(savedInstanceState); mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapBoxMap -> { mapView.getMapAsync(mapBoxMap -> {
this.mapBox=mapBoxMap; mapBox =mapBoxMap;
initViews(); initViews();
presenter.setActionListeners(applicationKvStore); presenter.setActionListeners(applicationKvStore);
initNearbyFilter(); initNearbyFilter();
mapBoxMap.setStyle(isDarkTheme?Style.DARK:Style.OUTDOORS, style -> { mapBoxMap.setStyle(isDarkTheme?Style.DARK:Style.OUTDOORS, style -> {
UiSettings uiSettings = mapBoxMap.getUiSettings(); final UiSettings uiSettings = mapBoxMap.getUiSettings();
uiSettings.setCompassGravity(Gravity.BOTTOM | Gravity.LEFT); uiSettings.setCompassGravity(Gravity.BOTTOM | Gravity.LEFT);
uiSettings.setCompassMargins(12, 0, 0, 24); uiSettings.setCompassMargins(12, 0, 0, 24);
uiSettings.setLogoEnabled(true); uiSettings.setLogoEnabled(true);
uiSettings.setAttributionEnabled(true); uiSettings.setAttributionEnabled(true);
uiSettings.setRotateGesturesEnabled(false); uiSettings.setRotateGesturesEnabled(false);
NearbyParentFragment.this.isMapBoxReady=true; isMapBoxReady =true;
performMapReadyActions(); performMapReadyActions();
CameraPosition cameraPosition = new CameraPosition.Builder() final CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(51.50550, -0.07520)) .target(new LatLng(51.50550, -0.07520))
.zoom(ZOOM_LEVEL) .zoom(ZOOM_LEVEL)
.build(); .build();
mapBoxMap.setCameraPosition(cameraPosition); mapBoxMap.setCameraPosition(cameraPosition);
ScaleBarPlugin scaleBarPlugin = new ScaleBarPlugin(mapView, mapBoxMap); final ScaleBarPlugin scaleBarPlugin = new ScaleBarPlugin(mapView, mapBoxMap);
int color = isDarkTheme ? R.color.bottom_bar_light : R.color.bottom_bar_dark; final int color = isDarkTheme ? R.color.bottom_bar_light : R.color.bottom_bar_dark;
ScaleBarOptions scaleBarOptions = new ScaleBarOptions(getContext()) final ScaleBarOptions scaleBarOptions = new ScaleBarOptions(getContext())
.setTextColor(color) .setTextColor(color)
.setTextSize(R.dimen.description_text_size) .setTextSize(R.dimen.description_text_size)
.setBarHeight(R.dimen.tiny_gap) .setBarHeight(R.dimen.tiny_gap)
@ -281,8 +277,18 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private void initRvNearbyList() { private void initRvNearbyList() {
rvNearbyList.setLayoutManager(new LinearLayoutManager(getContext())); rvNearbyList.setLayoutManager(new LinearLayoutManager(getContext()));
adapterFactory = new NearbyAdapterFactory(this, controller); adapter = new PlaceAdapter(bookmarkLocationDao,
rvNearbyList.setAdapter(adapterFactory.create(null)); place -> {
centerMapToPlace(place);
return Unit.INSTANCE;
},
(place, isBookmarked) -> {
updateMarker(isBookmarked, place, null);
return Unit.INSTANCE;
},
commonPlaceClickActions
);
rvNearbyList.setAdapter(adapter);
} }
private void addCheckBoxCallback() { private void addCheckBoxCallback() {
@ -292,13 +298,13 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private void performMapReadyActions() { private void performMapReadyActions() {
if (isVisible() && isVisibleToUser && isMapBoxReady) { if (isVisible() && isVisibleToUser && isMapBoxReady) {
checkPermissionsAndPerformAction(() -> { checkPermissionsAndPerformAction(() -> {
this.lastKnownLocation = locationManager.getLastLocation(); lastKnownLocation = locationManager.getLastLocation();
fr.free.nrw.commons.location.LatLng target=lastFocusLocation; fr.free.nrw.commons.location.LatLng target=lastFocusLocation;
if(null==lastFocusLocation){ if(null==lastFocusLocation){
target=lastKnownLocation; target=lastKnownLocation;
} }
if (lastKnownLocation != null) { if (lastKnownLocation != null) {
CameraPosition position = new CameraPosition.Builder() final CameraPosition position = new CameraPosition.Builder()
.target(LocationUtils.commonsLatLngToMapBoxLatLng(target)) // Sets the new camera position .target(LocationUtils.commonsLatLngToMapBoxLatLng(target)) // Sets the new camera position
.zoom(ZOOM_LEVEL) // Same zoom level .zoom(ZOOM_LEVEL) // Same zoom level
.build(); .build();
@ -325,8 +331,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
private void registerNetworkReceiver() { private void registerNetworkReceiver() {
if (getActivity() != null) if (getActivity() != null) {
getActivity().registerReceiver(broadcastReceiver, intentFilter); getActivity().registerReceiver(broadcastReceiver, intentFilter);
}
} }
@ -349,7 +356,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
if (null != mapBox) { if (null != mapBox) {
mapBox.removeOnCameraMoveListener(cameraMoveListener); mapBox.removeOnCameraMoveListener(cameraMoveListener);
} }
}catch (Exception e){ }catch (final Exception e){
Timber.e(e); Timber.e(e);
//Broadcast receivers should always be unregistered inside catch, you never know if they were already registered or not //Broadcast receivers should always be unregistered inside catch, you never know if they were already registered or not
} }
@ -362,7 +369,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState);
} }
@ -415,7 +422,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL)); DividerItemDecoration.VERTICAL));
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setLayoutManager(linearLayoutManager);
@ -427,7 +434,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void filterByMarkerType(ArrayList<Label> selectedLabels, int i, boolean b, boolean b1) { public void filterByMarkerType(final ArrayList<Label> selectedLabels, final int i, final boolean b, final boolean b1) {
presenter.filterByMarkerType(selectedLabels,i,b,b1); presenter.filterByMarkerType(selectedLabels,i,b,b1);
} }
@ -457,7 +464,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void setCheckBoxState(int state) { public void setCheckBoxState(final int state) {
checkBoxTriStates.setState(state); checkBoxTriStates.setState(state);
} }
@ -512,12 +519,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
bottomSheetDetailsBehavior.setBottomSheetCallback(new BottomSheetBehavior bottomSheetDetailsBehavior.setBottomSheetCallback(new BottomSheetBehavior
.BottomSheetCallback() { .BottomSheetCallback() {
@Override @Override
public void onStateChanged(@NonNull View bottomSheet, int newState) { public void onStateChanged(@NonNull final View bottomSheet, final int newState) {
prepareViewsForSheetPosition(newState); prepareViewsForSheetPosition(newState);
} }
@Override @Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) { public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
} }
}); });
@ -537,14 +544,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
bottomSheetListBehavior.setBottomSheetCallback(new BottomSheetBehavior bottomSheetListBehavior.setBottomSheetCallback(new BottomSheetBehavior
.BottomSheetCallback() { .BottomSheetCallback() {
@Override @Override
public void onStateChanged(@NonNull View bottomSheet, int newState) { public void onStateChanged(@NonNull final View bottomSheet, final int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) { if (newState == BottomSheetBehavior.STATE_EXPANDED) {
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
} }
} }
@Override @Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) { public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
} }
}); });
@ -598,21 +605,21 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* Centers the map in nearby fragment to a given place * Centers the map in nearby fragment to a given place
* @param place is new center of the map * @param place is new center of the map
*/ */
public void centerMapToPlace(Place place) { public void centerMapToPlace(final Place place) {
Timber.d("Map is centered to place"); Timber.d("Map is centered to place");
double cameraShift; final double cameraShift;
if(null!=place){ if(null!=place){
lastPlaceToCenter=place; lastPlaceToCenter=place;
} }
if (null != lastPlaceToCenter) { if (null != lastPlaceToCenter) {
Configuration configuration = getActivity().getResources().getConfiguration(); final Configuration configuration = getActivity().getResources().getConfiguration();
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
cameraShift = CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT; cameraShift = CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT;
} else { } else {
cameraShift = CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE; cameraShift = CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE;
} }
CameraPosition position = new CameraPosition.Builder() final CameraPosition position = new CameraPosition.Builder()
.target(LocationUtils.commonsLatLngToMapBoxLatLng( .target(LocationUtils.commonsLatLngToMapBoxLatLng(
new fr.free.nrw.commons.location.LatLng(lastPlaceToCenter.location.getLatitude() - cameraShift, new fr.free.nrw.commons.location.LatLng(lastPlaceToCenter.location.getLatitude() - cameraShift,
lastPlaceToCenter.getLocation().getLongitude(), lastPlaceToCenter.getLocation().getLongitude(),
@ -624,20 +631,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void updateListFragment(List<Place> placeList) { public void updateListFragment(final List<Place> placeList) {
adapterFactory.updateAdapterData(placeList, (RVRendererAdapter<Place>) rvNearbyList.getAdapter()); adapter.setItems(placeList);
} }
public void clearNearbyList() { public void clearNearbyList() {
adapterFactory.clear((RVRendererAdapter<Place>) rvNearbyList.getAdapter()); adapter.clear();
} }
public void updateNearbyList() {
adapterFactory.update((RVRendererAdapter<Place>) rvNearbyList.getAdapter());
}
public void addPlaceToNearbyList(Place place) { public void addPlaceToNearbyList(final Place place) {
adapterFactory.add(place, (RVRendererAdapter<Place>) rvNearbyList.getAdapter()); adapter.add(place);
} }
@Override @Override
@ -677,7 +681,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private void initNetworkBroadCastReceiver() { private void initNetworkBroadCastReceiver() {
broadcastReceiver = new BroadcastReceiver() { broadcastReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(final Context context, final Intent intent) {
if (getActivity() != null) { if (getActivity() != null) {
if (NetworkUtils.isInternetConnectionEstablished(getActivity())) { if (NetworkUtils.isInternetConnectionEstablished(getActivity())) {
if (isNetworkErrorOccurred) { if (isNetworkErrorOccurred) {
@ -718,10 +722,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void populatePlaces(fr.free.nrw.commons.location.LatLng curlatLng) { public void populatePlaces(final fr.free.nrw.commons.location.LatLng curlatLng) {
if (lastKnownLocation == null) {
lastKnownLocation = currentLocation;
}
if (curlatLng.equals(lastFocusLocation)|| lastFocusLocation==null) { // Means we are checking around current location if (curlatLng.equals(lastFocusLocation)|| lastFocusLocation==null) { // Means we are checking around current location
populatePlacesForCurrentLocation(lastKnownLocation, curlatLng); populatePlacesForCurrentLocation(lastKnownLocation, curlatLng);
} else { } else {
@ -729,8 +730,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
} }
private void populatePlacesForCurrentLocation(fr.free.nrw.commons.location.LatLng curlatLng, private void populatePlacesForCurrentLocation(final fr.free.nrw.commons.location.LatLng curlatLng,
fr.free.nrw.commons.location.LatLng searchLatLng) { final fr.free.nrw.commons.location.LatLng searchLatLng) {
compositeDisposable.add(Observable.fromCallable(() -> nearbyController compositeDisposable.add(Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, true)) .loadAttractionsFromLocation(curlatLng, searchLatLng, false, true))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -748,8 +749,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
})); }));
} }
private void populatePlacesForAnotherLocation(fr.free.nrw.commons.location.LatLng curlatLng, private void populatePlacesForAnotherLocation(final fr.free.nrw.commons.location.LatLng curlatLng,
fr.free.nrw.commons.location.LatLng searchLatLng) { final fr.free.nrw.commons.location.LatLng searchLatLng) {
compositeDisposable.add(Observable.fromCallable(() -> nearbyController compositeDisposable.add(Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curlatLng, searchLatLng, false, false)) .loadAttractionsFromLocation(curlatLng, searchLatLng, false, false))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -771,8 +772,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* location where you are. * location where you are.
* @param nearbyPlacesInfo This variable has place list information and distances. * @param nearbyPlacesInfo This variable has place list information and distances.
*/ */
private void updateMapMarkers(NearbyController.NearbyPlacesInfo nearbyPlacesInfo,boolean shouldUpdateSelectedMarker) { private void updateMapMarkers(final NearbyController.NearbyPlacesInfo nearbyPlacesInfo, final boolean shouldUpdateSelectedMarker) {
this.nearbyPlacesInfo=nearbyPlacesInfo;
presenter.updateMapMarkers(nearbyPlacesInfo, selectedMarker,shouldUpdateSelectedMarker); presenter.updateMapMarkers(nearbyPlacesInfo, selectedMarker,shouldUpdateSelectedMarker);
setFilterState(); setFilterState();
} }
@ -803,7 +803,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void setSearchThisAreaButtonVisibility(boolean isVisible) { public void setSearchThisAreaButtonVisibility(final boolean isVisible) {
if (isVisible) { if (isVisible) {
searchThisAreaButton.setVisibility(View.VISIBLE); searchThisAreaButton.setVisibility(View.VISIBLE);
} else { } else {
@ -813,11 +813,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@Override @Override
public boolean isSearchThisAreaButtonVisible() { public boolean isSearchThisAreaButtonVisible() {
if (searchThisAreaButton.getVisibility() == View.VISIBLE) { return searchThisAreaButton.getVisibility() == View.VISIBLE;
return true;
} else {
return false;
}
} }
@Override @Override
@ -835,7 +831,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void setProgressBarVisibility(boolean isVisible) { public void setProgressBarVisibility(final boolean isVisible) {
if (isVisible) { if (isVisible) {
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
} else { } else {
@ -849,7 +845,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void checkPermissionsAndPerformAction(Runnable runnable) { public void checkPermissionsAndPerformAction(final Runnable runnable) {
Timber.d("Checking permission and perfoming action"); Timber.d("Checking permission and perfoming action");
PermissionUtils.checkPermissionsAndPerformAction(getActivity(), PermissionUtils.checkPermissionsAndPerformAction(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,
@ -884,7 +880,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* Expands camera and gallery FABs, turn forward plus FAB * Expands camera and gallery FABs, turn forward plus FAB
* @param isFABsExpanded true if they are already expanded * @param isFABsExpanded true if they are already expanded
*/ */
private void expandFABs(boolean isFABsExpanded){ private void expandFABs(final boolean isFABsExpanded){
if (!isFABsExpanded) { if (!isFABsExpanded) {
showFABs(); showFABs();
fabPlus.startAnimation(rotate_forward); fabPlus.startAnimation(rotate_forward);
@ -912,7 +908,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* Collapses camera and gallery FABs, turn back plus FAB * Collapses camera and gallery FABs, turn back plus FAB
* @param isFABsExpanded * @param isFABsExpanded
*/ */
private void collapseFABs(boolean isFABsExpanded){ private void collapseFABs(final boolean isFABsExpanded){
if (isFABsExpanded) { if (isFABsExpanded) {
fabPlus.startAnimation(rotate_backward); fabPlus.startAnimation(rotate_backward);
fabCamera.startAnimation(fab_close); fabCamera.startAnimation(fab_close);
@ -939,19 +935,19 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
} }
private void handleLocationUpdate(fr.free.nrw.commons.location.LatLng latLng, LocationServiceManager.LocationChangeType locationChangeType){ private void handleLocationUpdate(final fr.free.nrw.commons.location.LatLng latLng, final LocationServiceManager.LocationChangeType locationChangeType){
this.lastKnownLocation = latLng; lastKnownLocation = latLng;
NearbyController.currentLocation = lastKnownLocation; NearbyController.currentLocation = lastKnownLocation;
presenter.updateMapAndList(locationChangeType); presenter.updateMapAndList(locationChangeType);
} }
private boolean isUserBrowsing() { private boolean isUserBrowsing() {
boolean isUserBrowsing = lastKnownLocation!=null && !presenter.areLocationsClose(getCameraTarget(), lastKnownLocation); final boolean isUserBrowsing = lastKnownLocation!=null && !presenter.areLocationsClose(getCameraTarget(), lastKnownLocation);
return isUserBrowsing; return isUserBrowsing;
} }
@Override @Override
public void onLocationChangedSignificantly(fr.free.nrw.commons.location.LatLng latLng) { public void onLocationChangedSignificantly(final fr.free.nrw.commons.location.LatLng latLng) {
Timber.d("Location significantly changed"); Timber.d("Location significantly changed");
if (isMapBoxReady && latLng != null &&!isUserBrowsing()) { if (isMapBoxReady && latLng != null &&!isUserBrowsing()) {
handleLocationUpdate(latLng,LOCATION_SIGNIFICANTLY_CHANGED); handleLocationUpdate(latLng,LOCATION_SIGNIFICANTLY_CHANGED);
@ -959,7 +955,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void onLocationChangedSlightly(fr.free.nrw.commons.location.LatLng latLng) { public void onLocationChangedSlightly(final fr.free.nrw.commons.location.LatLng latLng) {
Timber.d("Location slightly changed"); Timber.d("Location slightly changed");
if (isMapBoxReady && latLng != null &&!isUserBrowsing()) {//If the map has never ever shown the current location, lets do it know if (isMapBoxReady && latLng != null &&!isUserBrowsing()) {//If the map has never ever shown the current location, lets do it know
handleLocationUpdate(latLng,LOCATION_SLIGHTLY_CHANGED); handleLocationUpdate(latLng,LOCATION_SLIGHTLY_CHANGED);
@ -967,7 +963,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void onLocationChangedMedium(fr.free.nrw.commons.location.LatLng latLng) { public void onLocationChangedMedium(final fr.free.nrw.commons.location.LatLng latLng) {
Timber.d("Location changed medium"); Timber.d("Location changed medium");
if (isMapBoxReady && latLng != null && !isUserBrowsing()) {//If the map has never ever shown the current location, lets do it know if (isMapBoxReady && latLng != null && !isUserBrowsing()) {//If the map has never ever shown the current location, lets do it know
handleLocationUpdate(latLng, LOCATION_SIGNIFICANTLY_CHANGED); handleLocationUpdate(latLng, LOCATION_SIGNIFICANTLY_CHANGED);
@ -985,7 +981,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@Override @Override
public void onLogoutComplete() { public void onLogoutComplete() {
Timber.d("Logout complete callback received."); Timber.d("Logout complete callback received.");
Intent nearbyIntent = new Intent( getActivity(), LoginActivity.class); final Intent nearbyIntent = new Intent( getActivity(), LoginActivity.class);
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(nearbyIntent); startActivity(nearbyIntent);
@ -994,12 +990,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void setFABPlusAction(View.OnClickListener onClickListener) { public void setFABPlusAction(final View.OnClickListener onClickListener) {
fabPlus.setOnClickListener(onClickListener); fabPlus.setOnClickListener(onClickListener);
} }
@Override @Override
public void setFABRecenterAction(View.OnClickListener onClickListener) { public void setFABRecenterAction(final View.OnClickListener onClickListener) {
fabRecenter.setOnClickListener(onClickListener); fabRecenter.setOnClickListener(onClickListener);
} }
@ -1025,27 +1021,27 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* @param curLatLng current location * @param curLatLng current location
*/ */
@Override @Override
public void addCurrentLocationMarker(fr.free.nrw.commons.location.LatLng curLatLng) { public void addCurrentLocationMarker(final fr.free.nrw.commons.location.LatLng curLatLng) {
if (null != curLatLng) { if (null != curLatLng) {
ExecutorUtils.get().submit(() -> { ExecutorUtils.get().submit(() -> {
mapView.post(() -> removeCurrentLocationMarker()); mapView.post(() -> removeCurrentLocationMarker());
Timber.d("Adds current location marker"); Timber.d("Adds current location marker");
Icon icon = IconFactory.getInstance(getContext()) final Icon icon = IconFactory.getInstance(getContext())
.fromResource(R.drawable.current_location_marker); .fromResource(R.drawable.current_location_marker);
MarkerOptions currentLocationMarkerOptions = new MarkerOptions() final MarkerOptions currentLocationMarkerOptions = new MarkerOptions()
.position(new LatLng(curLatLng.getLatitude(), .position(new LatLng(curLatLng.getLatitude(),
curLatLng.getLongitude())); curLatLng.getLongitude()));
currentLocationMarkerOptions.setIcon(icon); // Set custom icon currentLocationMarkerOptions.setIcon(icon); // Set custom icon
mapView.post(() -> currentLocationMarker = mapBox.addMarker(currentLocationMarkerOptions)); mapView.post(() -> currentLocationMarker = mapBox.addMarker(currentLocationMarkerOptions));
List<LatLng> circle = UiUtils final List<LatLng> circle = UiUtils
.createCircleArray(curLatLng.getLatitude(), curLatLng.getLongitude(), .createCircleArray(curLatLng.getLatitude(), curLatLng.getLongitude(),
curLatLng.getAccuracy() * 2, 100); curLatLng.getAccuracy() * 2, 100);
PolygonOptions currentLocationPolygonOptions = new PolygonOptions() final PolygonOptions currentLocationPolygonOptions = new PolygonOptions()
.addAll(circle) .addAll(circle)
.strokeColor(getResources().getColor(R.color.current_marker_stroke)) .strokeColor(getResources().getColor(R.color.current_marker_stroke))
.fillColor(getResources().getColor(R.color.current_marker_fill)); .fillColor(getResources().getColor(R.color.current_marker_fill));
@ -1070,9 +1066,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* @param curLatLng current location of user * @param curLatLng current location of user
*/ */
@Override @Override
public void updateMapToTrackPosition(fr.free.nrw.commons.location.LatLng curLatLng) { public void updateMapToTrackPosition(final fr.free.nrw.commons.location.LatLng curLatLng) {
Timber.d("Updates map camera to track user position"); Timber.d("Updates map camera to track user position");
CameraPosition cameraPosition = new CameraPosition.Builder().target final CameraPosition cameraPosition = new CameraPosition.Builder().target
(LocationUtils.commonsLatLngToMapBoxLatLng(curLatLng)).build(); (LocationUtils.commonsLatLngToMapBoxLatLng(curLatLng)).build();
if(null!=mapBox) { if(null!=mapBox) {
mapBox.setCameraPosition(cameraPosition); mapBox.setCameraPosition(cameraPosition);
@ -1082,7 +1078,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void updateMapMarkers(List<NearbyBaseMarker> nearbyBaseMarkers, Marker selectedMarker) { public void updateMapMarkers(final List<NearbyBaseMarker> nearbyBaseMarkers, final Marker selectedMarker) {
if(mapBox!=null && isMapBoxReady){ if(mapBox!=null && isMapBoxReady){
mapBox.clear(); mapBox.clear();
addNearbyMarkersToMapBoxMap(nearbyBaseMarkers, selectedMarker); addNearbyMarkersToMapBoxMap(nearbyBaseMarkers, selectedMarker);
@ -1095,7 +1091,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@Override @Override
public void filterOutAllMarkers() { public void filterOutAllMarkers() {
hideAllMarkers(); hideAllMarkers();
updateNearbyList();
} }
/** /**
@ -1103,10 +1098,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
*/ */
@Override @Override
public void displayAllMarkers() { public void displayAllMarkers() {
for (MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { for (final MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) {
updateMarker(markerPlaceGroup.getIsBookmarked(), markerPlaceGroup.getPlace(), NearbyController.currentLocation); updateMarker(markerPlaceGroup.getIsBookmarked(), markerPlaceGroup.getPlace(), NearbyController.currentLocation);
} }
updateNearbyList();
} }
/** /**
@ -1118,17 +1112,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* @param filterForAllNoneType true if we filter places with all none button * @param filterForAllNoneType true if we filter places with all none button
*/ */
@Override @Override
public void filterMarkersByLabels(List<Label> selectedLabels, public void filterMarkersByLabels(final List<Label> selectedLabels,
boolean displayExists, final boolean displayExists,
boolean displayNeedsPhoto, final boolean displayNeedsPhoto,
boolean filterForPlaceState, final boolean filterForPlaceState,
boolean filterForAllNoneType) { final boolean filterForAllNoneType) {
// Remove the previous markers before updating them // Remove the previous markers before updating them
hideAllMarkers(); hideAllMarkers();
for (MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { for (final MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) {
Place place = markerPlaceGroup.getPlace(); final Place place = markerPlaceGroup.getPlace();
// When label filter is engaged // When label filter is engaged
// then compare it against place's label // then compare it against place's label
@ -1157,7 +1151,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
updateMarker(markerPlaceGroup.getIsBookmarked(), place, NearbyController.currentLocation); updateMarker(markerPlaceGroup.getIsBookmarked(), place, NearbyController.currentLocation);
} }
} }
updateNearbyList();
} }
@Override @Override
@ -1171,10 +1164,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* @param place * @param place
* @param curLatLng current location * @param curLatLng current location
*/ */
public void updateMarker(boolean isBookmarked, Place place, @Nullable fr.free.nrw.commons.location.LatLng curLatLng) { public void updateMarker(final boolean isBookmarked, final Place place, @Nullable final fr.free.nrw.commons.location.LatLng curLatLng) {
addPlaceToNearbyList(place); addPlaceToNearbyList(place);
VectorDrawableCompat vectorDrawable; final VectorDrawableCompat vectorDrawable;
if (isBookmarked) { if (isBookmarked) {
vectorDrawable = VectorDrawableCompat.create( vectorDrawable = VectorDrawableCompat.create(
getContext().getResources(), R.drawable.ic_custom_bookmark_marker, getContext().getTheme() getContext().getResources(), R.drawable.ic_custom_bookmark_marker, getContext().getTheme()
@ -1192,16 +1185,16 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
getContext().getResources(), R.drawable.ic_custom_map_marker, getContext().getTheme() getContext().getResources(), R.drawable.ic_custom_map_marker, getContext().getTheme()
); );
} }
for (Marker marker : mapBox.getMarkers()) { for (final Marker marker : mapBox.getMarkers()) {
if (marker.getTitle() != null && marker.getTitle().equals(place.getName())) { if (marker.getTitle() != null && marker.getTitle().equals(place.getName())) {
Bitmap icon = UiUtils.getBitmap(vectorDrawable); final Bitmap icon = UiUtils.getBitmap(vectorDrawable);
if (curLatLng != null) { if (curLatLng != null) {
String distance = formatDistanceBetween(curLatLng, place.location); final String distance = formatDistanceBetween(curLatLng, place.location);
place.setDistance(distance); place.setDistance(distance);
} }
NearbyBaseMarker nearbyBaseMarker = new NearbyBaseMarker(); final NearbyBaseMarker nearbyBaseMarker = new NearbyBaseMarker();
nearbyBaseMarker.title(place.name); nearbyBaseMarker.title(place.name);
nearbyBaseMarker.position( nearbyBaseMarker.position(
new com.mapbox.mapboxsdk.geometry.LatLng( new com.mapbox.mapboxsdk.geometry.LatLng(
@ -1221,11 +1214,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* since grey icon may lead the users to believe that it is disabled or prohibited contribution * since grey icon may lead the users to believe that it is disabled or prohibited contribution
*/ */
private void hideAllMarkers() { private void hideAllMarkers() {
VectorDrawableCompat vectorDrawable; final VectorDrawableCompat vectorDrawable;
vectorDrawable = VectorDrawableCompat.create( vectorDrawable = VectorDrawableCompat.create(
getContext().getResources(), R.drawable.ic_custom_greyed_out_marker, getContext().getTheme()); getContext().getResources(), R.drawable.ic_custom_greyed_out_marker, getContext().getTheme());
Bitmap icon = UiUtils.getBitmap(vectorDrawable); final Bitmap icon = UiUtils.getBitmap(vectorDrawable);
for (Marker marker : mapBox.getMarkers()) { for (final Marker marker : mapBox.getMarkers()) {
if (!marker.equals(currentLocationMarker)) { if (!marker.equals(currentLocationMarker)) {
marker.setIcon(IconFactory.getInstance(getContext()).fromBitmap(icon)); marker.setIcon(IconFactory.getInstance(getContext()).fromBitmap(icon));
} }
@ -1234,7 +1227,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
clearNearbyList(); clearNearbyList();
} }
private void addNearbyMarkersToMapBoxMap(List<NearbyBaseMarker> nearbyBaseMarkers, Marker selectedMarker) { private void addNearbyMarkersToMapBoxMap(final List<NearbyBaseMarker> nearbyBaseMarkers, final Marker selectedMarker) {
if (isMapBoxReady && mapBox != null) { if (isMapBoxReady && mapBox != null) {
mapBox.addMarkers(nearbyBaseMarkers); mapBox.addMarkers(nearbyBaseMarkers);
setMapMarkerActions(selectedMarker); setMapMarkerActions(selectedMarker);
@ -1242,7 +1235,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
} }
private void setMapMarkerActions(Marker selectedMarker) { private void setMapMarkerActions(final Marker selectedMarker) {
if (mapBox != null) { if (mapBox != null) {
mapBox.setOnInfoWindowCloseListener(marker -> { mapBox.setOnInfoWindowCloseListener(marker -> {
if (marker == selectedMarker) { if (marker == selectedMarker) {
@ -1260,7 +1253,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void recenterMap(fr.free.nrw.commons.location.LatLng curLatLng) { public void recenterMap(final fr.free.nrw.commons.location.LatLng curLatLng) {
if (curLatLng == null) { if (curLatLng == null) {
if (!(locationManager.isNetworkProviderEnabled() || locationManager.isGPSProviderEnabled())) { if (!(locationManager.isNetworkProviderEnabled() || locationManager.isGPSProviderEnabled())) {
showLocationOffDialog(); showLocationOffDialog();
@ -1268,7 +1261,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
return; return;
} }
addCurrentLocationMarker(curLatLng); addCurrentLocationMarker(curLatLng);
CameraPosition position; final CameraPosition position;
if (ViewUtil.isPortrait(getActivity())) { if (ViewUtil.isPortrait(getActivity())) {
position = new CameraPosition.Builder() position = new CameraPosition.Builder()
@ -1306,8 +1299,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@Override @Override
public void openLocationSettings() { public void openLocationSettings() {
// This method opens the location settings of the device along with a followup toast. // This method opens the location settings of the device along with a followup toast.
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
PackageManager packageManager = getActivity().getPackageManager(); final PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager)!= null) { if (intent.resolveActivity(packageManager)!= null) {
startActivity(intent); startActivity(intent);
@ -1328,10 +1321,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void displayBottomSheetWithInfo(Marker marker) { public void displayBottomSheetWithInfo(final Marker marker) {
this.selectedMarker = marker; selectedMarker = marker;
NearbyMarker nearbyMarker = (NearbyMarker) marker; final NearbyMarker nearbyMarker = (NearbyMarker) marker;
Place place = nearbyMarker.getNearbyBaseMarker().getPlace(); final Place place = nearbyMarker.getNearbyBaseMarker().getPlace();
passInfoToSheet(place); passInfoToSheet(place);
hideBottomSheet(); hideBottomSheet();
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
@ -1348,16 +1341,18 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* If nearby details bottom sheet state is hidden: hide all fabs * If nearby details bottom sheet state is hidden: hide all fabs
* @param bottomSheetState see bottom sheet states * @param bottomSheetState see bottom sheet states
*/ */
public void prepareViewsForSheetPosition(int bottomSheetState) { public void prepareViewsForSheetPosition(final int bottomSheetState) {
switch (bottomSheetState) { switch (bottomSheetState) {
case (BottomSheetBehavior.STATE_COLLAPSED): case (BottomSheetBehavior.STATE_COLLAPSED):
collapseFABs(isFABsExpanded); collapseFABs(isFABsExpanded);
if (!fabPlus.isShown()) showFABs(); if (!fabPlus.isShown()) {
this.getView().requestFocus(); showFABs();
}
getView().requestFocus();
break; break;
case (BottomSheetBehavior.STATE_EXPANDED): case (BottomSheetBehavior.STATE_EXPANDED):
this.getView().requestFocus(); getView().requestFocus();
break; break;
case (BottomSheetBehavior.STATE_HIDDEN): case (BottomSheetBehavior.STATE_HIDDEN):
if (null != mapBox) { if (null != mapBox) {
@ -1367,8 +1362,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
transparentView.setAlpha(0); transparentView.setAlpha(0);
collapseFABs(isFABsExpanded); collapseFABs(isFABsExpanded);
hideFABs(); hideFABs();
if (this.getView() != null) { if (getView() != null) {
this.getView().requestFocus(); getView().requestFocus();
} }
break; break;
} }
@ -1379,36 +1374,37 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
* (title, description, distance and links) to view on nearby marker click * (title, description, distance and links) to view on nearby marker click
* @param place Place of clicked nearby marker * @param place Place of clicked nearby marker
*/ */
private void passInfoToSheet(Place place) { private void passInfoToSheet(final Place place) {
this.selectedPlace = place; selectedPlace = place;
updateBookmarkButtonImage(this.selectedPlace); updateBookmarkButtonImage(selectedPlace);
bookmarkButton.setOnClickListener(view -> { bookmarkButton.setOnClickListener(view -> {
boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(this.selectedPlace); final boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(selectedPlace);
updateBookmarkButtonImage(this.selectedPlace); updateBookmarkButtonImage(selectedPlace);
updateMarker(isBookmarked, this.selectedPlace, locationManager.getLastLocation()); updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation());
}); });
wikipediaButton.setVisibility(place.hasWikipediaLink()?View.VISIBLE:View.GONE); wikipediaButton.setVisibility(place.hasWikipediaLink()?View.VISIBLE:View.GONE);
wikipediaButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), this.selectedPlace.siteLinks.getWikipediaLink())); wikipediaButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikipediaLink()));
wikidataButton.setVisibility(place.hasWikidataLink()?View.VISIBLE:View.GONE); wikidataButton.setVisibility(place.hasWikidataLink()?View.VISIBLE:View.GONE);
wikidataButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), this.selectedPlace.siteLinks.getWikidataLink())); wikidataButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikidataLink()));
directionsButton.setOnClickListener(view -> Utils.handleGeoCoordinates(getActivity(), this.selectedPlace.getLocation())); directionsButton.setOnClickListener(view -> Utils.handleGeoCoordinates(getActivity(),
selectedPlace.getLocation()));
commonsButton.setVisibility(this.selectedPlace.hasCommonsLink()?View.VISIBLE:View.GONE); commonsButton.setVisibility(selectedPlace.hasCommonsLink()?View.VISIBLE:View.GONE);
commonsButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), this.selectedPlace.siteLinks.getCommonsLink())); commonsButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getCommonsLink()));
icon.setImageResource(this.selectedPlace.getLabel().getIcon()); icon.setImageResource(selectedPlace.getLabel().getIcon());
title.setText(this.selectedPlace.name); title.setText(selectedPlace.name);
distance.setText(this.selectedPlace.distance); distance.setText(selectedPlace.distance);
description.setText(this.selectedPlace.getLongDescription()); description.setText(selectedPlace.getLongDescription());
fabCamera.setOnClickListener(view -> { fabCamera.setOnClickListener(view -> {
if (fabCamera.isShown()) { if (fabCamera.isShown()) {
Timber.d("Camera button tapped. Place: %s", this.selectedPlace.toString()); Timber.d("Camera button tapped. Place: %s", selectedPlace.toString());
storeSharedPrefs(selectedPlace); storeSharedPrefs(selectedPlace);
controller.initiateCameraPick(getActivity()); controller.initiateCameraPick(getActivity());
} }
@ -1416,20 +1412,20 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
fabGallery.setOnClickListener(view -> { fabGallery.setOnClickListener(view -> {
if (fabGallery.isShown()) { if (fabGallery.isShown()) {
Timber.d("Gallery button tapped. Place: %s", this.selectedPlace.toString()); Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString());
storeSharedPrefs(selectedPlace); storeSharedPrefs(selectedPlace);
controller.initiateGalleryPick(getActivity(), false); controller.initiateGalleryPick(getActivity(), false);
} }
}); });
} }
private void storeSharedPrefs(Place selectedPlace) { private void storeSharedPrefs(final Place selectedPlace) {
Timber.d("Store place object %s", selectedPlace.toString()); Timber.d("Store place object %s", selectedPlace.toString());
applicationKvStore.putJson(PLACE_OBJECT, selectedPlace); applicationKvStore.putJson(PLACE_OBJECT, selectedPlace);
} }
private void updateBookmarkButtonImage(Place place) { private void updateBookmarkButtonImage(final Place place) {
int bookmarkIcon; final int bookmarkIcon;
if (bookmarkLocationDao.findBookmarkLocation(place)) { if (bookmarkLocationDao.findBookmarkLocation(place)) {
bookmarkIcon = R.drawable.ic_round_star_filled_24px; bookmarkIcon = R.drawable.ic_round_star_filled_24px;
} else { } else {
@ -1441,7 +1437,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
@Override @Override
public void onAttach(Context context) { public void onAttach(final Context context) {
super.onAttach(context); super.onAttach(context);
wikidataEditListener.setAuthenticationStateListener(this); wikidataEditListener.setAuthenticationStateListener(this);
} }
@ -1459,11 +1455,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} }
} }
private void showErrorMessage(String message) { private void showErrorMessage(final String message) {
ViewUtil.showLongToast(getActivity(), message); ViewUtil.showLongToast(getActivity(), message);
} }
public void registerUnregisterLocationListener(boolean removeLocationListener) { public void registerUnregisterLocationListener(final boolean removeLocationListener) {
try { try {
if (removeLocationListener) { if (removeLocationListener) {
locationManager.unregisterLocationManager(); locationManager.unregisterLocationManager();
@ -1474,14 +1470,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
locationManager.registerLocationManager(); locationManager.registerLocationManager();
Timber.d("Location service manager added and registered"); Timber.d("Location service manager added and registered");
} }
}catch (Exception e){ }catch (final Exception e){
Timber.e(e); Timber.e(e);
//Broadcasts are tricky, should be catchedonR //Broadcasts are tricky, should be catchedonR
} }
} }
@Override @Override
public void setUserVisibleHint(boolean isVisibleToUser) { public void setUserVisibleHint(final boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser); super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser=isVisibleToUser; this.isVisibleToUser=isVisibleToUser;
if (isResumed() && isVisibleToUser) { if (isResumed() && isVisibleToUser) {

View file

@ -0,0 +1,25 @@
package fr.free.nrw.commons.nearby.fragments
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.nearby.placeAdapterDelegate
import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter
class PlaceAdapter(
bookmarkLocationsDao: BookmarkLocationsDao,
onPlaceClicked: ((Place) -> Unit)? = null,
onBookmarkClicked: (Place, Boolean) -> Unit,
commonPlaceClickActions: CommonPlaceClickActions
) :
BaseDelegateAdapter<Place>(
placeAdapterDelegate(
bookmarkLocationsDao,
onPlaceClicked,
commonPlaceClickActions.onCameraClicked(),
commonPlaceClickActions.onGalleryClicked(),
onBookmarkClicked,
commonPlaceClickActions.onOverflowClicked(),
commonPlaceClickActions.onDirectionsClicked()
),
areItemsTheSame = {oldItem, newItem -> oldItem.wikiDataEntityId == newItem.wikiDataEntityId }
)

View file

@ -20,14 +20,22 @@ abstract class BaseDelegateAdapter<T>(
*delegates *delegates
) { ) {
fun getItemAt(position: Int) = items[position]
fun addAll(newResults: List<T>) { fun addAll(newResults: List<T>) {
items = (items ?: emptyList<T>()) + newResults items = itemsOrEmpty + newResults
} }
fun clear() { fun clear() {
items = emptyList() items = emptyList()
} }
fun add(item: T) {
items = itemsOrEmpty + item
}
fun remove(item: T) {
items = itemsOrEmpty - item
}
private val itemsOrEmpty get() = items ?: emptyList<T>()
} }

View file

@ -1,56 +0,0 @@
package fr.free.nrw.commons.upload.structure.depictions;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckedTextView;
import android.widget.TextView;
import com.pedrogomez.renderers.Renderer;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
public class DepictionRenderer extends Renderer<DepictedItem> {
@BindView(R.id.depict_checkbox)
CheckedTextView checkedView;
private final UploadDepictsCallback listener;
@BindView(R.id.depicts_label)
TextView depictsLabel;
@BindView(R.id.description) TextView description;
public DepictionRenderer(UploadDepictsCallback listener) {
this.listener = listener;
}
@Override
protected void setUpView(View rootView) {
ButterKnife.bind(this, rootView);
}
@Override
protected void hookListeners(View rootView) {
rootView.setOnClickListener( v -> {
DepictedItem item = getContent();
item.setSelected(true);
checkedView.setChecked(item.isSelected());
if (listener != null) {
listener.depictsClicked(item);
}
});
}
@Override
protected View inflate(LayoutInflater inflater, ViewGroup parent) {
return inflater.inflate(R.layout.layout_upload_depicts_item, parent, false);
}
@Override
public void render() {
DepictedItem item = getContent();
checkedView.setChecked(item.isSelected());
depictsLabel.setText(item.getName());
description.setText(item.getDescription());
}
}

View file

@ -16,7 +16,7 @@
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.enableBuildCache=true android.enableBuildCache=true
KOTLIN_VERSION=1.3.21 KOTLIN_VERSION=1.3.72
BUTTERKNIFE_VERSION=10.1.0 BUTTERKNIFE_VERSION=10.1.0
LEAK_CANARY_VERSION=1.6.2 LEAK_CANARY_VERSION=1.6.2
DAGGER_VERSION=2.21 DAGGER_VERSION=2.21