From de3377c0fe908b216b2dd29fa8549b84ebbcdd16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Mac=20Gillicuddy?= Date: Wed, 20 May 2020 15:26:16 +0100 Subject: [PATCH 01/11] #3120 Suggest categories based on depictions (#3736) --- .../nrw/commons/OkHttpConnectionFactory.java | 5 --- .../nrw/commons/category/CategoriesModel.kt | 32 +++++++++++----- .../SearchDepictionsFragmentPresenter.java | 1 - .../free/nrw/commons/media/MediaClient.java | 2 +- .../commons/media/MediaDetailInterface.java | 2 +- .../fragments/NearbyParentFragment.java | 37 ++++++++----------- .../commons/repository/UploadRepository.java | 6 ++- .../upload/categories/CategoriesPresenter.kt | 2 +- .../upload/depicts/DepictsPresenter.kt | 1 - .../structure/depictions/DepictedItem.kt | 10 +++-- .../commons/wikidata/WikidataProperties.kt | 6 ++- app/src/test/kotlin/ModelFunctions.kt | 23 ++++++++++++ .../commons/category/CategoriesModelTest.kt | 17 ++++++--- .../SearchDepictionsPresenterTest.kt | 5 +-- .../commons/upload/CategoriesPresenterTest.kt | 16 ++------ .../commons/upload/DepictsPresenterTest.kt | 18 ++------- 16 files changed, 99 insertions(+), 84 deletions(-) create mode 100644 app/src/test/kotlin/ModelFunctions.kt diff --git a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java index b9c10496c..9d3bde848 100644 --- a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java @@ -1,11 +1,6 @@ package fr.free.nrw.commons; import androidx.annotation.NonNull; - -import okhttp3.logging.HttpLoggingInterceptor.Level; -import org.wikipedia.dataclient.SharedPreferenceCookieManager; -import org.wikipedia.dataclient.okhttp.HttpStatusException; - import java.io.File; import java.io.IOException; import okhttp3.Cache; diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt index ae2d0b0fd..48ac1fc7c 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt @@ -2,9 +2,10 @@ package fr.free.nrw.commons.category import android.text.TextUtils import fr.free.nrw.commons.upload.GpsCategoryModel +import fr.free.nrw.commons.upload.structure.depictions.DepictedItem import fr.free.nrw.commons.utils.StringSortingUtils import io.reactivex.Observable -import io.reactivex.functions.Function3 +import io.reactivex.functions.Function4 import timber.log.Timber import java.util.* import javax.inject.Inject @@ -67,30 +68,42 @@ class CategoriesModel @Inject constructor( * @param imageTitleList * @return */ - fun searchAll(term: String, imageTitleList: List): Observable> { - return suggestionsOrSearch(term, imageTitleList) + fun searchAll( + term: String, + imageTitleList: List, + selectedDepictions: List + ): Observable> { + return suggestionsOrSearch(term, imageTitleList, selectedDepictions) .map { it.map { CategoryItem(it, false) } } } - private fun suggestionsOrSearch(term: String, imageTitleList: List): - Observable> { + private fun suggestionsOrSearch( + term: String, + imageTitleList: List, + selectedDepictions: List + ): Observable> { return if (TextUtils.isEmpty(term)) Observable.combineLatest( + categoriesFromDepiction(selectedDepictions), gpsCategoryModel.categoriesFromLocation, titleCategories(imageTitleList), Observable.just(categoryDao.recentCategories(SEARCH_CATS_LIMIT)), - Function3(::combine) + Function4(::combine) ) else categoryClient.searchCategoriesForPrefix(term.toLowerCase(), SEARCH_CATS_LIMIT) .map { it.sortedWith(StringSortingUtils.sortBySimilarity(term)) } } + private fun categoriesFromDepiction(selectedDepictions: List) = + Observable.just(selectedDepictions.map { it.commonsCategories }.flatten()) + private fun combine( + depictionCategories: List, locationCategories: List, titles: List, recents: List - ) = locationCategories + titles + recents + ) = depictionCategories + locationCategories + titles + recents /** @@ -98,14 +111,13 @@ class CategoriesModel @Inject constructor( * @param titleList * @return */ - private fun titleCategories(titleList: List): Observable> { - return if (titleList.isNotEmpty()) + private fun titleCategories(titleList: List) = + if (titleList.isNotEmpty()) Observable.combineLatest(titleList.map { getTitleCategories(it) }) { searchResults -> searchResults.map { it as List }.flatten() } else Observable.just(emptyList()) - } /** * Return category for single title diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.java index 4d08bab61..5edaa5c3e 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.java @@ -155,5 +155,4 @@ public class SearchDepictionsFragmentPresenter extends CommonsDaggerSupportFragm offset=queryList.size(); } } - } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java index a6ba1897e..dbcda6677 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java @@ -171,7 +171,7 @@ public class MediaClient { * @return caption for image using wikibaseIdentifier */ public Single getCaptionByWikibaseIdentifier(String wikibaseIdentifier) { - return mediaDetailInterface.getCaptionForImage(Locale.getDefault().getLanguage(), wikibaseIdentifier) + return mediaDetailInterface.getEntityForImage(Locale.getDefault().getLanguage(), wikibaseIdentifier) .map(mediaDetailResponse -> { if (isSuccess(mediaDetailResponse)) { for (Entity wikibaseItem : mediaDetailResponse.entities().values()) { diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailInterface.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailInterface.java index c972ccc12..4ded940de 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailInterface.java @@ -33,5 +33,5 @@ public interface MediaDetailInterface { * @param wikibaseIdentifier pageId for the media */ @GET("/w/api.php?action=wbgetentities&props=labels&format=json&languagefallback=1&sites=commonswiki") - Observable getCaptionForImage(@Query("languages") String language, @Query("ids") String wikibaseIdentifier); + Observable getEntityForImage(@Query("languages") String language, @Query("ids") String wikibaseIdentifier); } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java index 4d1aafb01..48cdefee9 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java @@ -1,5 +1,13 @@ package fr.free.nrw.commons.nearby.fragments; +import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION; +import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED; +import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED; +import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.MAP_UPDATED; +import static fr.free.nrw.commons.nearby.Label.TEXT_TO_DESCRIPTION; +import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween; +import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT; + import android.Manifest; import android.app.AlertDialog; import android.content.BroadcastReceiver; @@ -26,14 +34,14 @@ import android.widget.RelativeLayout; import android.widget.SearchView; import android.widget.TextView; import android.widget.Toast; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; - +import butterknife.BindView; +import butterknife.ButterKnife; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.chip.Chip; import com.google.android.material.chip.ChipGroup; @@ -58,17 +66,6 @@ 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.utils.DialogUtil; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; @@ -92,6 +89,7 @@ import fr.free.nrw.commons.nearby.NearbyMarker; import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract; import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter; +import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.ExecutorUtils; import fr.free.nrw.commons.utils.LayoutUtils; import fr.free.nrw.commons.utils.LocationUtils; @@ -105,16 +103,13 @@ import fr.free.nrw.commons.wikidata.WikidataEditListener; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; 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 timber.log.Timber; -import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION; -import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED; -import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED; -import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.MAP_UPDATED; -import static fr.free.nrw.commons.nearby.Label.TEXT_TO_DESCRIPTION; -import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween; -import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT; - public class NearbyParentFragment extends CommonsDaggerSupportFragment implements NearbyParentFragmentContract.View, diff --git a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java index 405ed7ef4..1e7090b18 100644 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java +++ b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java @@ -108,10 +108,12 @@ public class UploadRepository { * * @param query * @param imageTitleList + * @param selectedDepictions * @return */ - public Observable> searchAll(String query, List imageTitleList) { - return categoriesModel.searchAll(query, imageTitleList); + public Observable> searchAll(String query, List imageTitleList, + List selectedDepictions) { + return categoriesModel.searchAll(query, imageTitleList, selectedDepictions); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt index a8bbda460..8ad0ccf69 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt @@ -60,7 +60,7 @@ class CategoriesPresenter @Inject constructor( } private fun searchResults(term: String) = - repository.searchAll(term, getImageTitleList()) + repository.searchAll(term, getImageTitleList(), repository.selectedDepictions) .subscribeOn(ioScheduler) .map { it.filterNot { categoryItem -> repository.containsYear(categoryItem.name) } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt index 7bc0c699c..c9b8bde66 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt @@ -107,7 +107,6 @@ class DepictsPresenter @Inject constructor( view.noDepictionSelected() } } - } inline fun proxy() = Proxy diff --git a/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt b/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt index 4ae374a48..7a2ba99ef 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt @@ -5,6 +5,7 @@ import fr.free.nrw.commons.explore.depictions.THUMB_IMAGE_SIZE import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.upload.WikidataItem import fr.free.nrw.commons.wikidata.WikidataProperties +import fr.free.nrw.commons.wikidata.WikidataProperties.* import org.wikipedia.wikidata.DataValue import org.wikipedia.wikidata.Entities import org.wikipedia.wikidata.Statement_partial @@ -17,6 +18,7 @@ data class DepictedItem constructor( val description: String?, val imageUrl: String?, val instanceOfs: List, + val commonsCategories: List, var isSelected: Boolean, override val id: String ) : WikidataItem { @@ -36,10 +38,12 @@ data class DepictedItem constructor( constructor(entity: Entities.Entity, name: String, description: String) : this( name, description, - entity[WikidataProperties.IMAGE].primaryImageValue?.let { + entity[IMAGE].primaryImageValue?.let { getImageUrl(it.value, THUMB_IMAGE_SIZE) }, - entity[WikidataProperties.INSTANCE_OF].toIds(), + entity[INSTANCE_OF].toIds(), + entity[COMMONS_CATEGORY]?.map { (it.mainSnak.dataValue as DataValue.ValueString).value } + ?: emptyList(), false, entity.id() ) @@ -57,7 +61,7 @@ data class DepictedItem constructor( } private fun List?.toIds(): List { - return this?.map { it.mainSnak.dataValue } + return this?.map { it.mainSnak.dataValue } ?.filterIsInstance() ?.map { it.value.id } ?: emptyList() diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt index 0e591d55f..14db02a27 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataProperties.kt @@ -3,6 +3,8 @@ package fr.free.nrw.commons.wikidata import fr.free.nrw.commons.BuildConfig enum class WikidataProperties(val propertyName: String) { - IMAGE("P18"), DEPICTS(BuildConfig.DEPICTS_PROPERTY), INSTANCE_OF("P31"); - + IMAGE("P18"), + DEPICTS(BuildConfig.DEPICTS_PROPERTY), + COMMONS_CATEGORY("P373"), + INSTANCE_OF("P31"); } diff --git a/app/src/test/kotlin/ModelFunctions.kt b/app/src/test/kotlin/ModelFunctions.kt new file mode 100644 index 000000000..269f8f977 --- /dev/null +++ b/app/src/test/kotlin/ModelFunctions.kt @@ -0,0 +1,23 @@ +import fr.free.nrw.commons.category.CategoryItem +import fr.free.nrw.commons.upload.structure.depictions.DepictedItem + +fun depictedItem( + name: String = "label", + description: String = "desc", + imageUrl: String = "", + instanceOfs: List = listOf(), + commonsCategories: List = listOf(), + isSelected: Boolean = false, + id: String = "entityId" +) = DepictedItem( + name = name, + description = description, + imageUrl = imageUrl, + instanceOfs = instanceOfs, + commonsCategories = commonsCategories, + isSelected = isSelected, + id = id +) + +fun categoryItem(name: String = "name", selected: Boolean = false) = + CategoryItem(name, selected) diff --git a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt index 33c5371a4..80d0be554 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt @@ -1,7 +1,10 @@ package fr.free.nrw.commons.category +import categoryItem import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever +import depictedItem +import fr.free.nrw.commons.explore.depictions.DepictsClient import fr.free.nrw.commons.upload.GpsCategoryModel import io.reactivex.Observable import io.reactivex.subjects.BehaviorSubject @@ -36,11 +39,11 @@ class CategoriesModelTest { // Checking if both return "Test" val expectedItems = expectedList.map { CategoryItem(it, false) } - categoriesModel.searchAll("tes", emptyList()) + categoriesModel.searchAll("tes", emptyList(), emptyList()) .test() .assertValues(expectedItems) - categoriesModel.searchAll("Tes", emptyList()) + categoriesModel.searchAll("Tes", emptyList(), emptyList()) .test() .assertValues(expectedItems) } @@ -48,6 +51,7 @@ class CategoriesModelTest { @Test fun `searchAll with empty search terms creates results from gps, title search & recents`() { val gpsCategoryModel: GpsCategoryModel = mock() + val depictedItem = depictedItem(commonsCategories = listOf("depictionCategory")) whenever(gpsCategoryModel.categoriesFromLocation) .thenReturn(BehaviorSubject.createDefault(listOf("gpsCategory"))) @@ -55,13 +59,14 @@ class CategoriesModelTest { .thenReturn(Observable.just(listOf("titleSearch"))) whenever(categoryDao.recentCategories(25)).thenReturn(listOf("recentCategories")) CategoriesModel(categoryClient, categoryDao, gpsCategoryModel) - .searchAll("", listOf("tes")) + .searchAll("", listOf("tes"), listOf(depictedItem)) .test() .assertValue( listOf( - CategoryItem("gpsCategory", false), - CategoryItem("titleSearch", false), - CategoryItem("recentCategories", false) + categoryItem("depictionCategory"), + categoryItem("gpsCategory"), + categoryItem("titleSearch"), + categoryItem("recentCategories") ) ) } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/SearchDepictionsPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/SearchDepictionsPresenterTest.kt index 97978263f..1cdae8b38 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/SearchDepictionsPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/SearchDepictionsPresenterTest.kt @@ -1,10 +1,9 @@ package fr.free.nrw.commons.explore.depictions import com.nhaarman.mockitokotlin2.whenever +import depictedItem import fr.free.nrw.commons.explore.recentsearches.RecentSearchesDao import fr.free.nrw.commons.kvstore.JsonKvStore -import fr.free.nrw.commons.upload.depictedItem -import fr.free.nrw.commons.upload.structure.depictions.DepictedItem import io.reactivex.Single import io.reactivex.schedulers.TestScheduler import org.junit.Before @@ -36,7 +35,6 @@ class SearchDepictionsPresenterTest { fun setUp() { MockitoAnnotations.initMocks(this) testScheduler = TestScheduler() - val depictedItem: DepictedItem = depictedItem(instanceOfs = listOf()) searchDepictionsFragmentPresenter = SearchDepictionsFragmentPresenter( jsonKvStore, recentSearchesDao, @@ -56,5 +54,4 @@ class SearchDepictionsPresenterTest { testScheduler.triggerActions() verify(view)?.onSuccess(expectedList) } - } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt index bf53c4e12..c4945e495 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt @@ -1,8 +1,8 @@ package fr.free.nrw.commons.upload +import categoryItem import com.nhaarman.mockitokotlin2.* import fr.free.nrw.commons.R -import fr.free.nrw.commons.category.CategoryItem import fr.free.nrw.commons.repository.UploadRepository import fr.free.nrw.commons.upload.categories.CategoriesContract import fr.free.nrw.commons.upload.categories.CategoriesPresenter @@ -27,11 +27,6 @@ class CategoriesPresenterTest { private lateinit var testScheduler: TestScheduler - private val categoryItems: ArrayList = ArrayList() - - @Mock - lateinit var categoryItem: CategoryItem - /** * initial setup */ @@ -40,7 +35,6 @@ class CategoriesPresenterTest { fun setUp() { MockitoAnnotations.initMocks(this) testScheduler = TestScheduler() - categoryItems.add(categoryItem) categoriesPresenter = CategoriesPresenter(repository, testScheduler, testScheduler) categoriesPresenter.onAttachView(view) } @@ -62,7 +56,7 @@ class CategoriesPresenterTest { emptyCaptionUploadItem ) ) - whenever(repository.searchAll("test", listOf("nonEmpty"))) + whenever(repository.searchAll("test", listOf("nonEmpty"), repository.selectedDepictions)) .thenReturn( Observable.just( listOf( @@ -87,7 +81,7 @@ class CategoriesPresenterTest { @Test fun `searchForCategoriesTest sets Error when list is empty`() { whenever(repository.uploads).thenReturn(listOf()) - whenever(repository.searchAll(any(), any())).thenReturn(Observable.just(listOf())) + whenever(repository.searchAll(any(), any(), any())).thenReturn(Observable.just(listOf())) whenever(repository.selectedCategories).thenReturn(listOf()) categoriesPresenter.searchForCategories("test") testScheduler.triggerActions() @@ -124,10 +118,8 @@ class CategoriesPresenterTest { */ @Test fun onCategoryItemClickedTest() { + val categoryItem = categoryItem() categoriesPresenter.onCategoryItemClicked(categoryItem) verify(repository).onCategoryClicked(categoryItem) } - - private fun categoryItem(name: String = "name", selected: Boolean = false) = - CategoryItem(name, selected) } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/DepictsPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/DepictsPresenterTest.kt index 74ee342b4..c1b2d40c7 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/DepictsPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/DepictsPresenterTest.kt @@ -4,11 +4,11 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.jraska.livedata.test import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever +import depictedItem import fr.free.nrw.commons.explore.depictions.DepictsClient import fr.free.nrw.commons.repository.UploadRepository import fr.free.nrw.commons.upload.depicts.DepictsContract import fr.free.nrw.commons.upload.depicts.DepictsPresenter -import fr.free.nrw.commons.upload.structure.depictions.DepictedItem import fr.free.nrw.commons.wikidata.WikidataDisambiguationItems import io.reactivex.Flowable import io.reactivex.schedulers.TestScheduler @@ -62,8 +62,8 @@ class DepictsPresenterTest { depictedItem(id="nonUnique"), depictedItem(id="nonUnique"), depictedItem( - id = "unique", - instanceOfs = listOf(WikidataDisambiguationItems.CATEGORY.id) + instanceOfs = listOf(WikidataDisambiguationItems.CATEGORY.id), + id = "unique" ) ) whenever(repository.searchAllEntities("")).thenReturn(Flowable.just(searchResults)) @@ -78,6 +78,7 @@ class DepictsPresenterTest { .assertValue(listOf(selectedItem, depictedItem(id="nonUnique"))) } + @Test fun `empty search results with empty term do not show error`() { whenever(repository.searchAllEntities("")).thenReturn(Flowable.just(emptyList())) @@ -137,15 +138,4 @@ class DepictsPresenterTest { depictsPresenter.verifyDepictions() verify(view).noDepictionSelected() } - - } - -fun depictedItem( - name: String = "label", - description: String = "desc", - imageUrl: String = "", - instanceOfs: List = listOf(), - isSelected: Boolean = false, - id: String = "entityId" -) = DepictedItem(name, description, imageUrl, instanceOfs, isSelected, id) From 384afa6c44ce72bb49bdd5e5b9b2a510b5276d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Mac=20Gillicuddy?= Date: Thu, 21 May 2020 00:54:09 +0100 Subject: [PATCH 02/11] #3753 Item label/description: Fall back to non-empty language - attempt to read labels by language or the first one in the list (#3759) --- .../free/nrw/commons/explore/depictions/DepictsClient.kt | 2 +- .../free/nrw/commons/upload/depicts/DepictsInterface.java | 2 +- .../commons/upload/structure/depictions/DepictedItem.kt | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt index 043bf9c41..829c4fc8f 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/DepictsClient.kt @@ -75,7 +75,7 @@ class DepictsClient @Inject constructor( } fun getEntities(ids: String): Single { - return depictsInterface.getEntities(ids, Locale.getDefault().language) + return depictsInterface.getEntities(ids) } fun toDepictions(sparqlResponse: Observable): Observable> { diff --git a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsInterface.java b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsInterface.java index ed7ab1680..00aa81287 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsInterface.java @@ -24,5 +24,5 @@ public interface DepictsInterface { Single searchForDepicts(@Query("search") String query, @Query("limit") String limit, @Query("language") String language, @Query("uselang") String uselang, @Query("continue") String offset); @GET("/w/api.php?format=json&action=wbgetentities") - Single getEntities(@Query("ids")String ids, @Query("languages")String language); + Single getEntities(@Query("ids") String ids); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt b/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt index 7a2ba99ef..0ed29cc46 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictedItem.kt @@ -9,6 +9,7 @@ import fr.free.nrw.commons.wikidata.WikidataProperties.* import org.wikipedia.wikidata.DataValue import org.wikipedia.wikidata.Entities import org.wikipedia.wikidata.Statement_partial +import java.util.* /** * Model class for Depicted Item in Upload and Explore @@ -25,8 +26,8 @@ data class DepictedItem constructor( constructor(entity: Entities.Entity) : this( entity, - entity.labels().values.firstOrNull()?.value() ?: "", - entity.descriptions().values.firstOrNull()?.value() ?: "" + entity.labels().byLanguageOrFirstOrEmpty(), + entity.descriptions().byLanguageOrFirstOrEmpty() ) constructor(entity: Entities.Entity, place: Place) : this( @@ -73,3 +74,5 @@ private val List?.primaryImageValue: DataValue.ValueString? operator fun Entities.Entity.get(property: WikidataProperties) = statements?.get(property.propertyName) +private fun Map.byLanguageOrFirstOrEmpty() = + let { it[Locale.getDefault().language] ?: it.values.firstOrNull() }?.value() ?: "" From 3f31c3eded44de2df8989c0868a0d1f8559874b8 Mon Sep 17 00:00:00 2001 From: neslihanturan Date: Thu, 21 May 2020 13:58:27 +0300 Subject: [PATCH 03/11] Add bookmarks to Nearby map (#3728) * Remove bookmark button from row button set and put to upper level list item * Fix npe caused by lookinf for parent fragment, we don't have one anymore * style * Add new icons for bookmarked places * Change bookmarked info when bookmarked * Add pic field to bookmark dao so that we can retrieve them later * Put bookmarks as the first item of list * Add bookmark as a label * Add logic to filter nearby * remove unneeded changes * fix word * Remove logs * Remove unused part of code * Fix tests * Remove logs * simplify icon picking * remove redundant margin left * Remove non needed map and swap * Add main thread annotation * Fix tests --- .../locations/BookmarkLocationsDao.java | 6 ++- .../fr/free/nrw/commons/nearby/Label.java | 7 +++ .../nrw/commons/nearby/NearbyController.java | 47 +++++++------------ ...NearbyFilterSearchRecyclerViewAdapter.java | 1 + .../nrw/commons/nearby/PlaceRenderer.java | 9 ++-- .../fragments/NearbyParentFragment.java | 45 ++++++++++-------- .../NearbyParentFragmentPresenter.java | 5 +- .../ic_custom_map_marker_blue_bookmarked.xml | 29 ++++++++++++ .../ic_custom_map_marker_green_bookmarked.xml | 29 ++++++++++++ .../ic_custom_map_marker_grey_bookmarked.xml | 29 ++++++++++++ app/src/main/res/layout/item_place.xml | 10 +++- app/src/main/res/layout/nearby_row_button.xml | 28 ----------- .../locations/BookMarkLocationDaoTest.kt | 6 ++- 13 files changed, 161 insertions(+), 90 deletions(-) create mode 100644 app/src/main/res/drawable/ic_custom_map_marker_blue_bookmarked.xml create mode 100644 app/src/main/res/drawable/ic_custom_map_marker_green_bookmarked.xml create mode 100644 app/src/main/res/drawable/ic_custom_map_marker_grey_bookmarked.xml diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsDao.java b/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsDao.java index 3efef06d4..610f1d30e 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsDao.java +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/locations/BookmarkLocationsDao.java @@ -9,6 +9,7 @@ import android.os.RemoteException; import androidx.annotation.NonNull; +import fr.free.nrw.commons.nearby.NearbyController; import java.util.ArrayList; import java.util.List; @@ -74,8 +75,10 @@ public class BookmarkLocationsDao { boolean bookmarkExists = findBookmarkLocation(bookmarkLocation); if (bookmarkExists) { deleteBookmarkLocation(bookmarkLocation); + NearbyController.updateMarkerLabelListBookmark(bookmarkLocation, false); } else { addBookmarkLocation(bookmarkLocation); + NearbyController.updateMarkerLabelListBookmark(bookmarkLocation, true); } return !bookmarkExists; } @@ -160,10 +163,9 @@ public class BookmarkLocationsDao { location, cursor.getString(cursor.getColumnIndex(Table.COLUMN_CATEGORY)), builder.build(), - null, + cursor.getString(cursor.getColumnIndex(Table.COLUMN_PIC)), null ); - // TODO: add pic and destroyed to bookmark location dao } private ContentValues toContentValues(Place bookmarkLocation) { diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/Label.java b/app/src/main/java/fr/free/nrw/commons/nearby/Label.java index ac939f5da..19c175fd8 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/Label.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/Label.java @@ -4,7 +4,9 @@ import android.os.Parcel; import androidx.annotation.DrawableRes; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import fr.free.nrw.commons.R; @@ -17,6 +19,7 @@ import fr.free.nrw.commons.R; */ public enum Label { + BOOKMARKS("BOOKMARK", R.drawable.ic_filled_star_24dp), BUILDING("Q41176", R.drawable.round_icon_generic_building), HOUSE("Q3947", R.drawable.round_icon_house), COTTAGE("Q5783996", R.drawable.round_icon_house), @@ -92,4 +95,8 @@ public enum Label { Label label = TEXT_TO_DESCRIPTION.get(text); return label == null ? UNKNOWN : label; } + + public static List