• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.localepicker;
18 
19 import static android.os.UserManager.DISALLOW_CONFIG_LOCALE;
20 
21 import static com.android.settings.flags.Flags.localeNotificationEnabled;
22 import static com.android.settings.localepicker.AppLocalePickerActivity.EXTRA_APP_LOCALE;
23 import static com.android.settings.localepicker.LocaleDialogFragment.DIALOG_ADD_SYSTEM_LOCALE;
24 import static com.android.settings.localepicker.LocaleDialogFragment.DIALOG_CONFIRM_SYSTEM_DEFAULT;
25 
26 import android.app.Activity;
27 import android.app.settings.SettingsEnums;
28 import android.content.Context;
29 import android.content.DialogInterface;
30 import android.content.Intent;
31 import android.content.res.Resources;
32 import android.os.Bundle;
33 import android.os.LocaleList;
34 import android.provider.Settings;
35 import android.text.TextUtils;
36 import android.util.Log;
37 import android.view.LayoutInflater;
38 import android.view.Menu;
39 import android.view.MenuInflater;
40 import android.view.MenuItem;
41 import android.view.MotionEvent;
42 import android.view.View;
43 import android.view.ViewGroup;
44 import android.widget.TextView;
45 
46 import androidx.annotation.NonNull;
47 import androidx.annotation.Nullable;
48 import androidx.annotation.VisibleForTesting;
49 import androidx.fragment.app.FragmentManager;
50 import androidx.preference.Preference;
51 import androidx.preference.PreferenceScreen;
52 import androidx.recyclerview.widget.RecyclerView;
53 
54 import com.android.internal.app.LocalePicker;
55 import com.android.internal.app.LocaleStore;
56 import com.android.settings.R;
57 import com.android.settings.RestrictedSettingsFragment;
58 import com.android.settings.overlay.FeatureFactory;
59 import com.android.settings.search.BaseSearchIndexProvider;
60 import com.android.settingslib.search.SearchIndexable;
61 import com.android.settingslib.search.SearchIndexableRaw;
62 import com.android.settingslib.utils.CustomDialogHelper;
63 import com.android.settingslib.utils.StringUtil;
64 import com.android.settingslib.widget.LayoutPreference;
65 import com.android.settingslib.widget.SettingsThemeHelper;
66 
67 import java.util.ArrayList;
68 import java.util.List;
69 import java.util.Locale;
70 
71 /**
72  * Drag-and-drop editor for the user-ordered locale lists.
73  */
74 @SearchIndexable
75 public class LocaleListEditor extends RestrictedSettingsFragment implements View.OnTouchListener {
76     public static final int REQUEST_LOCALE_PICKER = 0;
77 
78     protected static final String INTENT_LOCALE_KEY = "localeInfo";
79     protected static final String EXTRA_SYSTEM_LOCALE_DIALOG_TYPE = "system_locale_dialog_type";
80     protected static final String EXTRA_RESULT_LOCALE = "result_locale";
81     protected static final String LOCALE_SUGGESTION = "locale_suggestion";
82 
83     private static final String TAG = LocaleListEditor.class.getSimpleName();
84     private static final String CFGKEY_REMOVE_MODE = "localeRemoveMode";
85     private static final String CFGKEY_REMOVE_DIALOG = "showingLocaleRemoveDialog";
86     private static final String CFGKEY_ADD_LOCALE = "localeAdded";
87     private static final String INDEX_KEY_ADD_LANGUAGE = "add_language";
88     private static final String KEY_LANGUAGES_PICKER = "languages_picker";
89     private static final String KEY_CATEGORY_TERMS_OF_ADDRESS = "key_category_terms_of_address";
90     private static final String KEY_ADD_A_LANGUAGE = "add_a_language";
91     private static final String TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT = "dialog_confirm_system_default";
92     private static final String TAG_DIALOG_NOT_AVAILABLE = "dialog_not_available_locale";
93     private static final String TAG_DIALOG_ADD_SYSTEM_LOCALE = "dialog_add_system_locale";
94     private static final int MENU_ID_REMOVE = Menu.FIRST + 1;
95 
96     private LocaleDragAndDropAdapter mAdapter;
97     private Menu mMenu;
98     private View mAddLanguage;
99     private Preference mAddLanguagePreference;
100     private boolean mRemoveMode;
101     private boolean mShowingRemoveDialog;
102     private boolean mLocaleAdditionMode = false;
103     private boolean mIsUiRestricted;
104 
105     private LayoutPreference mLocalePickerPreference;
106     private LocaleHelperPreferenceController mLocaleHelperPreferenceController;
107     private FragmentManager mFragmentManager;
108     private TermsOfAddressCategoryController mTermsOfAddressCategoryController;
109 
LocaleListEditor()110     public LocaleListEditor() {
111         super(DISALLOW_CONFIG_LOCALE);
112     }
113 
114     @Override
getMetricsCategory()115     public int getMetricsCategory() {
116         return SettingsEnums.USER_LOCALE_LIST;
117     }
118 
119     @Override
onCreate(Bundle savedInstanceState)120     public void onCreate(Bundle savedInstanceState) {
121         super.onCreate(savedInstanceState);
122         setHasOptionsMenu(true);
123 
124         addPreferencesFromResource(R.xml.languages);
125         final Activity activity = getActivity();
126         mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(activity);
127         final PreferenceScreen screen = getPreferenceScreen();
128         mLocalePickerPreference = screen.findPreference(KEY_LANGUAGES_PICKER);
129         mLocaleHelperPreferenceController.displayPreference(screen);
130         mTermsOfAddressCategoryController = new TermsOfAddressCategoryController(activity,
131                 KEY_CATEGORY_TERMS_OF_ADDRESS);
132         mTermsOfAddressCategoryController.displayPreference(screen);
133 
134         LocaleStore.fillCache(this.getContext());
135         final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList();
136         mAdapter = new LocaleDragAndDropAdapter(this, feedsList);
137         mFragmentManager = getChildFragmentManager();
138     }
139 
140     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstState)141     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstState) {
142         configureDragAndDrop(mLocalePickerPreference);
143         return super.onCreateView(inflater, container, savedInstState);
144     }
145 
146     @Override
onResume()147     public void onResume() {
148         super.onResume();
149 
150         final boolean previouslyRestricted = mIsUiRestricted;
151         mIsUiRestricted = isUiRestricted();
152         final TextView emptyView = getEmptyTextView();
153         if (mIsUiRestricted && !previouslyRestricted) {
154             // Lock it down.
155             emptyView.setText(R.string.language_empty_list_user_restricted);
156             emptyView.setVisibility(View.VISIBLE);
157             updateVisibilityOfRemoveMenu();
158         } else if (!mIsUiRestricted && previouslyRestricted) {
159             // Unlock it.
160             emptyView.setVisibility(View.GONE);
161             updateVisibilityOfRemoveMenu();
162         }
163     }
164 
165     @Override
onViewStateRestored(Bundle savedInstanceState)166     public void onViewStateRestored(Bundle savedInstanceState) {
167         super.onViewStateRestored(savedInstanceState);
168         if (savedInstanceState != null) {
169             mRemoveMode = savedInstanceState.getBoolean(CFGKEY_REMOVE_MODE, false);
170             mShowingRemoveDialog = savedInstanceState.getBoolean(CFGKEY_REMOVE_DIALOG, false);
171             mLocaleAdditionMode = savedInstanceState.getBoolean(CFGKEY_ADD_LOCALE, false);
172         }
173         setRemoveMode(mRemoveMode);
174 
175         final LocaleDialogFragment dialogFragment =
176                 (LocaleDialogFragment) mFragmentManager.findFragmentByTag(
177                         TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT);
178         boolean isDialogShowing = false;
179         if (dialogFragment != null && dialogFragment.isAdded()) {
180             isDialogShowing = true;
181         }
182         mAdapter.restoreState(savedInstanceState, isDialogShowing);
183 
184         if (mShowingRemoveDialog) {
185             showRemoveLocaleWarningDialog();
186         }
187         Log.d(TAG, "LocaleAdditionMode:" + mLocaleAdditionMode);
188         if (!mLocaleAdditionMode && shouldShowConfirmationDialog()) {
189             showDialogForAddedLocale();
190             mLocaleAdditionMode = true;
191         }
192     }
193 
194     @Override
onSaveInstanceState(Bundle outState)195     public void onSaveInstanceState(Bundle outState) {
196         super.onSaveInstanceState(outState);
197         outState.putBoolean(CFGKEY_REMOVE_MODE, mRemoveMode);
198         outState.putBoolean(CFGKEY_REMOVE_DIALOG, mShowingRemoveDialog);
199         outState.putBoolean(CFGKEY_ADD_LOCALE, mLocaleAdditionMode);
200         mAdapter.saveState(outState);
201     }
202 
203     @Override
onOptionsItemSelected(MenuItem menuItem)204     public boolean onOptionsItemSelected(MenuItem menuItem) {
205         switch (menuItem.getItemId()) {
206             case MENU_ID_REMOVE:
207                 if (mRemoveMode) {
208                     showRemoveLocaleWarningDialog();
209                 } else {
210                     setRemoveMode(true);
211                 }
212                 return true;
213             case android.R.id.home:
214                 if (mRemoveMode) {
215                     setRemoveMode(false);
216                     return true;
217                 }
218                 break;
219         }
220         return super.onOptionsItemSelected(menuItem);
221     }
222 
223     @Override
onActivityResult(int requestCode, int resultCode, Intent data)224     public void onActivityResult(int requestCode, int resultCode, Intent data) {
225         LocaleStore.LocaleInfo localeInfo;
226         if (requestCode == REQUEST_LOCALE_PICKER && resultCode == Activity.RESULT_OK
227                 && data != null) {
228             localeInfo = (LocaleStore.LocaleInfo) data.getSerializableExtra(INTENT_LOCALE_KEY);
229             String preferencesTags = Settings.System.getString(
230                     getContext().getContentResolver(), Settings.System.LOCALE_PREFERENCES);
231             localeInfo = mayAppendUnicodeTags(localeInfo, preferencesTags);
232             mAdapter.addLocale(localeInfo);
233             updateVisibilityOfRemoveMenu();
234             mMetricsFeatureProvider.action(getContext(), SettingsEnums.ACTION_ADD_LANGUAGE);
235         } else if (requestCode == DIALOG_CONFIRM_SYSTEM_DEFAULT) {
236             localeInfo = mAdapter.getFeedItemList().get(0);
237             if (resultCode == Activity.RESULT_OK) {
238                 mAdapter.doTheUpdate();
239                 boolean showNotTranslatedDialog = data.getBooleanExtra(
240                         LocaleDialogFragment.ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED, true);
241                 if (showNotTranslatedDialog && !localeInfo.isTranslated()) {
242                     Bundle args = new Bundle();
243                     args.putInt(LocaleDialogFragment.ARG_DIALOG_TYPE,
244                             LocaleDialogFragment.DIALOG_NOT_AVAILABLE_LOCALE);
245                     args.putSerializable(LocaleDialogFragment.ARG_TARGET_LOCALE, localeInfo);
246                     LocaleDialogFragment localeDialogFragment = LocaleDialogFragment.newInstance();
247                     localeDialogFragment.setArguments(args);
248                     localeDialogFragment.show(mFragmentManager, TAG_DIALOG_NOT_AVAILABLE);
249                     mMetricsFeatureProvider.action(getContext(),
250                             SettingsEnums.ACTION_NOT_SUPPORTED_SYSTEM_LANGUAGE);
251                 }
252             } else {
253                 mAdapter.notifyListChanged(localeInfo);
254             }
255             mAdapter.setCacheItemList();
256         } else if (requestCode == DIALOG_ADD_SYSTEM_LOCALE) {
257             int action = SettingsEnums.ACTION_CANCEL_SYSTEM_LOCALE_FROM_RECOMMENDATION;
258             if (resultCode == Activity.RESULT_OK) {
259                 localeInfo = (LocaleStore.LocaleInfo) data.getExtras().getSerializable(
260                         LocaleDialogFragment.ARG_TARGET_LOCALE);
261                 String preferencesTags = Settings.System.getString(
262                         getContext().getContentResolver(),
263                         Settings.System.LOCALE_PREFERENCES);
264                 mAdapter.addLocale(mayAppendUnicodeTags(localeInfo, preferencesTags));
265                 action = SettingsEnums.ACTION_ADD_SYSTEM_LOCALE_FROM_RECOMMENDATION;
266             }
267             mMetricsFeatureProvider.action(getContext(), action);
268         }
269         super.onActivityResult(requestCode, resultCode, data);
270     }
271 
272     @VisibleForTesting
mayAppendUnicodeTags( LocaleStore.LocaleInfo localeInfo, String recordTags)273     static LocaleStore.LocaleInfo mayAppendUnicodeTags(
274             LocaleStore.LocaleInfo localeInfo, String recordTags) {
275         if (TextUtils.isEmpty(recordTags) || TextUtils.equals("und", recordTags)) {
276             // No recorded tag, return inputted LocaleInfo.
277             return localeInfo;
278         }
279         Locale recordLocale = Locale.forLanguageTag(recordTags);
280         Locale.Builder builder = new Locale.Builder()
281                 .setLocale(localeInfo.getLocale());
282         recordLocale.getUnicodeLocaleKeys().forEach(key ->
283                 builder.setUnicodeLocaleKeyword(key, recordLocale.getUnicodeLocaleType(key)));
284         LocaleStore.LocaleInfo newLocaleInfo = LocaleStore.fromLocale(builder.build());
285         newLocaleInfo.setTranslated(localeInfo.isTranslated());
286         return newLocaleInfo;
287     }
288 
setRemoveMode(boolean mRemoveMode)289     private void setRemoveMode(boolean mRemoveMode) {
290         this.mRemoveMode = mRemoveMode;
291         mAdapter.setRemoveMode(mRemoveMode);
292         if (SettingsThemeHelper.isExpressiveTheme(getContext())) {
293             mAddLanguagePreference.setVisible(!mRemoveMode);
294         } else {
295             mAddLanguage.setVisibility(mRemoveMode ? View.INVISIBLE : View.VISIBLE);
296         }
297         updateVisibilityOfRemoveMenu();
298     }
299 
shouldShowConfirmationDialog()300     private boolean shouldShowConfirmationDialog() {
301         Intent intent = this.getIntent();
302         String dialogType = intent.getStringExtra(EXTRA_SYSTEM_LOCALE_DIALOG_TYPE);
303         String localeTag = intent.getStringExtra(EXTRA_APP_LOCALE);
304         String callingPackage = getActivity().getCallingPackage();
305         if (!localeNotificationEnabled()
306                 || !getContext().getPackageName().equals(callingPackage)
307                 || !isValidDialogType(dialogType)
308                 || !isValidLocale(localeTag)
309                 || LocaleUtils.isInSystemLocale(localeTag)) {
310             return false;
311         }
312         return true;
313     }
314 
315     @VisibleForTesting
getNotificationController()316     NotificationController getNotificationController() {
317         return NotificationController.getInstance(getContext());
318     }
319 
isValidDialogType(String type)320     private boolean isValidDialogType(String type) {
321         return LOCALE_SUGGESTION.equals(type);
322     }
323 
isValidLocale(String tag)324     private boolean isValidLocale(String tag) {
325         if (TextUtils.isEmpty(tag)) {
326             return false;
327         }
328         String[] systemLocales = getSupportedLocales();
329         for (String systemTag : systemLocales) {
330             if (systemTag.equals(tag)) {
331                 return true;
332             }
333         }
334         return false;
335     }
336 
337     @VisibleForTesting
getSupportedLocales()338     String[] getSupportedLocales() {
339         return LocalePicker.getSupportedLocales(getContext());
340     }
341 
showDialogForAddedLocale()342     private void showDialogForAddedLocale() {
343         Log.d(TAG, "show confirmation dialog");
344         Intent intent = this.getIntent();
345         String appLocaleTag = intent.getStringExtra(EXTRA_APP_LOCALE);
346 
347         LocaleStore.LocaleInfo localeInfo = LocaleStore.getLocaleInfo(
348                 Locale.forLanguageTag(appLocaleTag));
349         final LocaleDialogFragment localeDialogFragment =
350                 LocaleDialogFragment.newInstance();
351         Bundle args = new Bundle();
352         args.putInt(LocaleDialogFragment.ARG_DIALOG_TYPE, DIALOG_ADD_SYSTEM_LOCALE);
353         args.putSerializable(LocaleDialogFragment.ARG_TARGET_LOCALE, localeInfo);
354         localeDialogFragment.setArguments(args);
355         localeDialogFragment.show(mFragmentManager, TAG_DIALOG_ADD_SYSTEM_LOCALE);
356     }
357 
getLocaleDialogView()358     protected View getLocaleDialogView() {
359         LayoutInflater inflater = this.getLayoutInflater();
360         return inflater.inflate(R.layout.locale_dialog, null);
361     }
362 
363     // Show the appropriate warning when the user tries to remove locales.
364     // Shows no warning if there is no locale checked, shows a warning
365     // about removing all the locales if all of them are checked, and
366     // a "regular" warning otherwise.
367     @VisibleForTesting
showRemoveLocaleWarningDialog()368     void showRemoveLocaleWarningDialog() {
369         int checkedCount = mAdapter.getCheckedCount();
370 
371         // Nothing checked, just exit remove mode without a warning dialog
372         if (checkedCount == 0) {
373             setRemoveMode(!mRemoveMode);
374             return;
375         }
376 
377         int messagePaddingLeftRight = getContext().getResources().getDimensionPixelSize(
378                 R.dimen.locale_picker_dialog_message_padding_left_right);
379         int messagePaddingBottom = getContext().getResources().getDimensionPixelSize(
380                 R.dimen.locale_picker_dialog_message_padding_bottom);
381         // All locales selected, warning dialog, can't remove them all
382         if (checkedCount == mAdapter.getItemCount()) {
383             mShowingRemoveDialog = true;
384 
385             CustomDialogHelper dialogHelper = createRegionDialog(getContext(),
386                     getContext().getString(R.string.dlg_remove_locales_error_title));
387             dialogHelper.setMessage(R.string.dlg_remove_locales_error_message)
388                     .setMessagePadding(messagePaddingLeftRight, 0, messagePaddingLeftRight,
389                             messagePaddingBottom)
390                     .setPositiveButton(android.R.string.ok,
391                             view -> {
392                                 dialogHelper.getDialog().dismiss();
393                             })
394                     .setBackButton(R.string.cancel, view -> {
395                         dialogHelper.getDialog().dismiss();
396                     });
397             dialogHelper.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
398                 @Override
399                 public void onDismiss(@NonNull DialogInterface dialog) {
400                     mShowingRemoveDialog = false;
401                 }
402             });
403             dialogHelper.getDialog().show();
404             return;
405         }
406 
407         final String title = StringUtil.getIcuPluralsString(getContext(), checkedCount,
408                 R.string.dlg_remove_locales_title);
409         mShowingRemoveDialog = true;
410 
411         CustomDialogHelper dialogHelper = createRegionDialog(getContext(), title);
412         if (mAdapter.isFirstLocaleChecked()) {
413             dialogHelper.setMessage(R.string.dlg_remove_locales_message)
414                     .setMessagePadding(messagePaddingLeftRight, 0, messagePaddingLeftRight,
415                             messagePaddingBottom);
416         }
417 
418         dialogHelper.setPositiveButton(R.string.locale_remove_menu,
419                         view -> {
420                             // This is a sensitive area to change.
421                             // removeChecked() triggers a system update and "kills" the frame.
422                             // This means that saveState + restoreState are called before
423                             // setRemoveMode is called.
424                             // So we want that mRemoveMode and dialog status have the right
425                             // values
426                             // before that save.
427                             // We can't just call setRemoveMode(false) before calling
428                             // removeCheched
429                             // because that unchecks all items and removeChecked would have
430                             // nothing
431                             // to remove.
432                             mRemoveMode = false;
433                             mShowingRemoveDialog = false;
434                             Locale defaultBeforeRemoval = Locale.getDefault();
435                             mAdapter.removeChecked();
436                             showConfirmDialog(mAdapter.getFeedItemList().get(0),
437                                     defaultBeforeRemoval);
438                             setRemoveMode(false);
439                             dialogHelper.getDialog().dismiss();
440                         })
441                 .setBackButton(R.string.cancel, view -> {
442                     setRemoveMode(false);
443                     dialogHelper.getDialog().dismiss();
444                 });
445         dialogHelper.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
446             @Override
447             public void onDismiss(@NonNull DialogInterface dialog) {
448                 mShowingRemoveDialog = false;
449             }
450         });
451         dialogHelper.getDialog().show();
452     }
453 
createRegionDialog(Context context, String title)454     private CustomDialogHelper createRegionDialog(Context context, String title) {
455         CustomDialogHelper dialogHelper = new CustomDialogHelper(context);
456         dialogHelper.setIcon(context.getDrawable(R.drawable.ic_settings_language_32dp))
457                 .setTitle(title)
458                 .setIconPadding(0, context.getResources().getDimensionPixelSize(
459                         R.dimen.locale_picker_dialog_icon_padding), 0, 0)
460                 .setTitlePadding(0, context.getResources().getDimensionPixelSize(
461                                 R.dimen.locale_picker_dialog_title_padding), 0,
462                         context.getResources().getDimensionPixelSize(
463                                 R.dimen.locale_picker_dialog_title_padding));
464         return dialogHelper;
465     }
466 
467     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)468     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
469         final MenuItem menuItem =
470                 menu.add(Menu.NONE, MENU_ID_REMOVE, 0, R.string.locale_remove_menu);
471         menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT);
472         menuItem.setIcon(R.drawable.ic_delete);
473         super.onCreateOptionsMenu(menu, inflater);
474         mMenu = menu;
475         updateVisibilityOfRemoveMenu();
476     }
477 
getUserLocaleList()478     private List<LocaleStore.LocaleInfo> getUserLocaleList() {
479         final List<LocaleStore.LocaleInfo> result = new ArrayList<>();
480         final LocaleList localeList = LocalePicker.getLocales();
481         for (int i = 0; i < localeList.size(); i++) {
482             Locale locale = localeList.get(i);
483             result.add(LocaleStore.getLocaleInfo(locale));
484         }
485         return result;
486     }
487 
configureDragAndDrop(LayoutPreference layout)488     private void configureDragAndDrop(LayoutPreference layout) {
489         final RecyclerView list = layout.findViewById(R.id.dragList);
490         final LocaleLinearLayoutManager llm = new LocaleLinearLayoutManager(getContext(), mAdapter);
491         llm.setLocaleListEditor(this);
492         llm.setAutoMeasureEnabled(true);
493         list.setLayoutManager(llm);
494         list.setHasFixedSize(true);
495         list.setNestedScrollingEnabled(false);
496         mAdapter.setRecyclerView(list);
497         list.setAdapter(mAdapter);
498         list.setOnTouchListener(this);
499         list.requestFocus();
500         if (SettingsThemeHelper.isExpressiveTheme(getContext())) {
501             mAddLanguagePreference = getPreferenceScreen().findPreference(KEY_ADD_A_LANGUAGE);
502         } else {
503             mAddLanguage = layout.findViewById(R.id.add_language);
504             mAddLanguage.setOnClickListener(new View.OnClickListener() {
505                 @Override
506                 public void onClick(@NonNull View v) {
507                     FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
508                             .logSettingsTileClick(INDEX_KEY_ADD_LANGUAGE, getMetricsCategory());
509 
510                     final Intent intent = new Intent(getActivity(),
511                             LocalePickerWithRegionActivity.class);
512                     intent.putExtras(getActivity().getIntent().getExtras());
513                     startActivityForResult(intent, REQUEST_LOCALE_PICKER);
514                 }
515             });
516         }
517     }
518 
519     @Override
onTouch(View v, MotionEvent event)520     public boolean onTouch(View v, MotionEvent event) {
521         if (event.getAction() == MotionEvent.ACTION_UP
522                 || event.getAction() == MotionEvent.ACTION_CANCEL) {
523             showConfirmDialog(mAdapter.getFeedItemList().get(0), null);
524         }
525         return false;
526     }
527 
showConfirmDialog(LocaleStore.LocaleInfo localeInfo, @Nullable Locale defaultLocaleBeforeRemoval)528     protected void showConfirmDialog(LocaleStore.LocaleInfo localeInfo,
529             @Nullable Locale defaultLocaleBeforeRemoval) {
530         Locale currentSystemLocale = LocalePicker.getLocales().get(0);
531         if (!localeInfo.getLocale().equals(currentSystemLocale)) {
532             if (Locale.getDefault().equals(localeInfo.getLocale())) {
533                 mAdapter.doTheUpdate();
534             } else {
535                 displayDialogFragment(localeInfo, true);
536             }
537         } else {
538             if (!localeInfo.isTranslated()) {
539                 if (defaultLocaleBeforeRemoval == null) {
540                     showDialogDueToDragAndDrop();
541                 } else {
542                     showDialogDueToRemoval(defaultLocaleBeforeRemoval);
543                 }
544             } else {
545                 mAdapter.doTheUpdate();
546             }
547         }
548     }
549 
showDialogDueToDragAndDrop()550     private void showDialogDueToDragAndDrop() {
551         LocaleStore.LocaleInfo newLocale = mAdapter.getFeedItemList().stream().filter(
552                 i -> i.isTranslated()).findFirst().orElse(null);
553         if (newLocale == null) {
554             return;
555         }
556         LocaleStore.LocaleInfo oldLocale = null;
557         final LocaleList localeList = LocalePicker.getLocales();
558         for (int i = 0; i < localeList.size(); i++) {
559             LocaleStore.LocaleInfo temp = LocaleStore.getLocaleInfo(localeList.get(i));
560             if (temp.isTranslated()) {
561                 oldLocale = temp;
562                 break;
563             }
564         }
565         if (oldLocale != null && !newLocale.getLocale().equals(
566                 oldLocale.getLocale())) {
567             displayDialogFragment(newLocale, false);
568         }
569     }
570 
showDialogDueToRemoval(Locale preDefault)571     private void showDialogDueToRemoval(Locale preDefault) {
572         if (preDefault == null) {
573             return;
574         }
575         LocaleStore.LocaleInfo currentDefault = mAdapter.getFeedItemList().stream().filter(
576                 i -> i.isTranslated()).findFirst().orElse(null);
577         if (currentDefault != null && !preDefault.equals(currentDefault.getLocale())) {
578             displayDialogFragment(currentDefault, false);
579         }
580     }
581 
displayDialogFragment(LocaleStore.LocaleInfo localeInfo, boolean showDialogForNotTranslated)582     private void displayDialogFragment(LocaleStore.LocaleInfo localeInfo,
583             boolean showDialogForNotTranslated) {
584         final LocaleDialogFragment localeDialogFragment = LocaleDialogFragment.newInstance();
585         Bundle args = new Bundle();
586         args.putBoolean(LocaleDialogFragment.ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED,
587                 showDialogForNotTranslated);
588         args.putInt(LocaleDialogFragment.ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
589         args.putSerializable(LocaleDialogFragment.ARG_TARGET_LOCALE, localeInfo);
590         localeDialogFragment.setArguments(args);
591         localeDialogFragment.show(mFragmentManager, TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT);
592     }
593 
594     // Hide the "Remove" menu if there is only one locale in the list, show it otherwise
595     // This is called when the menu is first created, and then one add / remove locale
updateVisibilityOfRemoveMenu()596     private void updateVisibilityOfRemoveMenu() {
597         if (mMenu == null) {
598             return;
599         }
600 
601         final MenuItem menuItemRemove = mMenu.findItem(MENU_ID_REMOVE);
602         if (menuItemRemove != null) {
603             menuItemRemove.setShowAsAction(
604                     mRemoveMode ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER);
605             final boolean hasMultipleLanguages = mAdapter.getItemCount() > 1;
606             menuItemRemove.setVisible(hasMultipleLanguages && !mIsUiRestricted);
607         }
608     }
609 
610     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
611             new BaseSearchIndexProvider() {
612                 @Override
613                 public List<SearchIndexableRaw> getRawDataToIndex(Context context,
614                         boolean enabled) {
615                     final Resources res = context.getResources();
616                     final List<SearchIndexableRaw> indexRaws = new ArrayList<>();
617                     final SearchIndexableRaw raw = new SearchIndexableRaw(context);
618                     raw.key = INDEX_KEY_ADD_LANGUAGE;
619                     raw.title = res.getString(R.string.add_a_language);
620                     raw.keywords = res.getString(R.string.keywords_add_language);
621                     indexRaws.add(raw);
622                     return indexRaws;
623                 }
624             };
625 }
626