Fixes 4544 : Language selection: history (#4880)

* Xml changes

* Content provider created

* Database setup done

* Database setup revised

* Database setup revised

* SettingsFragment finished

* SettingsFragment finished

* UploadMediaDetailFragment updated

* UploadMediaDetailFragment updated

* Java docs

* Test fixed

* Test added

* Test added

* Test updated

* More tests added
This commit is contained in:
Ayan Sarkar 2022-03-23 13:03:54 +05:30 committed by GitHub
parent 85bdcd5a7a
commit 4194409cd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 1312 additions and 9 deletions

View file

@ -11,6 +11,7 @@ import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao;
import fr.free.nrw.commons.category.CategoryDao;
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesDao;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
public class DBOpenHelper extends SQLiteOpenHelper {
@ -34,6 +35,7 @@ public class DBOpenHelper extends SQLiteOpenHelper {
BookmarkLocationsDao.Table.onCreate(sqLiteDatabase);
BookmarkItemsDao.Table.onCreate(sqLiteDatabase);
RecentSearchesDao.Table.onCreate(sqLiteDatabase);
RecentLanguagesDao.Table.onCreate(sqLiteDatabase);
}
@Override
@ -43,6 +45,7 @@ public class DBOpenHelper extends SQLiteOpenHelper {
BookmarkLocationsDao.Table.onUpdate(sqLiteDatabase, from, to);
BookmarkItemsDao.Table.onUpdate(sqLiteDatabase, from, to);
RecentSearchesDao.Table.onUpdate(sqLiteDatabase, from, to);
RecentLanguagesDao.Table.onUpdate(sqLiteDatabase, from, to);
deleteTable(sqLiteDatabase,CONTRIBUTIONS_TABLE);
}

View file

@ -169,6 +169,19 @@ public class CommonsApplicationModule {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.BOOKMARK_ITEMS_AUTHORITY);
}
/**
* This method is used to provide instance of RecentLanguagesContentProvider
* which provides content of recent used languages from database
* @param context Context
* @return returns RecentLanguagesContentProvider
*/
@Provides
@Named("recent_languages")
public ContentProviderClient provideRecentLanguagesContentProviderClient(final Context context) {
return context.getContentResolver()
.acquireContentProviderClient(BuildConfig.RECENT_LANGUAGE_AUTHORITY);
}
/**
* Provides a Json store instance(JsonKvStore) which keeps
* the provided Gson in it's instance

View file

@ -7,6 +7,7 @@ import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsContentProvider;
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider;
import fr.free.nrw.commons.category.CategoryContentProvider;
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesContentProvider;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesContentProvider;
/**
* This Class Represents the Module for dependency injection (using dagger)
@ -31,4 +32,7 @@ public abstract class ContentProviderBuilderModule {
@ContributesAndroidInjector
abstract BookmarkItemsContentProvider bindBookmarkItemContentProvider();
@ContributesAndroidInjector
abstract RecentLanguagesContentProvider bindRecentLanguagesContentProvider();
}

View file

@ -0,0 +1,3 @@
package fr.free.nrw.commons.recentlanguages
data class Language(val languageName: String, val languageCode: String)

View file

@ -0,0 +1,68 @@
package fr.free.nrw.commons.recentlanguages
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import fr.free.nrw.commons.R
import fr.free.nrw.commons.utils.LangCodeUtils
import kotlinx.android.synthetic.main.row_item_languages_spinner.view.*
import org.apache.commons.lang3.StringUtils
import java.util.HashMap
/**
* Array adapter for recent languages
*/
class RecentLanguagesAdapter constructor(
context: Context,
var recentLanguages: List<Language>,
private val selectedLanguages: HashMap<*, String>
) : ArrayAdapter<String?>(context, R.layout.row_item_languages_spinner) {
/**
* Selected language code in UploadMediaDetailAdapter
* Used for marking selected ones
*/
var selectedLangCode = ""
override fun isEnabled(position: Int) = recentLanguages[position].languageCode.let {
it.isNotEmpty() && !selectedLanguages.containsValue(it) && it != selectedLangCode
}
override fun getCount() = recentLanguages.size
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val rowView: View = convertView
?: LayoutInflater.from(context)
.inflate(R.layout.row_item_languages_spinner, parent, false)
val languageCode = recentLanguages[position].languageCode
val languageName = recentLanguages[position].languageName
rowView.tv_language.let {
it.isEnabled = isEnabled(position)
if (languageCode.isEmpty()) {
it.text = StringUtils.capitalize(languageName)
it.textAlignment = View.TEXT_ALIGNMENT_CENTER
} else {
it.text =
"${StringUtils.capitalize(languageName)}" +
" [${LangCodeUtils.fixLanguageCode(languageCode)}]"
}
}
return rowView
}
/**
* Provides code of a language from recent languages for a specific position
*/
fun getLanguageCode(position: Int): String {
return recentLanguages[position].languageCode
}
/**
* Provides name of a language from recent languages for a specific position
*/
fun getLanguageName(position: Int): String {
return recentLanguages[position].languageName
}
}

View file

@ -0,0 +1,122 @@
package fr.free.nrw.commons.recentlanguages;
import static fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.COLUMN_NAME;
import static fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.TABLE_NAME;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.data.DBOpenHelper;
import fr.free.nrw.commons.di.CommonsDaggerContentProvider;
import javax.inject.Inject;
import timber.log.Timber;
/**
* Content provider of recently used languages
*/
public class RecentLanguagesContentProvider extends CommonsDaggerContentProvider {
private static final String BASE_PATH = "recent_languages";
public static final Uri BASE_URI =
Uri.parse("content://" + BuildConfig.RECENT_LANGUAGE_AUTHORITY + "/" + BASE_PATH);
/**
* Append language code to the base uri
* @param languageCode Code of a language
*/
public static Uri uriForCode(final String languageCode) {
return Uri.parse(BASE_URI + "/" + languageCode);
}
@Inject
DBOpenHelper dbOpenHelper;
@Override
public String getType(@NonNull final Uri uri) {
return null;
}
/**
* Queries the SQLite database for the recently used languages
* @param uri : contains the uri for recently used languages
* @param projection : contains the all fields of the table
* @param selection : handles Where
* @param selectionArgs : the condition of Where clause
* @param sortOrder : ascending or descending
*/
@Override
public Cursor query(@NonNull final Uri uri, final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder) {
final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(TABLE_NAME);
final SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
final Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
/**
* Handles the update query of local SQLite Database
* @param uri : contains the uri for recently used languages
* @param contentValues : new values to be entered to db
* @param selection : handles Where
* @param selectionArgs : the condition of Where clause
*/
@Override
public int update(@NonNull final Uri uri, final ContentValues contentValues,
final String selection, final String[] selectionArgs) {
final SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
final int rowsUpdated;
if (TextUtils.isEmpty(selection)) {
final int id = Integer.parseInt(uri.getLastPathSegment());
rowsUpdated = sqlDB.update(TABLE_NAME,
contentValues,
COLUMN_NAME + " = ?",
new String[]{String.valueOf(id)});
} else {
throw new IllegalArgumentException(
"Parameter `selection` should be empty when updating an ID");
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
/**
* Handles the insertion of new recently used languages record to local SQLite Database
* @param uri : contains the uri for recently used languages
* @param contentValues : new values to be entered to db
*/
@Override
public Uri insert(@NonNull final Uri uri, final ContentValues contentValues) {
final SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
final long id = sqlDB.insert(TABLE_NAME, null, contentValues);
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(BASE_URI + "/" + id);
}
/**
* Handles the deletion of new recently used languages record to local SQLite Database
* @param uri : contains the uri for recently used languages
*/
@Override
public int delete(@NonNull final Uri uri, final String s, final String[] strings) {
final int rows;
final SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Timber.d("Deleting recently used language %s", uri.getLastPathSegment());
rows = db.delete(
TABLE_NAME,
"language_code = ?",
new String[]{uri.getLastPathSegment()}
);
getContext().getContentResolver().notifyChange(uri, null);
return rows;
}
}

View file

@ -0,0 +1,208 @@
package fr.free.nrw.commons.recentlanguages;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.RemoteException;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
/**
* Handles database operations for recently used languages
*/
@Singleton
public class RecentLanguagesDao {
private final Provider<ContentProviderClient> clientProvider;
@Inject
public RecentLanguagesDao
(@Named("recent_languages") final Provider<ContentProviderClient> clientProvider) {
this.clientProvider = clientProvider;
}
/**
* Find all persisted recently used languages on database
* @return list of recently used languages
*/
public List<Language> getRecentLanguages() {
final List<Language> languages = new ArrayList<>();
final ContentProviderClient db = clientProvider.get();
try (final Cursor cursor = db.query(
RecentLanguagesContentProvider.BASE_URI,
RecentLanguagesDao.Table.ALL_FIELDS,
null,
new String[]{},
null)) {
if(cursor != null && cursor.moveToLast()) {
do {
languages.add(fromCursor(cursor));
} while (cursor.moveToPrevious());
}
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
return languages;
}
/**
* Add a Language to database
* @param language : Language to add
*/
public void addRecentLanguage(final Language language) {
final ContentProviderClient db = clientProvider.get();
try {
db.insert(RecentLanguagesContentProvider.BASE_URI, toContentValues(language));
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
}
/**
* Delete a language from database
* @param languageCode : code of the Language to delete
*/
public void deleteRecentLanguage(final String languageCode) {
final ContentProviderClient db = clientProvider.get();
try {
db.delete(RecentLanguagesContentProvider.uriForCode(languageCode), null, null);
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
}
/**
* Find a language from database based on its name
* @param languageCode : code of the Language to find
* @return boolean : is language in database ?
*/
public boolean findRecentLanguage(final String languageCode) {
if (languageCode == null) { //Avoiding NPE's
return false;
}
final ContentProviderClient db = clientProvider.get();
try (final Cursor cursor = db.query(
RecentLanguagesContentProvider.BASE_URI,
RecentLanguagesDao.Table.ALL_FIELDS,
Table.COLUMN_CODE + "=?",
new String[]{languageCode},
null
)) {
if (cursor != null && cursor.moveToFirst()) {
return true;
}
} catch (final RemoteException e) {
throw new RuntimeException(e);
} finally {
db.release();
}
return false;
}
/**
* It creates an Recent Language object from data stored in the SQLite DB by using cursor
* @param cursor cursor
* @return Language object
*/
@NonNull
Language fromCursor(final Cursor cursor) {
// Hardcoding column positions!
final String languageName = cursor.getString(cursor.getColumnIndex(Table.COLUMN_NAME));
final String languageCode = cursor.getString(cursor.getColumnIndex(Table.COLUMN_CODE));
return new Language(languageName, languageCode);
}
/**
* Takes data from Language and create a content value object
* @param recentLanguage recently used language
* @return ContentValues
*/
private ContentValues toContentValues(final Language recentLanguage) {
final ContentValues cv = new ContentValues();
cv.put(Table.COLUMN_NAME, recentLanguage.getLanguageName());
cv.put(Table.COLUMN_CODE, recentLanguage.getLanguageCode());
return cv;
}
/**
* This class contains the database table architecture for recently used languages,
* It also contains queries and logic necessary to the create, update, delete this table.
*/
public static final class Table {
public static final String TABLE_NAME = "recent_languages";
static final String COLUMN_NAME = "language_name";
static final String COLUMN_CODE = "language_code";
// NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES.
public static final String[] ALL_FIELDS = {
COLUMN_NAME,
COLUMN_CODE
};
static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS " + TABLE_NAME;
static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " ("
+ COLUMN_NAME + " STRING,"
+ COLUMN_CODE + " STRING PRIMARY KEY"
+ ");";
/**
* This method creates a LanguagesTable in SQLiteDatabase
* @param db SQLiteDatabase
*/
public static void onCreate(final SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_STATEMENT);
}
/**
* This method deletes LanguagesTable from SQLiteDatabase
* @param db SQLiteDatabase
*/
public static void onDelete(final SQLiteDatabase db) {
db.execSQL(DROP_TABLE_STATEMENT);
onCreate(db);
}
/**
* This method is called on migrating from a older version to a newer version
* @param db SQLiteDatabase
* @param from Version from which we are migrating
* @param to Version to which we are migrating
*/
public static void onUpdate(final SQLiteDatabase db, int from, final int to) {
if (from == to) {
return;
}
if (from < 6) {
// doesn't exist yet
from++;
onUpdate(db, from, to);
return;
}
if (from == 6) {
// table added in version 7
onCreate(db);
from++;
onUpdate(db, from, to);
return;
}
if (from == 7) {
from++;
onUpdate(db, from, to);
return;
}
}
}
}

View file

@ -9,7 +9,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@ -18,6 +17,7 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import androidx.preference.ListPreference;
import androidx.preference.MultiSelectListPreference;
import androidx.preference.Preference;
@ -39,10 +39,12 @@ import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.logging.CommonsLogSender;
import fr.free.nrw.commons.recentlanguages.Language;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
import fr.free.nrw.commons.upload.LanguagesAdapter;
import fr.free.nrw.commons.utils.PermissionUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -60,10 +62,16 @@ public class SettingsFragment extends PreferenceFragmentCompat {
@Inject
CommonsLogSender commonsLogSender;
@Inject
RecentLanguagesDao recentLanguagesDao;
private ListPreference themeListPreference;
private Preference descriptionLanguageListPreference;
private Preference appUiLanguageListPreference;
private String keyLanguageListPreference;
private TextView recentLanguagesTextView;
private View separator;
private ListView languageHistoryListView;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
@ -211,6 +219,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
// Gets current language code from shared preferences
final String languageCode = getCurrentLanguageCode(keyListPreference);
final List<Language> recentLanguages = recentLanguagesDao.getRecentLanguages();
HashMap<Integer, String> selectedLanguages = new HashMap<>();
if (keyListPreference.equals("appUiDefaultLanguagePref")) {
@ -246,6 +255,11 @@ public class SettingsFragment extends PreferenceFragmentCompat {
EditText editText = dialog.findViewById(R.id.search_language);
ListView listView = dialog.findViewById(R.id.language_list);
languageHistoryListView = dialog.findViewById(R.id.language_history_list);
recentLanguagesTextView = dialog.findViewById(R.id.recent_searches);
separator = dialog.findViewById(R.id.separator);
setUpRecentLanguagesSection(recentLanguages, selectedLanguages);
listView.setAdapter(languagesAdapter);
@ -253,7 +267,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
hideRecentLanguagesSection();
}
@Override
@ -268,12 +282,23 @@ public class SettingsFragment extends PreferenceFragmentCompat {
}
});
languageHistoryListView.setOnItemClickListener((adapterView, view, position, id) -> {
onRecentLanguageClicked(keyListPreference, dialog, adapterView, position);
});
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i,
long l) {
String languageCode = ((LanguagesAdapter) adapterView.getAdapter())
.getLanguageCode(i);
final String languageName = ((LanguagesAdapter) adapterView.getAdapter())
.getLanguageName(i);
final boolean isExists = recentLanguagesDao.findRecentLanguage(languageCode);
if (isExists) {
recentLanguagesDao.deleteRecentLanguage(languageCode);
}
recentLanguagesDao.addRecentLanguage(new Language(languageName, languageCode));
saveLanguageValue(languageCode, keyListPreference);
Locale defLocale = new Locale(languageCode);
if(keyListPreference.equals("appUiDefaultLanguagePref")) {
@ -293,6 +318,75 @@ public class SettingsFragment extends PreferenceFragmentCompat {
dialogInterface -> languagesAdapter.getFilter().filter(""));
}
/**
* Set up recent languages section
*
* @param recentLanguages recently used languages
* @param selectedLanguages selected languages
*/
private void setUpRecentLanguagesSection(List<Language> recentLanguages,
HashMap<Integer, String> selectedLanguages) {
if (recentLanguages.isEmpty()) {
languageHistoryListView.setVisibility(View.GONE);
recentLanguagesTextView.setVisibility(View.GONE);
separator.setVisibility(View.GONE);
} else {
if (recentLanguages.size() > 5) {
for (int i = recentLanguages.size()-1; i >=5; i--) {
recentLanguagesDao
.deleteRecentLanguage(recentLanguages.get(i).getLanguageCode());
}
}
languageHistoryListView.setVisibility(View.VISIBLE);
recentLanguagesTextView.setVisibility(View.VISIBLE);
separator.setVisibility(View.VISIBLE);
final RecentLanguagesAdapter recentLanguagesAdapter
= new RecentLanguagesAdapter(
getActivity(),
recentLanguagesDao.getRecentLanguages(),
selectedLanguages);
languageHistoryListView.setAdapter(recentLanguagesAdapter);
}
}
/**
* Handles click event for recent language section
*/
private void onRecentLanguageClicked(String keyListPreference, Dialog dialog, AdapterView<?> adapterView,
int position) {
final String recentLanguageCode = ((RecentLanguagesAdapter) adapterView.getAdapter())
.getLanguageCode(position);
final String recentLanguageName = ((RecentLanguagesAdapter) adapterView.getAdapter())
.getLanguageName(position);
final boolean isExists = recentLanguagesDao.findRecentLanguage(recentLanguageCode);
if (isExists) {
recentLanguagesDao.deleteRecentLanguage(recentLanguageCode);
}
recentLanguagesDao.addRecentLanguage(
new Language(recentLanguageName, recentLanguageCode));
saveLanguageValue(recentLanguageCode, keyListPreference);
final Locale defLocale = new Locale(recentLanguageCode);
if (keyListPreference.equals("appUiDefaultLanguagePref")) {
appUiLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
setLocale(Objects.requireNonNull(getActivity()), recentLanguageCode);
getActivity().recreate();
final Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
} else {
descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
}
dialog.dismiss();
}
/**
* Remove the section of recent languages
*/
private void hideRecentLanguagesSection() {
languageHistoryListView.setVisibility(View.GONE);
recentLanguagesTextView.setVisibility(View.GONE);
separator.setVisibility(View.GONE);
}
/**
* Changing the default app language with selected one and save it to SharedPreferences
*/

View file

@ -74,6 +74,13 @@ class LanguagesAdapter constructor(
return languageCodesList[position]
}
/**
* Provides name of a language from languages for a specific position
*/
fun getLanguageName(position: Int): String {
return languageNamesList[position]
}
fun getIndexOfUserDefaultLocale(context: Context): Int {
return language.codes.indexOf(context.locale.language)
}

View file

@ -1,6 +1,7 @@
package fr.free.nrw.commons.upload;
import android.app.Dialog;
import android.content.Intent;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@ -21,26 +22,39 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import com.google.android.material.textfield.TextInputLayout;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.recentlanguages.Language;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText;
import fr.free.nrw.commons.utils.AbstractTextWatcher;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import javax.inject.Inject;
import timber.log.Timber;
public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDetailAdapter.ViewHolder> {
RecentLanguagesDao recentLanguagesDao;
private List<UploadMediaDetail> uploadMediaDetails;
private Callback callback;
private EventListener eventListener;
private HashMap<Integer, String> selectedLanguages;
private final String savedLanguageValue;
private TextView recentLanguagesTextView;
private View separator;
private ListView languageHistoryListView;
public UploadMediaDetailAdapter(String savedLanguageValue) {
public UploadMediaDetailAdapter(String savedLanguageValue, RecentLanguagesDao recentLanguagesDao) {
uploadMediaDetails = new ArrayList<>();
selectedLanguages = new HashMap<>();
this.savedLanguageValue = savedLanguageValue;
this.recentLanguagesDao = recentLanguagesDao;
}
public UploadMediaDetailAdapter(final String savedLanguageValue,
@ -183,7 +197,9 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
private void initLanguage(int position, UploadMediaDetail description) {
LanguagesAdapter languagesAdapter = new LanguagesAdapter(
final List<Language> recentLanguages = recentLanguagesDao.getRecentLanguages();
LanguagesAdapter languagesAdapter = new LanguagesAdapter(
descriptionLanguages.getContext(),
selectedLanguages
);
@ -200,6 +216,10 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
EditText editText = dialog.findViewById(R.id.search_language);
ListView listView = dialog.findViewById(R.id.language_list);
languageHistoryListView = dialog.findViewById(R.id.language_history_list);
recentLanguagesTextView = dialog.findViewById(R.id.recent_searches);
separator = dialog.findViewById(R.id.separator);
setUpRecentLanguagesSection(recentLanguages);
listView.setAdapter(languagesAdapter);
@ -207,7 +227,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
hideRecentLanguagesSection();
}
@Override
@ -222,6 +242,10 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
}
});
languageHistoryListView.setOnItemClickListener((adapterView, view1, position, id) -> {
onRecentLanguageClicked(dialog, adapterView, position, description);
});
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i,
@ -230,6 +254,16 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
String languageCode = ((LanguagesAdapter) adapterView.getAdapter())
.getLanguageCode(i);
description.setLanguageCode(languageCode);
final String languageName
= ((LanguagesAdapter) adapterView.getAdapter()).getLanguageName(i);
final boolean isExists
= recentLanguagesDao.findRecentLanguage(languageCode);
if (isExists) {
recentLanguagesDao.deleteRecentLanguage(languageCode);
}
recentLanguagesDao
.addRecentLanguage(new Language(languageName, languageCode));
selectedLanguages.remove(position);
selectedLanguages.put(position, languageCode);
((LanguagesAdapter) adapterView
@ -300,6 +334,70 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
selectedLanguages.put(position, description.getLanguageCode());
}
}
/**
* Handles click event for recent language section
*/
private void onRecentLanguageClicked(final Dialog dialog, final AdapterView<?> adapterView,
final int position, final UploadMediaDetail description) {
description.setSelectedLanguageIndex(position);
final String languageCode = ((RecentLanguagesAdapter) adapterView.getAdapter())
.getLanguageCode(position);
description.setLanguageCode(languageCode);
final String languageName = ((RecentLanguagesAdapter) adapterView.getAdapter())
.getLanguageName(position);
final boolean isExists = recentLanguagesDao.findRecentLanguage(languageCode);
if (isExists) {
recentLanguagesDao.deleteRecentLanguage(languageCode);
}
recentLanguagesDao.addRecentLanguage(new Language(languageName, languageCode));
selectedLanguages.remove(position);
selectedLanguages.put(position, languageCode);
((RecentLanguagesAdapter) adapterView
.getAdapter()).setSelectedLangCode(languageCode);
Timber.d("Description language code is: %s", languageCode);
descriptionLanguages.setText(languageCode);
dialog.dismiss();
}
/**
* Hides recent languages section
*/
private void hideRecentLanguagesSection() {
languageHistoryListView.setVisibility(View.GONE);
recentLanguagesTextView.setVisibility(View.GONE);
separator.setVisibility(View.GONE);
}
/**
* Set up recent languages section
*
* @param recentLanguages recently used languages
*/
private void setUpRecentLanguagesSection(final List<Language> recentLanguages) {
if (recentLanguages.isEmpty()) {
languageHistoryListView.setVisibility(View.GONE);
recentLanguagesTextView.setVisibility(View.GONE);
separator.setVisibility(View.GONE);
} else {
if (recentLanguages.size() > 5) {
for (int i = recentLanguages.size()-1; i >=5; i--) {
recentLanguagesDao.deleteRecentLanguage(recentLanguages.get(i)
.getLanguageCode());
}
}
languageHistoryListView.setVisibility(View.VISIBLE);
recentLanguagesTextView.setVisibility(View.VISIBLE);
separator.setVisibility(View.VISIBLE);
final RecentLanguagesAdapter recentLanguagesAdapter
= new RecentLanguagesAdapter(
descriptionLanguages.getContext(),
recentLanguagesDao.getRecentLanguages(),
selectedLanguages);
languageHistoryListView.setAdapter(recentLanguagesAdapter);
}
}
}
public interface Callback {

View file

@ -31,6 +31,7 @@ import fr.free.nrw.commons.R;
import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.upload.ImageCoordinates;
import fr.free.nrw.commons.upload.SimilarImageDialogFragment;
@ -90,6 +91,9 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Named("default_preferences")
JsonKvStore defaultKvStore;
@Inject
RecentLanguagesDao recentLanguagesDao;
private UploadableFile uploadableFile;
private Place place;
@ -201,7 +205,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* init the description recycler veiw and caption recyclerview
*/
private void initRecyclerView() {
uploadMediaDetailAdapter = new UploadMediaDetailAdapter(defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""));
uploadMediaDetailAdapter = new UploadMediaDetailAdapter(defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""), recentLanguagesDao);
uploadMediaDetailAdapter.setCallback(this::showInfoAlert);
uploadMediaDetailAdapter.setEventListener(this);
rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));