Home | History | Annotate | Download | only in settings
      1 /*******************************************************************************
      2  *      Copyright (C) 2014 Google Inc.
      3  *      Licensed to The Android Open Source Project.
      4  *
      5  *      Licensed under the Apache License, Version 2.0 (the "License");
      6  *      you may not use this file except in compliance with the License.
      7  *      You may obtain a copy of the License at
      8  *
      9  *           http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *      Unless required by applicable law or agreed to in writing, software
     12  *      distributed under the License is distributed on an "AS IS" BASIS,
     13  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *      See the License for the specific language governing permissions and
     15  *      limitations under the License.
     16  *******************************************************************************/
     17 
     18 package com.android.mail.ui.settings;
     19 
     20 import android.app.AlertDialog;
     21 import android.content.Context;
     22 import android.content.DialogInterface;
     23 import android.content.DialogInterface.OnClickListener;
     24 import android.os.AsyncTask;
     25 import android.os.Bundle;
     26 import android.preference.CheckBoxPreference;
     27 import android.preference.ListPreference;
     28 import android.preference.Preference;
     29 import android.preference.Preference.OnPreferenceChangeListener;
     30 import android.view.Menu;
     31 import android.view.MenuInflater;
     32 import android.view.MenuItem;
     33 import android.widget.Toast;
     34 
     35 import com.android.mail.preferences.MailPrefs;
     36 import com.android.mail.preferences.MailPrefs.PreferenceKeys;
     37 import com.android.mail.providers.SuggestionsProvider;
     38 import com.android.mail.providers.UIProvider.AutoAdvance;
     39 import com.android.mail.utils.LogUtils;
     40 import com.android.mail.R;
     41 import com.google.common.annotations.VisibleForTesting;
     42 
     43 /**
     44  * This fragment shows general app preferences.
     45  */
     46 public class GeneralPrefsFragment extends MailPreferenceFragment
     47         implements OnClickListener, OnPreferenceChangeListener {
     48 
     49     // Keys used to reference pref widgets which don't map directly to preference entries
     50     static final String AUTO_ADVANCE_WIDGET = "auto-advance-widget";
     51 
     52     static final String CALLED_FROM_TEST = "called-from-test";
     53 
     54     // Category for removal actions
     55     protected static final String REMOVAL_ACTIONS_GROUP = "removal-actions-group";
     56 
     57     protected MailPrefs mMailPrefs;
     58 
     59     private AlertDialog mClearSearchHistoryDialog;
     60 
     61     private ListPreference mAutoAdvance;
     62     private static final int[] AUTO_ADVANCE_VALUES = {
     63             AutoAdvance.NEWER,
     64             AutoAdvance.OLDER,
     65             AutoAdvance.LIST
     66     };
     67 
     68     @Override
     69     public void onCreate(Bundle savedInstanceState) {
     70         super.onCreate(savedInstanceState);
     71 
     72         setHasOptionsMenu(true);
     73 
     74         mMailPrefs = MailPrefs.get(getActivity());
     75 
     76         // Set the shared prefs name to use prefs auto-persist behavior by default.
     77         // Any pref more complex than the default (say, involving migration), should set
     78         // "persistent=false" in the XML and manually handle preference initialization and change.
     79         getPreferenceManager()
     80                 .setSharedPreferencesName(mMailPrefs.getSharedPreferencesName());
     81 
     82         addPreferencesFromResource(R.xml.general_preferences);
     83 
     84         mAutoAdvance = (ListPreference) findPreference(AUTO_ADVANCE_WIDGET);
     85     }
     86 
     87     @Override
     88     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
     89         /*
     90          * We deliberately do not call super because our menu includes the parent's menu options to
     91          * allow custom ordering.
     92          */
     93         menu.clear();
     94         inflater.inflate(R.menu.general_prefs_fragment_menu, menu);
     95     }
     96 
     97     @Override
     98     public boolean onOptionsItemSelected(MenuItem item) {
     99         final int itemId = item.getItemId();
    100         if (itemId == R.id.clear_search_history_menu_item) {
    101             clearSearchHistory();
    102             return true;
    103         } else if (itemId == R.id.clear_picture_approvals_menu_item) {
    104             clearDisplayImages();
    105             return true;
    106         }
    107 
    108         return super.onOptionsItemSelected(item);
    109     }
    110 
    111     @Override
    112     public boolean onPreferenceChange(Preference preference, Object newValue) {
    113         if (getActivity() == null) {
    114             // Monkeys cause bad things. This callback may be delayed if for some reason the
    115             // preference screen was closed really quickly - just bail then.
    116             return false;
    117         }
    118 
    119         final String key = preference.getKey();
    120 
    121         if (PreferenceKeys.REMOVAL_ACTION.equals(key)) {
    122             final String removalAction = newValue.toString();
    123             mMailPrefs.setRemovalAction(removalAction);
    124         } else if (AUTO_ADVANCE_WIDGET.equals(key)) {
    125             final int prefsAutoAdvanceMode =
    126                     AUTO_ADVANCE_VALUES[mAutoAdvance.findIndexOfValue((String) newValue)];
    127             mMailPrefs.setAutoAdvanceMode(prefsAutoAdvanceMode);
    128         } else if (!PreferenceKeys.CONVERSATION_LIST_SWIPE.equals(key) &&
    129                 !PreferenceKeys.SHOW_SENDER_IMAGES.equals(key) &&
    130                 !PreferenceKeys.DEFAULT_REPLY_ALL.equals(key) &&
    131                 !PreferenceKeys.CONVERSATION_OVERVIEW_MODE.equals(key) &&
    132                 !PreferenceKeys.CONFIRM_DELETE.equals(key) &&
    133                 !PreferenceKeys.CONFIRM_ARCHIVE.equals(key) &&
    134                 !PreferenceKeys.CONFIRM_SEND.equals(key)) {
    135             return false;
    136         }
    137 
    138         return true;
    139     }
    140 
    141     private void clearDisplayImages() {
    142         final ClearPictureApprovalsDialogFragment fragment =
    143                 ClearPictureApprovalsDialogFragment.newInstance();
    144         fragment.show(getActivity().getFragmentManager(),
    145                 ClearPictureApprovalsDialogFragment.FRAGMENT_TAG);
    146     }
    147 
    148     private void clearSearchHistory() {
    149         mClearSearchHistoryDialog = new AlertDialog.Builder(getActivity())
    150                 .setMessage(R.string.clear_history_dialog_message)
    151                 .setTitle(R.string.clear_history_dialog_title)
    152                 .setIconAttribute(android.R.attr.alertDialogIcon)
    153                 .setPositiveButton(R.string.clear, this)
    154                 .setNegativeButton(R.string.cancel, this)
    155                 .show();
    156     }
    157 
    158 
    159     @Override
    160     public void onClick(DialogInterface dialog, int which) {
    161         if (dialog.equals(mClearSearchHistoryDialog)) {
    162             if (which == DialogInterface.BUTTON_POSITIVE) {
    163                 final Context context = getActivity();
    164                 // Clear the history in the background, as it causes a disk
    165                 // write.
    166                 new AsyncTask<Void, Void, Void>() {
    167                     @Override
    168                     protected Void doInBackground(Void... params) {
    169                         final SuggestionsProvider suggestions =
    170                                 new SuggestionsProvider(context);
    171                         suggestions.clearHistory();
    172                         suggestions.cleanup();
    173                         return null;
    174                     }
    175                 }.execute();
    176                 Toast.makeText(getActivity(), R.string.search_history_cleared, Toast.LENGTH_SHORT)
    177                         .show();
    178             }
    179         }
    180     }
    181 
    182     @Override
    183     public void onStop() {
    184         super.onStop();
    185         if (mClearSearchHistoryDialog != null && mClearSearchHistoryDialog.isShowing()) {
    186             mClearSearchHistoryDialog.dismiss();
    187         }
    188     }
    189 
    190     @Override
    191     public void onResume() {
    192         super.onResume();
    193 
    194         // Manually initialize the preference views that require massaging. Prefs that require
    195         // massaging include:
    196         //  1. a prefs UI control that does not map 1:1 to storage
    197         //  2. a pref that must obtain its initial value from migrated storage, and for which we
    198         //     don't want to always persist a migrated value
    199         final int autoAdvanceModeIndex = prefValueToWidgetIndex(AUTO_ADVANCE_VALUES,
    200                 mMailPrefs.getAutoAdvanceMode(), AutoAdvance.DEFAULT);
    201         mAutoAdvance.setValueIndex(autoAdvanceModeIndex);
    202 
    203         listenForPreferenceChange(
    204                 PreferenceKeys.REMOVAL_ACTION,
    205                 PreferenceKeys.CONVERSATION_LIST_SWIPE,
    206                 PreferenceKeys.SHOW_SENDER_IMAGES,
    207                 PreferenceKeys.DEFAULT_REPLY_ALL,
    208                 PreferenceKeys.CONVERSATION_OVERVIEW_MODE,
    209                 AUTO_ADVANCE_WIDGET,
    210                 PreferenceKeys.CONFIRM_DELETE,
    211                 PreferenceKeys.CONFIRM_ARCHIVE,
    212                 PreferenceKeys.CONFIRM_SEND
    213         );
    214     }
    215 
    216     protected boolean supportsArchive() {
    217         return true;
    218     }
    219 
    220     /**
    221      * Converts the prefs value into an index useful for configuring the UI widget, falling back to
    222      * the default value if the value from the prefs can't be found for some reason. If neither can
    223      * be found, it throws an {@link java.lang.IllegalArgumentException}
    224      *
    225      * @param conversionArray An array of prefs values, in widget order
    226      * @param prefValue Value of the preference
    227      * @param defaultValue Default value, as a fallback if we can't map the real value
    228      * @return Index of the entry (or fallback) in the conversion array
    229      */
    230     @VisibleForTesting
    231     static int prefValueToWidgetIndex(int[] conversionArray, int prefValue, int defaultValue) {
    232         for (int i = 0; i < conversionArray.length; i++) {
    233             if (conversionArray[i] == prefValue) {
    234                 return i;
    235             }
    236         }
    237         LogUtils.e(LogUtils.TAG, "Can't map preference value " + prefValue);
    238         for (int i = 0; i < conversionArray.length; i++) {
    239             if (conversionArray[i] == defaultValue) {
    240                 return i;
    241             }
    242         }
    243         throw new IllegalArgumentException("Can't map default preference value " + prefValue);
    244     }
    245 
    246     private void listenForPreferenceChange(String... keys) {
    247         for (String key : keys) {
    248             Preference p = findPreference(key);
    249             if (p != null) {
    250                 p.setOnPreferenceChangeListener(this);
    251             }
    252         }
    253     }
    254 }
    255