From 7bea180c585f347d175cfdc14c4b2c176ffae65e Mon Sep 17 00:00:00 2001 From: antonio Date: Thu, 17 Aug 2023 14:09:17 +0200 Subject: [PATCH] feat: implemented language picker in app settings, dynamically populating the list of available languages programmatically. --- .../tempo/ui/fragment/SettingsFragment.java | 155 ++++++++++++------ .../cappielloantonio/tempo/util/UIUtil.java | 53 ++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/global_preferences.xml | 6 + 4 files changed, 161 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/SettingsFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/SettingsFragment.java index acc6d463..c28335cd 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/SettingsFragment.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/SettingsFragment.java @@ -12,6 +12,8 @@ import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.OptIn; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.core.os.LocaleListCompat; import androidx.lifecycle.ViewModelProvider; import androidx.media3.common.util.UnstableApi; import androidx.preference.ListPreference; @@ -28,8 +30,12 @@ import com.cappielloantonio.tempo.ui.dialog.DeleteDownloadStorageDialog; import com.cappielloantonio.tempo.ui.dialog.DownloadStorageDialog; import com.cappielloantonio.tempo.ui.dialog.StarredSyncDialog; import com.cappielloantonio.tempo.util.Preferences; +import com.cappielloantonio.tempo.util.UIUtil; import com.cappielloantonio.tempo.viewmodel.SettingViewModel; +import java.util.Locale; +import java.util.Map; + @OptIn(markerClass = UnstableApi.class) public class SettingsFragment extends PreferenceFragmentCompat { private static final String TAG = "SettingsFragment"; @@ -75,63 +81,16 @@ public class SettingsFragment extends PreferenceFragmentCompat { super.onResume(); checkEqualizer(); - checkStorage(); - findPreference("version").setSummary(BuildConfig.VERSION_NAME); + setAppLanguage(); + setVersion(); - findPreference("logout").setOnPreferenceClickListener(preference -> { - activity.quit(); - return true; - }); - - findPreference("scan_library").setOnPreferenceClickListener(preference -> { - settingViewModel.launchScan(new ScanCallback() { - @Override - public void onError(Exception exception) { - findPreference("scan_library").setSummary(exception.getMessage()); - } - - @Override - public void onSuccess(boolean isScanning, long count) { - getScanStatus(); - } - }); - - return true; - }); - - findPreference("sync_starred_tracks_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> { - if (newValue instanceof Boolean) { - if ((Boolean) newValue) { - StarredSyncDialog dialog = new StarredSyncDialog(); - dialog.show(activity.getSupportFragmentManager(), null); - } - } - return true; - }); - - findPreference("download_storage").setOnPreferenceClickListener(preference -> { - DownloadStorageDialog dialog = new DownloadStorageDialog(new DialogClickCallback() { - @Override - public void onPositiveClick() { - findPreference("download_storage").setSummary(R.string.download_storage_external_dialog_positive_button); - } - - @Override - public void onNegativeClick() { - findPreference("download_storage").setSummary(R.string.download_storage_internal_dialog_negative_button); - } - }); - dialog.show(activity.getSupportFragmentManager(), null); - return true; - }); - - findPreference("delete_download_storage").setOnPreferenceClickListener(preference -> { - DeleteDownloadStorageDialog dialog = new DeleteDownloadStorageDialog(); - dialog.show(activity.getSupportFragmentManager(), null); - return true; - }); + actionLogout(); + actionScan(); + actionSyncStarredTracks(); + actionChangeDownloadStorage(); + actionDeleteDownloadStorage(); } @Override @@ -187,6 +146,94 @@ public class SettingsFragment extends PreferenceFragmentCompat { } } + private void setAppLanguage() { + ListPreference localePref = (ListPreference) findPreference("language"); + + Map locales = UIUtil.getLangPreferenceDropdownEntries(requireContext()); + + CharSequence[] entries = locales.keySet().toArray(new CharSequence[locales.size()]); + CharSequence[] entryValues = locales.values().toArray(new CharSequence[locales.size()]); + + localePref.setEntries(entries); + localePref.setEntryValues(entryValues); + + localePref.setDefaultValue(entryValues[0]); + localePref.setSummary(Locale.forLanguageTag(localePref.getValue()).getDisplayLanguage()); + + localePref.setOnPreferenceChangeListener((preference, newValue) -> { + LocaleListCompat appLocale = LocaleListCompat.forLanguageTags((String) newValue); + AppCompatDelegate.setApplicationLocales(appLocale); + return true; + }); + } + + private void setVersion() { + findPreference("version").setSummary(BuildConfig.VERSION_NAME); + } + + private void actionLogout() { + findPreference("logout").setOnPreferenceClickListener(preference -> { + activity.quit(); + return true; + }); + } + + private void actionScan() { + findPreference("scan_library").setOnPreferenceClickListener(preference -> { + settingViewModel.launchScan(new ScanCallback() { + @Override + public void onError(Exception exception) { + findPreference("scan_library").setSummary(exception.getMessage()); + } + + @Override + public void onSuccess(boolean isScanning, long count) { + getScanStatus(); + } + }); + + return true; + }); + } + + private void actionSyncStarredTracks() { + findPreference("sync_starred_tracks_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> { + if (newValue instanceof Boolean) { + if ((Boolean) newValue) { + StarredSyncDialog dialog = new StarredSyncDialog(); + dialog.show(activity.getSupportFragmentManager(), null); + } + } + return true; + }); + } + + private void actionChangeDownloadStorage() { + findPreference("download_storage").setOnPreferenceClickListener(preference -> { + DownloadStorageDialog dialog = new DownloadStorageDialog(new DialogClickCallback() { + @Override + public void onPositiveClick() { + findPreference("download_storage").setSummary(R.string.download_storage_external_dialog_positive_button); + } + + @Override + public void onNegativeClick() { + findPreference("download_storage").setSummary(R.string.download_storage_internal_dialog_negative_button); + } + }); + dialog.show(activity.getSupportFragmentManager(), null); + return true; + }); + } + + private void actionDeleteDownloadStorage() { + findPreference("delete_download_storage").setOnPreferenceClickListener(preference -> { + DeleteDownloadStorageDialog dialog = new DeleteDownloadStorageDialog(); + dialog.show(activity.getSupportFragmentManager(), null); + return true; + }); + } + private void getScanStatus() { settingViewModel.getScanStatus(new ScanCallback() { @Override diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/UIUtil.java b/app/src/main/java/com/cappielloantonio/tempo/util/UIUtil.java index 7462a8b5..23609420 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/util/UIUtil.java +++ b/app/src/main/java/com/cappielloantonio/tempo/util/UIUtil.java @@ -5,8 +5,21 @@ import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; +import androidx.core.os.LocaleListCompat; import androidx.recyclerview.widget.DividerItemDecoration; +import com.cappielloantonio.tempo.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + public class UIUtil { public static int getSpanCount(int itemCount, int maxSpan) { int itemSize = itemCount == 0 ? 1 : itemCount; @@ -31,4 +44,44 @@ public class UIUtil { return itemDecoration; } + + private static LocaleListCompat getLocalesFromResources(Context context) { + final List tagsList = new ArrayList<>(); + + XmlPullParser xpp = context.getResources().getXml(R.xml.locale_config); + + try { + while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) { + String tagName = xpp.getName(); + + if (xpp.getEventType() == XmlPullParser.START_TAG) { + if ("locale".equals(tagName) && xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("name")) { + tagsList.add(xpp.getAttributeValue(0)); + } + } + + xpp.next(); + } + } catch (XmlPullParserException | IOException e) { + e.printStackTrace(); + } + + return LocaleListCompat.forLanguageTags(String.join(",", tagsList)); + } + + public static Map getLangPreferenceDropdownEntries(Context context) { + LocaleListCompat localeList = getLocalesFromResources(context); + + Map map = new HashMap<>(); + + for (int i = 0; i < localeList.size(); i++) { + Locale locale = localeList.get(i); + + if (locale != null) { + map.put(Util.toPascalCase(locale.getDisplayName()), locale.toLanguageTag()); + } + } + + return map; + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e9528c17..75acc09d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -206,6 +206,7 @@ Follow the development Github Set image resolution + Language Log out Bitrate for downloads Bitrate in Wi-Fi diff --git a/app/src/main/res/xml/global_preferences.xml b/app/src/main/res/xml/global_preferences.xml index 4dde2d4e..8f0a4f09 100644 --- a/app/src/main/res/xml/global_preferences.xml +++ b/app/src/main/res/xml/global_preferences.xml @@ -16,6 +16,12 @@ + +