mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-30 22:34:02 +01:00 
			
		
		
		
	* #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
This commit is contained in:
		
							parent
							
								
									82d662c8ef
								
							
						
					
					
						commit
						b063d6bdfd
					
				
					 61 changed files with 851 additions and 1609 deletions
				
			
		|  | @ -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; | ||||
|  |  | |||
|  | @ -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<Place> places = controller.loadFavoritesLocations(); | ||||
|         adapterFactory.updateAdapterData(places, (RVRendererAdapter<Place>) recyclerView.getAdapter()); | ||||
|         adapter.setItems(places); | ||||
|         progressBar.setVisibility(View.GONE); | ||||
|         if (places.size() <= 0) { | ||||
|             statusTextView.setText(R.string.bookmark_empty); | ||||
|  |  | |||
|  | @ -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<CategoryItem> { | ||||
|     @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()); | ||||
|     } | ||||
| } | ||||
|  | @ -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, "") } | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<String> 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<String> 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)); | ||||
|  |  | |||
|  | @ -40,6 +40,7 @@ public class DepictedImagesPresenter implements DepictedImagesContract.UserActio | |||
|      * Ex: Q9394 | ||||
|      */ | ||||
|     private List<Media> 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); | ||||
|  |  | |||
|  | @ -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<DepictedItem> 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 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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!! | ||||
| } | ||||
|  | @ -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<Application | |||
|     @Override | ||||
|     void inject(ApplicationlessInjection instance); | ||||
| 
 | ||||
|     void inject(PlaceRenderer placeRenderer); | ||||
| 
 | ||||
|     void inject(FileProcessor fileProcessor); | ||||
| 
 | ||||
|     void inject(PicOfDayAppWidget picOfDayAppWidget); | ||||
|  |  | |||
|  | @ -72,13 +72,13 @@ public abstract class FragmentBuilderModule { | |||
|     @ContributesAndroidInjector | ||||
|     abstract ContributionsFragment bindContributionsFragment(); | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     @ContributesAndroidInjector(modules = NearbyParentFragmentModule.class) | ||||
|     abstract NearbyParentFragment bindNearbyParentFragment(); | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     abstract BookmarkPicturesFragment bindBookmarkPictureListFragment(); | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     @ContributesAndroidInjector(modules = BookmarkLocationsFragmentModule.class) | ||||
|     abstract BookmarkLocationsFragment bindBookmarkLocationListFragment(); | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|  |  | |||
|  | @ -0,0 +1,13 @@ | |||
| package fr.free.nrw.commons.di | ||||
| 
 | ||||
| import android.app.Activity | ||||
| import dagger.Module | ||||
| import dagger.Provides | ||||
| import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment | ||||
| 
 | ||||
| @Module | ||||
| class NearbyParentFragmentModule{ | ||||
| 
 | ||||
|     @Provides | ||||
|     fun NearbyParentFragment.providesActivity(): Activity = activity!! | ||||
| } | ||||
|  | @ -5,23 +5,16 @@ import android.text.TextUtils; | |||
| import android.view.View; | ||||
| import android.widget.FrameLayout; | ||||
| import android.widget.SearchView; | ||||
| 
 | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import androidx.fragment.app.Fragment; | ||||
| import androidx.fragment.app.FragmentManager; | ||||
| import androidx.fragment.app.FragmentTransaction; | ||||
| import androidx.viewpager.widget.ViewPager; | ||||
| 
 | ||||
| import butterknife.BindView; | ||||
| import butterknife.ButterKnife; | ||||
| import com.google.android.material.tabs.TabLayout; | ||||
| import com.jakewharton.rxbinding2.view.RxView; | ||||
| import com.jakewharton.rxbinding2.widget.RxSearchView; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| 
 | ||||
| import butterknife.BindView; | ||||
| import butterknife.ButterKnife; | ||||
| import fr.free.nrw.commons.Media; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.category.CategoryImagesCallback; | ||||
|  | @ -34,6 +27,10 @@ import fr.free.nrw.commons.theme.NavigationBaseActivity; | |||
| import fr.free.nrw.commons.utils.FragmentUtils; | ||||
| import fr.free.nrw.commons.utils.ViewUtil; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| /** | ||||
|  * Represents search screen of this app | ||||
|  | @ -111,35 +108,35 @@ public class SearchActivity extends NavigationBaseActivity | |||
|                 .takeUntil(RxView.detaches(searchView)) | ||||
|                 .debounce(500, TimeUnit.MILLISECONDS) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .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); | ||||
|                 .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 | ||||
|                 )); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<String>( | ||||
|     searchCategoryDelegate(onCateoryClicked), | ||||
|     areItemsTheSame = { oldItem, newItem -> oldItem == newItem } | ||||
| ) | ||||
|  | @ -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<String, String>(R.layout.item_recent_searches) { | ||||
|         containerView.setOnClickListener { onCategoryClicked(item) } | ||||
|         bind { | ||||
|             textView1.text = item.substringAfter(CATEGORY_PREFIX) | ||||
|         } | ||||
|     } | ||||
|  | @ -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<String> create(List<String> searchImageItemList) { | ||||
|         RendererBuilder<String> builder = new RendererBuilder<String>().bind(String.class, new SearchCategoriesRenderer(listener)); | ||||
|         ListAdapteeCollection<String> collection = new ListAdapteeCollection<>( | ||||
|                 searchImageItemList != null ? searchImageItemList : Collections.<String>emptyList()); | ||||
|         return new RVRendererAdapter<>(builder, collection); | ||||
|     } | ||||
| } | ||||
|  | @ -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<String> { | ||||
|     @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); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -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<String> categoriesAdapter; | ||||
|     private SearchCategoriesAdapter categoriesAdapter; | ||||
|     private List<String> 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<String> 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(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<DepictedItem>( | ||||
|     depictionDelegate(clickListener), | ||||
|     areItemsTheSame = { oldItem, newItem -> oldItem.id == newItem.id } | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -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<DepictedItem, DepictedItem>(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) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -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<SparqlResponse>): Observable<List<DepictedItem>> { | ||||
|         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) } | ||||
|     } | ||||
|  |  | |||
|  | @ -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<DepictedItem> create() { | ||||
|         List<DepictedItem> searchImageItemList = new ArrayList<>(); | ||||
|         RendererBuilder<DepictedItem> builder = new RendererBuilder<DepictedItem>().bind(DepictedItem.class, new SearchDepictionsRenderer(listener)); | ||||
|         ListAdapteeCollection<DepictedItem> collection = new ListAdapteeCollection<>( | ||||
|                 searchImageItemList != null ? searchImageItemList : Collections.<DepictedItem>emptyList()); | ||||
|         return new RVRendererAdapter<>(builder, collection); | ||||
|     } | ||||
| } | ||||
|  | @ -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<DepictedItem> 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<DepictedItem> mediaList) { | ||||
|     public void onSuccess(final List<DepictedItem> 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<DepictedItem> 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); | ||||
|     } | ||||
|  |  | |||
|  | @ -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<DepictedItem> 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 | ||||
|  |  | |||
|  | @ -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<DepictedItem> { | ||||
| 
 | ||||
|     @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<CloseableReference<CloseableImage>> | ||||
|                         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); | ||||
|     } | ||||
| } | ||||
|  | @ -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<Media> imagesAdapter; | ||||
|     private SearchImagesAdapter imagesAdapter; | ||||
|     private List<Media> 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<Media> 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() { | ||||
|  |  | |||
|  | @ -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<List<Media>>( | ||||
|     searchImagesAdapter(onImageClicked) | ||||
| ) { | ||||
|     fun getItemAt(position: Int) = items[position] | ||||
| 
 | ||||
|     init { | ||||
|         items = emptyList() | ||||
|     } | ||||
| 
 | ||||
|     fun clear() { | ||||
|         items = emptyList() | ||||
|     } | ||||
| 
 | ||||
|     fun addAll(mediaList: List<Media>) { | ||||
|         items = items + mediaList | ||||
|     } | ||||
| 
 | ||||
|     fun updateThumbnail(position: Int, thumbnailTitle: String) { | ||||
|         items[position].thumbnailTitle = thumbnailTitle | ||||
|         notifyItemChanged(position) | ||||
|     } | ||||
| } | ||||
|  | @ -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<Media, Media>(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 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|  | @ -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<Media> create(List<Media> searchImageItemList) { | ||||
|         RendererBuilder<Media> builder = new RendererBuilder<Media>() | ||||
|                 .bind(Media.class, new SearchImagesRenderer(listener)); | ||||
|         ListAdapteeCollection<Media> collection = new ListAdapteeCollection<>( | ||||
|                 searchImageItemList != null ? searchImageItemList : Collections.<Media>emptyList()); | ||||
|         return new RVRendererAdapter<>(builder, collection); | ||||
|     } | ||||
| } | ||||
|  | @ -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<Media> { | ||||
|     @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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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, "")); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  |  | |||
|  | @ -1,57 +0,0 @@ | |||
| package fr.free.nrw.commons.nearby; | ||||
| 
 | ||||
| 
 | ||||
| import androidx.fragment.app.Fragment; | ||||
| 
 | ||||
| import com.pedrogomez.renderers.ListAdapteeCollection; | ||||
| import com.pedrogomez.renderers.RVRendererAdapter; | ||||
| import com.pedrogomez.renderers.RendererBuilder; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import fr.free.nrw.commons.contributions.ContributionController; | ||||
| 
 | ||||
| public class NearbyAdapterFactory { | ||||
| 
 | ||||
|     private Fragment fragment; | ||||
|     private ContributionController controller; | ||||
| 
 | ||||
|     public NearbyAdapterFactory(Fragment fragment, ContributionController controller) { | ||||
|         this.fragment = fragment; | ||||
|         this.controller = controller; | ||||
|     } | ||||
| 
 | ||||
|     public RVRendererAdapter<Place> create(List<Place> placeList) { | ||||
|         return create(placeList, null); | ||||
|     } | ||||
| 
 | ||||
|     public RVRendererAdapter<Place> create( | ||||
|             List<Place> placeList, | ||||
|             PlaceRenderer.OnBookmarkClick onBookmarkClick | ||||
|     ) { | ||||
|         RendererBuilder<Place> builder = new RendererBuilder<Place>() | ||||
|                 .bind(Place.class, new PlaceRenderer(fragment, controller, onBookmarkClick)); | ||||
|         ListAdapteeCollection<Place> collection = new ListAdapteeCollection<>( | ||||
|                 placeList != null ? placeList : Collections.emptyList()); | ||||
|         return new RVRendererAdapter<>(builder, collection); | ||||
|     } | ||||
| 
 | ||||
|     public void updateAdapterData(List<Place> newPlaceList, RVRendererAdapter<Place> rendererAdapter) { | ||||
|         rendererAdapter.notifyDataSetChanged(); | ||||
|         rendererAdapter.diffUpdate(newPlaceList); | ||||
|     } | ||||
| 
 | ||||
|     public void clear(RVRendererAdapter<Place> rendererAdapter){ | ||||
|         rendererAdapter.clear(); | ||||
|     } | ||||
| 
 | ||||
|     public void add(Place place, RVRendererAdapter<Place> rendererAdapter){ | ||||
|         rendererAdapter.add(place); | ||||
|     } | ||||
| 
 | ||||
|     public void update(RVRendererAdapter<Place> rendererAdapter){ | ||||
|         rendererAdapter.notifyDataSetChanged(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,84 @@ | |||
| package fr.free.nrw.commons.nearby | ||||
| 
 | ||||
| import android.view.View | ||||
| import android.view.View.* | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import androidx.transition.TransitionManager | ||||
| import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateLayoutContainerViewHolder | ||||
| import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer | ||||
| import fr.free.nrw.commons.R | ||||
| import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao | ||||
| import kotlinx.android.synthetic.main.item_place.* | ||||
| import kotlinx.android.synthetic.main.nearby_row_button.* | ||||
| 
 | ||||
| 
 | ||||
| fun placeAdapterDelegate( | ||||
|     bookmarkLocationDao: BookmarkLocationsDao, | ||||
|     onItemClick: ((Place) -> Unit)? = null, | ||||
|     onCameraClicked: (Place) -> Unit, | ||||
|     onGalleryClicked: (Place) -> Unit, | ||||
|     onBookmarkClicked: (Place, Boolean) -> Unit, | ||||
|     onOverflowIconClicked: (Place, View) -> Unit, | ||||
|     onDirectionsClicked: (Place) -> Unit | ||||
| ) = | ||||
|     adapterDelegateLayoutContainer<Place, Place>(R.layout.item_place) { | ||||
|         containerView.setOnClickListener { _: View? -> | ||||
|             showOrHideAndScrollToIfLast() | ||||
|             onItemClick?.invoke(item) | ||||
|         } | ||||
|         containerView.setOnFocusChangeListener { view1: View?, hasFocus: Boolean -> | ||||
|             if (!hasFocus && buttonLayout.isShown) { | ||||
|                 buttonLayout.visibility = GONE | ||||
|             } else if (hasFocus && !buttonLayout.isShown) { | ||||
|                 showOrHideAndScrollToIfLast() | ||||
|                 onItemClick?.invoke(item) | ||||
|             } | ||||
|         } | ||||
|         cameraButton.setOnClickListener { onCameraClicked(item) } | ||||
|         galleryButton.setOnClickListener { onGalleryClicked(item) } | ||||
|         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<Place>.showOrHideAndScrollToIfLast() { | ||||
|     TransitionManager.beginDelayedTransition(buttonLayout) | ||||
|     if (buttonLayout.isShown) { | ||||
|         buttonLayout.visibility = GONE | ||||
|     } else { | ||||
|         buttonLayout.visibility = VISIBLE | ||||
|         val recyclerView = containerView.parent as RecyclerView | ||||
|         val lastPosition = recyclerView.adapter!!.itemCount - 1 | ||||
|         if (recyclerView.getChildLayoutPosition(containerView) == lastPosition) { | ||||
|             (recyclerView.layoutManager as LinearLayoutManager?) | ||||
|                 ?.scrollToPositionWithOffset(lastPosition, buttonLayout.height) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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<Place> { | ||||
| 
 | ||||
|     @BindView(R.id.tvName) TextView tvName; | ||||
|     @BindView(R.id.tvDesc) TextView tvDesc; | ||||
|     @BindView(R.id.distance) TextView distance; | ||||
|     @BindView(R.id.icon) SimpleDraweeView icon; | ||||
|     @BindView(R.id.buttonLayout) LinearLayout buttonLayout; | ||||
|     @BindView(R.id.cameraButton) LinearLayout cameraButton; | ||||
| 
 | ||||
|     @BindView(R.id.galleryButton) LinearLayout galleryButton; | ||||
|     @BindView(R.id.directionsButton) LinearLayout directionsButton; | ||||
|     @BindView(R.id.iconOverflow) LinearLayout iconOverflow; | ||||
|     @BindView(R.id.cameraButtonText) TextView cameraButtonText; | ||||
|     @BindView(R.id.galleryButtonText) TextView galleryButtonText; | ||||
|     @BindView(R.id.bookmarkButtonImage) ImageView bookmarkButtonImage; | ||||
| 
 | ||||
|     @BindView(R.id.directionsButtonText) TextView directionsButtonText; | ||||
|     @BindView(R.id.iconOverflowText) TextView iconOverflowText; | ||||
| 
 | ||||
|     private View view; | ||||
|     private static ArrayList<LinearLayout> openedItems; | ||||
|     private Place place; | ||||
| 
 | ||||
|     private Fragment fragment; | ||||
|     private ContributionController controller; | ||||
|     private OnBookmarkClick onBookmarkClick; | ||||
| 
 | ||||
|     @Inject BookmarkLocationsDao bookmarkLocationDao; | ||||
|     @Inject | ||||
|     @Named("default_preferences") | ||||
|     JsonKvStore applicationKvStore; | ||||
| 
 | ||||
|     public PlaceRenderer(){ | ||||
|         openedItems = new ArrayList<>(); | ||||
|     } | ||||
| 
 | ||||
|     public PlaceRenderer( | ||||
|             Fragment fragment, | ||||
|             ContributionController controller, | ||||
|             OnBookmarkClick onBookmarkClick | ||||
|     ) { | ||||
|         this.fragment = fragment; | ||||
|         this.controller = controller; | ||||
|         openedItems = new ArrayList<>(); | ||||
|         this.onBookmarkClick = onBookmarkClick; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { | ||||
|         view = layoutInflater.inflate(R.layout.item_place, viewGroup, false); | ||||
|         return view; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void setUpView(View view) { | ||||
|         ButterKnife.bind(this, view); | ||||
|         closeLayout(buttonLayout); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void hookListeners(View view) { | ||||
| 
 | ||||
|         final View.OnClickListener listener = view12 -> { | ||||
|             Timber.d("Renderer clicked"); | ||||
|             TransitionManager.beginDelayedTransition(buttonLayout); | ||||
| 
 | ||||
|             if (buttonLayout.isShown()) { | ||||
|                 closeLayout(buttonLayout); | ||||
|             } else { | ||||
|                 openLayout(buttonLayout); | ||||
|                 RecyclerView recyclerView = (RecyclerView) view.getParent(); | ||||
|                 int lastPosition = recyclerView.getAdapter().getItemCount() - 1; | ||||
|                 if (recyclerView.getChildLayoutPosition(view) == lastPosition) { | ||||
|                     ((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(lastPosition, buttonLayout.getHeight()); | ||||
|                 } | ||||
|             } | ||||
|             if (onBookmarkClick == null) { | ||||
|                 ((NearbyParentFragment) fragment).centerMapToPlace(place); | ||||
|             } | ||||
|         }; | ||||
|         view.setOnClickListener(listener); | ||||
| 
 | ||||
|         view.requestFocus(); | ||||
|         view.setOnFocusChangeListener((view1, hasFocus) -> { | ||||
|             if (!hasFocus && buttonLayout.isShown()) { | ||||
|                 closeLayout(buttonLayout); | ||||
|             } else if (hasFocus && !buttonLayout.isShown()) { | ||||
|                 listener.onClick(view1); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         cameraButton.setOnClickListener(view2 -> { | ||||
|             if (applicationKvStore.getBoolean("login_skipped", false)) { | ||||
|                 // prompt the user to login | ||||
|                 new AlertDialog.Builder(getContext()) | ||||
|                         .setMessage(R.string.login_alert_message) | ||||
|                         .setPositiveButton(R.string.login, (dialog, which) -> { | ||||
|                             startActivityWithFlags( getContext(), LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP, | ||||
|                                     Intent.FLAG_ACTIVITY_SINGLE_TOP); | ||||
|                             applicationKvStore.putBoolean("login_skipped", false); | ||||
|                             fragment.getActivity().finish(); | ||||
|                         }) | ||||
|                         .show(); | ||||
|             } else { | ||||
|                 Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription()); | ||||
|                 storeSharedPrefs(); | ||||
|                 controller.initiateCameraPick(fragment.getActivity()); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
| 
 | ||||
|         galleryButton.setOnClickListener(view3 -> { | ||||
|             if (applicationKvStore.getBoolean("login_skipped", false)) { | ||||
|                 // prompt the user to login | ||||
|                 new AlertDialog.Builder(getContext()) | ||||
|                         .setMessage(R.string.login_alert_message) | ||||
|                         .setPositiveButton(R.string.login, (dialog, which) -> { | ||||
|                             startActivityWithFlags( getContext(), LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP, | ||||
|                                     Intent.FLAG_ACTIVITY_SINGLE_TOP); | ||||
|                             applicationKvStore.putBoolean("login_skipped", false); | ||||
|                             fragment.getActivity().finish(); | ||||
|                         }) | ||||
|                         .show(); | ||||
|             }else { | ||||
|                 Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription()); | ||||
|                 storeSharedPrefs(); | ||||
|                 controller.initiateGalleryPick(fragment.getActivity(), false); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         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(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -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() | ||||
|     } | ||||
| } | ||||
|  | @ -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<Label> selectedLabels, int i, boolean b, boolean b1) { | ||||
|             public void filterByMarkerType(final ArrayList<Label> selectedLabels, final int i, final boolean b, final boolean b1) { | ||||
|                 presenter.filterByMarkerType(selectedLabels,i,b,b1); | ||||
|             } | ||||
| 
 | ||||
|  | @ -456,7 +468,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setCheckBoxState(int state) { | ||||
|     public void setCheckBoxState(final int state) { | ||||
|         checkBoxTriStates.setState(state); | ||||
|     } | ||||
| 
 | ||||
|  | @ -511,12 +523,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         bottomSheetDetailsBehavior.setBottomSheetCallback(new BottomSheetBehavior | ||||
|                 .BottomSheetCallback() { | ||||
|             @Override | ||||
|             public void onStateChanged(@NonNull View bottomSheet, int newState) { | ||||
|             public void onStateChanged(@NonNull final View bottomSheet, final int newState) { | ||||
|                 prepareViewsForSheetPosition(newState); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onSlide(@NonNull View bottomSheet, float slideOffset) { | ||||
|             public void onSlide(@NonNull final View bottomSheet, final float slideOffset) { | ||||
| 
 | ||||
|             } | ||||
|         }); | ||||
|  | @ -536,14 +548,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         bottomSheetListBehavior.setBottomSheetCallback(new BottomSheetBehavior | ||||
|                 .BottomSheetCallback() { | ||||
|             @Override | ||||
|             public void onStateChanged(@NonNull View bottomSheet, int newState) { | ||||
|             public void onStateChanged(@NonNull final View bottomSheet, final int newState) { | ||||
|                 if (newState == BottomSheetBehavior.STATE_EXPANDED) { | ||||
|                     bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onSlide(@NonNull View bottomSheet, float slideOffset) { | ||||
|             public void onSlide(@NonNull final View bottomSheet, final float slideOffset) { | ||||
| 
 | ||||
|             } | ||||
|         }); | ||||
|  | @ -597,21 +609,21 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * Centers the map in nearby fragment to a given place | ||||
|      * @param place is new center of the map | ||||
|      */ | ||||
|     public void centerMapToPlace(Place place) { | ||||
|     public void centerMapToPlace(final Place place) { | ||||
|         Timber.d("Map is centered to place"); | ||||
|         double cameraShift; | ||||
|         final double cameraShift; | ||||
|         if(null!=place){ | ||||
|             lastPlaceToCenter=place; | ||||
|         } | ||||
| 
 | ||||
|         if (null != lastPlaceToCenter) { | ||||
|             Configuration configuration = getActivity().getResources().getConfiguration(); | ||||
|             final Configuration configuration = getActivity().getResources().getConfiguration(); | ||||
|             if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { | ||||
|                 cameraShift = CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT; | ||||
|             } else { | ||||
|                 cameraShift = CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE; | ||||
|             } | ||||
|             CameraPosition position = new CameraPosition.Builder() | ||||
|             final CameraPosition position = new CameraPosition.Builder() | ||||
|                     .target(LocationUtils.commonsLatLngToMapBoxLatLng( | ||||
|                             new fr.free.nrw.commons.location.LatLng(lastPlaceToCenter.location.getLatitude() - cameraShift, | ||||
|                                     lastPlaceToCenter.getLocation().getLongitude(), | ||||
|  | @ -623,22 +635,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void updateListFragment(List<Place> placeList) { | ||||
|         adapterFactory.updateAdapterData(placeList, (RVRendererAdapter<Place>) rvNearbyList.getAdapter()); | ||||
|         noResultsView.setVisibility(placeList.size() <= 0 ? View.VISIBLE : View.GONE); | ||||
|     public void updateListFragment(final List<Place> placeList) { | ||||
|         adapter.setItems(placeList); | ||||
|         noResultsView.setVisibility(placeList.isEmpty() ? View.VISIBLE : View.GONE); | ||||
|     } | ||||
| 
 | ||||
|     public void clearNearbyList() { | ||||
|         adapterFactory.clear((RVRendererAdapter<Place>) rvNearbyList.getAdapter()); | ||||
|         adapter.clear(); | ||||
|     } | ||||
| 
 | ||||
|     public void updateNearbyList() { | ||||
|         adapterFactory.update((RVRendererAdapter<Place>) rvNearbyList.getAdapter()); | ||||
|         noResultsView.setVisibility(rvNearbyList.getAdapter().getItemCount() <= 0 ? View.VISIBLE : View.GONE); | ||||
|     } | ||||
| 
 | ||||
|     public void addPlaceToNearbyList(Place place) { | ||||
|         adapterFactory.add(place, (RVRendererAdapter<Place>) rvNearbyList.getAdapter()); | ||||
|     public void addPlaceToNearbyList(final Place place) { | ||||
|         adapter.add(place); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|  | @ -678,7 +685,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     private void initNetworkBroadCastReceiver() { | ||||
|         broadcastReceiver = new BroadcastReceiver() { | ||||
|             @Override | ||||
|             public void onReceive(Context context, Intent intent) { | ||||
|             public void onReceive(final Context context, final Intent intent) { | ||||
|                 if (getActivity() != null) { | ||||
|                     if (NetworkUtils.isInternetConnectionEstablished(getActivity())) { | ||||
|                         if (isNetworkErrorOccurred) { | ||||
|  | @ -719,10 +726,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void populatePlaces(fr.free.nrw.commons.location.LatLng curlatLng) { | ||||
|         if (lastKnownLocation == null) { | ||||
|             lastKnownLocation = currentLocation; | ||||
|         } | ||||
|     public void populatePlaces(final fr.free.nrw.commons.location.LatLng curlatLng) { | ||||
|         if (curlatLng.equals(lastFocusLocation)|| lastFocusLocation==null) { // Means we are checking around current location | ||||
|             populatePlacesForCurrentLocation(lastKnownLocation, curlatLng); | ||||
|         } else { | ||||
|  | @ -730,8 +734,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void populatePlacesForCurrentLocation(fr.free.nrw.commons.location.LatLng curlatLng, | ||||
|                                                   fr.free.nrw.commons.location.LatLng searchLatLng) { | ||||
|     private void populatePlacesForCurrentLocation(final fr.free.nrw.commons.location.LatLng curlatLng, | ||||
|                                                   final fr.free.nrw.commons.location.LatLng searchLatLng) { | ||||
|         compositeDisposable.add(Observable.fromCallable(() -> nearbyController | ||||
|                 .loadAttractionsFromLocation(curlatLng, searchLatLng, false, true)) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|  | @ -749,8 +753,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|                         })); | ||||
|     } | ||||
| 
 | ||||
|     private void populatePlacesForAnotherLocation(fr.free.nrw.commons.location.LatLng curlatLng, | ||||
|                                                   fr.free.nrw.commons.location.LatLng searchLatLng) { | ||||
|     private void populatePlacesForAnotherLocation(final fr.free.nrw.commons.location.LatLng curlatLng, | ||||
|                                                   final fr.free.nrw.commons.location.LatLng searchLatLng) { | ||||
|         compositeDisposable.add(Observable.fromCallable(() -> nearbyController | ||||
|                 .loadAttractionsFromLocation(curlatLng, searchLatLng, false, false)) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|  | @ -772,8 +776,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * location where you are. | ||||
|      * @param nearbyPlacesInfo This variable has place list information and distances. | ||||
|      */ | ||||
|     private void updateMapMarkers(NearbyController.NearbyPlacesInfo nearbyPlacesInfo,boolean shouldUpdateSelectedMarker) { | ||||
|         this.nearbyPlacesInfo=nearbyPlacesInfo; | ||||
|     private void updateMapMarkers(final NearbyController.NearbyPlacesInfo nearbyPlacesInfo, final boolean shouldUpdateSelectedMarker) { | ||||
|         presenter.updateMapMarkers(nearbyPlacesInfo, selectedMarker,shouldUpdateSelectedMarker); | ||||
|         setFilterState(); | ||||
|     } | ||||
|  | @ -804,7 +807,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setSearchThisAreaButtonVisibility(boolean isVisible) { | ||||
|     public void setSearchThisAreaButtonVisibility(final boolean isVisible) { | ||||
|         if (isVisible) { | ||||
|             searchThisAreaButton.setVisibility(View.VISIBLE); | ||||
|         } else { | ||||
|  | @ -814,11 +817,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
| 
 | ||||
|     @Override | ||||
|     public boolean isSearchThisAreaButtonVisible() { | ||||
|         if (searchThisAreaButton.getVisibility() == View.VISIBLE) { | ||||
|             return true; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|         return searchThisAreaButton.getVisibility() == View.VISIBLE; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|  | @ -836,7 +835,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setProgressBarVisibility(boolean isVisible) { | ||||
|     public void setProgressBarVisibility(final boolean isVisible) { | ||||
|         if (isVisible) { | ||||
|             progressBar.setVisibility(View.VISIBLE); | ||||
|         } else { | ||||
|  | @ -850,7 +849,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void checkPermissionsAndPerformAction(Runnable runnable) { | ||||
|     public void checkPermissionsAndPerformAction(final Runnable runnable) { | ||||
|         Timber.d("Checking permission and perfoming action"); | ||||
|         PermissionUtils.checkPermissionsAndPerformAction(getActivity(), | ||||
|                 Manifest.permission.ACCESS_FINE_LOCATION, | ||||
|  | @ -885,7 +884,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * Expands camera and gallery FABs, turn forward plus FAB | ||||
|      * @param isFABsExpanded true if they are already expanded | ||||
|      */ | ||||
|     private void expandFABs(boolean isFABsExpanded){ | ||||
|     private void expandFABs(final boolean isFABsExpanded){ | ||||
|         if (!isFABsExpanded) { | ||||
|             showFABs(); | ||||
|             fabPlus.startAnimation(rotate_forward); | ||||
|  | @ -913,7 +912,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * Collapses camera and gallery FABs, turn back plus FAB | ||||
|      * @param isFABsExpanded | ||||
|      */ | ||||
|     private void collapseFABs(boolean isFABsExpanded){ | ||||
|     private void collapseFABs(final boolean isFABsExpanded){ | ||||
|         if (isFABsExpanded) { | ||||
|             fabPlus.startAnimation(rotate_backward); | ||||
|             fabCamera.startAnimation(fab_close); | ||||
|  | @ -940,19 +939,19 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void handleLocationUpdate(fr.free.nrw.commons.location.LatLng latLng, LocationServiceManager.LocationChangeType locationChangeType){ | ||||
|         this.lastKnownLocation = latLng; | ||||
|     private void handleLocationUpdate(final fr.free.nrw.commons.location.LatLng latLng, final LocationServiceManager.LocationChangeType locationChangeType){ | ||||
|         lastKnownLocation = latLng; | ||||
|         NearbyController.currentLocation = lastKnownLocation; | ||||
|         presenter.updateMapAndList(locationChangeType); | ||||
|     } | ||||
| 
 | ||||
|     private boolean isUserBrowsing() { | ||||
|         boolean isUserBrowsing = lastKnownLocation!=null && !presenter.areLocationsClose(getCameraTarget(), lastKnownLocation); | ||||
|         final boolean isUserBrowsing = lastKnownLocation!=null && !presenter.areLocationsClose(getCameraTarget(), lastKnownLocation); | ||||
|         return isUserBrowsing; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onLocationChangedSignificantly(fr.free.nrw.commons.location.LatLng latLng) { | ||||
|     public void onLocationChangedSignificantly(final fr.free.nrw.commons.location.LatLng latLng) { | ||||
|         Timber.d("Location significantly changed"); | ||||
|         if (isMapBoxReady && latLng != null &&!isUserBrowsing()) { | ||||
|             handleLocationUpdate(latLng,LOCATION_SIGNIFICANTLY_CHANGED); | ||||
|  | @ -960,7 +959,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onLocationChangedSlightly(fr.free.nrw.commons.location.LatLng latLng) { | ||||
|     public void onLocationChangedSlightly(final fr.free.nrw.commons.location.LatLng latLng) { | ||||
|         Timber.d("Location slightly changed"); | ||||
|         if (isMapBoxReady && latLng != null &&!isUserBrowsing()) {//If the map has never ever shown the current location, lets do it know | ||||
|             handleLocationUpdate(latLng,LOCATION_SLIGHTLY_CHANGED); | ||||
|  | @ -968,7 +967,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onLocationChangedMedium(fr.free.nrw.commons.location.LatLng latLng) { | ||||
|     public void onLocationChangedMedium(final fr.free.nrw.commons.location.LatLng latLng) { | ||||
|         Timber.d("Location changed medium"); | ||||
|         if (isMapBoxReady && latLng != null && !isUserBrowsing()) {//If the map has never ever shown the current location, lets do it know | ||||
|             handleLocationUpdate(latLng, LOCATION_SIGNIFICANTLY_CHANGED); | ||||
|  | @ -986,7 +985,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         @Override | ||||
|         public void onLogoutComplete() { | ||||
|             Timber.d("Logout complete callback received."); | ||||
|             Intent nearbyIntent = new Intent( getActivity(), LoginActivity.class); | ||||
|             final Intent nearbyIntent = new Intent( getActivity(), LoginActivity.class); | ||||
|             nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); | ||||
|             nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
|             startActivity(nearbyIntent); | ||||
|  | @ -995,12 +994,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setFABPlusAction(View.OnClickListener onClickListener) { | ||||
|     public void setFABPlusAction(final View.OnClickListener onClickListener) { | ||||
|         fabPlus.setOnClickListener(onClickListener); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setFABRecenterAction(View.OnClickListener onClickListener) { | ||||
|     public void setFABRecenterAction(final View.OnClickListener onClickListener) { | ||||
|         fabRecenter.setOnClickListener(onClickListener); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1026,27 +1025,27 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * @param curLatLng current location | ||||
|      */ | ||||
|     @Override | ||||
|     public void addCurrentLocationMarker(fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|     public void addCurrentLocationMarker(final fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|         if (null != curLatLng) { | ||||
|             ExecutorUtils.get().submit(() -> { | ||||
|                 mapView.post(() -> removeCurrentLocationMarker()); | ||||
|                 Timber.d("Adds current location marker"); | ||||
| 
 | ||||
|                 Icon icon = IconFactory.getInstance(getContext()) | ||||
|                 final Icon icon = IconFactory.getInstance(getContext()) | ||||
|                         .fromResource(R.drawable.current_location_marker); | ||||
| 
 | ||||
|                 MarkerOptions currentLocationMarkerOptions = new MarkerOptions() | ||||
|                 final MarkerOptions currentLocationMarkerOptions = new MarkerOptions() | ||||
|                         .position(new LatLng(curLatLng.getLatitude(), | ||||
|                                 curLatLng.getLongitude())); | ||||
|                 currentLocationMarkerOptions.setIcon(icon); // Set custom icon | ||||
|                 mapView.post(() -> currentLocationMarker = mapBox.addMarker(currentLocationMarkerOptions)); | ||||
| 
 | ||||
| 
 | ||||
|                 List<LatLng> circle = UiUtils | ||||
|                 final List<LatLng> circle = UiUtils | ||||
|                         .createCircleArray(curLatLng.getLatitude(), curLatLng.getLongitude(), | ||||
|                                 curLatLng.getAccuracy() * 2, 100); | ||||
| 
 | ||||
|                 PolygonOptions currentLocationPolygonOptions = new PolygonOptions() | ||||
|                 final PolygonOptions currentLocationPolygonOptions = new PolygonOptions() | ||||
|                         .addAll(circle) | ||||
|                         .strokeColor(getResources().getColor(R.color.current_marker_stroke)) | ||||
|                         .fillColor(getResources().getColor(R.color.current_marker_fill)); | ||||
|  | @ -1071,9 +1070,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * @param curLatLng current location of user | ||||
|      */ | ||||
|     @Override | ||||
|     public void updateMapToTrackPosition(fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|     public void updateMapToTrackPosition(final fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|         Timber.d("Updates map camera to track user position"); | ||||
|         CameraPosition cameraPosition = new CameraPosition.Builder().target | ||||
|         final CameraPosition cameraPosition = new CameraPosition.Builder().target | ||||
|                 (LocationUtils.commonsLatLngToMapBoxLatLng(curLatLng)).build(); | ||||
|         if(null!=mapBox) { | ||||
|             mapBox.setCameraPosition(cameraPosition); | ||||
|  | @ -1083,7 +1082,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void updateMapMarkers(List<NearbyBaseMarker> nearbyBaseMarkers, Marker selectedMarker) { | ||||
|     public void updateMapMarkers(final List<NearbyBaseMarker> nearbyBaseMarkers, final Marker selectedMarker) { | ||||
|         if(mapBox!=null && isMapBoxReady){ | ||||
|             mapBox.clear(); | ||||
|             addNearbyMarkersToMapBoxMap(nearbyBaseMarkers, selectedMarker); | ||||
|  | @ -1096,7 +1095,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     @Override | ||||
|     public void filterOutAllMarkers() { | ||||
|         hideAllMarkers(); | ||||
|         updateNearbyList(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -1104,10 +1102,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      */ | ||||
|     @Override | ||||
|     public void displayAllMarkers() { | ||||
|         for (MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { | ||||
|         for (final MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { | ||||
|             updateMarker(markerPlaceGroup.getIsBookmarked(), markerPlaceGroup.getPlace(), NearbyController.currentLocation); | ||||
|         } | ||||
|         updateNearbyList(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -1119,17 +1116,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * @param filterForAllNoneType true if we filter places with all none button | ||||
|      */ | ||||
|     @Override | ||||
|     public void filterMarkersByLabels(List<Label> selectedLabels, | ||||
|         boolean displayExists, | ||||
|         boolean displayNeedsPhoto, | ||||
|         boolean filterForPlaceState, | ||||
|         boolean filterForAllNoneType) { | ||||
|     public void filterMarkersByLabels(final List<Label> selectedLabels, | ||||
|         final boolean displayExists, | ||||
|         final boolean displayNeedsPhoto, | ||||
|         final boolean filterForPlaceState, | ||||
|         final boolean filterForAllNoneType) { | ||||
| 
 | ||||
|         // Remove the previous markers before updating them | ||||
|         hideAllMarkers(); | ||||
| 
 | ||||
|         for (MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { | ||||
|             Place place = markerPlaceGroup.getPlace(); | ||||
|         for (final MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { | ||||
|             final Place place = markerPlaceGroup.getPlace(); | ||||
| 
 | ||||
|             // When label filter is engaged | ||||
|             // then compare it against place's label | ||||
|  | @ -1159,7 +1156,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|                 updateMarker(markerPlaceGroup.getIsBookmarked(), place, NearbyController.currentLocation); | ||||
|             } | ||||
|         } | ||||
|         updateNearbyList(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|  | @ -1173,7 +1169,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * @param place | ||||
|      * @param curLatLng current location | ||||
|      */ | ||||
|     public void updateMarker(boolean isBookmarked, Place place, @Nullable fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|     public void updateMarker(final boolean isBookmarked, final Place place, @Nullable final fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|         addPlaceToNearbyList(place); | ||||
| 
 | ||||
|         VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create( | ||||
|  | @ -1182,13 +1178,13 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         for (Marker marker : mapBox.getMarkers()) { | ||||
|             if (marker.getTitle() != null && marker.getTitle().equals(place.getName())) { | ||||
| 
 | ||||
|                 Bitmap icon = UiUtils.getBitmap(vectorDrawable); | ||||
|                 final Bitmap icon = UiUtils.getBitmap(vectorDrawable); | ||||
|                 if (curLatLng != null) { | ||||
|                     String distance = formatDistanceBetween(curLatLng, place.location); | ||||
|                     final String distance = formatDistanceBetween(curLatLng, place.location); | ||||
|                     place.setDistance(distance); | ||||
|                 } | ||||
| 
 | ||||
|                 NearbyBaseMarker nearbyBaseMarker = new NearbyBaseMarker(); | ||||
|                 final NearbyBaseMarker nearbyBaseMarker = new NearbyBaseMarker(); | ||||
|                 nearbyBaseMarker.title(place.name); | ||||
|                 nearbyBaseMarker.position( | ||||
|                         new com.mapbox.mapboxsdk.geometry.LatLng( | ||||
|  | @ -1224,11 +1220,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * since grey icon may lead the users to believe that it is disabled or prohibited contribution | ||||
|      */ | ||||
|     private void hideAllMarkers() { | ||||
|         VectorDrawableCompat vectorDrawable; | ||||
|         final VectorDrawableCompat vectorDrawable; | ||||
|         vectorDrawable = VectorDrawableCompat.create( | ||||
|                 getContext().getResources(), R.drawable.ic_custom_greyed_out_marker, getContext().getTheme()); | ||||
|         Bitmap icon = UiUtils.getBitmap(vectorDrawable); | ||||
|         for (Marker marker : mapBox.getMarkers()) { | ||||
|         final Bitmap icon = UiUtils.getBitmap(vectorDrawable); | ||||
|         for (final Marker marker : mapBox.getMarkers()) { | ||||
|             if (!marker.equals(currentLocationMarker)) { | ||||
|                 marker.setIcon(IconFactory.getInstance(getContext()).fromBitmap(icon)); | ||||
|             } | ||||
|  | @ -1237,7 +1233,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         clearNearbyList(); | ||||
|     } | ||||
| 
 | ||||
|     private void addNearbyMarkersToMapBoxMap(List<NearbyBaseMarker> nearbyBaseMarkers, Marker selectedMarker) { | ||||
|     private void addNearbyMarkersToMapBoxMap(final List<NearbyBaseMarker> nearbyBaseMarkers, final Marker selectedMarker) { | ||||
|         if (isMapBoxReady && mapBox != null) { | ||||
|             mapBox.addMarkers(nearbyBaseMarkers); | ||||
|             setMapMarkerActions(selectedMarker); | ||||
|  | @ -1245,7 +1241,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void setMapMarkerActions(Marker selectedMarker) { | ||||
|     private void setMapMarkerActions(final Marker selectedMarker) { | ||||
|         if (mapBox != null) { | ||||
|             mapBox.setOnInfoWindowCloseListener(marker -> { | ||||
|                 if (marker == selectedMarker) { | ||||
|  | @ -1263,7 +1259,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void recenterMap(fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|     public void recenterMap(final fr.free.nrw.commons.location.LatLng curLatLng) { | ||||
|         if (curLatLng == null) { | ||||
|             if (!(locationManager.isNetworkProviderEnabled() || locationManager.isGPSProviderEnabled())) { | ||||
|                 showLocationOffDialog(); | ||||
|  | @ -1271,7 +1267,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|             return; | ||||
|         } | ||||
|         addCurrentLocationMarker(curLatLng); | ||||
|         CameraPosition position; | ||||
|         final CameraPosition position; | ||||
| 
 | ||||
|         if (ViewUtil.isPortrait(getActivity())) { | ||||
|             position = new CameraPosition.Builder() | ||||
|  | @ -1309,8 +1305,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     @Override | ||||
|     public void openLocationSettings() { | ||||
|         // This method opens the location settings of the device along with a followup toast. | ||||
|         Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); | ||||
|         PackageManager packageManager = getActivity().getPackageManager(); | ||||
|         final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); | ||||
|         final PackageManager packageManager = getActivity().getPackageManager(); | ||||
| 
 | ||||
|         if (intent.resolveActivity(packageManager)!= null) { | ||||
|             startActivity(intent); | ||||
|  | @ -1331,10 +1327,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void displayBottomSheetWithInfo(Marker marker) { | ||||
|         this.selectedMarker = marker; | ||||
|         NearbyMarker nearbyMarker = (NearbyMarker) marker; | ||||
|         Place place = nearbyMarker.getNearbyBaseMarker().getPlace(); | ||||
|     public void displayBottomSheetWithInfo(final Marker marker) { | ||||
|         selectedMarker = marker; | ||||
|         final NearbyMarker nearbyMarker = (NearbyMarker) marker; | ||||
|         final Place place = nearbyMarker.getNearbyBaseMarker().getPlace(); | ||||
|         passInfoToSheet(place); | ||||
|         hideBottomSheet(); | ||||
|         bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); | ||||
|  | @ -1351,16 +1347,18 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * If nearby details bottom sheet state is hidden: hide all fabs | ||||
|      * @param bottomSheetState see bottom sheet states | ||||
|      */ | ||||
|     public void prepareViewsForSheetPosition(int bottomSheetState) { | ||||
|     public void prepareViewsForSheetPosition(final int bottomSheetState) { | ||||
| 
 | ||||
|         switch (bottomSheetState) { | ||||
|             case (BottomSheetBehavior.STATE_COLLAPSED): | ||||
|                 collapseFABs(isFABsExpanded); | ||||
|                 if (!fabPlus.isShown()) showFABs(); | ||||
|                 this.getView().requestFocus(); | ||||
|                 if (!fabPlus.isShown()) { | ||||
|                     showFABs(); | ||||
|                 } | ||||
|                 getView().requestFocus(); | ||||
|                 break; | ||||
|             case (BottomSheetBehavior.STATE_EXPANDED): | ||||
|                 this.getView().requestFocus(); | ||||
|                 getView().requestFocus(); | ||||
|                 break; | ||||
|             case (BottomSheetBehavior.STATE_HIDDEN): | ||||
|                 if (null != mapBox) { | ||||
|  | @ -1370,8 +1368,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|                 transparentView.setAlpha(0); | ||||
|                 collapseFABs(isFABsExpanded); | ||||
|                 hideFABs(); | ||||
|                 if (this.getView() != null) { | ||||
|                     this.getView().requestFocus(); | ||||
|                 if (getView() != null) { | ||||
|                     getView().requestFocus(); | ||||
|                 } | ||||
|                 break; | ||||
|         } | ||||
|  | @ -1382,36 +1380,37 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|      * (title, description, distance and links) to view on nearby marker click | ||||
|      * @param place Place of clicked nearby marker | ||||
|      */ | ||||
|     private void passInfoToSheet(Place place) { | ||||
|         this.selectedPlace = place; | ||||
|         updateBookmarkButtonImage(this.selectedPlace); | ||||
|     private void passInfoToSheet(final Place place) { | ||||
|         selectedPlace = place; | ||||
|         updateBookmarkButtonImage(selectedPlace); | ||||
| 
 | ||||
|         bookmarkButton.setOnClickListener(view -> { | ||||
|             boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(this.selectedPlace); | ||||
|             updateBookmarkButtonImage(this.selectedPlace); | ||||
|             updateMarker(isBookmarked, this.selectedPlace, locationManager.getLastLocation()); | ||||
|             final boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(selectedPlace); | ||||
|             updateBookmarkButtonImage(selectedPlace); | ||||
|             updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation()); | ||||
|         }); | ||||
| 
 | ||||
|         wikipediaButton.setVisibility(place.hasWikipediaLink()?View.VISIBLE:View.GONE); | ||||
|         wikipediaButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), this.selectedPlace.siteLinks.getWikipediaLink())); | ||||
|         wikipediaButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikipediaLink())); | ||||
| 
 | ||||
|         wikidataButton.setVisibility(place.hasWikidataLink()?View.VISIBLE:View.GONE); | ||||
|         wikidataButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), this.selectedPlace.siteLinks.getWikidataLink())); | ||||
|         wikidataButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikidataLink())); | ||||
| 
 | ||||
|         directionsButton.setOnClickListener(view -> Utils.handleGeoCoordinates(getActivity(), this.selectedPlace.getLocation())); | ||||
|         directionsButton.setOnClickListener(view -> Utils.handleGeoCoordinates(getActivity(), | ||||
|             selectedPlace.getLocation())); | ||||
| 
 | ||||
|         commonsButton.setVisibility(this.selectedPlace.hasCommonsLink()?View.VISIBLE:View.GONE); | ||||
|         commonsButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), this.selectedPlace.siteLinks.getCommonsLink())); | ||||
|         commonsButton.setVisibility(selectedPlace.hasCommonsLink()?View.VISIBLE:View.GONE); | ||||
|         commonsButton.setOnClickListener(view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getCommonsLink())); | ||||
| 
 | ||||
|         icon.setImageResource(this.selectedPlace.getLabel().getIcon()); | ||||
|         icon.setImageResource(selectedPlace.getLabel().getIcon()); | ||||
| 
 | ||||
|         title.setText(this.selectedPlace.name); | ||||
|         distance.setText(this.selectedPlace.distance); | ||||
|         description.setText(this.selectedPlace.getLongDescription()); | ||||
|         title.setText(selectedPlace.name); | ||||
|         distance.setText(selectedPlace.distance); | ||||
|         description.setText(selectedPlace.getLongDescription()); | ||||
| 
 | ||||
|         fabCamera.setOnClickListener(view -> { | ||||
|             if (fabCamera.isShown()) { | ||||
|                 Timber.d("Camera button tapped. Place: %s", this.selectedPlace.toString()); | ||||
|                 Timber.d("Camera button tapped. Place: %s", selectedPlace.toString()); | ||||
|                 storeSharedPrefs(selectedPlace); | ||||
|                 controller.initiateCameraPick(getActivity()); | ||||
|             } | ||||
|  | @ -1419,20 +1418,20 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
| 
 | ||||
|         fabGallery.setOnClickListener(view -> { | ||||
|             if (fabGallery.isShown()) { | ||||
|                 Timber.d("Gallery button tapped. Place: %s", this.selectedPlace.toString()); | ||||
|                 Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString()); | ||||
|                 storeSharedPrefs(selectedPlace); | ||||
|                 controller.initiateGalleryPick(getActivity(), false); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private void storeSharedPrefs(Place selectedPlace) { | ||||
|     private void storeSharedPrefs(final Place selectedPlace) { | ||||
|         Timber.d("Store place object %s", selectedPlace.toString()); | ||||
|         applicationKvStore.putJson(PLACE_OBJECT, selectedPlace); | ||||
|     } | ||||
| 
 | ||||
|     private void updateBookmarkButtonImage(Place place) { | ||||
|         int bookmarkIcon; | ||||
|     private void updateBookmarkButtonImage(final Place place) { | ||||
|         final int bookmarkIcon; | ||||
|         if (bookmarkLocationDao.findBookmarkLocation(place)) { | ||||
|             bookmarkIcon = R.drawable.ic_round_star_filled_24px; | ||||
|         } else { | ||||
|  | @ -1444,7 +1443,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onAttach(Context context) { | ||||
|     public void onAttach(final Context context) { | ||||
|         super.onAttach(context); | ||||
|         wikidataEditListener.setAuthenticationStateListener(this); | ||||
|     } | ||||
|  | @ -1462,11 +1461,11 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void showErrorMessage(String message) { | ||||
|     private void showErrorMessage(final String message) { | ||||
|         ViewUtil.showLongToast(getActivity(), message); | ||||
|     } | ||||
| 
 | ||||
|     public void registerUnregisterLocationListener(boolean removeLocationListener) { | ||||
|     public void registerUnregisterLocationListener(final boolean removeLocationListener) { | ||||
|         try { | ||||
|             if (removeLocationListener) { | ||||
|                 locationManager.unregisterLocationManager(); | ||||
|  | @ -1477,14 +1476,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment | |||
|                 locationManager.registerLocationManager(); | ||||
|                 Timber.d("Location service manager added and registered"); | ||||
|             } | ||||
|         }catch (Exception e){ | ||||
|         }catch (final Exception e){ | ||||
|             Timber.e(e); | ||||
|             //Broadcasts are tricky, should be catchedonR | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setUserVisibleHint(boolean isVisibleToUser) { | ||||
|     public void setUserVisibleHint(final boolean isVisibleToUser) { | ||||
|         super.setUserVisibleHint(isVisibleToUser); | ||||
|         this.isVisibleToUser=isVisibleToUser; | ||||
|         if (isResumed() && isVisibleToUser) { | ||||
|  |  | |||
|  | @ -0,0 +1,25 @@ | |||
| package fr.free.nrw.commons.nearby.fragments | ||||
| 
 | ||||
| import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao | ||||
| import fr.free.nrw.commons.nearby.Place | ||||
| import fr.free.nrw.commons.nearby.placeAdapterDelegate | ||||
| import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter | ||||
| 
 | ||||
| class PlaceAdapter( | ||||
|     bookmarkLocationsDao: BookmarkLocationsDao, | ||||
|     onPlaceClicked: ((Place) -> Unit)? = null, | ||||
|     onBookmarkClicked: (Place, Boolean) -> Unit, | ||||
|     commonPlaceClickActions: CommonPlaceClickActions | ||||
| ) : | ||||
|     BaseDelegateAdapter<Place>( | ||||
|         placeAdapterDelegate( | ||||
|             bookmarkLocationsDao, | ||||
|             onPlaceClicked, | ||||
|             commonPlaceClickActions.onCameraClicked(), | ||||
|             commonPlaceClickActions.onGalleryClicked(), | ||||
|             onBookmarkClicked, | ||||
|             commonPlaceClickActions.onOverflowClicked(), | ||||
|             commonPlaceClickActions.onDirectionsClicked() | ||||
|         ), | ||||
|         areItemsTheSame = {oldItem, newItem -> oldItem.wikiDataEntityId == newItem.wikiDataEntityId } | ||||
|     ) | ||||
|  | @ -0,0 +1,9 @@ | |||
| package fr.free.nrw.commons.notification | ||||
| 
 | ||||
| import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter | ||||
| 
 | ||||
| internal class NotificatinAdapter(onNotificationClicked: (Notification) -> Unit) : | ||||
|     BaseDelegateAdapter<Notification>( | ||||
|         notificationDelegate(onNotificationClicked), | ||||
|         areItemsTheSame = { oldItem, newItem -> oldItem.notificationId == newItem.notificationId } | ||||
|     ) | ||||
|  | @ -11,16 +11,6 @@ data class Notification(var notificationType: NotificationType, | |||
|                    var link: String, | ||||
|                    var iconUrl: String, | ||||
|                    var notificationId: String) { | ||||
|     override fun toString(): String { | ||||
|         return "Notification" + | ||||
|                 "notificationType='" + notificationType + '\'' + | ||||
|                 ", notificationText='" + notificationText + '\'' + | ||||
|                 ", date='" + date + '\'' + | ||||
|                 ", link='" + link + '\'' + | ||||
|                 ", iconUrl='" + iconUrl + '\'' + | ||||
|                 ", notificationId='" + notificationId + '\'' + | ||||
|                 '}' | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         @JvmStatic | ||||
|  | @ -35,4 +25,4 @@ data class Notification(var notificationType: NotificationType, | |||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -13,23 +13,13 @@ import android.widget.ProgressBar; | |||
| import android.widget.RelativeLayout; | ||||
| import android.widget.TextView; | ||||
| import android.widget.Toast; | ||||
| 
 | ||||
| import androidx.constraintlayout.widget.ConstraintLayout; | ||||
| import androidx.recyclerview.widget.DividerItemDecoration; | ||||
| import androidx.recyclerview.widget.LinearLayoutManager; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 
 | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import com.pedrogomez.renderers.RVRendererAdapter; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.Callable; | ||||
| 
 | ||||
| import javax.inject.Inject; | ||||
| 
 | ||||
| import butterknife.BindView; | ||||
| import butterknife.ButterKnife; | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.Utils; | ||||
| import fr.free.nrw.commons.theme.NavigationBaseActivity; | ||||
|  | @ -40,6 +30,11 @@ import io.reactivex.ObservableSource; | |||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.Disposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.Callable; | ||||
| import javax.inject.Inject; | ||||
| import kotlin.Unit; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| /** | ||||
|  | @ -47,7 +42,6 @@ import timber.log.Timber; | |||
|  */ | ||||
| 
 | ||||
| public class NotificationActivity extends NavigationBaseActivity { | ||||
|     NotificationAdapterFactory notificationAdapterFactory; | ||||
|     @BindView(R.id.listView) | ||||
|     RecyclerView recyclerView; | ||||
|     @BindView(R.id.progressBar) | ||||
|  | @ -64,7 +58,7 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
| 
 | ||||
|     private static final String TAG_NOTIFICATION_WORKER_FRAGMENT = "NotificationWorkerFragment"; | ||||
|     private NotificationWorkerFragment mNotificationWorkerFragment; | ||||
|     private RVRendererAdapter<Notification> adapter; | ||||
|     private NotificatinAdapter adapter; | ||||
|     private List<Notification> notificationList; | ||||
|     MenuItem notificationMenuItem; | ||||
| 
 | ||||
|  | @ -89,7 +83,7 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
|                 .subscribe(result -> { | ||||
|                     if (result) { | ||||
|                         notificationList.remove(notification); | ||||
|                         setAdapter(notificationList); | ||||
|                         setItems(notificationList); | ||||
|                         adapter.notifyDataSetChanged(); | ||||
|                         Snackbar snackbar = Snackbar | ||||
|                                 .make(relativeLayout, getString(R.string.notification_mark_read), Snackbar.LENGTH_LONG); | ||||
|  | @ -102,7 +96,7 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
|                         } | ||||
|                     } else { | ||||
|                         adapter.notifyDataSetChanged(); | ||||
|                         setAdapter(notificationList); | ||||
|                         setItems(notificationList); | ||||
|                         Toast.makeText(NotificationActivity.this, getString(R.string.some_error), Toast.LENGTH_SHORT).show(); | ||||
|                     } | ||||
|                 }, throwable -> { | ||||
|  | @ -126,6 +120,13 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
|         } else { | ||||
|             refresh(false); | ||||
|         } | ||||
|         adapter = new NotificatinAdapter(item -> { | ||||
|             Timber.d("Notification clicked %s", item.getLink()); | ||||
|             handleUrl(item.getLink()); | ||||
|             removeNotification(item); | ||||
|             return Unit.INSTANCE; | ||||
|         }); | ||||
|         recyclerView.setAdapter(this.adapter); | ||||
|     } | ||||
| 
 | ||||
|     private void refresh(boolean archived) { | ||||
|  | @ -158,7 +159,7 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
|                             relativeLayout.setVisibility(View.GONE); | ||||
|                             no_notification.setVisibility(View.VISIBLE); | ||||
|                         } else { | ||||
|                             setAdapter(notificationList); | ||||
|                             setItems(notificationList); | ||||
|                         } | ||||
|                         progressBar.setVisibility(View.GONE); | ||||
|                     }, throwable -> { | ||||
|  | @ -168,7 +169,7 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
|                     })); | ||||
|         } else { | ||||
|             notificationList = mNotificationWorkerFragment.getNotificationList(); | ||||
|             setAdapter(notificationList); | ||||
|             setItems(notificationList); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -204,7 +205,7 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
|         Utils.handleWebUrl(this, Uri.parse(url)); | ||||
|     } | ||||
| 
 | ||||
|     private void setAdapter(List<Notification> notificationList) { | ||||
|     private void setItems(List<Notification> notificationList) { | ||||
|         if (notificationList == null || notificationList.isEmpty()) { | ||||
|             ViewUtil.showShortSnackbar(relativeLayout, R.string.no_notifications); | ||||
|             /*progressBar.setVisibility(View.GONE); | ||||
|  | @ -214,32 +215,9 @@ public class NotificationActivity extends NavigationBaseActivity { | |||
|             no_notification.setVisibility(View.VISIBLE); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         boolean isarchivedvisible; | ||||
|         if (getIntent().getStringExtra("title").equals("read")) { | ||||
|             isarchivedvisible = true; | ||||
|         } else { | ||||
|             isarchivedvisible = false; | ||||
|         } | ||||
| 
 | ||||
|         notificationAdapterFactory = new NotificationAdapterFactory(new NotificationRenderer.NotificationClicked() { | ||||
|             @Override | ||||
|             public void notificationClicked(Notification notification) { | ||||
|                 Timber.d("Notification clicked %s", notification.getLink()); | ||||
|                 handleUrl(notification.getLink()); | ||||
|                 removeNotification(notification); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void markNotificationAsRead(Notification notification) { | ||||
|                 Timber.d("Notification to mark as read %s", notification.getNotificationId()); | ||||
|                 removeNotification(notification); | ||||
|             } | ||||
|         }, isarchivedvisible); | ||||
|         adapter = notificationAdapterFactory.create(notificationList); | ||||
|         relativeLayout.setVisibility(View.VISIBLE); | ||||
|         no_notification.setVisibility(View.GONE); | ||||
|         recyclerView.setAdapter(adapter); | ||||
|         adapter.setItems(notificationList); | ||||
|     } | ||||
| 
 | ||||
|     public static void startYourself(Context context, String title) { | ||||
|  |  | |||
|  | @ -0,0 +1,24 @@ | |||
| package fr.free.nrw.commons.notification | ||||
| 
 | ||||
| import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer | ||||
| import fr.free.nrw.commons.R | ||||
| import kotlinx.android.synthetic.main.activity_login.title | ||||
| import kotlinx.android.synthetic.main.item_notification.* | ||||
| import org.wikipedia.util.StringUtil | ||||
| 
 | ||||
| 
 | ||||
| fun notificationDelegate(onNotificationClicked: (Notification) -> Unit) = | ||||
|     adapterDelegateLayoutContainer<Notification, Notification>(R.layout.item_notification) { | ||||
|         containerView.setOnClickListener { onNotificationClicked(item) } | ||||
|         bind { | ||||
|             title.text = item.processedNotificationText | ||||
|             time.text = item.date | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| private val Notification.processedNotificationText: CharSequence | ||||
|     get() = notificationText.trim() | ||||
|         .replace("(^\\s*)|(\\s*$)".toRegex(), "") | ||||
|         .let { StringUtil.fromHtml(it).toString() } | ||||
|         .let { if (it.length > 280) "${it.substring(0, 279)}..." else it } + " " | ||||
|  | @ -1,32 +0,0 @@ | |||
| package fr.free.nrw.commons.notification; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.pedrogomez.renderers.ListAdapteeCollection; | ||||
| import com.pedrogomez.renderers.RVRendererAdapter; | ||||
| import com.pedrogomez.renderers.RendererBuilder; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| /** | ||||
|  * Created by root on 19.12.2017. | ||||
|  */ | ||||
| 
 | ||||
| class NotificationAdapterFactory { | ||||
|     private NotificationRenderer.NotificationClicked listener; | ||||
|     private boolean isarchivedvisible = false; | ||||
| 
 | ||||
|     NotificationAdapterFactory(@NonNull NotificationRenderer.NotificationClicked listener, boolean isarchivedvisible) { | ||||
|         this.listener = listener; | ||||
|         this.isarchivedvisible = isarchivedvisible; | ||||
|     } | ||||
| 
 | ||||
|     public RVRendererAdapter<Notification> create(List<Notification> notifications) { | ||||
|         RendererBuilder<Notification> builder = new RendererBuilder<Notification>() | ||||
|                 .bind(Notification.class, new NotificationRenderer(listener, isarchivedvisible)); | ||||
|         ListAdapteeCollection<Notification> collection = new ListAdapteeCollection<>( | ||||
|                 notifications != null ? notifications : Collections.<Notification>emptyList()); | ||||
|         return new RVRendererAdapter<>(builder, collection); | ||||
|     } | ||||
| } | ||||
|  | @ -1,91 +0,0 @@ | |||
| package fr.free.nrw.commons.notification; | ||||
| 
 | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.ImageView; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import com.pedrogomez.renderers.Renderer; | ||||
| 
 | ||||
| import org.wikipedia.util.StringUtil; | ||||
| 
 | ||||
| import butterknife.BindView; | ||||
| import butterknife.ButterKnife; | ||||
| import butterknife.OnClick; | ||||
| import fr.free.nrw.commons.R; | ||||
| 
 | ||||
| /** | ||||
|  * Created by root on 19.12.2017. | ||||
|  */ | ||||
| 
 | ||||
| public class NotificationRenderer extends Renderer<Notification> { | ||||
|     @BindView(R.id.title) | ||||
|     TextView title; | ||||
|     @BindView(R.id.time) | ||||
|     TextView time; | ||||
|     @BindView(R.id.icon) | ||||
|     ImageView icon; | ||||
|     /*@BindView(R.id.bottom) | ||||
|     LinearLayout bottomLayout;*/ | ||||
| 
 | ||||
|     private NotificationClicked listener; | ||||
|     private boolean isarchivedvisible = false; | ||||
| 
 | ||||
| 
 | ||||
|     NotificationRenderer(NotificationClicked listener, boolean isarchivedvisible) { | ||||
|         this.listener = listener; | ||||
|         this.isarchivedvisible = isarchivedvisible; | ||||
|     } | ||||
| 
 | ||||
|     @OnClick(R.id.notification_view) | ||||
|     void onNotificationClicked() { | ||||
|         listener.notificationClicked(getContent()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void setUpView(View rootView) { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void hookListeners(View rootView) { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { | ||||
|         View inflatedView = layoutInflater.inflate(R.layout.item_notification, viewGroup, false); | ||||
|         ButterKnife.bind(this, inflatedView); | ||||
|         return inflatedView; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render() { | ||||
|         Notification notification = getContent(); | ||||
|         setTitle(notification.getNotificationText()); | ||||
|         time.setText(notification.getDate()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Cleans up the notification text and sets it as the title | ||||
|      * Clean up is required to fix escaped HTML string and extra white spaces at the beginning of the notification | ||||
|      * | ||||
|      * @param notificationText | ||||
|      */ | ||||
|     private void setTitle(String notificationText) { | ||||
|         notificationText = notificationText.trim().replaceAll("(^\\s*)|(\\s*$)", ""); | ||||
|         notificationText = StringUtil.fromHtml(notificationText).toString(); | ||||
|         if (notificationText.length() > 280) { | ||||
|             notificationText = notificationText.substring(0, 279); | ||||
|             notificationText = notificationText.concat("..."); | ||||
|         } | ||||
|         notificationText = notificationText.concat(" "); | ||||
|         title.setText(notificationText); | ||||
|     } | ||||
| 
 | ||||
|     public interface NotificationClicked { | ||||
|         void notificationClicked(Notification notification); | ||||
|         void markNotificationAsRead(Notification notification); | ||||
|     } | ||||
| } | ||||
|  | @ -1,27 +0,0 @@ | |||
| package fr.free.nrw.commons.upload; | ||||
| 
 | ||||
| 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.category.CategoryClickedListener; | ||||
| import fr.free.nrw.commons.category.CategoryItem; | ||||
| 
 | ||||
| public class UploadCategoriesAdapterFactory { | ||||
|     private final CategoryClickedListener listener; | ||||
| 
 | ||||
|     public UploadCategoriesAdapterFactory(CategoryClickedListener listener) { | ||||
|         this.listener = listener; | ||||
|     } | ||||
| 
 | ||||
|     public RVRendererAdapter<CategoryItem> create(List<CategoryItem> placeList) { | ||||
|         RendererBuilder<CategoryItem> builder = new RendererBuilder<CategoryItem>() | ||||
|                 .bind(CategoryItem.class, new UploadCategoriesRenderer(listener)); | ||||
|         ListAdapteeCollection<CategoryItem> collection = new ListAdapteeCollection<>( | ||||
|                 placeList != null ? placeList : Collections.emptyList()); | ||||
|         return new RVRendererAdapter<>(builder, collection); | ||||
|     } | ||||
| } | ||||
|  | @ -1,59 +0,0 @@ | |||
| package fr.free.nrw.commons.upload; | ||||
| 
 | ||||
| import android.annotation.SuppressLint; | ||||
| import android.content.res.Configuration; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.CheckBox; | ||||
| 
 | ||||
| import com.pedrogomez.renderers.Renderer; | ||||
| 
 | ||||
| import butterknife.BindView; | ||||
| import butterknife.ButterKnife; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.category.CategoryClickedListener; | ||||
| import fr.free.nrw.commons.category.CategoryItem; | ||||
| 
 | ||||
| public class UploadCategoriesRenderer extends Renderer<CategoryItem> { | ||||
|     @BindView(R.id.tvName) CheckBox checkedView; | ||||
|     private final CategoryClickedListener listener; | ||||
| 
 | ||||
|     UploadCategoriesRenderer(CategoryClickedListener listener) { | ||||
|         this.listener = listener; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { | ||||
|         return layoutInflater.inflate(R.layout.layout_upload_categories_item, viewGroup, false); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void setUpView(View view) { | ||||
|         ButterKnife.bind(this, view); | ||||
|         Configuration config = getContext().getResources().getConfiguration(); | ||||
|         if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { | ||||
|             checkedView.setLayoutDirection(View.LAYOUT_DIRECTION_LTR); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("WrongConstant") | ||||
|     @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(); | ||||
|         checkedView.setChecked(item.isSelected()); | ||||
|         checkedView.setText(item.getName()); | ||||
|     } | ||||
| } | ||||
|  | @ -1,31 +0,0 @@ | |||
| package fr.free.nrw.commons.upload; | ||||
| 
 | ||||
| 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.upload.structure.depictions.DepictedItem; | ||||
| import fr.free.nrw.commons.upload.structure.depictions.UploadDepictsCallback; | ||||
| 
 | ||||
| /** | ||||
|  * Adapter Factory for DepictsClicked Listener | ||||
|  */ | ||||
| 
 | ||||
| public class UploadDepictsAdapterFactory { | ||||
|     private final UploadDepictsCallback listener; | ||||
| 
 | ||||
|     public UploadDepictsAdapterFactory(UploadDepictsCallback listener) { | ||||
|         this.listener = listener; | ||||
|     } | ||||
| 
 | ||||
|     public RVRendererAdapter<DepictedItem> create(List<DepictedItem> itemList) { | ||||
|         RendererBuilder<DepictedItem> builder = new RendererBuilder<DepictedItem>() | ||||
|                 .bind(DepictedItem.class, new UploadDepictsRenderer(listener)); | ||||
|         ListAdapteeCollection<DepictedItem> collection = new ListAdapteeCollection<>( | ||||
|                 itemList != null ? itemList : Collections.emptyList()); | ||||
|         return new RVRendererAdapter<>(builder, collection); | ||||
|     } | ||||
| } | ||||
|  | @ -1,87 +0,0 @@ | |||
| package fr.free.nrw.commons.upload; | ||||
| 
 | ||||
| import android.net.Uri; | ||||
| import android.text.TextUtils; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.CheckBox; | ||||
| import android.widget.TextView; | ||||
| import butterknife.BindView; | ||||
| import butterknife.ButterKnife; | ||||
| import com.facebook.common.util.UriUtil; | ||||
| import com.facebook.drawee.view.SimpleDraweeView; | ||||
| import com.pedrogomez.renderers.Renderer; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; | ||||
| import fr.free.nrw.commons.upload.structure.depictions.UploadDepictsCallback; | ||||
| 
 | ||||
| /** | ||||
|  * Depicts Renderer for setting up inflating layout, | ||||
|  * and setting views for the layout of each depicted Item | ||||
|  */ | ||||
| public class UploadDepictsRenderer extends Renderer<DepictedItem> { | ||||
|     private final UploadDepictsCallback listener; | ||||
|     @BindView(R.id.depict_checkbox) | ||||
|     CheckBox checkedView; | ||||
|     @BindView(R.id.depicts_label) | ||||
|     TextView depictsLabel; | ||||
|     @BindView(R.id.description) TextView description; | ||||
|     @BindView(R.id.depicted_image) | ||||
|     SimpleDraweeView imageView; | ||||
| 
 | ||||
|     public UploadDepictsRenderer(UploadDepictsCallback listener) { | ||||
|         this.listener = listener; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void setUpView(View rootView) { | ||||
|         ButterKnife.bind(this, rootView); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Setup OnClicklisteners on the views | ||||
|      */ | ||||
|     @Override | ||||
|     protected void hookListeners(View rootView) { | ||||
|         rootView.setOnClickListener(v -> { | ||||
|             DepictedItem item = getContent(); | ||||
|             item.setSelected(!item.isSelected()); | ||||
|             checkedView.setChecked(item.isSelected()); | ||||
|             if (listener != null) { | ||||
|                 listener.depictsClicked(item); | ||||
|             } | ||||
|         }); | ||||
|         checkedView.setOnClickListener(v -> { | ||||
|             DepictedItem item = getContent(); | ||||
|             item.setSelected(!item.isSelected()); | ||||
|             checkedView.setChecked(item.isSelected()); | ||||
|             if (listener != null) { | ||||
|                 listener.depictsClicked(item); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected View inflate(LayoutInflater inflater, ViewGroup parent) { | ||||
|         return inflater.inflate(R.layout.layout_upload_depicts_item, parent, false); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * initialise views for every item in the adapter | ||||
|      */ | ||||
|     @Override | ||||
|     public void render() { | ||||
|         DepictedItem item = getContent(); | ||||
|         checkedView.setChecked(item.isSelected()); | ||||
|         depictsLabel.setText(item.getName()); | ||||
|         description.setText(item.getDescription()); | ||||
|         final String imageUrl = item.getImageUrl(); | ||||
|         if (TextUtils.isEmpty(imageUrl)) { | ||||
|             imageView.setImageURI(UriUtil.getUriForResourceId(R.drawable.ic_wikidata_logo_24dp)); | ||||
|         } else { | ||||
|             imageView.setImageURI(Uri.parse(imageUrl)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,41 @@ | |||
| package fr.free.nrw.commons.upload.categories | ||||
| 
 | ||||
| import androidx.recyclerview.widget.DiffUtil | ||||
| import com.hannesdorfmann.adapterdelegates4.AdapterDelegate | ||||
| import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter | ||||
| 
 | ||||
| 
 | ||||
| abstract class BaseDelegateAdapter<T>( | ||||
|     vararg delegates: AdapterDelegate<List<T>>, | ||||
|     areItemsTheSame: (T, T) -> Boolean, | ||||
|     areContentsTheSame: (T, T) -> Boolean = { old, new -> old == new } | ||||
| ) : AsyncListDifferDelegationAdapter<T>( | ||||
|     object : DiffUtil.ItemCallback<T>() { | ||||
|         override fun areItemsTheSame(oldItem: T, newItem: T) = | ||||
|             areItemsTheSame(oldItem, newItem) | ||||
| 
 | ||||
|         override fun areContentsTheSame(oldItem: T, newItem: T) = | ||||
|             areContentsTheSame(oldItem, newItem) | ||||
|     }, | ||||
|     *delegates | ||||
| ) { | ||||
| 
 | ||||
|     fun addAll(newResults: List<T>) { | ||||
|         items = itemsOrEmpty + newResults | ||||
|     } | ||||
| 
 | ||||
|     fun clear() { | ||||
|         items = emptyList() | ||||
|     } | ||||
| 
 | ||||
|     fun add(item: T) { | ||||
|         items = itemsOrEmpty + item | ||||
|     } | ||||
| 
 | ||||
|     fun remove(item: T) { | ||||
|         items = itemsOrEmpty - item | ||||
|     } | ||||
| 
 | ||||
|     private val itemsOrEmpty get() = items ?: emptyList<T>() | ||||
| } | ||||
| 
 | ||||
|  | @ -18,23 +18,19 @@ import com.google.android.material.textfield.TextInputEditText; | |||
| import com.google.android.material.textfield.TextInputLayout; | ||||
| import com.jakewharton.rxbinding2.view.RxView; | ||||
| import com.jakewharton.rxbinding2.widget.RxTextView; | ||||
| import com.pedrogomez.renderers.RVRendererAdapter; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.category.CategoryClickedListener; | ||||
| import fr.free.nrw.commons.category.CategoryItem; | ||||
| import fr.free.nrw.commons.upload.UploadBaseFragment; | ||||
| import fr.free.nrw.commons.upload.UploadCategoriesAdapterFactory; | ||||
| import fr.free.nrw.commons.utils.DialogUtil; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.Disposable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import javax.inject.Inject; | ||||
| import kotlin.Unit; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| public class UploadCategoriesFragment extends UploadBaseFragment implements CategoriesContract.View, | ||||
|         CategoryClickedListener { | ||||
| public class UploadCategoriesFragment extends UploadBaseFragment implements CategoriesContract.View { | ||||
| 
 | ||||
|     @BindView(R.id.tv_title) | ||||
|     TextView tvTitle; | ||||
|  | @ -49,14 +45,9 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate | |||
| 
 | ||||
|     @Inject | ||||
|     CategoriesContract.UserActionListener presenter; | ||||
|     private RVRendererAdapter<CategoryItem> adapter; | ||||
|     private UploadCategoryAdapter adapter; | ||||
|     private Disposable subscribe; | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     @Override | ||||
|     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, | ||||
|  | @ -93,8 +84,10 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate | |||
|     } | ||||
| 
 | ||||
|     private void initRecyclerView() { | ||||
|         adapter = new UploadCategoriesAdapterFactory(this) | ||||
|                 .create(new ArrayList<>()); | ||||
|         adapter = new UploadCategoryAdapter(categoryItem -> { | ||||
|             presenter.onCategoryItemClicked(categoryItem); | ||||
|             return Unit.INSTANCE; | ||||
|         }); | ||||
|         rvCategories.setLayoutManager(new LinearLayoutManager(getContext())); | ||||
|         rvCategories.setAdapter(adapter); | ||||
|     } | ||||
|  | @ -123,10 +116,11 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate | |||
| 
 | ||||
|     @Override | ||||
|     public void setCategories(List<CategoryItem> categories) { | ||||
|         adapter.clear(); | ||||
|         if (categories != null) { | ||||
|             adapter.addAll(categories); | ||||
|             adapter.notifyDataSetChanged(); | ||||
|         if(categories==null) { | ||||
|             adapter.clear(); | ||||
|         } | ||||
|         else{ | ||||
|             adapter.setItems(categories); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -157,11 +151,6 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate | |||
|         callback.onPreviousButtonClicked(callback.getIndexInViewFlipper(this)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void categoryClicked(CategoryItem item) { | ||||
|         presenter.onCategoryItemClicked(item); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onBecameVisible() { | ||||
|         super.onBecameVisible(); | ||||
|  |  | |||
|  | @ -0,0 +1,14 @@ | |||
| package fr.free.nrw.commons.upload.categories | ||||
| 
 | ||||
| import fr.free.nrw.commons.category.CategoryItem | ||||
| 
 | ||||
| class UploadCategoryAdapter(onCategoryClicked: (CategoryItem) -> Unit) : | ||||
|     BaseDelegateAdapter<CategoryItem>( | ||||
|         uploadCategoryDelegate(onCategoryClicked), | ||||
|         areItemsTheSame = { oldItem, newItem -> oldItem.name == newItem.name }, | ||||
|         areContentsTheSame = { oldItem, newItem -> | ||||
|             oldItem.name == newItem.name && oldItem.isSelected == newItem.isSelected | ||||
|         } | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,19 @@ | |||
| package fr.free.nrw.commons.upload.categories | ||||
| 
 | ||||
| import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer | ||||
| import fr.free.nrw.commons.R | ||||
| import fr.free.nrw.commons.category.CategoryItem | ||||
| import kotlinx.android.synthetic.main.layout_upload_categories_item.* | ||||
| 
 | ||||
| fun uploadCategoryDelegate(onCategoryClicked: (CategoryItem) -> Unit) = | ||||
|     adapterDelegateLayoutContainer<CategoryItem, CategoryItem>(R.layout.layout_upload_categories_item) { | ||||
|         containerView.setOnClickListener { | ||||
|             item.isSelected = !item.isSelected | ||||
|             uploadCategoryCheckbox.isChecked = item.isSelected | ||||
|             onCategoryClicked(item) | ||||
|         } | ||||
|         bind { | ||||
|             uploadCategoryCheckbox.isChecked = item.isSelected | ||||
|             uploadCategoryCheckbox.text = item.name | ||||
|         } | ||||
|     } | ||||
|  | @ -1,7 +1,6 @@ | |||
| package fr.free.nrw.commons.upload.depicts; | ||||
| 
 | ||||
| import android.os.Bundle; | ||||
| import android.util.Pair; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
|  | @ -18,27 +17,23 @@ import com.google.android.material.textfield.TextInputEditText; | |||
| import com.google.android.material.textfield.TextInputLayout; | ||||
| import com.jakewharton.rxbinding2.view.RxView; | ||||
| import com.jakewharton.rxbinding2.widget.RxTextView; | ||||
| import com.pedrogomez.renderers.RVRendererAdapter; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.upload.UploadBaseFragment; | ||||
| import fr.free.nrw.commons.upload.UploadDepictsAdapterFactory; | ||||
| import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; | ||||
| import fr.free.nrw.commons.upload.structure.depictions.UploadDepictsCallback; | ||||
| import fr.free.nrw.commons.utils.DialogUtil; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.Disposable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import javax.inject.Inject; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| import kotlin.Unit; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Fragment for showing depicted items list in Upload activity after media details | ||||
|  */ | ||||
| public class DepictsFragment extends UploadBaseFragment implements DepictsContract.View, UploadDepictsCallback { | ||||
| public class DepictsFragment extends UploadBaseFragment implements DepictsContract.View { | ||||
| 
 | ||||
|     @BindView(R.id.depicts_title) | ||||
|     TextView depictsTitle; | ||||
|  | @ -53,7 +48,7 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra | |||
| 
 | ||||
|     @Inject | ||||
|     DepictsContract.UserActionListener presenter; | ||||
|     private RVRendererAdapter<DepictedItem> adapter; | ||||
|     private UploadDepictsAdapter adapter; | ||||
|     private Disposable subscribe; | ||||
| 
 | ||||
|     @Nullable | ||||
|  | @ -86,8 +81,10 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra | |||
|      * Initialise recyclerView and set adapter | ||||
|      */ | ||||
|     private void initRecyclerView() { | ||||
|         adapter = new UploadDepictsAdapterFactory(this) | ||||
|                 .create(new ArrayList<>()); | ||||
|         adapter = new UploadDepictsAdapter(item -> { | ||||
|             presenter.onDepictItemClicked(item); | ||||
|             return Unit.INSTANCE; | ||||
|         }); | ||||
|         depictsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); | ||||
|         depictsRecyclerView.setAdapter(adapter); | ||||
|     } | ||||
|  | @ -137,22 +134,7 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra | |||
| 
 | ||||
|     @Override | ||||
|     public void setDepictsList(List<DepictedItem> depictedItemList) { | ||||
|         adapter.clear(); | ||||
|         if (depictedItemList != null) { | ||||
|             adapter.addAll(depictedItemList); | ||||
|             adapter.notifyDataSetChanged(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     private Pair<DepictedItem,Integer> returnItemAndPosition(@NotNull DepictedItem depictedItem) { | ||||
|         for (int i = 0; i < adapter.getItemCount(); i++) { | ||||
|             final DepictedItem item = adapter.getItem(i); | ||||
|             if(item.getId().equals(depictedItem.getId())){ | ||||
|                 return new Pair<>(item, i); | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|         adapter.setItems(depictedItemList); | ||||
|     } | ||||
| 
 | ||||
|     @OnClick(R.id.depicts_next) | ||||
|  | @ -165,11 +147,6 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra | |||
|         callback.onPreviousButtonClicked(callback.getIndexInViewFlipper(this)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void depictsClicked(DepictedItem item) { | ||||
|         presenter.onDepictItemClicked(item); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Text change listener for the edit text view of depicts | ||||
|      */ | ||||
|  |  | |||
|  | @ -0,0 +1,10 @@ | |||
| package fr.free.nrw.commons.upload.depicts | ||||
| 
 | ||||
| import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter | ||||
| import fr.free.nrw.commons.upload.structure.depictions.DepictedItem | ||||
| 
 | ||||
| class UploadDepictsAdapter(onDepictsClicked: (DepictedItem) -> Unit) : | ||||
|     BaseDelegateAdapter<DepictedItem>( | ||||
|         uploadDepictsDelegate(onDepictsClicked), | ||||
|         areItemsTheSame = { oldItem, newItem -> oldItem.id == newItem.id } | ||||
|     ) | ||||
|  | @ -0,0 +1,32 @@ | |||
| package fr.free.nrw.commons.upload.depicts | ||||
| 
 | ||||
| import android.net.Uri | ||||
| import android.text.TextUtils | ||||
| import android.view.View | ||||
| 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.layout_upload_depicts_item.* | ||||
| 
 | ||||
| 
 | ||||
| fun uploadDepictsDelegate(onDepictClicked: (DepictedItem) -> Unit) = | ||||
|     adapterDelegateLayoutContainer<DepictedItem, DepictedItem>(R.layout.layout_upload_depicts_item) { | ||||
|         val onClickListener = { _: View? -> | ||||
|             item.isSelected = !item.isSelected | ||||
|             depict_checkbox.isChecked = item.isSelected | ||||
|             onDepictClicked(item) | ||||
|         } | ||||
|         containerView.setOnClickListener(onClickListener) | ||||
|         depict_checkbox.setOnClickListener(onClickListener) | ||||
|         bind { | ||||
|             depict_checkbox.isChecked = item.isSelected | ||||
|             depicts_label.text = item.name | ||||
|             description.text = item.description | ||||
|             val imageUrl = item.imageUrl | ||||
|             if (TextUtils.isEmpty(imageUrl)) { | ||||
|                 depicted_image.setActualImageResource(R.drawable.ic_wikidata_logo_24dp) | ||||
|             } else { | ||||
|                 depicted_image.setImageURI(Uri.parse(imageUrl)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -1,56 +0,0 @@ | |||
| package fr.free.nrw.commons.upload.structure.depictions; | ||||
| 
 | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.CheckedTextView; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import com.pedrogomez.renderers.Renderer; | ||||
| 
 | ||||
| import butterknife.BindView; | ||||
| import butterknife.ButterKnife; | ||||
| import fr.free.nrw.commons.R; | ||||
| 
 | ||||
| public class DepictionRenderer extends Renderer<DepictedItem> { | ||||
|     @BindView(R.id.depict_checkbox) | ||||
|     CheckedTextView checkedView; | ||||
|     private final UploadDepictsCallback listener; | ||||
|     @BindView(R.id.depicts_label) | ||||
|     TextView depictsLabel; | ||||
|     @BindView(R.id.description) TextView description; | ||||
| 
 | ||||
|     public DepictionRenderer(UploadDepictsCallback listener) { | ||||
|         this.listener = listener; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void setUpView(View rootView) { | ||||
|             ButterKnife.bind(this, rootView); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void hookListeners(View rootView) { | ||||
|         rootView.setOnClickListener( v -> { | ||||
|             DepictedItem item = getContent(); | ||||
|             item.setSelected(true); | ||||
|             checkedView.setChecked(item.isSelected()); | ||||
|             if (listener != null) { | ||||
|                 listener.depictsClicked(item); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected View inflate(LayoutInflater inflater, ViewGroup parent) { | ||||
|         return inflater.inflate(R.layout.layout_upload_depicts_item, parent, false); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render() { | ||||
|         DepictedItem item = getContent(); | ||||
|         checkedView.setChecked(item.isSelected()); | ||||
|         depictsLabel.setText(item.getName()); | ||||
|         description.setText(item.getDescription()); | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Seán Mac Gillicuddy
						Seán Mac Gillicuddy