diff options
| author | Norbel Ambanumben <nambanumben@riseup.net> | 2024-10-07 21:31:33 +0000 |
|---|---|---|
| committer | cyberta <cyberta@riseup.net> | 2024-10-07 21:31:33 +0000 |
| commit | 61106968cbdf96a4fa578d16aff03865b985e547 (patch) | |
| tree | 8ff5d3ea1f2b562e885f4c7e3297ec3bda804fd3 /app/src/main/java | |
| parent | e15787e844ffe1c74b0ba783a9e37c7daa72b72a (diff) | |
feat: add language selection
Diffstat (limited to 'app/src/main/java')
| -rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/base/fragments/LanguageSelectionFragment.java | 166 | ||||
| -rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java | 25 |
2 files changed, 191 insertions, 0 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/LanguageSelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/LanguageSelectionFragment.java new file mode 100644 index 00000000..263a8d46 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/LanguageSelectionFragment.java @@ -0,0 +1,166 @@ +package se.leap.bitmaskclient.base.fragments; + +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.core.os.LocaleListCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; + +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.views.SimpleCheckBox; +import se.leap.bitmaskclient.databinding.FLanguageSelectionBinding; +import se.leap.bitmaskclient.databinding.VSelectTextListItemBinding; + +public class LanguageSelectionFragment extends BottomSheetDialogFragment { + static final String TAG = LanguageSelectionFragment.class.getSimpleName(); + static final String SYSTEM_LOCALE = "systemLocale"; + private FLanguageSelectionBinding binding; + + public static LanguageSelectionFragment newInstance(Locale defaultLocale) { + LanguageSelectionFragment fragment = new LanguageSelectionFragment(); + Bundle args = new Bundle(); + args.putString(SYSTEM_LOCALE, defaultLocale.toLanguageTag()); + fragment.setArguments(args); + return fragment; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + binding = FLanguageSelectionBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setActionBarSubtitle(this, R.string.select_language); + + initRecyclerView(Arrays.asList(getResources().getStringArray(R.array.supported_languages))); + } + + private static void customizeSelectionItem(VSelectTextListItemBinding binding) { + binding.title.setVisibility(View.GONE); + binding.bridgeImage.setVisibility(View.GONE); + binding.quality.setVisibility(View.GONE); + } + + private void initRecyclerView(List<String> supportedLanguages) { + Locale defaultLocale = AppCompatDelegate.getApplicationLocales().get(0); + if (defaultLocale == null) { + defaultLocale = LocaleListCompat.getDefault().get(0); + } + // NOTE: Sort the supported languages by their display names. + // This would make updating supported languages easier as we don't have to tip toe around the order + Collections.sort(supportedLanguages, (lang1, lang2) -> { + String displayName1 = Locale.forLanguageTag(lang1).getDisplayName(Locale.ENGLISH); + String displayName2 = Locale.forLanguageTag(lang2).getDisplayName(Locale.ENGLISH); + return displayName1.compareTo(displayName2); + }); + binding.languages.setAdapter( + new LanguageSelectionAdapter(supportedLanguages, this::updateLocale, defaultLocale) + ); + binding.languages.setLayoutManager(new LinearLayoutManager(getContext())); + } + + public static Locale getCurrentLocale() { + Locale defaultLocale = AppCompatDelegate.getApplicationLocales().get(0); + if (defaultLocale == null) { + defaultLocale = LocaleListCompat.getDefault().get(0); + } + return defaultLocale; + } + + /** + * Update the locale of the application + * + * @param languageTag the language tag to set the locale to + */ + private void updateLocale(String languageTag) { + if (languageTag.isEmpty()) { + AppCompatDelegate.setApplicationLocales(LocaleListCompat.getEmptyLocaleList()); + } else { + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(languageTag)); + } + } + + /** + * Adapter for the language selection recycler view. + */ + static class LanguageSelectionAdapter extends RecyclerView.Adapter<LanguageSelectionAdapter.LanguageViewHolder> { + + private final List<String> languages; + private final LanguageClickListener clickListener; + private final Locale selectedLocale; + + public LanguageSelectionAdapter(List<String> languages, LanguageClickListener clickListener, Locale defaultLocale) { + this.languages = languages; + this.clickListener = clickListener; + this.selectedLocale = defaultLocale; + } + + @NonNull + @Override + public LanguageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + VSelectTextListItemBinding binding = VSelectTextListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + return new LanguageViewHolder(binding); + } + + @Override + public void onBindViewHolder(@NonNull LanguageViewHolder holder, int position) { + String languageTag = languages.get(position); + holder.languageName.setText(Locale.forLanguageTag(languageTag).getDisplayName(Locale.ENGLISH)); + if (languages.contains(selectedLocale.toLanguageTag())) { + holder.selected.setChecked(selectedLocale.toLanguageTag().equals(languageTag)); + } else { + holder.selected.setChecked(selectedLocale.getLanguage().equals(languageTag)); + } + holder.itemView.setOnClickListener(v -> clickListener.onLanguageClick(languageTag)); + } + + @Override + public int getItemCount() { + return languages.size(); + } + + /** + * View holder for the language item + */ + static class LanguageViewHolder extends RecyclerView.ViewHolder { + TextView languageName; + SimpleCheckBox selected; + + public LanguageViewHolder(@NonNull VSelectTextListItemBinding binding) { + super(binding.getRoot()); + languageName = binding.location; + selected = binding.selected; + customizeSelectionItem(binding); + } + } + } + + + /** + * Interface for the language click listener + */ + interface LanguageClickListener { + void onLanguageClick(String languageTag); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index cbab1d32..41e102bb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -46,15 +46,19 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.graphics.drawable.DrawerArrowDrawable; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; +import androidx.core.os.LocaleListCompat; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Locale; +import java.util.Map; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; @@ -211,6 +215,7 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen initSwitchProviderEntry(); initSaveBatteryEntry(); initManualGatewayEntry(); + initLanguageSettingsEntry(); initAdvancedSettingsEntry(); initDonateEntry(); initLogEntry(); @@ -314,6 +319,26 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen }); } + + private void initLanguageSettingsEntry() { + IconTextEntry languageSwitcher = drawerView.findViewById(R.id.language_switcher); + + Locale currentLocale = LanguageSelectionFragment.getCurrentLocale(); + languageSwitcher.setSubtitle(currentLocale.getDisplayName(Locale.ENGLISH)); + + languageSwitcher.setOnClickListener(v -> { + FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); + closeDrawer(); + Fragment current = fragmentManager.findFragmentByTag(MainActivity.TAG); + if (current instanceof LanguageSelectionFragment) { + return; + } + Fragment fragment = LanguageSelectionFragment.newInstance(Locale.getDefault()); + setDrawerToggleColor(drawerView.getContext(), ContextCompat.getColor(drawerView.getContext(), R.color.colorActionBarTitleFont)); + fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); + }); + } + private void initDonateEntry() { if (ENABLE_DONATION) { IconTextEntry donate = drawerView.findViewById(R.id.donate); |
