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