From b063d6bdfd64db6847193d841f490ce831a0d55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Mac=20Gillicuddy?= Date: Wed, 27 May 2020 10:44:21 +0100 Subject: [PATCH] #3468 Switch from RvRenderer to AdapterDelegates (#3750) * #3468 Switch from RvRenderer to AdapterDelegates - replace SearchDepictionsRenderer * #3468 Switch from RvRenderer to AdapterDelegates - replace UploadCategoryDepictionsRenderer * #3468 Switch from RvRenderer to AdapterDelegates - update BaseAdapter to be easier to use * #3468 Switch from RvRenderer to AdapterDelegates - replace SearchImagesRenderer * #3468 Switch from RvRenderer to AdapterDelegates - replace SearchCategoriesRenderer * #3468 Switch from RvRenderer to AdapterDelegates - replace NotificationRenderer * #3468 Switch from RvRenderer to AdapterDelegates - replace UploadDepictsRenderer * #3468 Switch from RvRenderer to AdapterDelegates - replace PlaceRenderer * #3468 fix constant import * #3468 Switch from RvRenderer to AdapterDelegates - resolve id conflict --- app/build.gradle | 20 +- .../free/nrw/commons/CommonsApplication.java | 2 - .../locations/BookmarkLocationsFragment.java | 32 +- .../commons/category/CategoriesRenderer.java | 55 ---- .../nrw/commons/category/CategoryClient.kt | 3 +- .../category/SubCategoryListFragment.java | 29 +- .../Media/DepictedImagesPresenter.java | 2 + .../subClass/SubDepictionListFragment.java | 35 +-- .../subClass/models/SparqlResponses.kt | 3 +- .../di/BookmarkLocationsFragmentModule.kt | 12 + .../di/CommonsApplicationComponent.java | 4 - .../nrw/commons/di/FragmentBuilderModule.java | 4 +- .../commons/di/NearbyParentFragmentModule.kt | 13 + .../nrw/commons/explore/SearchActivity.java | 67 ++-- .../categories/SearchCategoriesAdapter.kt | 9 + .../SearchCategoriesAdapterDelegates.kt | 15 + .../SearchCategoriesAdapterFactory.java | 32 -- .../categories/SearchCategoriesRenderer.java | 56 ---- .../categories/SearchCategoryFragment.java | 24 +- .../explore/depictions/DepictionAdapter.kt | 12 + .../depictions/DepictionAdapterDelegates.kt | 21 ++ .../explore/depictions/DepictsClient.kt | 12 +- .../SearchDepictionsAdapterFactory.java | 31 -- .../depictions/SearchDepictionsFragment.java | 78 ++--- .../SearchDepictionsFragmentContract.java | 10 +- .../depictions/SearchDepictionsRenderer.java | 112 ------- .../explore/images/SearchImageFragment.java | 29 +- .../explore/images/SearchImagesAdapter.kt | 27 ++ .../images/SearchImagesAdapterDelegates.kt | 24 ++ .../images/SearchImagesAdapterFactory.java | 35 --- .../explore/images/SearchImagesRenderer.java | 74 ----- .../commons/media/MediaDetailFragment.java | 4 +- .../free/nrw/commons/mwapi/CategoryApi.java | 14 +- .../commons/nearby/NearbyAdapterFactory.java | 57 ---- .../commons/nearby/PlaceAdapterDelegate.kt | 84 +++++ .../nrw/commons/nearby/PlaceRenderer.java | 289 ------------------ .../fragments/CommonPlaceClickActions.kt | 99 ++++++ .../fragments/NearbyParentFragment.java | 289 +++++++++--------- .../commons/nearby/fragments/PlaceAdapter.kt | 25 ++ .../notification/NotificatinAdapter.kt | 9 + .../nrw/commons/notification/Notification.kt | 12 +- .../notification/NotificationActivity.java | 62 ++-- .../NotificationAdapterDelegates.kt | 24 ++ .../NotificationAdapterFactory.java | 32 -- .../notification/NotificationRenderer.java | 91 ------ .../UploadCategoriesAdapterFactory.java | 27 -- .../upload/UploadCategoriesRenderer.java | 59 ---- .../upload/UploadDepictsAdapterFactory.java | 31 -- .../commons/upload/UploadDepictsRenderer.java | 87 ------ .../upload/categories/BaseDelegateAdapter.kt | 41 +++ .../categories/UploadCategoriesFragment.java | 35 +-- .../categories/UploadCategoryAdapter.kt | 14 + .../UploadCategoryAdapterDelegates.kt | 19 ++ .../upload/depicts/DepictsFragment.java | 39 +-- .../upload/depicts/UploadDepictsAdapter.kt | 10 + .../depicts/UploadDepictsAdapterDelegates.kt | 32 ++ .../depictions/DepictionRenderer.java | 56 ---- app/src/main/res/layout/item_depictions.xml | 6 +- .../layout/layout_upload_categories_item.xml | 4 +- app/src/main/res/layout/nearby_row_button.xml | 24 +- gradle.properties | 3 +- 61 files changed, 851 insertions(+), 1609 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/category/CategoriesRenderer.java create mode 100644 app/src/main/java/fr/free/nrw/commons/di/BookmarkLocationsFragmentModule.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/di/NearbyParentFragmentModule.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterDelegates.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterFactory.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesRenderer.java create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapterDelegates.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsAdapterFactory.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsRenderer.java create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterDelegates.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterFactory.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java create mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/PlaceAdapterDelegate.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java create mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/fragments/PlaceAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/notification/NotificatinAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/notification/NotificationAdapterDelegates.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/notification/NotificationAdapterFactory.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/notification/NotificationRenderer.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/UploadCategoriesAdapterFactory.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/UploadCategoriesRenderer.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/UploadDepictsAdapterFactory.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/UploadDepictsRenderer.java create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/categories/BaseDelegateAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapterDelegates.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapter.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapterDelegates.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictionRenderer.java diff --git a/app/build.gradle b/app/build.gradle index 9ec9103e0..ab311228e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ apply from: 'quality.gradle' def isRunningOnTravisAndIsNotPRBuild = System.getenv("CI") == "true" && file('../play.p12').exists() -if(isRunningOnTravisAndIsNotPRBuild) { +if (isRunningOnTravisAndIsNotPRBuild) { apply plugin: 'com.github.triplet.play' } @@ -35,7 +35,6 @@ dependencies { // UI implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' 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-plugin-localization-v8:0.11.0' implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-scalebar-v9:0.4.0' @@ -43,8 +42,9 @@ dependencies { implementation 'com.dinuscxj:circleprogressbar:1.1.1' implementation 'com.karumi:dexter:5.0.0' implementation "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION" - kapt "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION" + implementation "com.hannesdorfmann:adapterdelegates4-kotlin-dsl-layoutcontainer:$ADAPTER_DELEGATES_VERSION" + implementation "com.hannesdorfmann:adapterdelegates4-pagination:$ADAPTER_DELEGATES_VERSION" // Logging implementation 'ch.acra:acra-dialog:5.3.0' @@ -104,6 +104,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation "androidx.exifinterface:exifinterface:1.0.0" implementation "androidx.core:core-ktx:$CORE_KTX_VERSION" + implementation "androidx.multidex:multidex:2.0.1" //swipe_layout implementation 'com.daimajia.swipelayout:library:1.2.0@aar' @@ -112,7 +113,8 @@ dependencies { implementation "androidx.room:room-runtime:$ROOM_VERSION" implementation "androidx.room:room-ktx:$ROOM_VERSION" implementation "androidx.room:room-rxjava2:$ROOM_VERSION" - kapt "androidx.room:room-compiler:$ROOM_VERSION" // For Kotlin use kapt instead of annotationProcessor + kapt "androidx.room:room-compiler:$ROOM_VERSION" + // For Kotlin use kapt instead of annotationProcessor implementation 'com.squareup.retrofit2:retrofit:2.8.1' testImplementation "androidx.arch.core:core-testing:2.1.0" @@ -145,7 +147,7 @@ android { testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' } - + multiDexEnabled true vectorDrawables.useSupportLibrary = true } @@ -172,7 +174,7 @@ android { test.resources.srcDirs += 'src/main/resoures' } - signingConfigs { + signingConfigs { release } @@ -181,7 +183,7 @@ android { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' testProguardFile 'test-proguard-rules.txt' - if(isRunningOnTravisAndIsNotPRBuild) { + if (isRunningOnTravisAndIsNotPRBuild) { signingConfig signingConfigs.release } } @@ -210,7 +212,7 @@ android { productFlavors { prod { - applicationId 'fr.free.nrw.commons' + applicationId 'fr.free.nrw.commons' buildConfigField "String", "WIKIMEDIA_API_POTD", "\"https://commons.wikimedia.org/w/api.php?action=featuredfeed&feed=potd&feedformat=rss&language=en\"" buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\"" @@ -291,7 +293,7 @@ android { buildToolsVersion buildToolsVersion } -if(isRunningOnTravisAndIsNotPRBuild) { +if (isRunningOnTravisAndIsNotPRBuild) { play { track = "alpha" userFraction = 1 diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index eb8cebb6d..dc37db26c 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -9,7 +9,6 @@ import static org.acra.ReportField.STACK_TRACE; import static org.acra.ReportField.USER_COMMENT; import android.annotation.SuppressLint; -import android.app.Application; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; @@ -25,7 +24,6 @@ import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.mapbox.mapboxsdk.Mapbox; import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.RefWatcher; - import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao; diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsFragment.java b/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsFragment.java index d3f193784..21d4d7460 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsFragment.java @@ -8,26 +8,21 @@ import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; 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.ButterKnife; import dagger.android.support.DaggerFragment; import fr.free.nrw.commons.R; 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.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 { @@ -37,8 +32,10 @@ public class BookmarkLocationsFragment extends DaggerFragment { @BindView(R.id.parentLayout) RelativeLayout parentLayout; @Inject BookmarkLocationsController controller; - private NearbyAdapterFactory adapterFactory; @Inject ContributionController contributionController; + @Inject BookmarkLocationsDao bookmarkLocationDao; + @Inject CommonPlaceClickActions commonPlaceClickActions; + private PlaceAdapter adapter; /** * 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); ButterKnife.bind(this, v); - adapterFactory = new NearbyAdapterFactory(this, contributionController); return v; } @@ -65,7 +61,15 @@ public class BookmarkLocationsFragment extends DaggerFragment { super.onViewCreated(view, savedInstanceState); progressBar.setVisibility(View.VISIBLE); 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 @@ -79,7 +83,7 @@ public class BookmarkLocationsFragment extends DaggerFragment { */ private void initList() { List places = controller.loadFavoritesLocations(); - adapterFactory.updateAdapterData(places, (RVRendererAdapter) recyclerView.getAdapter()); + adapter.setItems(places); progressBar.setVisibility(View.GONE); if (places.size() <= 0) { statusTextView.setText(R.string.bookmark_empty); diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoriesRenderer.java b/app/src/main/java/fr/free/nrw/commons/category/CategoriesRenderer.java deleted file mode 100644 index 7fc8f9d68..000000000 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoriesRenderer.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.free.nrw.commons.category; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckedTextView; - -import com.pedrogomez.renderers.Renderer; - -import butterknife.BindView; -import butterknife.ButterKnife; -import fr.free.nrw.commons.R; -import timber.log.Timber; - -/** - * Renders the Categories view - */ -public class CategoriesRenderer extends Renderer { - @BindView(R.id.tvName) CheckedTextView checkedView; - private final CategoryClickedListener listener; - - CategoriesRenderer(CategoryClickedListener listener) { - this.listener = listener; - } - - @Override - protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return layoutInflater.inflate(R.layout.layout_categories_item, viewGroup, false); - } - - @Override - protected void setUpView(View view) { - ButterKnife.bind(this, view); - } - - @Override - protected void hookListeners(View view) { - view.setOnClickListener(v -> { - CategoryItem item = getContent(); - item.setSelected(!item.isSelected()); - checkedView.setChecked(item.isSelected()); - if (listener != null) { - listener.categoryClicked(item); - } - }); - } - - @Override - public void render() { - CategoryItem item = getContent(); - Timber.e("Rendering: %s", item); - checkedView.setChecked(item.isSelected()); - checkedView.setText(item.getName()); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt index 8b07f9d4a..3750229db 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt @@ -5,6 +5,7 @@ import org.wikipedia.dataclient.mwapi.MwQueryResponse import javax.inject.Inject import javax.inject.Singleton +const val CATEGORY_PREFIX = "Category:" /** * Category Client to handle custom calls to Commons MediaWiki APIs */ @@ -72,7 +73,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category return responseObservable .map { it.query()?.pages() ?: emptyList() } .map { - it.map { page -> page.title().replace("Category:", "") } + it.map { page -> page.title().replace(CATEGORY_PREFIX, "") } } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java b/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java index 256ebcdea..bc884d535 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java @@ -3,6 +3,7 @@ package fr.free.nrw.commons.category; import static android.view.View.GONE; import static android.view.View.VISIBLE; +import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_PREFIX; import android.content.Intent; import android.content.res.Configuration; @@ -17,17 +18,16 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.pedrogomez.renderers.RVRendererAdapter; import fr.free.nrw.commons.R; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; -import fr.free.nrw.commons.explore.categories.SearchCategoriesAdapterFactory; +import fr.free.nrw.commons.explore.categories.SearchCategoriesAdapter; import fr.free.nrw.commons.utils.NetworkUtils; import fr.free.nrw.commons.utils.ViewUtil; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; -import java.util.ArrayList; import java.util.List; import javax.inject.Inject; +import kotlin.Unit; import timber.log.Timber; /** @@ -46,16 +46,9 @@ public class SubCategoryListFragment extends CommonsDaggerSupportFragment { private String categoryName = null; @Inject CategoryClient categoryClient; - private RVRendererAdapter categoriesAdapter; + private SearchCategoriesAdapter categoriesAdapter; private boolean isParentCategory = true; - private final SearchCategoriesAdapterFactory adapterFactory = new SearchCategoriesAdapterFactory(item -> { - // Open SubCategory Details page - Intent intent = new Intent(getContext(), CategoryDetailsActivity.class); - intent.putExtra("categoryName", item); - getContext().startActivity(intent); - - }); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { @@ -70,8 +63,12 @@ public class SubCategoryListFragment extends CommonsDaggerSupportFragment { else{ categoriesRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2)); } - ArrayList items = new ArrayList<>(); - categoriesAdapter = adapterFactory.create(items); + categoriesAdapter = new SearchCategoriesAdapter(item->{ + Intent intent = new Intent(getContext(), CategoryDetailsActivity.class); + intent.putExtra("categoryName", item); + getContext().startActivity(intent); + return Unit.INSTANCE; + }); categoriesRecyclerView.setAdapter(categoriesAdapter); return rootView; } @@ -88,12 +85,14 @@ public class SubCategoryListFragment extends CommonsDaggerSupportFragment { } progressBar.setVisibility(View.VISIBLE); if (isParentCategory) { - compositeDisposable.add(categoryClient.getParentCategoryList("Category:"+categoryName) + compositeDisposable.add(categoryClient.getParentCategoryList( + CATEGORY_PREFIX +categoryName) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::handleSuccess, this::handleError)); } else { - compositeDisposable.add(categoryClient.getSubCategoryList("Category:"+categoryName) + compositeDisposable.add(categoryClient.getSubCategoryList( + CATEGORY_PREFIX +categoryName) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::handleSuccess, this::handleError)); diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.java b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.java index 3e0d5a6ac..02707b652 100644 --- a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.java @@ -40,6 +40,7 @@ public class DepictedImagesPresenter implements DepictedImagesContract.UserActio * Ex: Q9394 */ private List queryList = new ArrayList<>(); + private String entityId; @Inject public DepictedImagesPresenter(@Named("default_preferences") JsonKvStore depictionKvStore, DepictsClient depictsClient, MediaClient mediaClient, @Named(IO_THREAD) Scheduler ioScheduler, @@ -67,6 +68,7 @@ public class DepictedImagesPresenter implements DepictedImagesContract.UserActio @SuppressLint("CheckResult") @Override public void initList(String entityId) { + this.entityId = entityId; view.setLoadingStatus(true); view.progressBarVisible(true); view.setIsLastPage(false); diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/subClass/SubDepictionListFragment.java b/app/src/main/java/fr/free/nrw/commons/depictions/subClass/SubDepictionListFragment.java index c67fe57e5..db071047a 100644 --- a/app/src/main/java/fr/free/nrw/commons/depictions/subClass/SubDepictionListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/depictions/subClass/SubDepictionListFragment.java @@ -17,12 +17,10 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.pedrogomez.renderers.RVRendererAdapter; import dagger.android.support.DaggerFragment; import fr.free.nrw.commons.R; import fr.free.nrw.commons.depictions.WikidataItemDetailsActivity; -import fr.free.nrw.commons.explore.depictions.SearchDepictionsAdapterFactory; -import fr.free.nrw.commons.explore.depictions.SearchDepictionsRenderer; +import fr.free.nrw.commons.explore.depictions.DepictionAdapter; import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; import fr.free.nrw.commons.utils.NetworkUtils; import fr.free.nrw.commons.utils.ViewUtil; @@ -30,6 +28,7 @@ import java.io.IOException; import java.util.List; import java.util.Locale; import javax.inject.Inject; +import kotlin.Unit; /** * Fragment for parent classes and child classes of Depicted items in Explore @@ -48,7 +47,7 @@ public class SubDepictionListFragment extends DaggerFragment implements SubDepic * Keeps a record of whether current instance of the fragment if of SubClass or ParentClass */ private boolean isParentClass = false; - private RVRendererAdapter depictionsAdapter; + private DepictionAdapter depictionsAdapter; RecyclerView.LayoutManager layoutManager; /** * Stores entityId for the depiction @@ -61,20 +60,6 @@ public class SubDepictionListFragment extends DaggerFragment implements SubDepic @Inject SubDepictionListPresenter presenter; - private final SearchDepictionsAdapterFactory adapterFactory = new SearchDepictionsAdapterFactory(new SearchDepictionsRenderer.DepictCallback() { - @Override - public void depictsClicked(DepictedItem item) { - // Open SubDepiction Details page - getActivity().finish(); - WikidataItemDetailsActivity.startYourself(getContext(), item); - } - }); - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - } - private void initViews() { if (getArguments() != null) { depictsName = getArguments().getString("wikidataItemName"); @@ -115,7 +100,12 @@ public class SubDepictionListFragment extends DaggerFragment implements SubDepic } initViews(); depictionsRecyclerView.setLayoutManager(layoutManager); - depictionsAdapter = adapterFactory.create(); + depictionsAdapter = new DepictionAdapter(depictedItem -> { + // Open SubDepiction Details page + getActivity().finish(); + WikidataItemDetailsActivity.startYourself(getContext(), depictedItem); + return Unit.INSTANCE; + }); depictionsRecyclerView.setAdapter(depictionsAdapter); return v; } @@ -130,14 +120,7 @@ public class SubDepictionListFragment extends DaggerFragment implements SubDepic progressBar.setVisibility(View.GONE); depictionNotFound.setVisibility(GONE); bottomProgressBar.setVisibility(GONE); - int itemCount=layoutManager.getItemCount(); depictionsAdapter.addAll(mediaList); - depictionsRecyclerView.getRecycledViewPool().clear(); - if(itemCount!=0) { - depictionsAdapter.notifyItemRangeInserted(itemCount, mediaList.size()-1); - }else{ - depictionsAdapter.notifyDataSetChanged(); - } } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/subClass/models/SparqlResponses.kt b/app/src/main/java/fr/free/nrw/commons/depictions/subClass/models/SparqlResponses.kt index 9a6435124..be9dea64a 100644 --- a/app/src/main/java/fr/free/nrw/commons/depictions/subClass/models/SparqlResponses.kt +++ b/app/src/main/java/fr/free/nrw/commons/depictions/subClass/models/SparqlResponses.kt @@ -9,7 +9,8 @@ data class Binding( val itemLabel: SparqInfo, val itemDescription: SparqInfo? = null ) { - val id: String by lazy { item.value.substringAfterLast("/") } + val id: String + get() = item.value.substringAfterLast("/") } data class SparqInfo(val type: String, val value: String) diff --git a/app/src/main/java/fr/free/nrw/commons/di/BookmarkLocationsFragmentModule.kt b/app/src/main/java/fr/free/nrw/commons/di/BookmarkLocationsFragmentModule.kt new file mode 100644 index 000000000..7570fbedc --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/di/BookmarkLocationsFragmentModule.kt @@ -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!! +} diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java index f813de762..5c97ce9d9 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java @@ -10,11 +10,9 @@ import dagger.android.AndroidInjector; import dagger.android.support.AndroidSupportInjectionModule; import fr.free.nrw.commons.CommonsApplication; 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.depictions.DepictionModule; 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.settings.SettingsFragment; import fr.free.nrw.commons.upload.FileProcessor; @@ -49,8 +47,6 @@ public interface CommonsApplicationComponent extends AndroidInjector { - this.query = query.toString(); - //update image list - if (!TextUtils.isEmpty(query)) { - viewPager.setVisibility(View.VISIBLE); - tabLayout.setVisibility(View.VISIBLE); - searchHistoryContainer.setVisibility(View.GONE); + .subscribe(query -> { + this.query = query.toString(); + //update image list + if (!TextUtils.isEmpty(query)) { + viewPager.setVisibility(View.VISIBLE); + tabLayout.setVisibility(View.VISIBLE); + searchHistoryContainer.setVisibility(View.GONE); - if (FragmentUtils.isFragmentUIActive(searchDepictionsFragment)) { - searchDepictionsFragment.updateDepictionList(query.toString()); - } - - if (FragmentUtils.isFragmentUIActive(searchImageFragment)) { - searchImageFragment.updateImageList(query.toString()); - } - - if (FragmentUtils.isFragmentUIActive(searchCategoryFragment)) { - searchCategoryFragment.updateCategoryList(query.toString()); - } - - }else { - //Open RecentSearchesFragment - recentSearchesFragment.updateRecentSearches(); - viewPager.setVisibility(View.GONE); - tabLayout.setVisibility(View.GONE); - setSearchHistoryFragment(); - searchHistoryContainer.setVisibility(View.VISIBLE); + if (FragmentUtils.isFragmentUIActive(searchDepictionsFragment)) { + searchDepictionsFragment.updateDepictionList(query.toString()); } + + if (FragmentUtils.isFragmentUIActive(searchImageFragment)) { + searchImageFragment.updateImageList(query.toString()); + } + + if (FragmentUtils.isFragmentUIActive(searchCategoryFragment)) { + searchCategoryFragment.updateCategoryList(query.toString()); + } + + } else { + //Open RecentSearchesFragment + recentSearchesFragment.updateRecentSearches(); + viewPager.setVisibility(View.GONE); + tabLayout.setVisibility(View.GONE); + setSearchHistoryFragment(); + searchHistoryContainer.setVisibility(View.VISIBLE); } + }, Timber::e )); } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapter.kt new file mode 100644 index 000000000..6e7bae236 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapter.kt @@ -0,0 +1,9 @@ +package fr.free.nrw.commons.explore.categories + +import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter + + +class SearchCategoriesAdapter(onCateoryClicked: (String) -> Unit) : BaseDelegateAdapter( + searchCategoryDelegate(onCateoryClicked), + areItemsTheSame = { oldItem, newItem -> oldItem == newItem } +) diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterDelegates.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterDelegates.kt new file mode 100644 index 000000000..6cd3a3386 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterDelegates.kt @@ -0,0 +1,15 @@ +package fr.free.nrw.commons.explore.categories + +import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer +import fr.free.nrw.commons.R +import fr.free.nrw.commons.category.CATEGORY_PREFIX +import kotlinx.android.synthetic.main.item_recent_searches.* + + +fun searchCategoryDelegate(onCategoryClicked: (String) -> Unit) = + adapterDelegateLayoutContainer(R.layout.item_recent_searches) { + containerView.setOnClickListener { onCategoryClicked(item) } + bind { + textView1.text = item.substringAfter(CATEGORY_PREFIX) + } + } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterFactory.java deleted file mode 100644 index 3ac75e07e..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package fr.free.nrw.commons.explore.categories; - -import com.pedrogomez.renderers.ListAdapteeCollection; -import com.pedrogomez.renderers.RVRendererAdapter; -import com.pedrogomez.renderers.RendererBuilder; - -import java.util.Collections; -import java.util.List; - -/** - * This class helps in creating adapter for categoriesRecyclerView in SearchCategoryFragment, - * implementing onClicks on categoriesRecyclerView Items - **/ -public class SearchCategoriesAdapterFactory { - private final SearchCategoriesRenderer.CategoryClickedListener listener; - - public SearchCategoriesAdapterFactory(SearchCategoriesRenderer.CategoryClickedListener listener) { - this.listener = listener; - } - - /** - * This method creates a recyclerViewAdapter for Categories. - * @param searchImageItemList List of category name to be displayed - * @return categoriesAdapter - **/ - public RVRendererAdapter create(List searchImageItemList) { - RendererBuilder builder = new RendererBuilder().bind(String.class, new SearchCategoriesRenderer(listener)); - ListAdapteeCollection collection = new ListAdapteeCollection<>( - searchImageItemList != null ? searchImageItemList : Collections.emptyList()); - return new RVRendererAdapter<>(builder, collection); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesRenderer.java b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesRenderer.java deleted file mode 100644 index 631b7b552..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesRenderer.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.free.nrw.commons.explore.categories; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.pedrogomez.renderers.Renderer; - -import butterknife.BindView; -import butterknife.ButterKnife; -import fr.free.nrw.commons.R; - -/** - * presentation logic of individual category in search is handled here - **/ -class SearchCategoriesRenderer extends Renderer { - @BindView(R.id.textView1) TextView tvCategoryName; - - private final CategoryClickedListener listener; - - SearchCategoriesRenderer(CategoryClickedListener listener) { - this.listener = listener; - } - - @Override - protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return layoutInflater.inflate(R.layout.item_recent_searches, viewGroup, false); - } - - @Override - protected void setUpView(View view) { - ButterKnife.bind(this, view); - } - - @Override - protected void hookListeners(View view) { - view.setOnClickListener(v -> { - String item = getContent(); - if (listener != null) { - listener.categoryClicked(item); - } - }); - } - - @Override - public void render() { - String item = getContent(); - tvCategoryName.setText(item.replaceFirst("^Category:", "")); - } - - public interface CategoryClickedListener { - void categoryClicked(String item); - } - -} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java index ac5797adc..855461e1d 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java @@ -16,7 +16,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.pedrogomez.renderers.RVRendererAdapter; import fr.free.nrw.commons.R; import fr.free.nrw.commons.category.CategoryClient; import fr.free.nrw.commons.category.CategoryDetailsActivity; @@ -33,6 +32,7 @@ import java.util.Date; import java.util.List; import javax.inject.Inject; import javax.inject.Named; +import kotlin.Unit; import timber.log.Timber; /** @@ -59,16 +59,9 @@ public class SearchCategoryFragment extends CommonsDaggerSupportFragment { @Named("default_preferences") JsonKvStore basicKvStore; - private RVRendererAdapter categoriesAdapter; + private SearchCategoriesAdapter categoriesAdapter; private List queryList = new ArrayList<>(); - private final SearchCategoriesAdapterFactory adapterFactory = new SearchCategoriesAdapterFactory(item -> { - // Called on Click of a individual category Item - // Open Category Details activity - CategoryDetailsActivity.startYourself(getContext(), item); - saveQuery(query); - }); - /** * This method saves Search Query in the Recent Searches Database. * @param query @@ -98,8 +91,11 @@ public class SearchCategoryFragment extends CommonsDaggerSupportFragment { else{ categoriesRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2)); } - ArrayList items = new ArrayList<>(); - categoriesAdapter = adapterFactory.create(items); + categoriesAdapter = new SearchCategoriesAdapter(item -> { + CategoryDetailsActivity.startYourself(getContext(), item); + saveQuery(query); + return Unit.INSTANCE; + }); categoriesRecyclerView.setAdapter(categoriesAdapter); categoriesRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -141,7 +137,9 @@ public class SearchCategoryFragment extends CommonsDaggerSupportFragment { * Adds 25 more results to existing search results */ public void addCategoriesToList(String query) { - if(isLoadingCategories) return; + if(isLoadingCategories) { + return; + } isLoadingCategories=true; this.query = query; bottomProgressBar.setVisibility(View.VISIBLE); @@ -161,7 +159,6 @@ public class SearchCategoryFragment extends CommonsDaggerSupportFragment { progressBar.setVisibility(View.GONE); bottomProgressBar.setVisibility(GONE); categoriesAdapter.addAll(mediaList); - categoriesAdapter.notifyDataSetChanged(); isLoadingCategories=false; } @@ -181,7 +178,6 @@ public class SearchCategoryFragment extends CommonsDaggerSupportFragment { bottomProgressBar.setVisibility(View.GONE); progressBar.setVisibility(GONE); categoriesAdapter.addAll(mediaList); - categoriesAdapter.notifyDataSetChanged(); } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapter.kt new file mode 100644 index 000000000..39a367eff --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapter.kt @@ -0,0 +1,12 @@ +package fr.free.nrw.commons.explore.depictions + +import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter +import fr.free.nrw.commons.upload.structure.depictions.DepictedItem + + +class DepictionAdapter(clickListener: (DepictedItem) -> Unit) : BaseDelegateAdapter( + depictionDelegate(clickListener), + areItemsTheSame = { oldItem, newItem -> oldItem.id == newItem.id } +) + + diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapterDelegates.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapterDelegates.kt new file mode 100644 index 000000000..e1c37c0e5 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictionAdapterDelegates.kt @@ -0,0 +1,21 @@ +package fr.free.nrw.commons.explore.depictions + +import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer +import fr.free.nrw.commons.R +import fr.free.nrw.commons.upload.structure.depictions.DepictedItem +import kotlinx.android.synthetic.main.item_depictions.* + + +fun depictionDelegate(onDepictionClicked: (DepictedItem) -> Unit) = + adapterDelegateLayoutContainer(R.layout.item_depictions) { + containerView.setOnClickListener { onDepictionClicked(item) } + bind { + depicts_label.text = item.name + description.text = item.description + if (item.imageUrl?.isNotBlank() == true) { + depicts_image.setImageURI(item.imageUrl) + } else { + depicts_image.setActualImageResource(R.drawable.ic_wikidata_logo_24dp) + } + } + } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt index 829c4fc8f..183282d33 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt @@ -3,7 +3,6 @@ package fr.free.nrw.commons.explore.depictions import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.Media import fr.free.nrw.commons.depictions.models.DepictionResponse -import fr.free.nrw.commons.depictions.subClass.models.Binding import fr.free.nrw.commons.depictions.subClass.models.SparqlResponse import fr.free.nrw.commons.media.MediaInterface import fr.free.nrw.commons.upload.depicts.DepictsInterface @@ -20,8 +19,9 @@ import java.util.* import javax.inject.Inject import javax.inject.Singleton -const val LARGE_IMAGE_SIZE="640px" -const val THUMB_IMAGE_SIZE="70px" +const val LARGE_IMAGE_SIZE = "640px" +const val THUMB_IMAGE_SIZE = "70px" + /** * Depicts Client to handle custom calls to Commons Wikibase APIs */ @@ -79,7 +79,11 @@ class DepictsClient @Inject constructor( } fun toDepictions(sparqlResponse: Observable): Observable> { - return sparqlResponse.map { it.results.bindings.joinToString("|", transform = Binding::id) } + return sparqlResponse.map { + it.results.bindings.joinToString("|") { binding -> + binding.id + } + } .flatMap { getEntities(it).toObservable() } .map { it.entities().values.map(::DepictedItem) } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsAdapterFactory.java deleted file mode 100644 index 71d64b0ea..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsAdapterFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package fr.free.nrw.commons.explore.depictions; - -import com.pedrogomez.renderers.ListAdapteeCollection; -import com.pedrogomez.renderers.RVRendererAdapter; -import com.pedrogomez.renderers.RendererBuilder; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; - -/** - * Adapter factory for Items in Explore - */ - -public class SearchDepictionsAdapterFactory { - private final SearchDepictionsRenderer.DepictCallback listener; - - public SearchDepictionsAdapterFactory(SearchDepictionsRenderer.DepictCallback listener) { - this.listener = listener; - } - - public RVRendererAdapter create() { - List searchImageItemList = new ArrayList<>(); - RendererBuilder builder = new RendererBuilder().bind(DepictedItem.class, new SearchDepictionsRenderer(listener)); - ListAdapteeCollection collection = new ListAdapteeCollection<>( - searchImageItemList != null ? searchImageItemList : Collections.emptyList()); - return new RVRendererAdapter<>(builder, collection); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.java index 18b75e751..b0d269061 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.java @@ -2,6 +2,7 @@ package fr.free.nrw.commons.explore.depictions; import static android.view.View.GONE; import static android.view.View.VISIBLE; +import static fr.free.nrw.commons.explore.depictions.DepictionAdapterDelegatesKt.depictionDelegate; import android.content.Context; import android.content.res.Configuration; @@ -12,12 +13,13 @@ import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DiffUtil.ItemCallback; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.pedrogomez.renderers.RVRendererAdapter; +import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter; import fr.free.nrw.commons.R; import fr.free.nrw.commons.depictions.WikidataItemDetailsActivity; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; @@ -28,6 +30,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.inject.Inject; +import kotlin.Unit; /** * Display depictions in search fragment @@ -42,24 +45,17 @@ public class SearchDepictionsFragment extends CommonsDaggerSupportFragment imple TextView depictionNotFound; @BindView(R.id.bottomProgressBar) ProgressBar bottomProgressBar; - RecyclerView.LayoutManager layoutManager; + private RecyclerView.LayoutManager layoutManager; private boolean isLoading = true; - private int PAGE_SIZE = 25; + private final int PAGE_SIZE = 25; @Inject SearchDepictionsFragmentPresenter presenter; - private final SearchDepictionsAdapterFactory adapterFactory = new SearchDepictionsAdapterFactory(new SearchDepictionsRenderer.DepictCallback() { - @Override - public void depictsClicked(DepictedItem item) { - WikidataItemDetailsActivity.startYourself(getContext(), item); - presenter.saveQuery(); - } - }); - private RVRendererAdapter depictionsAdapter; + private DepictionAdapter depictionsAdapter; private boolean isLastPage; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_browse_image, container, false); + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + final View rootView = inflater.inflate(R.layout.fragment_browse_image, container, false); ButterKnife.bind(this, rootView); if (getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { @@ -68,20 +64,25 @@ public class SearchDepictionsFragment extends CommonsDaggerSupportFragment imple layoutManager = new GridLayoutManager(getContext(), 2); } depictionsRecyclerView.setLayoutManager(layoutManager); - depictionsAdapter = adapterFactory.create(); + depictionsAdapter = new DepictionAdapter( + depictedItem -> { + WikidataItemDetailsActivity.startYourself(getContext(), depictedItem); + presenter.saveQuery(); + return Unit.INSTANCE; + }); depictionsRecyclerView.setAdapter(depictionsAdapter); depictionsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + public void onScrollStateChanged(final RecyclerView recyclerView, final int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override - public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) { super.onScrolled(recyclerView, dx, dy); - int visibleItemCount = layoutManager.getChildCount(); - int totalItemCount = layoutManager.getItemCount(); + final int visibleItemCount = layoutManager.getChildCount(); + final int totalItemCount = layoutManager.getItemCount(); int firstVisibleItemPosition=0; if(layoutManager instanceof GridLayoutManager){ firstVisibleItemPosition=((GridLayoutManager) layoutManager).findFirstVisibleItemPosition(); @@ -108,12 +109,12 @@ public class SearchDepictionsFragment extends CommonsDaggerSupportFragment imple /** * Fetch PAGE_SIZE number of items */ - private void loadMoreItems(boolean reInitialise) { + private void loadMoreItems(final boolean reInitialise) { presenter.updateDepictionList(presenter.getQuery(),PAGE_SIZE, reInitialise); } @Override - public void onAttach(Context context) { + public void onAttach(final Context context) { super.onAttach(context); presenter.onAttachView(this); } @@ -124,7 +125,7 @@ public class SearchDepictionsFragment extends CommonsDaggerSupportFragment imple * * @param query string searched in the Explore Activity */ - public void updateDepictionList(String query) { + public void updateDepictionList(final String query) { presenter.initializeQuery(query); if (!NetworkUtils.isInternetConnectionEstablished(getContext())) { handleNoInternet(); @@ -142,22 +143,10 @@ public class SearchDepictionsFragment extends CommonsDaggerSupportFragment imple progressBar.setVisibility(GONE); bottomProgressBar.setVisibility(GONE); depictionNotFound.setVisibility(VISIBLE); - String no_depiction = getString(R.string.depictions_not_found); + final String no_depiction = getString(R.string.depictions_not_found); depictionNotFound.setText(String.format(Locale.getDefault(), no_depiction, presenter.getQuery())); } - @Override - public void onDestroy() { - super.onDestroy(); - } - - @Override - public void onResume() { - super.onResume(); - depictionsAdapter.clear(); - depictionsRecyclerView.cancelPendingInputEvents(); - } - /** * Handles the UI updates for no internet scenario */ @@ -172,24 +161,18 @@ public class SearchDepictionsFragment extends CommonsDaggerSupportFragment imple * like hiding empty labels, hiding progressbar and notifying the apdapter that list of items has been fetched from the API */ @Override - public void onSuccess(List mediaList) { + public void onSuccess(final List mediaList) { isLoading = false; - progressBar.setVisibility(View.GONE); + progressBar.setVisibility(GONE); depictionNotFound.setVisibility(GONE); bottomProgressBar.setVisibility(GONE); - int itemCount = layoutManager.getItemCount(); depictionsAdapter.addAll(mediaList); - if(itemCount!=0) { - depictionsAdapter.notifyItemRangeInserted(itemCount, mediaList.size()-1); - }else{ - depictionsAdapter.notifyDataSetChanged(); - } } @Override - public void loadingDepictions(boolean isLoading) { + public void loadingDepictions(final boolean isLoading) { depictionNotFound.setVisibility(GONE); - bottomProgressBar.setVisibility(View.VISIBLE); + bottomProgressBar.setVisibility(VISIBLE); progressBar.setVisibility(GONE); this.isLoading = isLoading; } @@ -204,18 +187,13 @@ public class SearchDepictionsFragment extends CommonsDaggerSupportFragment imple ViewUtil.showShortSnackbar(depictionsRecyclerView, R.string.error_loading_depictions); } - @Override - public RVRendererAdapter getAdapter() { - return depictionsAdapter; - } - /** * Inform the view that there are no more items to be loaded for this search query * or reset the isLastPage for the current query * @param isLastPage */ @Override - public void setIsLastPage(boolean isLastPage) { + public void setIsLastPage(final boolean isLastPage) { this.isLastPage=isLastPage; progressBar.setVisibility(GONE); } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.java index 2524b39b3..8b041bb83 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.java @@ -1,11 +1,8 @@ package fr.free.nrw.commons.explore.depictions; -import com.pedrogomez.renderers.RVRendererAdapter; - -import java.util.List; - import fr.free.nrw.commons.BasePresenter; import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; +import java.util.List; /** * The contract with with SearchDepictionsFragment and its presenter would talk to each other @@ -44,11 +41,6 @@ public interface SearchDepictionsFragmentContract { */ void showSnackbar(); - /** - * @return adapter - */ - RVRendererAdapter getAdapter(); - /** * Inform the view that there are no more items to be loaded for this search query * or reset the isLastPage for the current query diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsRenderer.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsRenderer.java deleted file mode 100644 index 5490013b9..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsRenderer.java +++ /dev/null @@ -1,112 +0,0 @@ -package fr.free.nrw.commons.explore.depictions; - - -import android.graphics.Bitmap; -import android.net.Uri; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; -import androidx.annotation.Nullable; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.facebook.common.executors.CallerThreadExecutor; -import com.facebook.common.references.CloseableReference; -import com.facebook.datasource.DataSource; -import com.facebook.drawee.backends.pipeline.Fresco; -import com.facebook.imagepipeline.core.ImagePipeline; -import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber; -import com.facebook.imagepipeline.image.CloseableImage; -import com.facebook.imagepipeline.request.ImageRequest; -import com.facebook.imagepipeline.request.ImageRequestBuilder; -import com.pedrogomez.renderers.Renderer; -import fr.free.nrw.commons.R; -import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; - -/** - * Renderer for DepictedItem - */ -public class SearchDepictionsRenderer extends Renderer { - - @BindView(R.id.depicts_label) - TextView tvDepictionLabel; - - @BindView(R.id.description) - TextView tvDepictionDesc; - - @BindView(R.id.depicts_image) - ImageView imageView; - - private DepictCallback listener; - - public SearchDepictionsRenderer(DepictCallback 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(); - if (listener != null) { - listener.depictsClicked(item); - } - }); - } - - @Override - protected View inflate(LayoutInflater inflater, ViewGroup parent) { - return inflater.inflate(R.layout.item_depictions, parent, false); - } - - /** - * Render value to all the items in the search depictions list - */ - @Override - public void render() { - DepictedItem item = getContent(); - tvDepictionLabel.setText(item.getName()); - tvDepictionDesc.setText(item.getDescription()); - imageView.setImageDrawable(getContext().getResources().getDrawable(R.drawable.ic_wikidata_logo_24dp)); - - if (!TextUtils.isEmpty(item.getImageUrl())) { - ImageRequest imageRequest = ImageRequestBuilder - .newBuilderWithSource(Uri.parse(item.getImageUrl())) - .setAutoRotateEnabled(true) - .build(); - - ImagePipeline imagePipeline = Fresco.getImagePipeline(); - final DataSource> - dataSource = imagePipeline.fetchDecodedImage(imageRequest, getContext()); - - dataSource.subscribe(new BaseBitmapDataSubscriber() { - - @Override - public void onNewResultImpl(@Nullable Bitmap bitmap) { - if (dataSource.isFinished() && bitmap != null) { - //imageView.setImageBitmap(Bitmap.createBitmap(bitmap)); - imageView.post(() -> imageView.setImageBitmap(Bitmap.createBitmap(bitmap))); - dataSource.close(); - } - } - - @Override - public void onFailureImpl(DataSource dataSource) { - if (dataSource != null) { - dataSource.close(); - } - } - }, CallerThreadExecutor.getInstance()); - } - } - - public interface DepictCallback { - void depictsClicked(DepictedItem item); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java index ddfbdecdb..d1af331b3 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java @@ -17,7 +17,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.pedrogomez.renderers.RVRendererAdapter; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; @@ -33,9 +32,9 @@ import io.reactivex.schedulers.Schedulers; import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; +import kotlin.Unit; import timber.log.Timber; /** @@ -66,16 +65,9 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { */ private int mediaSize = 0; - private RVRendererAdapter imagesAdapter; + private SearchImagesAdapter imagesAdapter; private List queryList = new ArrayList<>(); - private final SearchImagesAdapterFactory adapterFactory = new SearchImagesAdapterFactory(item -> { - // Called on Click of a individual media Item - int index = queryList.indexOf(item); - ((SearchActivity)getContext()).onSearchImageClicked(index); - saveQuery(query); - }); - /** * This method saves Search Query in the Recent Searches Database. * @param query @@ -106,8 +98,11 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { else{ imagesRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2)); } - ArrayList items = new ArrayList<>(); - imagesAdapter = adapterFactory.create(items); + imagesAdapter =new SearchImagesAdapter(media -> { + ((SearchActivity)getContext()).onSearchImageClicked(imagesAdapter.getItems().indexOf(media)); + saveQuery(query); + return Unit.INSTANCE; + }); imagesRecyclerView.setAdapter(imagesAdapter); imagesRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -173,7 +168,6 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { if (mediaList.size() != 0 && !queryList.get(queryList.size() - 1).getFilename().equals(mediaList.get(mediaList.size() - 1).getFilename())) { queryList.addAll(mediaList); imagesAdapter.addAll(mediaList); - imagesAdapter.notifyDataSetChanged(); ((SearchActivity) getContext()).viewPagerNotifyDataSetChanged(); } } @@ -222,8 +216,7 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { private void handleLabelforImage(String s, int position) { if (!s.trim().equals(getString(R.string.detail_caption_empty))) { - imagesAdapter.getItem(position).setThumbnailTitle(s); - imagesAdapter.notifyDataSetChanged(); + imagesAdapter.updateThumbnail(position, s); } } @@ -281,13 +274,11 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { * @param i position of Media in the recyclerview adapter. */ public Media getImageAtPosition(int i) { - if (imagesAdapter.getItem(i).getFilename() == null) { + if (imagesAdapter.getItemAt(i).getFilename() == null) { // not yet ready to return data return null; } - else { - return imagesAdapter.getItem(i); - } + return imagesAdapter.getItemAt(i); } @Override public void onDestroyView() { diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapter.kt new file mode 100644 index 000000000..65e1510ec --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapter.kt @@ -0,0 +1,27 @@ +package fr.free.nrw.commons.explore.images + +import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter +import fr.free.nrw.commons.Media + +class SearchImagesAdapter(onImageClicked: (Media) -> Unit) : ListDelegationAdapter>( + searchImagesAdapter(onImageClicked) +) { + fun getItemAt(position: Int) = items[position] + + init { + items = emptyList() + } + + fun clear() { + items = emptyList() + } + + fun addAll(mediaList: List) { + items = items + mediaList + } + + fun updateThumbnail(position: Int, thumbnailTitle: String) { + items[position].thumbnailTitle = thumbnailTitle + notifyItemChanged(position) + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterDelegates.kt b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterDelegates.kt new file mode 100644 index 000000000..12feb4e50 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterDelegates.kt @@ -0,0 +1,24 @@ +package fr.free.nrw.commons.explore.images + +import android.view.View +import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer +import fr.free.nrw.commons.Media +import fr.free.nrw.commons.R +import kotlinx.android.synthetic.main.layout_category_images.* + + +fun searchImagesAdapter(onImageClicked: (Media) -> Unit) = + adapterDelegateLayoutContainer(R.layout.layout_category_images) { + categoryImageView.setOnClickListener { onImageClicked(item) } + bind { + categoryImageTitle.text = item.thumbnailTitle + categoryImageView.setImageURI(item.thumbUrl) + if (item.creator?.isNotEmpty() == true) { + categoryImageAuthor.visibility = View.VISIBLE + categoryImageAuthor.text = getString(R.string.image_uploaded_by, item.creator) + } else { + categoryImageAuthor.visibility = View.GONE + } + } + + } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterFactory.java deleted file mode 100644 index 94930e261..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesAdapterFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.free.nrw.commons.explore.images; - -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.Media; - -/** - * This class helps in creating adapter for imagesRecyclerView in SearchImagesFragment, - * implementing onClicks on imagesRecyclerView Items - **/ -class SearchImagesAdapterFactory { - private final SearchImagesRenderer.ImageClickedListener listener; - - SearchImagesAdapterFactory(SearchImagesRenderer.ImageClickedListener listener) { - this.listener = listener; - } - - /** - * This method creates a recyclerViewAdapter for Media. - * @param searchImageItemList List of Media objects to be displayed - * @return imagesAdapter - **/ - public RVRendererAdapter create(List searchImageItemList) { - RendererBuilder builder = new RendererBuilder() - .bind(Media.class, new SearchImagesRenderer(listener)); - ListAdapteeCollection collection = new ListAdapteeCollection<>( - searchImageItemList != null ? searchImageItemList : Collections.emptyList()); - return new RVRendererAdapter<>(builder, collection); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java deleted file mode 100644 index 8985a8484..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java +++ /dev/null @@ -1,74 +0,0 @@ -package fr.free.nrw.commons.explore.images; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.facebook.drawee.view.SimpleDraweeView; -import com.pedrogomez.renderers.Renderer; - -import butterknife.BindView; -import butterknife.ButterKnife; -import fr.free.nrw.commons.Media; -import fr.free.nrw.commons.R; - -/** - * presentation logic of individual image in search is handled here - **/ -class SearchImagesRenderer extends Renderer { - @BindView(R.id.categoryImageTitle) TextView tvImageName; - @BindView(R.id.categoryImageAuthor) TextView categoryImageAuthor; - @BindView(R.id.categoryImageView) SimpleDraweeView browseImage; - - private final ImageClickedListener listener; - - SearchImagesRenderer(ImageClickedListener listener) { - this.listener = listener; - } - - @Override - protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { - return layoutInflater.inflate(R.layout.layout_category_images, viewGroup, false); - } - - @Override - protected void setUpView(View view) { - ButterKnife.bind(this, view); - } - - @Override - protected void hookListeners(View view) { - view.setOnClickListener(v -> { - Media item = getContent(); - if (listener != null) { - listener.imageClicked(item); - } - }); - } - - @Override - public void render() { - Media item = getContent(); - tvImageName.setText(item.getThumbnailTitle()); - browseImage.setImageURI(item.getThumbUrl()); - setAuthorView(item, categoryImageAuthor); - } - - interface ImageClickedListener { - void imageClicked(Media item); - } - - /** - * formats author name as "Uploaded by: authorName" and sets it in textview - */ - private void setAuthorView(Media item, TextView author) { - if (item.getCreator() != null && !item.getCreator().equals("")) { - author.setVisibility(View.VISIBLE); - String uploadedByTemplate = getContext().getString(R.string.image_uploaded_by); - author.setText(String.format(uploadedByTemplate, item.getCreator())); - } else { - author.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java index fd511c176..e3a132b81 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java @@ -2,6 +2,7 @@ package fr.free.nrw.commons.media; import static android.view.View.GONE; import static android.view.View.VISIBLE; +import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_PREFIX; import android.annotation.SuppressLint; import android.app.AlertDialog; @@ -49,7 +50,6 @@ import fr.free.nrw.commons.delete.ReasonBuilder; import fr.free.nrw.commons.depictions.WikidataItemDetailsActivity; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.ui.widget.HtmlTextView; -import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; import fr.free.nrw.commons.utils.ViewUtilWrapper; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -619,7 +619,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { if (categoriesLoaded && categoriesPresent) { textView.setOnClickListener(view -> { // Open Category Details page - String selectedCategoryTitle = "Category:" + catName; + String selectedCategoryTitle = CATEGORY_PREFIX + catName; Intent intent = new Intent(getContext(), CategoryDetailsActivity.class); intent.putExtra("categoryName", selectedCategoryTitle); getContext().startActivity(intent); diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/CategoryApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/CategoryApi.java index 20aeb516f..199237951 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/CategoryApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/CategoryApi.java @@ -1,25 +1,23 @@ package fr.free.nrw.commons.mwapi; +import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_PREFIX; + import com.google.gson.Gson; - -import org.wikipedia.dataclient.mwapi.MwQueryPage; -import org.wikipedia.dataclient.mwapi.MwQueryResponse; - +import io.reactivex.Single; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; - import javax.inject.Inject; import javax.inject.Named; - -import io.reactivex.Single; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; +import org.wikipedia.dataclient.mwapi.MwQueryPage; +import org.wikipedia.dataclient.mwapi.MwQueryResponse; import timber.log.Timber; /** @@ -60,7 +58,7 @@ public class CategoryApi { for (MwQueryPage page : apiResponse.query().pages()) { if (page.categories() != null) { for (MwQueryPage.Category category : page.categories()) { - categories.add(category.title().replace("Category:", "")); + categories.add(category.title().replace(CATEGORY_PREFIX, "")); } } } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java deleted file mode 100644 index 3f4dacd84..000000000 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java +++ /dev/null @@ -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 create(List placeList) { - return create(placeList, null); - } - - public RVRendererAdapter create( - List placeList, - PlaceRenderer.OnBookmarkClick onBookmarkClick - ) { - RendererBuilder builder = new RendererBuilder() - .bind(Place.class, new PlaceRenderer(fragment, controller, onBookmarkClick)); - ListAdapteeCollection collection = new ListAdapteeCollection<>( - placeList != null ? placeList : Collections.emptyList()); - return new RVRendererAdapter<>(builder, collection); - } - - public void updateAdapterData(List newPlaceList, RVRendererAdapter rendererAdapter) { - rendererAdapter.notifyDataSetChanged(); - rendererAdapter.diffUpdate(newPlaceList); - } - - public void clear(RVRendererAdapter rendererAdapter){ - rendererAdapter.clear(); - } - - public void add(Place place, RVRendererAdapter rendererAdapter){ - rendererAdapter.add(place); - } - - public void update(RVRendererAdapter rendererAdapter){ - rendererAdapter.notifyDataSetChanged(); - } - -} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceAdapterDelegate.kt b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceAdapterDelegate.kt new file mode 100644 index 000000000..eaf32a48b --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceAdapterDelegate.kt @@ -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(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) } + bookmarkButtonImage.setOnClickListener { + val isBookmarked = bookmarkLocationDao.updateBookmarkLocation(item) + bookmarkButtonImage.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 + + bookmarkButtonImage.setImageResource( + if (bookmarkLocationDao.findBookmarkLocation(item)) + R.drawable.ic_round_star_filled_24px + else + R.drawable.ic_round_star_border_24px + ) + } + } + +private fun AdapterDelegateLayoutContainerViewHolder.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) + } + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java deleted file mode 100644 index 8a53f78d8..000000000 --- a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java +++ /dev/null @@ -1,289 +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 { - - @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.bookmarkButtonImage) ImageView bookmarkButtonImage; - - @BindView(R.id.directionsButtonText) TextView directionsButtonText; - @BindView(R.id.iconOverflowText) TextView iconOverflowText; - - private View view; - private static ArrayList 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); - } - }); - - bookmarkButtonImage.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)).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(); - } - -} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt new file mode 100644 index 000000000..15186de56 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt @@ -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() + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java index 91792b035..5173d66f9 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java @@ -9,7 +9,6 @@ import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween; import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT; import android.Manifest; -import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -39,6 +38,8 @@ import android.widget.Toast; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -68,7 +69,6 @@ import com.mapbox.mapboxsdk.maps.Style; import com.mapbox.mapboxsdk.maps.UiSettings; import com.mapbox.pluginscalebar.ScaleBarOptions; import com.mapbox.pluginscalebar.ScaleBarPlugin; -import com.pedrogomez.renderers.RVRendererAdapter; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; @@ -76,6 +76,7 @@ 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.MainActivity; +import fr.free.nrw.commons.di.ApplicationlessInjection; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.location.LocationServiceManager; @@ -83,7 +84,6 @@ import fr.free.nrw.commons.location.LocationUpdateListener; 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.NearbyAdapterFactory; import fr.free.nrw.commons.nearby.NearbyBaseMarker; import fr.free.nrw.commons.nearby.NearbyController; import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter; @@ -105,12 +105,14 @@ 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.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; @@ -163,6 +165,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment @Inject SystemThemeUtils systemThemeUtils; + @Inject + CommonPlaceClickActions commonPlaceClickActions; private NearbyFilterSearchRecyclerViewAdapter nearbyFilterSearchRecyclerViewAdapter; @@ -176,7 +180,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment private static final float ZOOM_LEVEL = 14f; private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; private BroadcastReceiver broadcastReceiver; - private boolean isNetworkErrorOccurred = false; + private boolean isNetworkErrorOccurred; private Snackbar snackbar; private View view; private NearbyParentFragmentPresenter presenter; @@ -188,25 +192,22 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.005; private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.004; - private boolean isMapBoxReady=false; + private boolean isMapBoxReady; private MapboxMap mapBox; IntentFilter intentFilter = new IntentFilter(NETWORK_INTENT_ACTION); private Marker currentLocationMarker; private Polygon currentLocationPolygon; private Place lastPlaceToCenter; 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 MapboxMap.OnCameraMoveListener cameraMoveListener; private fr.free.nrw.commons.location.LatLng lastFocusLocation; private LatLngBounds latLngBounds; - + private PlaceAdapter adapter; @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container, + final Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_nearby_parent, container, false); ButterKnife.bind(this, view); initNetworkBroadCastReceiver(); @@ -217,7 +218,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment } @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); isDarkTheme = systemThemeUtils.isDeviceInNightMode(); cameraMoveListener= () -> presenter.onCameraMove(mapBox.getCameraPosition().target); @@ -227,28 +228,28 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment initThemePreferences(); mapView.onCreate(savedInstanceState); mapView.getMapAsync(mapBoxMap -> { - this.mapBox=mapBoxMap; + mapBox =mapBoxMap; initViews(); presenter.setActionListeners(applicationKvStore); initNearbyFilter(); mapBoxMap.setStyle(isDarkTheme?Style.DARK:Style.OUTDOORS, style -> { - UiSettings uiSettings = mapBoxMap.getUiSettings(); + final UiSettings uiSettings = mapBoxMap.getUiSettings(); uiSettings.setCompassGravity(Gravity.BOTTOM | Gravity.LEFT); uiSettings.setCompassMargins(12, 0, 0, 24); uiSettings.setLogoEnabled(true); uiSettings.setAttributionEnabled(true); uiSettings.setRotateGesturesEnabled(false); - NearbyParentFragment.this.isMapBoxReady=true; + isMapBoxReady =true; performMapReadyActions(); - CameraPosition cameraPosition = new CameraPosition.Builder() + final CameraPosition cameraPosition = new CameraPosition.Builder() .target(new LatLng(51.50550, -0.07520)) .zoom(ZOOM_LEVEL) .build(); mapBoxMap.setCameraPosition(cameraPosition); - ScaleBarPlugin scaleBarPlugin = new ScaleBarPlugin(mapView, mapBoxMap); - int color = isDarkTheme ? R.color.bottom_bar_light : R.color.bottom_bar_dark; - ScaleBarOptions scaleBarOptions = new ScaleBarOptions(getContext()) + final ScaleBarPlugin scaleBarPlugin = new ScaleBarPlugin(mapView, mapBoxMap); + final int color = isDarkTheme ? R.color.bottom_bar_light : R.color.bottom_bar_dark; + final ScaleBarOptions scaleBarOptions = new ScaleBarOptions(getContext()) .setTextColor(color) .setTextSize(R.dimen.description_text_size) .setBarHeight(R.dimen.tiny_gap) @@ -280,8 +281,18 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment private void initRvNearbyList() { rvNearbyList.setLayoutManager(new LinearLayoutManager(getContext())); - adapterFactory = new NearbyAdapterFactory(this, controller); - rvNearbyList.setAdapter(adapterFactory.create(null)); + adapter = new PlaceAdapter(bookmarkLocationDao, + place -> { + centerMapToPlace(place); + return Unit.INSTANCE; + }, + (place, isBookmarked) -> { + updateMarker(isBookmarked, place, null); + return Unit.INSTANCE; + }, + commonPlaceClickActions + ); + rvNearbyList.setAdapter(adapter); } private void addCheckBoxCallback() { @@ -291,13 +302,13 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment private void performMapReadyActions() { if (isVisible() && isVisibleToUser && isMapBoxReady) { checkPermissionsAndPerformAction(() -> { - this.lastKnownLocation = locationManager.getLastLocation(); + lastKnownLocation = locationManager.getLastLocation(); fr.free.nrw.commons.location.LatLng target=lastFocusLocation; if(null==lastFocusLocation){ target=lastKnownLocation; } if (lastKnownLocation != null) { - CameraPosition position = new CameraPosition.Builder() + final CameraPosition position = new CameraPosition.Builder() .target(LocationUtils.commonsLatLngToMapBoxLatLng(target)) // Sets the new camera position .zoom(ZOOM_LEVEL) // Same zoom level .build(); @@ -324,8 +335,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment } private void registerNetworkReceiver() { - if (getActivity() != null) + if (getActivity() != null) { getActivity().registerReceiver(broadcastReceiver, intentFilter); + } } @@ -348,7 +360,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment if (null != mapBox) { mapBox.removeOnCameraMoveListener(cameraMoveListener); } - }catch (Exception e){ + }catch (final Exception e){ Timber.e(e); //Broadcast receivers should always be unregistered inside catch, you never know if they were already registered or not } @@ -361,7 +373,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment } @Override - public void onSaveInstanceState(Bundle outState) { + public void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } @@ -414,7 +426,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL)); - LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); + final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(linearLayoutManager); @@ -426,7 +438,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment } @Override - public void filterByMarkerType(ArrayList