Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd3daa87 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Create a new region picker page" into main

parents 70c56ec8 09b9d052
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -381,6 +381,18 @@
    <!-- Used in setup wizard Wi-Fi screen. The button label for going to the next screen and submitting. [CHAR LIMIT=20] -->
    <string name="next_label">Next</string>
    <!-- RegionPicker-->
    <!-- Title for region picker preferences. [CHAR LIMIT=50] -->
    <string name="region_picker_preference_title">Region</string>
    <!-- Title for the region picker activity. [CHAR LIMIT=30]-->
    <string name="region_picker_title">Choose a region</string>
    <!-- The subtitle of region picker activity. [CHAR LIMIT=NONE] -->
    <string name="region_picker_sub_title">The region you choose affects how your device displays time, dates, temperature, and more.</string>
    <!-- Category for suggested regions. [CHAR LIMIT=50]-->
    <string name="suggested_region_title">Suggested</string>
    <!-- Category for all supported regions. [CHAR LIMIT=50]-->
    <string name="all_supported_region_title">All regions</string>
    <!-- LocalePicker -->
    <!-- Title for the locale picker activity. [CHAR LIMIT=30]-->
    <string name="language_picker_title">Languages</string>
+7 −0
Original line number Diff line number Diff line
@@ -51,6 +51,13 @@
      android:title="@string/regional_preferences_category_title"
      settings:controller="com.android.settings.regionalpreferences.RegionalPreferencesCategoryController">

    <Preference
        android:key="region_preference"
        android:title="@string/region_picker_preference_title"
        settings:controller="com.android.settings.regionalpreferences.RegionPreferenceController"
        settings:fragment="com.android.settings.regionalpreferences.RegionPickerFragment">
    </Preference>

    <Preference
        android:key="temperature_preference"
        android:title="@string/temperature_preferences_title"
+35 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2024 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:key="key_system_region_picker_page"
    android:title="@string/region_picker_title">

  <com.android.settingslib.widget.TopIntroPreference
      android:key="key_region_picker_sub_title"
      android:title="@string/region_picker_sub_title"
      android:persistent="false"/>

  <PreferenceCategory
      android:key="system_region_suggested_category"
      android:title="@string/suggested_region_title"/>

  <PreferenceCategory
      android:key="system_region_all_supported_category"
      android:title="@string/all_supported_region_title"/>

</PreferenceScreen>
+183 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.regionalpreferences;

import android.content.Context;
import android.os.LocaleList;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;

import com.android.internal.annotations.Initializer;
import com.android.internal.app.LocaleCollectorBase;
import com.android.internal.app.LocaleHelper;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.LocaleStore;
import com.android.internal.app.LocaleStore.LocaleInfo;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.SelectorWithWidgetPreference;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;

public abstract class RegionPickerBaseListPreferenceController extends BasePreferenceController {

    private static final String TAG = "RegionPickerBaseListPreferenceController";
    private static final String KEY_SUGGESTED = "suggested";
    private PreferenceCategory mPreferenceCategory;
    private Set<LocaleInfo> mLocaleList;
    private ArrayList<LocaleInfo> mLocaleOptions;

    public RegionPickerBaseListPreferenceController(@NonNull Context context,
            @NonNull String preferenceKey) {
        super(context, preferenceKey);
        mLocaleList = getLocaleCollectorController(context).getSupportedLocaleList(null,
            false, false);
        mLocaleOptions = new ArrayList<>();
        mLocaleOptions.ensureCapacity(mLocaleList.size());
    }

    @Override
    @Initializer
    public void displayPreference(@NonNull PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreferenceCategory = screen.findPreference(getPreferenceCategoryKey());
        updatePreferences();
    }

    private void updatePreferences() {
        if (mPreferenceCategory == null) {
            Log.d(TAG, "updatePreferences, mPreferenceCategory is null");
            return;
        }
        List<LocaleStore.LocaleInfo> result;
        LocaleStore.LocaleInfo parentLocale = getParentLocale();
        if (parentLocale != null) {
            mLocaleList = getLocaleCollectorController(mContext).getSupportedLocaleList(
                    parentLocale, false, true);
        }
        mLocaleOptions.clear();
        mLocaleOptions.ensureCapacity(mLocaleList.size());
        result = getPreferenceCategoryKey().contains(KEY_SUGGESTED)
                    ? getSuggestedLocaleList()
                    : getSupportedLocaleList();
        if (getPreferenceCategoryKey().contains(KEY_SUGGESTED)) {
            Locale systemLocale = Locale.getDefault();
            LocaleStore.LocaleInfo localeInfo = LocaleStore.getLocaleInfo(systemLocale);
            result.add(localeInfo);
        }
        result = getSortedLocaleList(result);
        setupPreference(result);
    }

    private void setupPreference(List<LocaleStore.LocaleInfo> localeInfoList) {
        localeInfoList.stream().forEach(locale -> {
            SelectorWithWidgetPreference pref = new SelectorWithWidgetPreference(mContext);
            mPreferenceCategory.addPreference(pref);
            pref.setTitle(locale.getFullCountryNameNative());
            pref.setKey(locale.toString());
            if (locale.getLocale().equals(Locale.getDefault())) {
                pref.setChecked(true);
            } else {
                pref.setChecked(false);
            }
            pref.setOnClickListener(v -> {
                switchRegion(locale);
            });
        });
        mPreferenceCategory.setVisible(mPreferenceCategory.getPreferenceCount() > 0);
    }

    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE;
    }

    protected abstract String getPreferenceCategoryKey();

    protected abstract LocaleCollectorBase getLocaleCollectorController(Context context);

    @Nullable protected abstract LocaleStore.LocaleInfo getParentLocale();

    protected List<LocaleStore.LocaleInfo> getSuggestedLocaleList() {
        if (mLocaleList != null && !mLocaleList.isEmpty()) {
            mLocaleOptions.addAll(mLocaleList.stream()
                    .filter(localeInfo -> localeInfo.isSuggested())
                    .collect(Collectors.toList()));
        } else {
            Log.d(TAG, "Can not get suggested locales because the locale list is null or empty.");
        }

        return mLocaleOptions;
    }

    protected List<LocaleStore.LocaleInfo> getSupportedLocaleList() {
        if (mLocaleList != null && !mLocaleList.isEmpty()) {
            mLocaleOptions.addAll(mLocaleList.stream()
                    .filter(localeInfo -> !localeInfo.isSuggested())
                    .collect(Collectors.toList()));
        } else {
            Log.d(TAG, "Can not get supported locales because the locale list is null or empty.");
        }
        return mLocaleOptions;
    }

    private List<LocaleStore.LocaleInfo> getSortedLocaleList(
            List<LocaleStore.LocaleInfo> localeInfos) {
        final Locale sortingLocale = Locale.getDefault();
        final LocaleHelper.LocaleInfoComparator comp =
                new LocaleHelper.LocaleInfoComparator(sortingLocale, true);
        Collections.sort(localeInfos, comp);
        return localeInfos;
    }

    private void switchRegion(LocaleStore.LocaleInfo localeInfo) {
        if (localeInfo.getLocale().equals(Locale.getDefault())) {
            return;
        }
        updateRegion(localeInfo.getLocale().toLanguageTag());
        updatePreferences();
    }

    private void updateRegion(String selectedLanguageTag) {
        LocaleList localeList = LocaleList.getDefault();
        Locale systemLocale = Locale.getDefault();
        Set<Character> extensionKeys = systemLocale.getExtensionKeys();
        Locale selectedLocale = Locale.forLanguageTag(selectedLanguageTag);
        Locale.Builder builder = new Locale.Builder();
        builder.setLocale(selectedLocale);
        if (!extensionKeys.isEmpty()) {
            for (Character extKey : extensionKeys) {
                builder.setExtension(extKey, systemLocale.getExtension(extKey));
            }
        }
        Locale newLocale = builder.build();
        Locale[] resultLocales = new Locale[localeList.size()];
        resultLocales[0] = newLocale;
        for (int i = 1; i < localeList.size(); i++) {
            resultLocales[i] = localeList.get(i);
        }
        LocalePicker.updateLocales(new LocaleList(resultLocales));
    }
}
+93 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.regionalpreferences;

import android.content.Context;
import android.os.Bundle;

import androidx.annotation.NonNull;

import com.android.internal.app.LocaleStore;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class RegionPickerFragment extends DashboardFragment{

    private static final String TAG = "RegionPickerFragment";
    private static final String KEY_PREFERENCE_SYSTEM_REGION_LIST = "system_region_list";
    private static final String KEY_PREFERENCE_SYSTEM_REGION_SUGGESTED_LIST =
            "system_region_suggested_list";

    @Override
    public void onCreate(@NonNull Bundle icicle) {
        super.onCreate(icicle);
    }

    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.system_region_picker;
    }

    @Override
    protected String getLogTag() {
        return TAG;
    }

    @Override
    public int getMetricsCategory() {
        return 0;
    }

    @Override
    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
        return buildPreferenceControllers(context);
    }

    private List<AbstractPreferenceController> buildPreferenceControllers(
            @NonNull Context context) {
        Locale parentLocale = LocaleStore.getLocaleInfo(Locale.getDefault()).getParent();
        LocaleStore.LocaleInfo parentLocaleInfo = LocaleStore.getLocaleInfo(parentLocale);
        SystemRegionSuggestedListPreferenceController mSuggestedListPreferenceController =
                new SystemRegionSuggestedListPreferenceController(
                    context, KEY_PREFERENCE_SYSTEM_REGION_SUGGESTED_LIST, parentLocaleInfo);
        SystemRegionAllListPreferenceController mSystemRegionAllListPreferenceController =
                new SystemRegionAllListPreferenceController(
                    context, KEY_PREFERENCE_SYSTEM_REGION_LIST, parentLocaleInfo);
        final List<AbstractPreferenceController> controllers = new ArrayList<>();
        controllers.add(mSuggestedListPreferenceController);
        controllers.add(mSystemRegionAllListPreferenceController);
        return controllers;
    }

    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
            new BaseSearchIndexProvider(R.xml.system_region_picker) {
                @Override
                protected boolean isPageSearchEnabled(Context context) {
                    if (!Flags.regionalPreferencesApiEnabled()) {
                        return false;
                    }
                    return true;
                }
            };
}
Loading