#3120 Suggest categories based on depictions (#3736)

This commit is contained in:
Seán Mac Gillicuddy 2020-05-20 15:26:16 +01:00 committed by GitHub
parent 01839dec6e
commit de3377c0fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 99 additions and 84 deletions

View file

@ -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;

View file

@ -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<String>): Observable<List<CategoryItem>> {
return suggestionsOrSearch(term, imageTitleList)
fun searchAll(
term: String,
imageTitleList: List<String>,
selectedDepictions: List<DepictedItem>
): Observable<List<CategoryItem>> {
return suggestionsOrSearch(term, imageTitleList, selectedDepictions)
.map { it.map { CategoryItem(it, false) } }
}
private fun suggestionsOrSearch(term: String, imageTitleList: List<String>):
Observable<List<String>> {
private fun suggestionsOrSearch(
term: String,
imageTitleList: List<String>,
selectedDepictions: List<DepictedItem>
): Observable<List<String>> {
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<DepictedItem>) =
Observable.just(selectedDepictions.map { it.commonsCategories }.flatten())
private fun combine(
depictionCategories: List<String>,
locationCategories: List<String>,
titles: List<String>,
recents: List<String>
) = locationCategories + titles + recents
) = depictionCategories + locationCategories + titles + recents
/**
@ -98,14 +111,13 @@ class CategoriesModel @Inject constructor(
* @param titleList
* @return
*/
private fun titleCategories(titleList: List<String>): Observable<List<String>> {
return if (titleList.isNotEmpty())
private fun titleCategories(titleList: List<String>) =
if (titleList.isNotEmpty())
Observable.combineLatest(titleList.map { getTitleCategories(it) }) { searchResults ->
searchResults.map { it as List<String> }.flatten()
}
else
Observable.just(emptyList())
}
/**
* Return category for single title

View file

@ -155,5 +155,4 @@ public class SearchDepictionsFragmentPresenter extends CommonsDaggerSupportFragm
offset=queryList.size();
}
}
}

View file

@ -171,7 +171,7 @@ public class MediaClient {
* @return caption for image using wikibaseIdentifier
*/
public Single<String> 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()) {

View file

@ -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<Entities> getCaptionForImage(@Query("languages") String language, @Query("ids") String wikibaseIdentifier);
Observable<Entities> getEntityForImage(@Query("languages") String language, @Query("ids") String wikibaseIdentifier);
}

View file

@ -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,

View file

@ -108,10 +108,12 @@ public class UploadRepository {
*
* @param query
* @param imageTitleList
* @param selectedDepictions
* @return
*/
public Observable<List<CategoryItem>> searchAll(String query, List<String> imageTitleList) {
return categoriesModel.searchAll(query, imageTitleList);
public Observable<List<CategoryItem>> searchAll(String query, List<String> imageTitleList,
List<DepictedItem> selectedDepictions) {
return categoriesModel.searchAll(query, imageTitleList, selectedDepictions);
}
/**

View file

@ -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) } }

View file

@ -107,7 +107,6 @@ class DepictsPresenter @Inject constructor(
view.noDepictionSelected()
}
}
}
inline fun <reified T> proxy() = Proxy

View file

@ -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<String>,
val commonsCategories: List<String>,
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<Statement_partial>?.toIds(): List<String> {
return this?.map { it.mainSnak.dataValue }
return this?.map { it.mainSnak.dataValue }
?.filterIsInstance<DataValue.EntityId>()
?.map { it.value.id }
?: emptyList()

View file

@ -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");
}