mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 12:53:55 +01:00
Displaying Category image and Description (#4531)
* API call done * API call * Image implementation done * Gradle * Java docs and code convention * Description added * Refactoring Category * Refactoring Category * Refactoring Category * Description and thumbnail issue fixed * Description and thumbnail issue fixed * Minor issue fixed * Minor issue fixed * Server changed * Logo changed * Change in structure * Fixed failed tests * Fixed Test failed * Optimized imports * Dialog can't be dismissed * Dialog can't be dismissed * Resolved Conflicts * UI fixed * Added description and thumbnail in local DB * Added description and thumbnail in local DB * Test fixed * Added * Updated with latest master * Test Updated with latest master * Issue fixed * Revert gradle changes * Revert gradle changes * Update gradle-wrapper.properties * Require Api removed
This commit is contained in:
parent
0914eeea53
commit
92957f4204
31 changed files with 373 additions and 151 deletions
|
|
@ -5,6 +5,7 @@ import android.content.ContentValues;
|
|||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.RemoteException;
|
||||
import fr.free.nrw.commons.category.CategoryItem;
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -141,9 +142,17 @@ public class BookmarkItemsDao {
|
|||
final String instanceListString
|
||||
= cursor.getString(cursor.getColumnIndex(Table.COLUMN_INSTANCE_LIST));
|
||||
final List<String> instanceList = StringToArray(instanceListString);
|
||||
final String categoryListString = cursor.getString(cursor
|
||||
.getColumnIndex(Table.COLUMN_CATEGORIES_LIST));
|
||||
final List<String> categoryList = StringToArray(categoryListString);
|
||||
final String categoryNameListString = cursor.getString(cursor
|
||||
.getColumnIndex(Table.COLUMN_CATEGORIES_NAME_LIST));
|
||||
final List<String> categoryNameList = StringToArray(categoryNameListString);
|
||||
final String categoryDescriptionListString = cursor.getString(cursor
|
||||
.getColumnIndex(Table.COLUMN_CATEGORIES_DESCRIPTION_LIST));
|
||||
final List<String> categoryDescriptionList = StringToArray(categoryDescriptionListString);
|
||||
final String categoryThumbnailListString = cursor.getString(cursor
|
||||
.getColumnIndex(Table.COLUMN_CATEGORIES_THUMBNAIL_LIST));
|
||||
final List<String> categoryThumbnailList = StringToArray(categoryThumbnailListString);
|
||||
final List<CategoryItem> categoryList = convertToCategoryItems(categoryNameList,
|
||||
categoryDescriptionList, categoryThumbnailList);
|
||||
final boolean isSelected
|
||||
= Boolean.parseBoolean(cursor.getString(cursor
|
||||
.getColumnIndex(Table.COLUMN_IS_SELECTED)));
|
||||
|
|
@ -160,6 +169,17 @@ public class BookmarkItemsDao {
|
|||
);
|
||||
}
|
||||
|
||||
private List<CategoryItem> convertToCategoryItems(List<String> categoryNameList,
|
||||
List<String> categoryDescriptionList, List<String> categoryThumbnailList) {
|
||||
List<CategoryItem> categoryItems = new ArrayList<>();
|
||||
for(int i=0; i<categoryNameList.size(); i++){
|
||||
categoryItems.add(new CategoryItem(categoryNameList.get(i),
|
||||
categoryDescriptionList.get(i),
|
||||
categoryThumbnailList.get(i), false));
|
||||
}
|
||||
return categoryItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string to List
|
||||
* @param listString comma separated single string from of list items
|
||||
|
|
@ -188,12 +208,35 @@ public class BookmarkItemsDao {
|
|||
* @return ContentValues
|
||||
*/
|
||||
private ContentValues toContentValues(final DepictedItem depictedItem) {
|
||||
|
||||
final List<String> namesOfCommonsCategories = new ArrayList<>();
|
||||
for (final CategoryItem category :
|
||||
depictedItem.getCommonsCategories()) {
|
||||
namesOfCommonsCategories.add(category.getName());
|
||||
}
|
||||
|
||||
final List<String> descriptionsOfCommonsCategories = new ArrayList<>();
|
||||
for (final CategoryItem category :
|
||||
depictedItem.getCommonsCategories()) {
|
||||
descriptionsOfCommonsCategories.add(category.getDescription());
|
||||
}
|
||||
|
||||
final List<String> thumbnailsOfCommonsCategories = new ArrayList<>();
|
||||
for (final CategoryItem category :
|
||||
depictedItem.getCommonsCategories()) {
|
||||
thumbnailsOfCommonsCategories.add(category.getThumbnail());
|
||||
}
|
||||
|
||||
final ContentValues cv = new ContentValues();
|
||||
cv.put(Table.COLUMN_NAME, depictedItem.getName());
|
||||
cv.put(Table.COLUMN_DESCRIPTION, depictedItem.getDescription());
|
||||
cv.put(Table.COLUMN_IMAGE, depictedItem.getImageUrl());
|
||||
cv.put(Table.COLUMN_INSTANCE_LIST, ArrayToString(depictedItem.getInstanceOfs()));
|
||||
cv.put(Table.COLUMN_CATEGORIES_LIST, ArrayToString(depictedItem.getCommonsCategories()));
|
||||
cv.put(Table.COLUMN_CATEGORIES_NAME_LIST, ArrayToString(namesOfCommonsCategories));
|
||||
cv.put(Table.COLUMN_CATEGORIES_DESCRIPTION_LIST,
|
||||
ArrayToString(descriptionsOfCommonsCategories));
|
||||
cv.put(Table.COLUMN_CATEGORIES_THUMBNAIL_LIST,
|
||||
ArrayToString(thumbnailsOfCommonsCategories));
|
||||
cv.put(Table.COLUMN_IS_SELECTED, depictedItem.isSelected());
|
||||
cv.put(Table.COLUMN_ID, depictedItem.getId());
|
||||
return cv;
|
||||
|
|
@ -208,7 +251,9 @@ public class BookmarkItemsDao {
|
|||
public static final String COLUMN_DESCRIPTION = "item_description";
|
||||
public static final String COLUMN_IMAGE = "item_image_url";
|
||||
public static final String COLUMN_INSTANCE_LIST = "item_instance_of";
|
||||
public static final String COLUMN_CATEGORIES_LIST = "item_categories";
|
||||
public static final String COLUMN_CATEGORIES_NAME_LIST = "item_name_categories";
|
||||
public static final String COLUMN_CATEGORIES_DESCRIPTION_LIST = "item_description_categories";
|
||||
public static final String COLUMN_CATEGORIES_THUMBNAIL_LIST = "item_thumbnail_categories";
|
||||
public static final String COLUMN_IS_SELECTED = "item_is_selected";
|
||||
public static final String COLUMN_ID = "item_id";
|
||||
|
||||
|
|
@ -217,7 +262,9 @@ public class BookmarkItemsDao {
|
|||
COLUMN_DESCRIPTION,
|
||||
COLUMN_IMAGE,
|
||||
COLUMN_INSTANCE_LIST,
|
||||
COLUMN_CATEGORIES_LIST,
|
||||
COLUMN_CATEGORIES_NAME_LIST,
|
||||
COLUMN_CATEGORIES_DESCRIPTION_LIST,
|
||||
COLUMN_CATEGORIES_THUMBNAIL_LIST,
|
||||
COLUMN_IS_SELECTED,
|
||||
COLUMN_ID
|
||||
};
|
||||
|
|
@ -228,7 +275,9 @@ public class BookmarkItemsDao {
|
|||
+ COLUMN_DESCRIPTION + " STRING,"
|
||||
+ COLUMN_IMAGE + " STRING,"
|
||||
+ COLUMN_INSTANCE_LIST + " STRING,"
|
||||
+ COLUMN_CATEGORIES_LIST + " STRING,"
|
||||
+ COLUMN_CATEGORIES_NAME_LIST + " STRING,"
|
||||
+ COLUMN_CATEGORIES_DESCRIPTION_LIST + " STRING,"
|
||||
+ COLUMN_CATEGORIES_THUMBNAIL_LIST + " STRING,"
|
||||
+ COLUMN_IS_SELECTED + " STRING,"
|
||||
+ COLUMN_ID + " STRING PRIMARY KEY"
|
||||
+ ");";
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class CategoriesModel @Inject constructor(
|
|||
|
||||
// Newly used category...
|
||||
if (category == null) {
|
||||
category = Category(null, item.name, Date(), 0)
|
||||
category = Category(null, item.name, item.description, item.thumbnail, Date(), 0)
|
||||
}
|
||||
category.incTimesUsed()
|
||||
categoryDao.save(category)
|
||||
|
|
@ -74,14 +74,14 @@ class CategoriesModel @Inject constructor(
|
|||
selectedDepictions: List<DepictedItem>
|
||||
): Observable<List<CategoryItem>> {
|
||||
return suggestionsOrSearch(term, imageTitleList, selectedDepictions)
|
||||
.map { it.map { CategoryItem(it, false) } }
|
||||
.map { it.map { CategoryItem(it.name, it.description, it.thumbnail, false) } }
|
||||
}
|
||||
|
||||
private fun suggestionsOrSearch(
|
||||
term: String,
|
||||
imageTitleList: List<String>,
|
||||
selectedDepictions: List<DepictedItem>
|
||||
): Observable<List<String>> {
|
||||
): Observable<List<CategoryItem>> {
|
||||
return if (TextUtils.isEmpty(term))
|
||||
Observable.combineLatest(
|
||||
categoriesFromDepiction(selectedDepictions),
|
||||
|
|
@ -100,10 +100,10 @@ class CategoriesModel @Inject constructor(
|
|||
Observable.just(selectedDepictions.map { it.commonsCategories }.flatten())
|
||||
|
||||
private fun combine(
|
||||
depictionCategories: List<String>,
|
||||
locationCategories: List<String>,
|
||||
titles: List<String>,
|
||||
recents: List<String>
|
||||
depictionCategories: List<CategoryItem>,
|
||||
locationCategories: List<CategoryItem>,
|
||||
titles: List<CategoryItem>,
|
||||
recents: List<CategoryItem>
|
||||
) = depictionCategories + locationCategories + titles + recents
|
||||
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ class CategoriesModel @Inject constructor(
|
|||
private fun titleCategories(titleList: List<String>) =
|
||||
if (titleList.isNotEmpty())
|
||||
Observable.combineLatest(titleList.map { getTitleCategories(it) }) { searchResults ->
|
||||
searchResults.map { it as List<String> }.flatten()
|
||||
searchResults.map { it as List<CategoryItem> }.flatten()
|
||||
}
|
||||
else
|
||||
Observable.just(emptyList())
|
||||
|
|
@ -125,7 +125,7 @@ class CategoriesModel @Inject constructor(
|
|||
* @param title
|
||||
* @return
|
||||
*/
|
||||
private fun getTitleCategories(title: String): Observable<List<String>> {
|
||||
private fun getTitleCategories(title: String): Observable<List<CategoryItem>> {
|
||||
return categoryClient.searchCategories(title, SEARCH_CATS_LIMIT).toObservable()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,15 +10,19 @@ import java.util.Date;
|
|||
public class Category {
|
||||
private Uri contentUri;
|
||||
private String name;
|
||||
private String description;
|
||||
private String thumbnail;
|
||||
private Date lastUsed;
|
||||
private int timesUsed;
|
||||
|
||||
public Category() {
|
||||
}
|
||||
|
||||
public Category(Uri contentUri, String name, Date lastUsed, int timesUsed) {
|
||||
public Category(Uri contentUri, String name, String description, String thumbnail, Date lastUsed, int timesUsed) {
|
||||
this.contentUri = contentUri;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.thumbnail = thumbnail;
|
||||
this.lastUsed = lastUsed;
|
||||
this.timesUsed = timesUsed;
|
||||
}
|
||||
|
|
@ -93,4 +97,19 @@ public class Category {
|
|||
this.contentUri = contentUri;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getThumbnail() {
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public void setDescription(final String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setThumbnail(final String thumbnail) {
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const val CATEGORY_NEEDING_CATEGORIES = "needing categories"
|
|||
*/
|
||||
@Singleton
|
||||
class CategoryClient @Inject constructor(private val categoryInterface: CategoryInterface) :
|
||||
ContinuationClient<MwQueryResponse, String>() {
|
||||
ContinuationClient<MwQueryResponse, CategoryItem>() {
|
||||
|
||||
/**
|
||||
* Searches for categories containing the specified string.
|
||||
|
|
@ -28,7 +28,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
|||
*/
|
||||
@JvmOverloads
|
||||
fun searchCategories(filter: String?, itemLimit: Int, offset: Int = 0):
|
||||
Single<List<String>> {
|
||||
Single<List<CategoryItem>> {
|
||||
return responseMapper(categoryInterface.searchCategories(filter, itemLimit, offset))
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
|||
*/
|
||||
@JvmOverloads
|
||||
fun searchCategoriesForPrefix(prefix: String?, itemLimit: Int, offset: Int = 0):
|
||||
Single<List<String>> {
|
||||
Single<List<CategoryItem>> {
|
||||
return responseMapper(
|
||||
categoryInterface.searchCategoriesForPrefix(prefix, itemLimit, offset)
|
||||
)
|
||||
|
|
@ -55,7 +55,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
|||
* @param categoryName Category name as defined on commons
|
||||
* @return Observable emitting the categories returned. If our search yielded "Category:Test", "Test" is emitted.
|
||||
*/
|
||||
fun getSubCategoryList(categoryName: String): Single<List<String>> {
|
||||
fun getSubCategoryList(categoryName: String): Single<List<CategoryItem>> {
|
||||
return continuationRequest(SUB_CATEGORY_CONTINUATION_PREFIX, categoryName) {
|
||||
categoryInterface.getSubCategoryList(
|
||||
categoryName, it
|
||||
|
|
@ -70,7 +70,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
|||
* @param categoryName Category name as defined on commons
|
||||
* @return
|
||||
*/
|
||||
fun getParentCategoryList(categoryName: String): Single<List<String>> {
|
||||
fun getParentCategoryList(categoryName: String): Single<List<CategoryItem>> {
|
||||
return continuationRequest(PARENT_CATEGORY_CONTINUATION_PREFIX, categoryName) {
|
||||
categoryInterface.getParentCategoryList(categoryName, it)
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
|||
override fun responseMapper(
|
||||
networkResult: Single<MwQueryResponse>,
|
||||
key: String?
|
||||
): Single<List<String>> {
|
||||
): Single<List<CategoryItem>> {
|
||||
return networkResult
|
||||
.map {
|
||||
handleContinuationResponse(it.continuation(), key)
|
||||
|
|
@ -96,7 +96,10 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
|||
.map {
|
||||
it.filter {
|
||||
page -> page.categoryInfo() == null || !page.categoryInfo().isHidden
|
||||
}.map { page -> page.title().replace(CATEGORY_PREFIX, "") }
|
||||
}.map {
|
||||
CategoryItem(it.title().replace(CATEGORY_PREFIX, ""),
|
||||
it.description().toString(), it.thumbUrl().toString(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ public class CategoryDao {
|
|||
* @return a list containing recent categories
|
||||
*/
|
||||
@NonNull
|
||||
List<String> recentCategories(int limit) {
|
||||
List<String> items = new ArrayList<>();
|
||||
List<CategoryItem> recentCategories(int limit) {
|
||||
List<CategoryItem> items = new ArrayList<>();
|
||||
Cursor cursor = null;
|
||||
ContentProviderClient db = clientProvider.get();
|
||||
try {
|
||||
|
|
@ -93,7 +93,9 @@ public class CategoryDao {
|
|||
// fixme add a limit on the original query instead of falling out of the loop?
|
||||
while (cursor != null && cursor.moveToNext()
|
||||
&& cursor.getPosition() < limit) {
|
||||
items.add(fromCursor(cursor).getName());
|
||||
items.add(new CategoryItem(fromCursor(cursor).getName(),
|
||||
fromCursor(cursor).getDescription(), fromCursor(cursor).getThumbnail(),
|
||||
false));
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
@ -112,6 +114,8 @@ public class CategoryDao {
|
|||
return new Category(
|
||||
CategoryContentProvider.uriForId(cursor.getInt(cursor.getColumnIndex(Table.COLUMN_ID))),
|
||||
cursor.getString(cursor.getColumnIndex(Table.COLUMN_NAME)),
|
||||
cursor.getString(cursor.getColumnIndex(Table.COLUMN_DESCRIPTION)),
|
||||
cursor.getString(cursor.getColumnIndex(Table.COLUMN_THUMBNAIL)),
|
||||
new Date(cursor.getLong(cursor.getColumnIndex(Table.COLUMN_LAST_USED))),
|
||||
cursor.getInt(cursor.getColumnIndex(Table.COLUMN_TIMES_USED))
|
||||
);
|
||||
|
|
@ -120,6 +124,8 @@ public class CategoryDao {
|
|||
private ContentValues toContentValues(Category category) {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(CategoryDao.Table.COLUMN_NAME, category.getName());
|
||||
cv.put(Table.COLUMN_DESCRIPTION, category.getDescription());
|
||||
cv.put(Table.COLUMN_THUMBNAIL, category.getThumbnail());
|
||||
cv.put(CategoryDao.Table.COLUMN_LAST_USED, category.getLastUsed().getTime());
|
||||
cv.put(CategoryDao.Table.COLUMN_TIMES_USED, category.getTimesUsed());
|
||||
return cv;
|
||||
|
|
@ -130,6 +136,8 @@ public class CategoryDao {
|
|||
|
||||
public static final String COLUMN_ID = "_id";
|
||||
static final String COLUMN_NAME = "name";
|
||||
static final String COLUMN_DESCRIPTION = "description";
|
||||
static final String COLUMN_THUMBNAIL = "thumbnail";
|
||||
static final String COLUMN_LAST_USED = "last_used";
|
||||
static final String COLUMN_TIMES_USED = "times_used";
|
||||
|
||||
|
|
@ -137,6 +145,8 @@ public class CategoryDao {
|
|||
public static final String[] ALL_FIELDS = {
|
||||
COLUMN_ID,
|
||||
COLUMN_NAME,
|
||||
COLUMN_DESCRIPTION,
|
||||
COLUMN_THUMBNAIL,
|
||||
COLUMN_LAST_USED,
|
||||
COLUMN_TIMES_USED
|
||||
};
|
||||
|
|
@ -146,6 +156,8 @@ public class CategoryDao {
|
|||
static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " ("
|
||||
+ COLUMN_ID + " INTEGER PRIMARY KEY,"
|
||||
+ COLUMN_NAME + " STRING,"
|
||||
+ COLUMN_DESCRIPTION + " STRING,"
|
||||
+ COLUMN_THUMBNAIL + " STRING,"
|
||||
+ COLUMN_LAST_USED + " INTEGER,"
|
||||
+ COLUMN_TIMES_USED + " INTEGER"
|
||||
+ ");";
|
||||
|
|
|
|||
|
|
@ -94,8 +94,14 @@ public class CategoryEditSearchRecyclerViewAdapter
|
|||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
FilterResults results = new FilterResults();
|
||||
List<String> resultCategories = categoryClient.searchCategories(constraint.toString(), 10).blockingGet();
|
||||
results.values = resultCategories;
|
||||
List<CategoryItem> resultCategories = categoryClient
|
||||
.searchCategories(constraint.toString(), 10).blockingGet();
|
||||
final List<String> namesOfCommonsCategories = new ArrayList<>();
|
||||
for (final CategoryItem category :
|
||||
resultCategories) {
|
||||
namesOfCommonsCategories.add(category.getName());
|
||||
}
|
||||
results.values = namesOfCommonsCategories;
|
||||
results.count = resultCategories.size();
|
||||
return results;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@ public interface CategoryInterface {
|
|||
* @return
|
||||
*/
|
||||
@GET("w/api.php?action=query&format=json&formatversion=2"
|
||||
+ "&generator=search&gsrnamespace=14")
|
||||
+ "&generator=search&prop=description|pageimages&piprop=thumbnail&pithumbsize=70"
|
||||
+ "&gsrnamespace=14")
|
||||
Single<MwQueryResponse> searchCategories(@Query("gsrsearch") String filter,
|
||||
@Query("gsrlimit") int itemLimit, @Query("gsroffset") int offset);
|
||||
@Query("gsrlimit") int itemLimit,
|
||||
@Query("gsroffset") int offset);
|
||||
|
||||
/**
|
||||
* Searches for categories starting with the specified prefix.
|
||||
|
|
@ -32,9 +34,11 @@ public interface CategoryInterface {
|
|||
* @return
|
||||
*/
|
||||
@GET("w/api.php?action=query&format=json&formatversion=2"
|
||||
+ "&generator=allcategories&prop=categoryinfo")
|
||||
+ "&generator=allcategories&prop=categoryinfo|description|pageimages&piprop=thumbnail"
|
||||
+ "&pithumbsize=70")
|
||||
Single<MwQueryResponse> searchCategoriesForPrefix(@Query("gacprefix") String prefix,
|
||||
@Query("gaclimit") int itemLimit, @Query("gacoffset") int offset);
|
||||
@Query("gaclimit") int itemLimit,
|
||||
@Query("gacoffset") int offset);
|
||||
|
||||
@GET("w/api.php?action=query&format=json&formatversion=2"
|
||||
+ "&generator=categorymembers&gcmtype=subcat"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import android.os.Parcelable
|
|||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class CategoryItem(val name: String, var isSelected: Boolean) : Parcelable {
|
||||
data class CategoryItem(val name: String, val description: String,
|
||||
val thumbnail: String, var isSelected: Boolean) : Parcelable {
|
||||
|
||||
override fun toString(): String {
|
||||
return "CategoryItem: '$name'"
|
||||
|
|
|
|||
|
|
@ -250,8 +250,10 @@ public class NetworkingModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
public CategoryInterface provideCategoryInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
|
||||
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, CategoryInterface.class);
|
||||
public CategoryInterface provideCategoryInterface(
|
||||
@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
|
||||
return ServiceFactory
|
||||
.get(commonsWikiSite, BuildConfig.COMMONS_URL, CategoryInterface.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ class PageableParentCategoriesDataSource @Inject constructor(
|
|||
if (startPosition == 0) {
|
||||
categoryClient.resetParentCategoryContinuation(query)
|
||||
}
|
||||
categoryClient.getParentCategoryList(query).blockingGet()
|
||||
categoryClient.getParentCategoryList(query).blockingGet().map { it.name }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,6 @@ class PageableSearchCategoriesDataSource @Inject constructor(
|
|||
|
||||
override val loadFunction = { loadSize: Int, startPosition: Int ->
|
||||
categoryClient.searchCategories(query, loadSize, startPosition).blockingGet()
|
||||
.map { it.name }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ class PageableSubCategoriesDataSource @Inject constructor(
|
|||
if (startPosition == 0) {
|
||||
categoryClient.resetSubCategoryContinuation(query)
|
||||
}
|
||||
categoryClient.getSubCategoryList(query).blockingGet()
|
||||
categoryClient.getSubCategoryList(query).blockingGet().map { it.name }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.mwapi;
|
|||
import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_PREFIX;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import fr.free.nrw.commons.category.CategoryItem;
|
||||
import io.reactivex.Single;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
@ -40,7 +41,7 @@ public class CategoryApi {
|
|||
this.gson = gson;
|
||||
}
|
||||
|
||||
public Single<List<String>> request(String coords) {
|
||||
public Single<List<CategoryItem>> request(String coords) {
|
||||
return Single.fromCallable(() -> {
|
||||
HttpUrl apiUrl = buildUrl(coords);
|
||||
Timber.d("URL: %s", apiUrl.toString());
|
||||
|
|
@ -53,12 +54,12 @@ public class CategoryApi {
|
|||
}
|
||||
|
||||
MwQueryResponse apiResponse = gson.fromJson(body.charStream(), MwQueryResponse.class);
|
||||
Set<String> categories = new LinkedHashSet<>();
|
||||
Set<CategoryItem> categories = new LinkedHashSet<>();
|
||||
if (apiResponse != null && apiResponse.query() != null && apiResponse.query().pages() != null) {
|
||||
for (MwQueryPage page : apiResponse.query().pages()) {
|
||||
if (page.categories() != null) {
|
||||
for (MwQueryPage.Category category : page.categories()) {
|
||||
categories.add(category.title().replace(CATEGORY_PREFIX, ""));
|
||||
categories.add(new CategoryItem(category.title().replace(CATEGORY_PREFIX, ""), "", "", false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import fr.free.nrw.commons.category.CategoryItem
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class GpsCategoryModel @Inject constructor() {
|
||||
val categoriesFromLocation = BehaviorSubject.createDefault(emptyList<String>())
|
||||
val categoriesFromLocation = BehaviorSubject.createDefault(emptyList<CategoryItem>())
|
||||
|
||||
fun clear() {
|
||||
categoriesFromLocation.onNext(emptyList())
|
||||
}
|
||||
|
||||
fun setCategoriesFromLocation(categoryList: List<String>) {
|
||||
fun setCategoriesFromLocation(categoryList: List<CategoryItem>) {
|
||||
categoriesFromLocation.onNext(categoryList)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package fr.free.nrw.commons.upload.categories
|
||||
|
||||
import fr.free.nrw.commons.category.CategoryItem
|
||||
import org.jetbrains.annotations.NotNull
|
||||
|
||||
class UploadCategoryAdapter(onCategoryClicked: (CategoryItem) -> Unit) :
|
||||
class UploadCategoryAdapter(
|
||||
onCategoryClicked: @NotNull() (CategoryItem) -> Unit) :
|
||||
BaseDelegateAdapter<CategoryItem>(
|
||||
uploadCategoryDelegate(onCategoryClicked),
|
||||
areItemsTheSame = { oldItem, newItem -> oldItem.name == newItem.name },
|
||||
|
|
|
|||
|
|
@ -1,20 +1,38 @@
|
|||
package fr.free.nrw.commons.upload.categories
|
||||
|
||||
import android.view.View
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.category.CategoryItem
|
||||
import fr.free.nrw.commons.databinding.LayoutUploadCategoriesItemBinding
|
||||
|
||||
fun uploadCategoryDelegate(onCategoryClicked: (CategoryItem) -> Unit) =
|
||||
adapterDelegateViewBinding<CategoryItem, CategoryItem, LayoutUploadCategoriesItemBinding>({ layoutInflater, root ->
|
||||
adapterDelegateViewBinding<CategoryItem, CategoryItem,
|
||||
LayoutUploadCategoriesItemBinding>({ layoutInflater, root ->
|
||||
LayoutUploadCategoriesItemBinding.inflate(layoutInflater, root, false)
|
||||
}) {
|
||||
binding.root.setOnClickListener {
|
||||
val onClickListener = { _: View? ->
|
||||
item.isSelected = !item.isSelected
|
||||
binding.uploadCategoryCheckbox.isChecked = item.isSelected
|
||||
onCategoryClicked(item)
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener(onClickListener)
|
||||
binding.uploadCategoryCheckbox.setOnClickListener(onClickListener)
|
||||
|
||||
bind {
|
||||
binding.uploadCategoryCheckbox.isChecked = item.isSelected
|
||||
binding.uploadCategoryCheckbox.text = item.name
|
||||
binding.categoryLabel.text = item.name
|
||||
if(item.thumbnail != "null") {
|
||||
binding.categoryImage.setImageURI(item.thumbnail)
|
||||
} else {
|
||||
binding.categoryImage.setActualImageResource(R.drawable.commons)
|
||||
}
|
||||
|
||||
if(item.description != "null") {
|
||||
binding.categoryDescription.text = item.description
|
||||
} else {
|
||||
binding.categoryDescription.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.upload.structure.depictions
|
|||
import android.os.Parcelable
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import fr.free.nrw.commons.category.CategoryItem
|
||||
import fr.free.nrw.commons.nearby.Place
|
||||
import fr.free.nrw.commons.upload.WikidataItem
|
||||
import fr.free.nrw.commons.wikidata.WikidataProperties
|
||||
|
|
@ -28,7 +29,7 @@ data class DepictedItem constructor(
|
|||
val description: String?,
|
||||
val imageUrl: String?,
|
||||
val instanceOfs: List<String>,
|
||||
val commonsCategories: List<String>,
|
||||
val commonsCategories: List<CategoryItem>,
|
||||
var isSelected: Boolean,
|
||||
@PrimaryKey override val id: String
|
||||
) : WikidataItem, Parcelable {
|
||||
|
|
@ -52,7 +53,8 @@ data class DepictedItem constructor(
|
|||
getImageUrl(it.value, THUMB_IMAGE_SIZE)
|
||||
},
|
||||
entity[INSTANCE_OF].toIds(),
|
||||
entity[COMMONS_CATEGORY]?.map { (it.mainSnak.dataValue as DataValue.ValueString).value }
|
||||
entity[COMMONS_CATEGORY]?.map { CategoryItem((it.mainSnak.dataValue as DataValue.ValueString).value,
|
||||
"", "", false) }
|
||||
?: emptyList(),
|
||||
false,
|
||||
entity.id()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package fr.free.nrw.commons.utils;
|
||||
|
||||
import fr.free.nrw.commons.category.CategoryItem;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class StringSortingUtils {
|
||||
|
|
@ -16,10 +17,10 @@ public class StringSortingUtils {
|
|||
* @param filter String to compare similarity with
|
||||
* @return Comparator with string similarity
|
||||
*/
|
||||
public static Comparator<String> sortBySimilarity(final String filter) {
|
||||
public static Comparator<CategoryItem> sortBySimilarity(final String filter) {
|
||||
return (firstItem, secondItem) -> {
|
||||
double firstItemSimilarity = calculateSimilarity(firstItem, filter);
|
||||
double secondItemSimilarity = calculateSimilarity(secondItem, filter);
|
||||
double firstItemSimilarity = calculateSimilarity(firstItem.getName(), filter);
|
||||
double secondItemSimilarity = calculateSimilarity(secondItem.getName(), filter);
|
||||
return (int) Math.signum(secondItemSimilarity - firstItemSimilarity);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/uploadCategoryCheckbox"
|
||||
android:layout_width="match_parent"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/category_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/upload_category_checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checkMark="?android:attr/textCheckMark"
|
||||
android:checked="false"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="@dimen/tiny_gap"/>
|
||||
android:padding="@dimen/tiny_gap"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/category_image"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
android:id="@+id/category_image"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:paddingEnd="@dimen/tiny_gap"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@+id/upload_category_checkbox"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:placeholderImage="@drawable/commons" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/category_image"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="@string/label"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="@string/description" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -652,6 +652,8 @@ Upload your first media by tapping on the add button.</string>
|
|||
The shadow of the image view of the location picker</string>
|
||||
<string name="image_location">Image Location</string>
|
||||
<string name="check_whether_location_is_correct">Check whether location is correct</string>
|
||||
<string name="label">Label</string>
|
||||
<string name="description">Description</string>
|
||||
<string name="title_page_bookmarks_items">Items</string>
|
||||
<string name="custom_selector_title">Custom Selector</string>
|
||||
<string name="custom_selector_empty_text">No Images</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue