Migrated settings module to Kotlin

This commit is contained in:
Saifuddin 2024-11-21 17:00:05 +05:30
parent f6fdd9c6a1
commit 09849c803c
3 changed files with 429 additions and 454 deletions

View file

@ -1,21 +1,21 @@
package fr.free.nrw.commons.settings; package fr.free.nrw.commons.settings
public class Prefs { object Prefs {
public static String GLOBAL_PREFS = "fr.free.nrw.commons.preferences"; const val GLOBAL_PREFS = "fr.free.nrw.commons.preferences"
public static String TRACKING_ENABLED = "eventLogging"; const val TRACKING_ENABLED = "eventLogging"
public static final String DEFAULT_LICENSE = "defaultLicense"; const val DEFAULT_LICENSE = "defaultLicense"
public static final String UPLOADS_SHOWING = "uploadsshowing"; const val UPLOADS_SHOWING = "uploadsShowing"
public static final String MANAGED_EXIF_TAGS = "managed_exif_tags"; const val MANAGED_EXIF_TAGS = "managed_exif_tags"
public static final String DESCRIPTION_LANGUAGE = "languageDescription"; const val DESCRIPTION_LANGUAGE = "languageDescription"
public static final String APP_UI_LANGUAGE = "appUiLanguage"; const val APP_UI_LANGUAGE = "appUiLanguage"
public static final String KEY_THEME_VALUE = "appThemePref"; const val KEY_THEME_VALUE = "appThemePref"
public static class Licenses { object Licenses {
public static final String CC_BY_SA_3 = "CC BY-SA 3.0"; const val CC_BY_SA_3 = "CC BY-SA 3.0"
public static final String CC_BY_3 = "CC BY 3.0"; const val CC_BY_3 = "CC BY 3.0"
public static final String CC_BY_SA_4 = "CC BY-SA 4.0"; const val CC_BY_SA_4 = "CC BY-SA 4.0"
public static final String CC_BY_4 = "CC BY 4.0"; const val CC_BY_4 = "CC BY 4.0"
public static final String CC0 = "CC0"; const val CC0 = "CC0"
} }
} }

View file

@ -1,34 +1,31 @@
package fr.free.nrw.commons.settings; package fr.free.nrw.commons.settings
import android.os.Bundle; import android.os.Bundle
import android.view.MenuItem; import android.view.MenuItem
import fr.free.nrw.commons.databinding.ActivitySettingsBinding
import fr.free.nrw.commons.theme.BaseActivity
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 * allows the user to change the settings
*/ */
public class SettingsActivity extends BaseActivity { class SettingsActivity : BaseActivity() {
private lateinit var binding: ActivitySettingsBinding
// private var settingsDelegate: AppCompatDelegate? = null
private ActivitySettingsBinding binding;
// private AppCompatDelegate settingsDelegate;
/** /**
* to be called when the activity starts * to be called when the activity starts
* @param savedInstanceState the previously saved state * @param savedInstanceState the previously saved state
*/ */
@Override override fun onCreate(savedInstanceState: Bundle?) {
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState)
super.onCreate(savedInstanceState); binding = ActivitySettingsBinding.inflate(layoutInflater)
binding = ActivitySettingsBinding.inflate(getLayoutInflater()); val view = binding.root
final View view = binding.getRoot(); setContentView(view)
setContentView(view);
setSupportActionBar(binding.toolbarBinding.toolbar); setSupportActionBar(binding.toolbarBinding.toolbar)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); supportActionBar?.setDisplayHomeAsUpEnabled(true)
} }
// Get an action bar // Get an action bar
@ -36,19 +33,17 @@ public class SettingsActivity extends BaseActivity {
* takes care of actions taken after the creation has happened * takes care of actions taken after the creation has happened
* @param savedInstanceState the saved state * @param savedInstanceState the saved state
*/ */
@Override override fun onPostCreate(savedInstanceState: Bundle?) {
protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState)
super.onPostCreate(savedInstanceState);
// if (settingsDelegate == null) { // if (settingsDelegate == null) {
// settingsDelegate = AppCompatDelegate.create(this, null); // settingsDelegate = AppCompatDelegate.create(this, null)
// } // }
// settingsDelegate.onPostCreate(savedInstanceState); // settingsDelegate?.onPostCreate(savedInstanceState)
} }
@Override override fun onSupportNavigateUp(): Boolean {
public boolean onSupportNavigateUp() { onBackPressed()
onBackPressed(); return true
return true;
} }
/** /**
@ -56,14 +51,13 @@ public class SettingsActivity extends BaseActivity {
* @param item the selected item * @param item the selected item
* @return true on success, false on failure * @return true on success, false on failure
*/ */
@Override override fun onOptionsItemSelected(item: MenuItem): Boolean {
public boolean onOptionsItemSelected(MenuItem item) { return when (item.itemId) {
switch (item.getItemId()) { android.R.id.home -> {
case android.R.id.home: finish()
finish(); true
return true; }
default: else -> super.onOptionsItemSelected(item)
return super.onOptionsItemSelected(item);
} }
} }
} }

View file

@ -1,239 +1,241 @@
package fr.free.nrw.commons.settings; 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.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
import android.Manifest.permission; class SettingsFragment : PreferenceFragmentCompat() {
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 @Inject
@Named("default_preferences") @field: Named("default_preferences")
JsonKvStore defaultKvStore; lateinit var defaultKvStore: JsonKvStore
@Inject @Inject
CommonsLogSender commonsLogSender; lateinit var commonsLogSender: CommonsLogSender
@Inject @Inject
RecentLanguagesDao recentLanguagesDao; lateinit var recentLanguagesDao: RecentLanguagesDao
@Inject @Inject
ContributionController contributionController; lateinit var contributionController: ContributionController
@Inject @Inject
LocationServiceManager locationManager; lateinit var locationManager: LocationServiceManager
private ListPreference themeListPreference; private var themeListPreference: ListPreference? = null
private Preference descriptionLanguageListPreference; private var descriptionLanguageListPreference: Preference? = null
private Preference appUiLanguageListPreference; private var appUiLanguageListPreference: Preference? = null
private Preference showDeletionButtonPreference; private var showDeletionButtonPreference: Preference? = null
private String keyLanguageListPreference; private var keyLanguageListPreference: String? = null
private TextView recentLanguagesTextView; private var recentLanguagesTextView: TextView? = null
private View separator; private var separator: View? = null
private ListView languageHistoryListView; private var languageHistoryListView: ListView? = null
private static final String GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content"; private lateinit var inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>
private val GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content"
private final ActivityResultLauncher<Intent> cameraPickLauncherForResult = private val cameraPickLauncherForResult: ActivityResultLauncher<Intent> =
registerForActivityResult(new StartActivityForResult(), registerForActivityResult(StartActivityForResult()) { result ->
result -> { contributionController.handleActivityResultWithCallback(requireActivity()) { callbacks ->
contributionController.handleActivityResultWithCallback(requireActivity(), callbacks -> { contributionController.onPictureReturnedFromCamera(result, 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) { * 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 ApplicationlessInjection
.getInstance(getActivity().getApplicationContext()) .getInstance(requireActivity().applicationContext)
.getCommonsApplicationComponent() .commonsApplicationComponent
.inject(this); .inject(this)
// Set the preferences from an XML resource // Set the preferences from an XML resource
setPreferencesFromResource(R.xml.preferences, rootKey); setPreferencesFromResource(R.xml.preferences, rootKey)
themeListPreference = findPreference(Prefs.KEY_THEME_VALUE); themeListPreference = findPreference(Prefs.KEY_THEME_VALUE)
prepareTheme(); prepareTheme()
MultiSelectListPreference multiSelectListPref = findPreference(Prefs.MANAGED_EXIF_TAGS); val multiSelectListPref: MultiSelectListPreference? = findPreference(
if (multiSelectListPref != null) { Prefs.MANAGED_EXIF_TAGS
multiSelectListPref.setOnPreferenceChangeListener((preference, newValue) -> { )
if (newValue instanceof HashSet && !((HashSet) newValue).contains(getString(R.string.exif_tag_location))) { multiSelectListPref?.setOnPreferenceChangeListener { _, newValue ->
defaultKvStore.putBoolean("has_user_manually_removed_location", true); if (newValue is HashSet<*> && !newValue.contains(getString(R.string.exif_tag_location)))
} {
return true; defaultKvStore.putBoolean("has_user_manually_removed_location", true)
}); }
true
} }
Preference inAppCameraLocationPref = findPreference("inAppCameraLocationPref"); val inAppCameraLocationPref: Preference? = findPreference("inAppCameraLocationPref")
inAppCameraLocationPref?.setOnPreferenceChangeListener { _, newValue ->
inAppCameraLocationPref.setOnPreferenceChangeListener( val isInAppCameraLocationTurnedOn = newValue as Boolean
(preference, newValue) -> { if (isInAppCameraLocationTurnedOn) {
boolean isInAppCameraLocationTurnedOn = (boolean) newValue; createDialogsAndHandleLocationPermissions(requireActivity())
if (isInAppCameraLocationTurnedOn) {
createDialogsAndHandleLocationPermissions(getActivity());
}
return true;
} }
); 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 // Gets current language code from shared preferences
String languageCode; var languageCode: String?
appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref"); appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref")
assert appUiLanguageListPreference != null; appUiLanguageListPreference?.let { appUiLanguageListPreference ->
keyLanguageListPreference = appUiLanguageListPreference.getKey(); keyLanguageListPreference = appUiLanguageListPreference.key
languageCode = getCurrentLanguageCode(keyLanguageListPreference); 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"); languageCode?.let { code ->
assert descriptionLanguageListPreference != null; if (code.isEmpty()) {
keyLanguageListPreference = descriptionLanguageListPreference.getKey(); // If current language code is empty, means none selected by user yet so use
languageCode = getCurrentLanguageCode(keyLanguageListPreference); // phone locale
assert languageCode != null; appUiLanguageListPreference.summary = Locale.getDefault().displayLanguage
if (languageCode.equals("")) { } else {
// If current language code is empty, means none selected by user yet so use phone local // If any language is selected by user previously, use it
descriptionLanguageListPreference.setSummary(Locale.getDefault().getDisplayLanguage()); val defLocale = createLocale(code)
} else { appUiLanguageListPreference.summary = defLocale.getDisplayLanguage(defLocale)
// 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;
} }
);
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. // Disable some settings when not logged in.
if (defaultKvStore.getBoolean("login_skipped", false)) { if (defaultKvStore.getBoolean("login_skipped", false)) {
findPreference("useExternalStorage").setEnabled(false); findPreference<Preference>("useExternalStorage")?.isEnabled = false
findPreference("useAuthorName").setEnabled(false); findPreference<Preference>("useAuthorName")?.isEnabled = false
findPreference("displayNearbyCardView").setEnabled(false); findPreference<Preference>("displayNearbyCardView")?.isEnabled = false
findPreference("descriptionDefaultLanguagePref").setEnabled(false); findPreference<Preference>("descriptionDefaultLanguagePref")?.isEnabled = false
findPreference("displayLocationPermissionForCardView").setEnabled(false); findPreference<Preference>("displayLocationPermissionForCardView")?.isEnabled = false
findPreference(CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE).setEnabled(false); findPreference<Preference>(CampaignView.CAMPAIGNS_DEFAULT_PREFERENCE)?.isEnabled = false
findPreference("managed_exif_tags").setEnabled(false); findPreference<Preference>("managed_exif_tags")?.isEnabled = false
findPreference("openDocumentPhotoPickerPref").setEnabled(false); findPreference<Preference>("openDocumentPhotoPickerPref")?.isEnabled = false
findPreference("inAppCameraLocationPref").setEnabled(false); findPreference<Preference>("inAppCameraLocationPref")?.isEnabled = false
} }
} }
@ -242,8 +244,8 @@ public class SettingsFragment extends PreferenceFragmentCompat {
* *
* @param activity * @param activity
*/ */
private void createDialogsAndHandleLocationPermissions(Activity activity) { private fun createDialogsAndHandleLocationPermissions(activity: Activity) {
inAppCameraLocationPermissionLauncher.launch(new String[]{permission.ACCESS_FINE_LOCATION}); inAppCameraLocationPermissionLauncher.launch(arrayOf(permission.ACCESS_FINE_LOCATION))
} }
/** /**
@ -252,43 +254,40 @@ public class SettingsFragment extends PreferenceFragmentCompat {
* *
* Show warning to the user when ACTION_GET_CONTENT intent is enabled * Show warning to the user when ACTION_GET_CONTENT intent is enabled
*/ */
private void showLocationLossWarning() { private fun showLocationLossWarning() {
DialogUtil.showAlertDialog( DialogUtil.showAlertDialog(
getActivity(), requireActivity(),
null, null,
getString(R.string.location_loss_warning), getString(R.string.location_loss_warning),
getString(R.string.ok), getString(R.string.ok),
getString(R.string.read_help_link), getString(R.string.read_help_link),
() -> {}, { },
() -> Utils.handleWebUrl(requireContext(), Uri.parse(GET_CONTENT_PICKER_HELP_URL)), { Utils.handleWebUrl(requireContext(), Uri.parse(GET_CONTENT_PICKER_HELP_URL)) },
null, null,
true true
); )
} }
@Override override fun onCreateAdapter(preferenceScreen: PreferenceScreen): Adapter<PreferenceViewHolder>
protected Adapter onCreateAdapter(final PreferenceScreen preferenceScreen) { {
return new PreferenceGroupAdapter(preferenceScreen) { return object : PreferenceGroupAdapter(preferenceScreen) {
@Override override fun onBindViewHolder(holder: PreferenceViewHolder, position: Int) {
public void onBindViewHolder(PreferenceViewHolder holder, int position) { super.onBindViewHolder(holder, position)
super.onBindViewHolder(holder, position); val preference = getItem(position)
Preference preference = getItem(position); val iconFrame: View? = holder.itemView.findViewById(R.id.icon_frame)
View iconFrame = holder.itemView.findViewById(R.id.icon_frame); iconFrame?.visibility = View.GONE
if (iconFrame != null) {
iconFrame.setVisibility(View.GONE);
}
} }
}; }
} }
/** /**
* Sets the theme pref * Sets the theme pref
*/ */
private void prepareTheme() { private fun prepareTheme() {
themeListPreference.setOnPreferenceChangeListener((preference, newValue) -> { themeListPreference?.setOnPreferenceChangeListener { _, _ ->
getActivity().recreate(); requireActivity().recreate()
return true; true
}); }
} }
/** /**
@ -300,107 +299,86 @@ public class SettingsFragment extends PreferenceFragmentCompat {
* to remember later and recall MainActivity to reflect language changes * to remember later and recall MainActivity to reflect language changes
* @param keyListPreference * @param keyListPreference
*/ */
private void prepareAppLanguages(final String keyListPreference) { private fun prepareAppLanguages(keyListPreference: String) {
// Gets current language code from shared preferences // Gets current language code from shared preferences
final String languageCode = getCurrentLanguageCode(keyListPreference); val languageCode = getCurrentLanguageCode(keyListPreference)
final List<Language> recentLanguages = recentLanguagesDao.getRecentLanguages(); val recentLanguages = recentLanguagesDao.getRecentLanguages()
HashMap<Integer, String> selectedLanguages = new HashMap<>(); val selectedLanguages = hashMapOf<Int, String>()
if (keyListPreference.equals("appUiDefaultLanguagePref")) { if (keyListPreference == "appUiDefaultLanguagePref") {
if (languageCode.isNullOrEmpty()) {
assert languageCode != null; selectedLanguages[0] = Locale.getDefault().language
if (languageCode.equals("")) {
selectedLanguages.put(0, Locale.getDefault().getLanguage());
} else { } else {
selectedLanguages.put(0, languageCode); selectedLanguages[0] = languageCode
} }
} else if (keyListPreference.equals("descriptionDefaultLanguagePref")) { } else if (keyListPreference == "descriptionDefaultLanguagePref") {
if (languageCode.isNullOrEmpty()) {
assert languageCode != null; selectedLanguages[0] = Locale.getDefault().language
if (languageCode.equals("")) {
selectedLanguages.put(0, Locale.getDefault().getLanguage());
} else { } else {
selectedLanguages.put(0, languageCode); selectedLanguages[0] = languageCode
} }
} }
LanguagesAdapter languagesAdapter = new LanguagesAdapter( val languagesAdapter = LanguagesAdapter(requireActivity(), selectedLanguages)
getActivity(),
selectedLanguages
);
Dialog dialog = new Dialog(getActivity()); val dialog = Dialog(requireActivity())
dialog.setContentView(R.layout.dialog_select_language); dialog.setContentView(R.layout.dialog_select_language)
dialog.setCanceledOnTouchOutside(true); dialog.setCanceledOnTouchOutside(true)
dialog.getWindow().setLayout((int)(getActivity().getResources().getDisplayMetrics().widthPixels*0.90), dialog.window?.setLayout(
(int)(getActivity().getResources().getDisplayMetrics().heightPixels*0.90)); (resources.displayMetrics.widthPixels * 0.90).toInt(),
dialog.show(); (resources.displayMetrics.heightPixels * 0.90).toInt()
)
dialog.show()
EditText editText = dialog.findViewById(R.id.search_language); val editText: EditText = dialog.findViewById(R.id.search_language)
ListView listView = dialog.findViewById(R.id.language_list); val listView: ListView = dialog.findViewById(R.id.language_list)
languageHistoryListView = dialog.findViewById(R.id.language_history_list); languageHistoryListView = dialog.findViewById(R.id.language_history_list)
recentLanguagesTextView = dialog.findViewById(R.id.recent_searches); recentLanguagesTextView = dialog.findViewById(R.id.recent_searches)
separator = dialog.findViewById(R.id.separator); separator = dialog.findViewById(R.id.separator)
setUpRecentLanguagesSection(recentLanguages, selectedLanguages); setUpRecentLanguagesSection(recentLanguages, selectedLanguages)
listView.setAdapter(languagesAdapter); listView.adapter = languagesAdapter
editText.addTextChangedListener(new TextWatcher() { editText.addTextChangedListener(object : TextWatcher {
@Override override fun beforeTextChanged(charSequence: CharSequence, start: Int, count: Int, after: Int) {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, hideRecentLanguagesSection()
int i2) {
hideRecentLanguagesSection();
} }
@Override override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
public void onTextChanged(CharSequence charSequence, int i, int i1, languagesAdapter.filter.filter(charSequence)
int i2) {
languagesAdapter.getFilter().filter(charSequence);
} }
@Override override fun afterTextChanged(editable: Editable?) {}
public void 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)
languageHistoryListView.setOnItemClickListener((adapterView, view, position, id) -> { val defLocale = createLocale(lCode)
onRecentLanguageClicked(keyListPreference, dialog, adapterView, position); if (keyListPreference == "appUiDefaultLanguagePref") {
}); appUiLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
setLocale(requireActivity(), lCode)
listView.setOnItemClickListener(new OnItemClickListener() { requireActivity().recreate()
@Override val intent = Intent(requireActivity(), MainActivity::class.java)
public void onItemClick(AdapterView<?> adapterView, View view, int i, startActivity(intent)
long l) { } else {
String languageCode = ((LanguagesAdapter) adapterView.getAdapter()) descriptionLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
.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.dismiss()
}
dialog.setOnDismissListener( dialog.setOnDismissListener { languagesAdapter.filter.filter("") }
dialogInterface -> languagesAdapter.getFilter().filter(""));
} }
/** /**
@ -409,86 +387,88 @@ public class SettingsFragment extends PreferenceFragmentCompat {
* @param recentLanguages recently used languages * @param recentLanguages recently used languages
* @param selectedLanguages selected languages * @param selectedLanguages selected languages
*/ */
private void setUpRecentLanguagesSection(List<Language> recentLanguages, private fun setUpRecentLanguagesSection(
HashMap<Integer, String> selectedLanguages) { recentLanguages: List<Language>,
selectedLanguages: HashMap<Int, String>
) {
if (recentLanguages.isEmpty()) { if (recentLanguages.isEmpty()) {
languageHistoryListView.setVisibility(View.GONE); languageHistoryListView?.visibility = View.GONE
recentLanguagesTextView.setVisibility(View.GONE); recentLanguagesTextView?.visibility = View.GONE
separator.setVisibility(View.GONE); separator?.visibility = View.GONE
} else { } else {
if (recentLanguages.size() > 5) { if (recentLanguages.size > 5) {
for (int i = recentLanguages.size()-1; i >=5; i--) { for (i in recentLanguages.size - 1 downTo 5) {
recentLanguagesDao recentLanguagesDao.deleteRecentLanguage(recentLanguages[i].languageCode)
.deleteRecentLanguage(recentLanguages.get(i).getLanguageCode());
} }
} }
languageHistoryListView.setVisibility(View.VISIBLE); languageHistoryListView?.visibility = View.VISIBLE
recentLanguagesTextView.setVisibility(View.VISIBLE); recentLanguagesTextView?.visibility = View.VISIBLE
separator.setVisibility(View.VISIBLE); separator?.visibility = View.VISIBLE
final RecentLanguagesAdapter recentLanguagesAdapter val recentLanguagesAdapter = RecentLanguagesAdapter(
= new RecentLanguagesAdapter( requireActivity(),
getActivity(),
recentLanguagesDao.getRecentLanguages(), recentLanguagesDao.getRecentLanguages(),
selectedLanguages); selectedLanguages
languageHistoryListView.setAdapter(recentLanguagesAdapter); )
languageHistoryListView?.adapter = recentLanguagesAdapter
} }
} }
/** /**
* Handles click event for recent language section * Handles click event for recent language section
*/ */
private void onRecentLanguageClicked(String keyListPreference, Dialog dialog, AdapterView<?> adapterView, private fun onRecentLanguageClicked(
int position) { keyListPreference: String,
final String recentLanguageCode = ((RecentLanguagesAdapter) adapterView.getAdapter()) dialog: Dialog,
.getLanguageCode(position); adapterView: AdapterView<*>,
final String recentLanguageName = ((RecentLanguagesAdapter) adapterView.getAdapter()) position: Int
.getLanguageName(position); ) {
final boolean isExists = recentLanguagesDao.findRecentLanguage(recentLanguageCode); val recentLanguageCode = (adapterView.adapter as RecentLanguagesAdapter).getLanguageCode(position)
val recentLanguageName = (adapterView.adapter as RecentLanguagesAdapter).getLanguageName(position)
val isExists = recentLanguagesDao.findRecentLanguage(recentLanguageCode)
if (isExists) { if (isExists) {
recentLanguagesDao.deleteRecentLanguage(recentLanguageCode); recentLanguagesDao.deleteRecentLanguage(recentLanguageCode)
} }
recentLanguagesDao.addRecentLanguage( recentLanguagesDao.addRecentLanguage(Language(recentLanguageName, recentLanguageCode))
new Language(recentLanguageName, recentLanguageCode)); saveLanguageValue(recentLanguageCode, keyListPreference)
saveLanguageValue(recentLanguageCode, keyListPreference); val defLocale = createLocale(recentLanguageCode)
final Locale defLocale = createLocale(recentLanguageCode); if (keyListPreference == "appUiDefaultLanguagePref") {
if (keyListPreference.equals("appUiDefaultLanguagePref")) { appUiLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
appUiLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale)); setLocale(requireActivity(), recentLanguageCode)
setLocale(requireActivity(), recentLanguageCode); requireActivity().recreate()
getActivity().recreate(); val intent = Intent(requireActivity(), MainActivity::class.java)
final Intent intent = new Intent(getActivity(), MainActivity.class); startActivity(intent)
startActivity(intent);
} else { } else {
descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale)); descriptionLanguageListPreference?.summary = defLocale.getDisplayLanguage(defLocale)
} }
dialog.dismiss(); dialog.dismiss()
} }
/** /**
* Remove the section of recent languages * Remove the section of recent languages
*/ */
private void hideRecentLanguagesSection() { private fun hideRecentLanguagesSection() {
languageHistoryListView.setVisibility(View.GONE); languageHistoryListView?.visibility = View.GONE
recentLanguagesTextView.setVisibility(View.GONE); recentLanguagesTextView?.visibility = View.GONE
separator.setVisibility(View.GONE); separator?.visibility = View.GONE
} }
/** /**
* Changing the default app language with selected one and save it to SharedPreferences * Changing the default app language with selected one and save it to SharedPreferences
*/ */
public void setLocale(final Activity activity, String userSelectedValue) { fun setLocale(activity: Activity, userSelectedValue: String) {
if (userSelectedValue.equals("")) { var selectedLanguage = userSelectedValue
userSelectedValue = Locale.getDefault().getLanguage(); if (selectedLanguage == "") {
selectedLanguage = Locale.getDefault().language
} }
final Locale locale = createLocale(userSelectedValue); val locale = createLocale(selectedLanguage)
Locale.setDefault(locale); Locale.setDefault(locale)
final Configuration configuration = new Configuration(); val configuration = Configuration()
configuration.locale = locale; configuration.locale = locale
activity.getBaseContext().getResources().updateConfiguration(configuration, activity.baseContext.resources.updateConfiguration(configuration, activity.baseContext.resources.displayMetrics)
activity.getBaseContext().getResources().getDisplayMetrics());
final SharedPreferences.Editor editor = activity.getSharedPreferences("Settings", MODE_PRIVATE).edit(); val editor = activity.getSharedPreferences("Settings", MODE_PRIVATE).edit()
editor.putString("language", userSelectedValue); editor.putString("language", selectedLanguage)
editor.apply(); editor.apply()
} }
/** /**
@ -496,30 +476,25 @@ public class SettingsFragment extends PreferenceFragmentCompat {
* @param languageCode * @param languageCode
* @return Locale and throws error for invalid language codes * @return Locale and throws error for invalid language codes
*/ */
public static Locale createLocale(String languageCode) { fun createLocale(languageCode: String): Locale {
String[] parts = languageCode.split("-"); val parts = languageCode.split("-")
switch (parts.length) { return when (parts.size) {
case 1: 1 -> Locale(parts[0])
return new Locale(parts[0]); 2 -> Locale(parts[0], parts[1])
case 2: 3 -> Locale(parts[0], parts[1], parts[2])
return new Locale(parts[0], parts[1]); else -> throw IllegalArgumentException("Invalid language code: $languageCode")
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 * Save userSelected language in List Preference
* @param userSelectedValue * @param userSelectedValue
* @param preferenceKey * @param preferenceKey
*/ */
private void saveLanguageValue(final String userSelectedValue, final String preferenceKey) { private fun saveLanguageValue(userSelectedValue: String, preferenceKey: String) {
if (preferenceKey.equals("appUiDefaultLanguagePref")) { when (preferenceKey) {
defaultKvStore.putString(Prefs.APP_UI_LANGUAGE, userSelectedValue); "appUiDefaultLanguagePref" -> defaultKvStore.putString(Prefs.APP_UI_LANGUAGE, userSelectedValue)
} else if (preferenceKey.equals("descriptionDefaultLanguagePref")) { "descriptionDefaultLanguagePref" -> defaultKvStore.putString(Prefs.DESCRIPTION_LANGUAGE, userSelectedValue)
defaultKvStore.putString(Prefs.DESCRIPTION_LANGUAGE, userSelectedValue);
} }
} }
@ -528,24 +503,31 @@ public class SettingsFragment extends PreferenceFragmentCompat {
* @param preferenceKey * @param preferenceKey
* @return * @return
*/ */
private String getCurrentLanguageCode(final String preferenceKey) { private fun getCurrentLanguageCode(preferenceKey: String): String? {
if (preferenceKey.equals("appUiDefaultLanguagePref")) { return when (preferenceKey) {
return defaultKvStore.getString(Prefs.APP_UI_LANGUAGE, ""); "appUiDefaultLanguagePref" -> defaultKvStore.getString(
Prefs.APP_UI_LANGUAGE, ""
)
"descriptionDefaultLanguagePref" -> defaultKvStore.getString(
Prefs.DESCRIPTION_LANGUAGE, ""
)
else -> null
} }
if (preferenceKey.equals("descriptionDefaultLanguagePref")) {
return defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, "");
}
return null;
} }
/** /**
* First checks for external storage permissions and then sends logs via email * First checks for external storage permissions and then sends logs via email
*/ */
private void checkPermissionsAndSendLogs() { private fun checkPermissionsAndSendLogs() {
if (PermissionUtils.hasPermission(getActivity(), PermissionUtils.getPERMISSIONS_STORAGE())) { if (
commonsLogSender.send(getActivity(), null); PermissionUtils.hasPermission(
requireActivity(),
PermissionUtils.PERMISSIONS_STORAGE
)
) {
commonsLogSender.send(requireActivity(), null)
} else { } else {
requestExternalStoragePermissions(); requestExternalStoragePermissions()
} }
} }
@ -553,23 +535,22 @@ public class SettingsFragment extends PreferenceFragmentCompat {
* Requests external storage permissions and shows a toast stating that log collection has * Requests external storage permissions and shows a toast stating that log collection has
* started * started
*/ */
private void requestExternalStoragePermissions() { private fun requestExternalStoragePermissions() {
Dexter.withActivity(getActivity()) Dexter.withActivity(requireActivity())
.withPermissions(PermissionUtils.getPERMISSIONS_STORAGE()) .withPermissions(*PermissionUtils.PERMISSIONS_STORAGE)
.withListener(new MultiplePermissionsListener() { .withListener(object : MultiplePermissionsListener {
@Override override fun onPermissionsChecked(report: MultiplePermissionsReport) {
public void onPermissionsChecked(MultiplePermissionsReport report) { ViewUtil.showLongToast(requireActivity(), getString(R.string.log_collection_started))
ViewUtil.showLongToast(getActivity(),
getResources().getString(R.string.log_collection_started));
} }
@Override override fun onPermissionRationaleShouldBeShown(
public void onPermissionRationaleShouldBeShown( permissions: List<PermissionRequest>, token: PermissionToken
List<PermissionRequest> permissions, PermissionToken token) { ) {
// No action needed
} }
}) })
.onSameThread() .onSameThread()
.check(); .check()
} }
} }