mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Migrated settings modules from Java to Kotlin (#5944)
* Rename .java to .kt * Migrated settings module to Kotlin
This commit is contained in:
parent
5f1d284309
commit
cf88f9b796
6 changed files with 640 additions and 665 deletions
|
|
@ -1,21 +0,0 @@
|
|||
package fr.free.nrw.commons.settings;
|
||||
|
||||
public class Prefs {
|
||||
public static String GLOBAL_PREFS = "fr.free.nrw.commons.preferences";
|
||||
|
||||
public static String TRACKING_ENABLED = "eventLogging";
|
||||
public static final String DEFAULT_LICENSE = "defaultLicense";
|
||||
public static final String UPLOADS_SHOWING = "uploadsshowing";
|
||||
public static final String MANAGED_EXIF_TAGS = "managed_exif_tags";
|
||||
public static final String DESCRIPTION_LANGUAGE = "languageDescription";
|
||||
public static final String APP_UI_LANGUAGE = "appUiLanguage";
|
||||
public static final String KEY_THEME_VALUE = "appThemePref";
|
||||
|
||||
public static class Licenses {
|
||||
public static final String CC_BY_SA_3 = "CC BY-SA 3.0";
|
||||
public static final String CC_BY_3 = "CC BY 3.0";
|
||||
public static final String CC_BY_SA_4 = "CC BY-SA 4.0";
|
||||
public static final String CC_BY_4 = "CC BY 4.0";
|
||||
public static final String CC0 = "CC0";
|
||||
}
|
||||
}
|
||||
21
app/src/main/java/fr/free/nrw/commons/settings/Prefs.kt
Normal file
21
app/src/main/java/fr/free/nrw/commons/settings/Prefs.kt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package fr.free.nrw.commons.settings
|
||||
|
||||
object Prefs {
|
||||
const val GLOBAL_PREFS = "fr.free.nrw.commons.preferences"
|
||||
|
||||
const val TRACKING_ENABLED = "eventLogging"
|
||||
const val DEFAULT_LICENSE = "defaultLicense"
|
||||
const val UPLOADS_SHOWING = "uploadsShowing"
|
||||
const val MANAGED_EXIF_TAGS = "managed_exif_tags"
|
||||
const val DESCRIPTION_LANGUAGE = "languageDescription"
|
||||
const val APP_UI_LANGUAGE = "appUiLanguage"
|
||||
const val KEY_THEME_VALUE = "appThemePref"
|
||||
|
||||
object Licenses {
|
||||
const val CC_BY_SA_3 = "CC BY-SA 3.0"
|
||||
const val CC_BY_3 = "CC BY 3.0"
|
||||
const val CC_BY_SA_4 = "CC BY-SA 4.0"
|
||||
const val CC_BY_4 = "CC BY 4.0"
|
||||
const val CC0 = "CC0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package fr.free.nrw.commons.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
import fr.free.nrw.commons.databinding.ActivitySettingsBinding;
|
||||
import fr.free.nrw.commons.theme.BaseActivity;
|
||||
|
||||
/**
|
||||
* allows the user to change the settings
|
||||
*/
|
||||
public class SettingsActivity extends BaseActivity {
|
||||
|
||||
private ActivitySettingsBinding binding;
|
||||
// private AppCompatDelegate settingsDelegate;
|
||||
/**
|
||||
* to be called when the activity starts
|
||||
* @param savedInstanceState the previously saved state
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivitySettingsBinding.inflate(getLayoutInflater());
|
||||
final View view = binding.getRoot();
|
||||
setContentView(view);
|
||||
|
||||
setSupportActionBar(binding.toolbarBinding.toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
// Get an action bar
|
||||
/**
|
||||
* takes care of actions taken after the creation has happened
|
||||
* @param savedInstanceState the saved state
|
||||
*/
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
// if (settingsDelegate == null) {
|
||||
// settingsDelegate = AppCompatDelegate.create(this, null);
|
||||
// }
|
||||
// settingsDelegate.onPostCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle action-bar clicks
|
||||
* @param item the selected item
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package fr.free.nrw.commons.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import fr.free.nrw.commons.databinding.ActivitySettingsBinding
|
||||
import fr.free.nrw.commons.theme.BaseActivity
|
||||
|
||||
|
||||
/**
|
||||
* allows the user to change the settings
|
||||
*/
|
||||
class SettingsActivity : BaseActivity() {
|
||||
|
||||
private lateinit var binding: ActivitySettingsBinding
|
||||
// private var settingsDelegate: AppCompatDelegate? = null
|
||||
|
||||
/**
|
||||
* to be called when the activity starts
|
||||
* @param savedInstanceState the previously saved state
|
||||
*/
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||
val view = binding.root
|
||||
setContentView(view)
|
||||
|
||||
setSupportActionBar(binding.toolbarBinding.toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
// Get an action bar
|
||||
/**
|
||||
* takes care of actions taken after the creation has happened
|
||||
* @param savedInstanceState the saved state
|
||||
*/
|
||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
// if (settingsDelegate == null) {
|
||||
// settingsDelegate = AppCompatDelegate.create(this, null)
|
||||
// }
|
||||
// settingsDelegate?.onPostCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle action-bar clicks
|
||||
* @param item the selected item
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
finish()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,575 +0,0 @@
|
|||
package fr.free.nrw.commons.settings;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import androidx.activity.result.ActivityResultCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.MultiSelectListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.Preference.OnPreferenceClickListener;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceGroupAdapter;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter;
|
||||
import com.karumi.dexter.Dexter;
|
||||
import com.karumi.dexter.MultiplePermissionsReport;
|
||||
import com.karumi.dexter.PermissionToken;
|
||||
import com.karumi.dexter.listener.PermissionRequest;
|
||||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.campaigns.CampaignView;
|
||||
import fr.free.nrw.commons.contributions.ContributionController;
|
||||
import fr.free.nrw.commons.contributions.MainActivity;
|
||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
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.DialogUtil;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class SettingsFragment extends PreferenceFragmentCompat {
|
||||
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
JsonKvStore defaultKvStore;
|
||||
|
||||
@Inject
|
||||
CommonsLogSender commonsLogSender;
|
||||
|
||||
@Inject
|
||||
RecentLanguagesDao recentLanguagesDao;
|
||||
|
||||
@Inject
|
||||
ContributionController contributionController;
|
||||
|
||||
@Inject
|
||||
LocationServiceManager locationManager;
|
||||
|
||||
private ListPreference themeListPreference;
|
||||
private Preference descriptionLanguageListPreference;
|
||||
private Preference appUiLanguageListPreference;
|
||||
private Preference showDeletionButtonPreference;
|
||||
private String keyLanguageListPreference;
|
||||
private TextView recentLanguagesTextView;
|
||||
private View separator;
|
||||
private ListView languageHistoryListView;
|
||||
private static final String GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content";
|
||||
|
||||
private final ActivityResultLauncher<Intent> cameraPickLauncherForResult =
|
||||
registerForActivityResult(new StartActivityForResult(),
|
||||
result -> {
|
||||
contributionController.handleActivityResultWithCallback(requireActivity(), callbacks -> {
|
||||
contributionController.onPictureReturnedFromCamera(result, requireActivity(), callbacks);
|
||||
});
|
||||
});
|
||||
|
||||
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
|
||||
@Override
|
||||
public void onActivityResult(Map<String, Boolean> result) {
|
||||
boolean areAllGranted = true;
|
||||
for (final boolean b : result.values()) {
|
||||
areAllGranted = areAllGranted && b;
|
||||
}
|
||||
if (!areAllGranted && shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
contributionController.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
ApplicationlessInjection
|
||||
.getInstance(getActivity().getApplicationContext())
|
||||
.getCommonsApplicationComponent()
|
||||
.inject(this);
|
||||
|
||||
// Set the preferences from an XML resource
|
||||
setPreferencesFromResource(R.xml.preferences, rootKey);
|
||||
|
||||
themeListPreference = findPreference(Prefs.KEY_THEME_VALUE);
|
||||
prepareTheme();
|
||||
|
||||
MultiSelectListPreference multiSelectListPref = findPreference(Prefs.MANAGED_EXIF_TAGS);
|
||||
if (multiSelectListPref != null) {
|
||||
multiSelectListPref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
if (newValue instanceof HashSet && !((HashSet) newValue).contains(getString(R.string.exif_tag_location))) {
|
||||
defaultKvStore.putBoolean("has_user_manually_removed_location", true);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Preference inAppCameraLocationPref = findPreference("inAppCameraLocationPref");
|
||||
|
||||
inAppCameraLocationPref.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
boolean isInAppCameraLocationTurnedOn = (boolean) newValue;
|
||||
if (isInAppCameraLocationTurnedOn) {
|
||||
createDialogsAndHandleLocationPermissions(getActivity());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
// Gets current language code from shared preferences
|
||||
String languageCode;
|
||||
|
||||
appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref");
|
||||
assert appUiLanguageListPreference != null;
|
||||
keyLanguageListPreference = appUiLanguageListPreference.getKey();
|
||||
languageCode = getCurrentLanguageCode(keyLanguageListPreference);
|
||||
assert languageCode != null;
|
||||
if (languageCode.equals("")) {
|
||||
// If current language code is empty, means none selected by user yet so use phone local
|
||||
appUiLanguageListPreference.setSummary(Locale.getDefault().getDisplayLanguage());
|
||||
} else {
|
||||
// If any language is selected by user previously, use it
|
||||
Locale defLocale = createLocale(languageCode);
|
||||
appUiLanguageListPreference.setSummary((defLocale).getDisplayLanguage(defLocale));
|
||||
}
|
||||
appUiLanguageListPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
prepareAppLanguages(appUiLanguageListPreference.getKey());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
descriptionLanguageListPreference = findPreference("descriptionDefaultLanguagePref");
|
||||
assert descriptionLanguageListPreference != null;
|
||||
keyLanguageListPreference = descriptionLanguageListPreference.getKey();
|
||||
languageCode = getCurrentLanguageCode(keyLanguageListPreference);
|
||||
assert languageCode != null;
|
||||
if (languageCode.equals("")) {
|
||||
// If current language code is empty, means none selected by user yet so use phone local
|
||||
descriptionLanguageListPreference.setSummary(Locale.getDefault().getDisplayLanguage());
|
||||
} else {
|
||||
// If any language is selected by user previously, use it
|
||||
Locale defLocale = createLocale(languageCode);
|
||||
descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||
}
|
||||
descriptionLanguageListPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
prepareAppLanguages(descriptionLanguageListPreference.getKey());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
showDeletionButtonPreference = findPreference("displayDeletionButton");
|
||||
if (showDeletionButtonPreference != null) {
|
||||
showDeletionButtonPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean isEnabled = (boolean) newValue;
|
||||
// Save preference when user toggles the button
|
||||
defaultKvStore.putBoolean("displayDeletionButton", isEnabled);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Preference betaTesterPreference = findPreference("becomeBetaTester");
|
||||
betaTesterPreference.setOnPreferenceClickListener(preference -> {
|
||||
Utils.handleWebUrl(getActivity(), Uri.parse(getResources().getString(R.string.beta_opt_in_link)));
|
||||
return true;
|
||||
});
|
||||
Preference sendLogsPreference = findPreference("sendLogFile");
|
||||
sendLogsPreference.setOnPreferenceClickListener(preference -> {
|
||||
checkPermissionsAndSendLogs();
|
||||
return true;
|
||||
});
|
||||
|
||||
Preference documentBasedPickerPreference = findPreference("openDocumentPhotoPickerPref");
|
||||
documentBasedPickerPreference.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
boolean isGetContentPickerTurnedOn = !(boolean) newValue;
|
||||
if (isGetContentPickerTurnedOn) {
|
||||
showLocationLossWarning();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
// Disable some settings when not logged in.
|
||||
if (defaultKvStore.getBoolean("login_skipped", false)) {
|
||||
findPreference("useExternalStorage").setEnabled(false);
|
||||
findPreference("useAuthorName").setEnabled(false);
|
||||
findPreference("displayNearbyCardView").setEnabled(false);
|
||||
findPreference("descriptionDefaultLanguagePref").setEnabled(false);
|
||||
findPreference("displayLocationPermissionForCardView").setEnabled(false);
|
||||
findPreference(CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE).setEnabled(false);
|
||||
findPreference("managed_exif_tags").setEnabled(false);
|
||||
findPreference("openDocumentPhotoPickerPref").setEnabled(false);
|
||||
findPreference("inAppCameraLocationPref").setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks users to provide location access
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
private void createDialogsAndHandleLocationPermissions(Activity activity) {
|
||||
inAppCameraLocationPermissionLauncher.launch(new String[]{permission.ACCESS_FINE_LOCATION});
|
||||
}
|
||||
|
||||
/**
|
||||
* On some devices, the new Photo Picker with GET_CONTENT takeover
|
||||
* redacts location tags from EXIF metadata
|
||||
*
|
||||
* Show warning to the user when ACTION_GET_CONTENT intent is enabled
|
||||
*/
|
||||
private void showLocationLossWarning() {
|
||||
DialogUtil.showAlertDialog(
|
||||
getActivity(),
|
||||
null,
|
||||
getString(R.string.location_loss_warning),
|
||||
getString(R.string.ok),
|
||||
getString(R.string.read_help_link),
|
||||
() -> {},
|
||||
() -> Utils.handleWebUrl(requireContext(), Uri.parse(GET_CONTENT_PICKER_HELP_URL)),
|
||||
null,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Adapter onCreateAdapter(final PreferenceScreen preferenceScreen) {
|
||||
return new PreferenceGroupAdapter(preferenceScreen) {
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
|
||||
super.onBindViewHolder(holder, position);
|
||||
Preference preference = getItem(position);
|
||||
View iconFrame = holder.itemView.findViewById(R.id.icon_frame);
|
||||
if (iconFrame != null) {
|
||||
iconFrame.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the theme pref
|
||||
*/
|
||||
private void prepareTheme() {
|
||||
themeListPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
getActivity().recreate();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare and Show language selection dialog box
|
||||
* Uses previously saved language if there is any, if not uses phone locale as initial language.
|
||||
* Disable default/already selected language from dialog box
|
||||
* Get ListPreference key and act accordingly for each ListPreference.
|
||||
* saves value chosen by user to shared preferences
|
||||
* to remember later and recall MainActivity to reflect language changes
|
||||
* @param keyListPreference
|
||||
*/
|
||||
private void prepareAppLanguages(final String keyListPreference) {
|
||||
|
||||
// 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")) {
|
||||
|
||||
assert languageCode != null;
|
||||
if (languageCode.equals("")) {
|
||||
selectedLanguages.put(0, Locale.getDefault().getLanguage());
|
||||
} else {
|
||||
selectedLanguages.put(0, languageCode);
|
||||
}
|
||||
} else if (keyListPreference.equals("descriptionDefaultLanguagePref")) {
|
||||
|
||||
assert languageCode != null;
|
||||
if (languageCode.equals("")) {
|
||||
selectedLanguages.put(0, Locale.getDefault().getLanguage());
|
||||
|
||||
} else {
|
||||
selectedLanguages.put(0, languageCode);
|
||||
}
|
||||
}
|
||||
|
||||
LanguagesAdapter languagesAdapter = new LanguagesAdapter(
|
||||
getActivity(),
|
||||
selectedLanguages
|
||||
);
|
||||
|
||||
Dialog dialog = new Dialog(getActivity());
|
||||
dialog.setContentView(R.layout.dialog_select_language);
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
dialog.getWindow().setLayout((int)(getActivity().getResources().getDisplayMetrics().widthPixels*0.90),
|
||||
(int)(getActivity().getResources().getDisplayMetrics().heightPixels*0.90));
|
||||
dialog.show();
|
||||
|
||||
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);
|
||||
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
|
||||
int i2) {
|
||||
hideRecentLanguagesSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1,
|
||||
int i2) {
|
||||
languagesAdapter.getFilter().filter(charSequence);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
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 = createLocale(languageCode);
|
||||
if(keyListPreference.equals("appUiDefaultLanguagePref")) {
|
||||
appUiLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||
setLocale(requireActivity(), languageCode);
|
||||
getActivity().recreate();
|
||||
final Intent intent = new Intent(getActivity(), MainActivity.class);
|
||||
startActivity(intent);
|
||||
}else {
|
||||
descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||
}
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
dialog.setOnDismissListener(
|
||||
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 = createLocale(recentLanguageCode);
|
||||
if (keyListPreference.equals("appUiDefaultLanguagePref")) {
|
||||
appUiLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||
setLocale(requireActivity(), 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
|
||||
*/
|
||||
public void setLocale(final Activity activity, String userSelectedValue) {
|
||||
if (userSelectedValue.equals("")) {
|
||||
userSelectedValue = Locale.getDefault().getLanguage();
|
||||
}
|
||||
final Locale locale = createLocale(userSelectedValue);
|
||||
Locale.setDefault(locale);
|
||||
final Configuration configuration = new Configuration();
|
||||
configuration.locale = locale;
|
||||
activity.getBaseContext().getResources().updateConfiguration(configuration,
|
||||
activity.getBaseContext().getResources().getDisplayMetrics());
|
||||
|
||||
final SharedPreferences.Editor editor = activity.getSharedPreferences("Settings", MODE_PRIVATE).edit();
|
||||
editor.putString("language", userSelectedValue);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Locale based on different types of language codes
|
||||
* @param languageCode
|
||||
* @return Locale and throws error for invalid language codes
|
||||
*/
|
||||
public static Locale createLocale(String languageCode) {
|
||||
String[] parts = languageCode.split("-");
|
||||
switch (parts.length) {
|
||||
case 1:
|
||||
return new Locale(parts[0]);
|
||||
case 2:
|
||||
return new Locale(parts[0], parts[1]);
|
||||
case 3:
|
||||
return new Locale(parts[0], parts[1], parts[2]);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid language code: " + languageCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save userselected language in List Preference
|
||||
* @param userSelectedValue
|
||||
* @param preferenceKey
|
||||
*/
|
||||
private void saveLanguageValue(final String userSelectedValue, final String preferenceKey) {
|
||||
if (preferenceKey.equals("appUiDefaultLanguagePref")) {
|
||||
defaultKvStore.putString(Prefs.APP_UI_LANGUAGE, userSelectedValue);
|
||||
} else if (preferenceKey.equals("descriptionDefaultLanguagePref")) {
|
||||
defaultKvStore.putString(Prefs.DESCRIPTION_LANGUAGE, userSelectedValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current language code from shared preferences
|
||||
* @param preferenceKey
|
||||
* @return
|
||||
*/
|
||||
private String getCurrentLanguageCode(final String preferenceKey) {
|
||||
if (preferenceKey.equals("appUiDefaultLanguagePref")) {
|
||||
return defaultKvStore.getString(Prefs.APP_UI_LANGUAGE, "");
|
||||
}
|
||||
if (preferenceKey.equals("descriptionDefaultLanguagePref")) {
|
||||
return defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, "");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* First checks for external storage permissions and then sends logs via email
|
||||
*/
|
||||
private void checkPermissionsAndSendLogs() {
|
||||
if (PermissionUtils.hasPermission(getActivity(), PermissionUtils.getPERMISSIONS_STORAGE())) {
|
||||
commonsLogSender.send(getActivity(), null);
|
||||
} else {
|
||||
requestExternalStoragePermissions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests external storage permissions and shows a toast stating that log collection has
|
||||
* started
|
||||
*/
|
||||
private void requestExternalStoragePermissions() {
|
||||
Dexter.withActivity(getActivity())
|
||||
.withPermissions(PermissionUtils.getPERMISSIONS_STORAGE())
|
||||
.withListener(new MultiplePermissionsListener() {
|
||||
@Override
|
||||
public void onPermissionsChecked(MultiplePermissionsReport report) {
|
||||
ViewUtil.showLongToast(getActivity(),
|
||||
getResources().getString(R.string.log_collection_started));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionRationaleShouldBeShown(
|
||||
List<PermissionRequest> permissions, PermissionToken token) {
|
||||
|
||||
}
|
||||
})
|
||||
.onSameThread()
|
||||
.check();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,556 @@
|
|||
package fr.free.nrw.commons.settings
|
||||
|
||||
import android.Manifest.permission
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context.MODE_PRIVATE
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.EditText
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.MultiSelectListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceGroupAdapter
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter
|
||||
import com.karumi.dexter.Dexter
|
||||
import com.karumi.dexter.MultiplePermissionsReport
|
||||
import com.karumi.dexter.PermissionToken
|
||||
import com.karumi.dexter.listener.PermissionRequest
|
||||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.Utils
|
||||
import fr.free.nrw.commons.campaigns.CampaignView
|
||||
import fr.free.nrw.commons.contributions.ContributionController
|
||||
import fr.free.nrw.commons.contributions.MainActivity
|
||||
import fr.free.nrw.commons.di.ApplicationlessInjection
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore
|
||||
import fr.free.nrw.commons.location.LocationServiceManager
|
||||
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.DialogUtil
|
||||
import fr.free.nrw.commons.utils.PermissionUtils
|
||||
import fr.free.nrw.commons.utils.ViewUtil
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
@Inject
|
||||
@field: Named("default_preferences")
|
||||
lateinit var defaultKvStore: JsonKvStore
|
||||
|
||||
@Inject
|
||||
lateinit var commonsLogSender: CommonsLogSender
|
||||
|
||||
@Inject
|
||||
lateinit var recentLanguagesDao: RecentLanguagesDao
|
||||
|
||||
@Inject
|
||||
lateinit var contributionController: ContributionController
|
||||
|
||||
@Inject
|
||||
lateinit var locationManager: LocationServiceManager
|
||||
|
||||
private var themeListPreference: ListPreference? = null
|
||||
private var descriptionLanguageListPreference: Preference? = null
|
||||
private var appUiLanguageListPreference: Preference? = null
|
||||
private var showDeletionButtonPreference: Preference? = null
|
||||
private var keyLanguageListPreference: String? = null
|
||||
private var recentLanguagesTextView: TextView? = null
|
||||
private var separator: View? = null
|
||||
private var languageHistoryListView: ListView? = null
|
||||
private lateinit var inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>
|
||||
private val GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content"
|
||||
|
||||
private val cameraPickLauncherForResult: ActivityResultLauncher<Intent> =
|
||||
registerForActivityResult(StartActivityForResult()) { result ->
|
||||
contributionController.handleActivityResultWithCallback(requireActivity()) { callbacks ->
|
||||
contributionController.onPictureReturnedFromCamera(result, requireActivity(), callbacks)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* to be called when the fragment creates preferences
|
||||
* @param savedInstanceState the previously saved state
|
||||
* @param rootKey the root key for preferences
|
||||
*/
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
ApplicationlessInjection
|
||||
.getInstance(requireActivity().applicationContext)
|
||||
.commonsApplicationComponent
|
||||
.inject(this)
|
||||
|
||||
// Set the preferences from an XML resource
|
||||
setPreferencesFromResource(R.xml.preferences, rootKey)
|
||||
|
||||
themeListPreference = findPreference(Prefs.KEY_THEME_VALUE)
|
||||
prepareTheme()
|
||||
|
||||
val multiSelectListPref: MultiSelectListPreference? = findPreference(
|
||||
Prefs.MANAGED_EXIF_TAGS
|
||||
)
|
||||
multiSelectListPref?.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue is HashSet<*> && !newValue.contains(getString(R.string.exif_tag_location)))
|
||||
{
|
||||
defaultKvStore.putBoolean("has_user_manually_removed_location", true)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
val inAppCameraLocationPref: Preference? = findPreference("inAppCameraLocationPref")
|
||||
inAppCameraLocationPref?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val isInAppCameraLocationTurnedOn = newValue as Boolean
|
||||
if (isInAppCameraLocationTurnedOn) {
|
||||
createDialogsAndHandleLocationPermissions(requireActivity())
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
inAppCameraLocationPermissionLauncher = registerForActivityResult(
|
||||
RequestMultiplePermissions()
|
||||
) { result ->
|
||||
var areAllGranted = true
|
||||
for (b in result.values) {
|
||||
areAllGranted = areAllGranted && b
|
||||
}
|
||||
if (
|
||||
!areAllGranted
|
||||
&&
|
||||
shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)
|
||||
) {
|
||||
contributionController.handleShowRationaleFlowCameraLocation(
|
||||
requireActivity(),
|
||||
inAppCameraLocationPermissionLauncher,
|
||||
cameraPickLauncherForResult
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Gets current language code from shared preferences
|
||||
var languageCode: String?
|
||||
|
||||
appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref")
|
||||
appUiLanguageListPreference?.let { appUiLanguageListPreference ->
|
||||
keyLanguageListPreference = appUiLanguageListPreference.key
|
||||
languageCode = getCurrentLanguageCode(keyLanguageListPreference!!)
|
||||
|
||||
languageCode?.let { code ->
|
||||
if (code.isEmpty()) {
|
||||
// If current language code is empty, means none selected by user yet so use
|
||||
// phone locale
|
||||
appUiLanguageListPreference.summary = Locale.getDefault().displayLanguage
|
||||
} else {
|
||||
// If any language is selected by user previously, use it
|
||||
val defLocale = createLocale(code)
|
||||
appUiLanguageListPreference.summary = defLocale.getDisplayLanguage(defLocale)
|
||||
}
|
||||
}
|
||||
|
||||
appUiLanguageListPreference.setOnPreferenceClickListener {
|
||||
prepareAppLanguages(keyLanguageListPreference!!)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
descriptionLanguageListPreference = findPreference("descriptionDefaultLanguagePref")
|
||||
descriptionLanguageListPreference?.let { descriptionLanguageListPreference ->
|
||||
languageCode = getCurrentLanguageCode(descriptionLanguageListPreference.key)
|
||||
|
||||
languageCode?.let { code ->
|
||||
if (code.isEmpty()) {
|
||||
// If current language code is empty, means none selected by user yet so use
|
||||
// phone locale
|
||||
descriptionLanguageListPreference.summary = Locale.getDefault().displayLanguage
|
||||
} else {
|
||||
// If any language is selected by user previously, use it
|
||||
val defLocale = createLocale(code)
|
||||
descriptionLanguageListPreference.summary = defLocale.getDisplayLanguage(
|
||||
defLocale
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
descriptionLanguageListPreference.setOnPreferenceClickListener {
|
||||
prepareAppLanguages(it.key)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
showDeletionButtonPreference = findPreference("displayDeletionButton")
|
||||
showDeletionButtonPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val isEnabled = newValue as Boolean
|
||||
// Save preference when user toggles the button
|
||||
defaultKvStore.putBoolean("displayDeletionButton", isEnabled)
|
||||
true
|
||||
}
|
||||
|
||||
val betaTesterPreference: Preference? = findPreference("becomeBetaTester")
|
||||
betaTesterPreference?.setOnPreferenceClickListener {
|
||||
Utils.handleWebUrl(requireActivity(), Uri.parse(getString(R.string.beta_opt_in_link)))
|
||||
true
|
||||
}
|
||||
|
||||
val sendLogsPreference: Preference? = findPreference("sendLogFile")
|
||||
sendLogsPreference?.setOnPreferenceClickListener {
|
||||
checkPermissionsAndSendLogs()
|
||||
true
|
||||
}
|
||||
|
||||
val documentBasedPickerPreference: Preference? = findPreference(
|
||||
"openDocumentPhotoPickerPref"
|
||||
)
|
||||
documentBasedPickerPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val isGetContentPickerTurnedOn = newValue as Boolean
|
||||
if (!isGetContentPickerTurnedOn) {
|
||||
showLocationLossWarning()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
// Disable some settings when not logged in.
|
||||
if (defaultKvStore.getBoolean("login_skipped", false)) {
|
||||
findPreference<Preference>("useExternalStorage")?.isEnabled = false
|
||||
findPreference<Preference>("useAuthorName")?.isEnabled = false
|
||||
findPreference<Preference>("displayNearbyCardView")?.isEnabled = false
|
||||
findPreference<Preference>("descriptionDefaultLanguagePref")?.isEnabled = false
|
||||
findPreference<Preference>("displayLocationPermissionForCardView")?.isEnabled = false
|
||||
findPreference<Preference>(CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE)?.isEnabled = false
|
||||
findPreference<Preference>("managed_exif_tags")?.isEnabled = false
|
||||
findPreference<Preference>("openDocumentPhotoPickerPref")?.isEnabled = false
|
||||
findPreference<Preference>("inAppCameraLocationPref")?.isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks users to provide location access
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
private fun createDialogsAndHandleLocationPermissions(activity: Activity) {
|
||||
inAppCameraLocationPermissionLauncher.launch(arrayOf(permission.ACCESS_FINE_LOCATION))
|
||||
}
|
||||
|
||||
/**
|
||||
* On some devices, the new Photo Picker with GET_CONTENT takeover
|
||||
* redacts location tags from EXIF metadata
|
||||
*
|
||||
* Show warning to the user when ACTION_GET_CONTENT intent is enabled
|
||||
*/
|
||||
private fun showLocationLossWarning() {
|
||||
DialogUtil.showAlertDialog(
|
||||
requireActivity(),
|
||||
null,
|
||||
getString(R.string.location_loss_warning),
|
||||
getString(R.string.ok),
|
||||
getString(R.string.read_help_link),
|
||||
{ },
|
||||
{ Utils.handleWebUrl(requireContext(), Uri.parse(GET_CONTENT_PICKER_HELP_URL)) },
|
||||
null,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateAdapter(preferenceScreen: PreferenceScreen): Adapter<PreferenceViewHolder>
|
||||
{
|
||||
return object : PreferenceGroupAdapter(preferenceScreen) {
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder, position: Int) {
|
||||
super.onBindViewHolder(holder, position)
|
||||
val preference = getItem(position)
|
||||
val iconFrame: View? = holder.itemView.findViewById(R.id.icon_frame)
|
||||
iconFrame?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the theme pref
|
||||
*/
|
||||
private fun prepareTheme() {
|
||||
themeListPreference?.setOnPreferenceChangeListener { _, _ ->
|
||||
requireActivity().recreate()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare and Show language selection dialog box
|
||||
* Uses previously saved language if there is any, if not uses phone locale as initial language.
|
||||
* Disable default/already selected language from dialog box
|
||||
* Get ListPreference key and act accordingly for each ListPreference.
|
||||
* saves value chosen by user to shared preferences
|
||||
* to remember later and recall MainActivity to reflect language changes
|
||||
* @param keyListPreference
|
||||
*/
|
||||
private fun prepareAppLanguages(keyListPreference: String) {
|
||||
// Gets current language code from shared preferences
|
||||
val languageCode = getCurrentLanguageCode(keyListPreference)
|
||||
val recentLanguages = recentLanguagesDao.getRecentLanguages()
|
||||
val selectedLanguages = hashMapOf<Int, String>()
|
||||
|
||||
if (keyListPreference == "appUiDefaultLanguagePref") {
|
||||
if (languageCode.isNullOrEmpty()) {
|
||||
selectedLanguages[0] = Locale.getDefault().language
|
||||
} else {
|
||||
selectedLanguages[0] = languageCode
|
||||
}
|
||||
} else if (keyListPreference == "descriptionDefaultLanguagePref") {
|
||||
if (languageCode.isNullOrEmpty()) {
|
||||
selectedLanguages[0] = Locale.getDefault().language
|
||||
} else {
|
||||
selectedLanguages[0] = languageCode
|
||||
}
|
||||
}
|
||||
|
||||
val languagesAdapter = LanguagesAdapter(requireActivity(), selectedLanguages)
|
||||
|
||||
val dialog = Dialog(requireActivity())
|
||||
dialog.setContentView(R.layout.dialog_select_language)
|
||||
dialog.setCanceledOnTouchOutside(true)
|
||||
dialog.window?.setLayout(
|
||||
(resources.displayMetrics.widthPixels * 0.90).toInt(),
|
||||
(resources.displayMetrics.heightPixels * 0.90).toInt()
|
||||
)
|
||||
dialog.show()
|
||||
|
||||
val editText: EditText = dialog.findViewById(R.id.search_language)
|
||||
val 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.adapter = languagesAdapter
|
||||
|
||||
editText.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(charSequence: CharSequence, start: Int, count: Int, after: Int) {
|
||||
hideRecentLanguagesSection()
|
||||
}
|
||||
|
||||
override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
|
||||
languagesAdapter.filter.filter(charSequence)
|
||||
}
|
||||
|
||||
override fun afterTextChanged(editable: Editable?) {}
|
||||
})
|
||||
|
||||
languageHistoryListView?.setOnItemClickListener { adapterView, _, position, _ ->
|
||||
onRecentLanguageClicked(keyListPreference, dialog, adapterView, position)
|
||||
}
|
||||
|
||||
listView.setOnItemClickListener { adapterView, _, position, _ ->
|
||||
val lCode = (adapterView.adapter as LanguagesAdapter).getLanguageCode(position)
|
||||
val languageName = (adapterView.adapter as LanguagesAdapter).getLanguageName(position)
|
||||
val isExists = recentLanguagesDao.findRecentLanguage(lCode)
|
||||
if (isExists) {
|
||||
recentLanguagesDao.deleteRecentLanguage(lCode)
|
||||
}
|
||||
recentLanguagesDao.addRecentLanguage(Language(languageName, lCode))
|
||||
saveLanguageValue(lCode, keyListPreference)
|
||||
val defLocale = createLocale(lCode)
|
||||
if (keyListPreference == "appUiDefaultLanguagePref") {
|
||||
appUiLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
|
||||
setLocale(requireActivity(), lCode)
|
||||
requireActivity().recreate()
|
||||
val intent = Intent(requireActivity(), MainActivity::class.java)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
descriptionLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
dialog.setOnDismissListener { languagesAdapter.filter.filter("") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up recent languages section
|
||||
*
|
||||
* @param recentLanguages recently used languages
|
||||
* @param selectedLanguages selected languages
|
||||
*/
|
||||
private fun setUpRecentLanguagesSection(
|
||||
recentLanguages: List<Language>,
|
||||
selectedLanguages: HashMap<Int, String>
|
||||
) {
|
||||
if (recentLanguages.isEmpty()) {
|
||||
languageHistoryListView?.visibility = View.GONE
|
||||
recentLanguagesTextView?.visibility = View.GONE
|
||||
separator?.visibility = View.GONE
|
||||
} else {
|
||||
if (recentLanguages.size > 5) {
|
||||
for (i in recentLanguages.size - 1 downTo 5) {
|
||||
recentLanguagesDao.deleteRecentLanguage(recentLanguages[i].languageCode)
|
||||
}
|
||||
}
|
||||
languageHistoryListView?.visibility = View.VISIBLE
|
||||
recentLanguagesTextView?.visibility = View.VISIBLE
|
||||
separator?.visibility = View.VISIBLE
|
||||
val recentLanguagesAdapter = RecentLanguagesAdapter(
|
||||
requireActivity(),
|
||||
recentLanguagesDao.getRecentLanguages(),
|
||||
selectedLanguages
|
||||
)
|
||||
languageHistoryListView?.adapter = recentLanguagesAdapter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles click event for recent language section
|
||||
*/
|
||||
private fun onRecentLanguageClicked(
|
||||
keyListPreference: String,
|
||||
dialog: Dialog,
|
||||
adapterView: AdapterView<*>,
|
||||
position: Int
|
||||
) {
|
||||
val recentLanguageCode = (adapterView.adapter as RecentLanguagesAdapter).getLanguageCode(position)
|
||||
val recentLanguageName = (adapterView.adapter as RecentLanguagesAdapter).getLanguageName(position)
|
||||
val isExists = recentLanguagesDao.findRecentLanguage(recentLanguageCode)
|
||||
if (isExists) {
|
||||
recentLanguagesDao.deleteRecentLanguage(recentLanguageCode)
|
||||
}
|
||||
recentLanguagesDao.addRecentLanguage(Language(recentLanguageName, recentLanguageCode))
|
||||
saveLanguageValue(recentLanguageCode, keyListPreference)
|
||||
val defLocale = createLocale(recentLanguageCode)
|
||||
if (keyListPreference == "appUiDefaultLanguagePref") {
|
||||
appUiLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
|
||||
setLocale(requireActivity(), recentLanguageCode)
|
||||
requireActivity().recreate()
|
||||
val intent = Intent(requireActivity(), MainActivity::class.java)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
descriptionLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the section of recent languages
|
||||
*/
|
||||
private fun hideRecentLanguagesSection() {
|
||||
languageHistoryListView?.visibility = View.GONE
|
||||
recentLanguagesTextView?.visibility = View.GONE
|
||||
separator?.visibility = View.GONE
|
||||
}
|
||||
|
||||
/**
|
||||
* Changing the default app language with selected one and save it to SharedPreferences
|
||||
*/
|
||||
fun setLocale(activity: Activity, userSelectedValue: String) {
|
||||
var selectedLanguage = userSelectedValue
|
||||
if (selectedLanguage == "") {
|
||||
selectedLanguage = Locale.getDefault().language
|
||||
}
|
||||
val locale = createLocale(selectedLanguage)
|
||||
Locale.setDefault(locale)
|
||||
val configuration = Configuration()
|
||||
configuration.locale = locale
|
||||
activity.baseContext.resources.updateConfiguration(configuration, activity.baseContext.resources.displayMetrics)
|
||||
|
||||
val editor = activity.getSharedPreferences("Settings", MODE_PRIVATE).edit()
|
||||
editor.putString("language", selectedLanguage)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Locale based on different types of language codes
|
||||
* @param languageCode
|
||||
* @return Locale and throws error for invalid language codes
|
||||
*/
|
||||
fun createLocale(languageCode: String): Locale {
|
||||
val parts = languageCode.split("-")
|
||||
return when (parts.size) {
|
||||
1 -> Locale(parts[0])
|
||||
2 -> Locale(parts[0], parts[1])
|
||||
3 -> Locale(parts[0], parts[1], parts[2])
|
||||
else -> throw IllegalArgumentException("Invalid language code: $languageCode")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save userSelected language in List Preference
|
||||
* @param userSelectedValue
|
||||
* @param preferenceKey
|
||||
*/
|
||||
private fun saveLanguageValue(userSelectedValue: String, preferenceKey: String) {
|
||||
when (preferenceKey) {
|
||||
"appUiDefaultLanguagePref" -> defaultKvStore.putString(Prefs.APP_UI_LANGUAGE, userSelectedValue)
|
||||
"descriptionDefaultLanguagePref" -> defaultKvStore.putString(Prefs.DESCRIPTION_LANGUAGE, userSelectedValue)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current language code from shared preferences
|
||||
* @param preferenceKey
|
||||
* @return
|
||||
*/
|
||||
private fun getCurrentLanguageCode(preferenceKey: String): String? {
|
||||
return when (preferenceKey) {
|
||||
"appUiDefaultLanguagePref" -> defaultKvStore.getString(
|
||||
Prefs.APP_UI_LANGUAGE, ""
|
||||
)
|
||||
"descriptionDefaultLanguagePref" -> defaultKvStore.getString(
|
||||
Prefs.DESCRIPTION_LANGUAGE, ""
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* First checks for external storage permissions and then sends logs via email
|
||||
*/
|
||||
private fun checkPermissionsAndSendLogs() {
|
||||
if (
|
||||
PermissionUtils.hasPermission(
|
||||
requireActivity(),
|
||||
PermissionUtils.PERMISSIONS_STORAGE
|
||||
)
|
||||
) {
|
||||
commonsLogSender.send(requireActivity(), null)
|
||||
} else {
|
||||
requestExternalStoragePermissions()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests external storage permissions and shows a toast stating that log collection has
|
||||
* started
|
||||
*/
|
||||
private fun requestExternalStoragePermissions() {
|
||||
Dexter.withActivity(requireActivity())
|
||||
.withPermissions(*PermissionUtils.PERMISSIONS_STORAGE)
|
||||
.withListener(object : MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport) {
|
||||
ViewUtil.showLongToast(requireActivity(), getString(R.string.log_collection_started))
|
||||
}
|
||||
|
||||
override fun onPermissionRationaleShouldBeShown(
|
||||
permissions: List<PermissionRequest>, token: PermissionToken
|
||||
) {
|
||||
// No action needed
|
||||
}
|
||||
})
|
||||
.onSameThread()
|
||||
.check()
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue