From 707cdc8b18f7af12559894e970fdec3c275d07b6 Mon Sep 17 00:00:00 2001 From: Jorge Ruesga Date: Sat, 4 Apr 2015 20:42:30 +0200 Subject: [PATCH] email: support per-folder notifications This change enables support to configure per-folder notifications options. Change-Id: I6107340da3438ea223506bb22ff898cca179c1f6 Signed-off-by: Jorge Ruesga --- res/layout/preference_mailbox_item.xml | 58 ++ res/values/cm_dimens.xml | 20 + res/values/cm_strings.xml | 8 + res/xml/mailbox_notifications_preferences.xml | 36 ++ .../setup/AccountSettingsFragment.java | 110 ++-- .../email/activity/setup/MailboxSettings.java | 519 +++++++++++++++++- 6 files changed, 697 insertions(+), 54 deletions(-) create mode 100644 res/layout/preference_mailbox_item.xml create mode 100644 res/values/cm_dimens.xml create mode 100644 res/xml/mailbox_notifications_preferences.xml diff --git a/res/layout/preference_mailbox_item.xml b/res/layout/preference_mailbox_item.xml new file mode 100644 index 000000000..07d3ba83f --- /dev/null +++ b/res/layout/preference_mailbox_item.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + diff --git a/res/values/cm_dimens.xml b/res/values/cm_dimens.xml new file mode 100644 index 000000000..6748f80d3 --- /dev/null +++ b/res/values/cm_dimens.xml @@ -0,0 +1,20 @@ + + + + + + 8dp + diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 0e3594f64..c0534bfb1 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -21,4 +21,12 @@ account %s. This operation cannot be undone.\n\nContinue? Deleting account\u2026 Couldn\'t delete the account + + + Notification options + + Notification options (%s) + + + Folder notification settings diff --git a/res/xml/mailbox_notifications_preferences.xml b/res/xml/mailbox_notifications_preferences.xml new file mode 100644 index 000000000..76841420c --- /dev/null +++ b/res/xml/mailbox_notifications_preferences.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + diff --git a/src/com/android/email/activity/setup/AccountSettingsFragment.java b/src/com/android/email/activity/setup/AccountSettingsFragment.java index 49bd8535d..e7abc1cab 100644 --- a/src/com/android/email/activity/setup/AccountSettingsFragment.java +++ b/src/com/android/email/activity/setup/AccountSettingsFragment.java @@ -103,12 +103,14 @@ public class AccountSettingsFragment extends MailAccountPrefsFragment private static final String PREFERENCE_QUICK_RESPONSES = "account_quick_responses"; private static final String PREFERENCE_FREQUENCY = "account_check_frequency"; private static final String PREFERENCE_SYNC_WINDOW = "account_sync_window"; - private static final String PREFERENCE_SYNC_SETTINGS = "account_sync_settings"; + private static final String PREFERENCE_SYNC_SETTINGS = MailboxSettings.PREFERENCE_SYNC_SETTINGS; private static final String PREFERENCE_SYNC_EMAIL = "account_sync_email"; private static final String PREFERENCE_SYNC_CONTACTS = "account_sync_contacts"; private static final String PREFERENCE_SYNC_CALENDAR = "account_sync_calendar"; private static final String PREFERENCE_BACKGROUND_ATTACHMENTS = "account_background_attachments"; + private static final String PREFERENCE_PER_FOLDER_NOTIFICATIONS = + MailboxSettings.PREFERENCE_PER_FOLDER_NOTIFICATIONS; private static final String PREFERENCE_CATEGORY_DATA_USAGE = "data_usage"; private static final String PREFERENCE_CATEGORY_NOTIFICATIONS = "account_notifications"; private static final String PREFERENCE_CATEGORY_SERVER = "account_servers"; @@ -142,6 +144,7 @@ public class AccountSettingsFragment extends MailAccountPrefsFragment private Preference mSyncSettings; private CheckBoxPreference mInboxVibrate; private Preference mInboxRingtone; + private Preference mPerFolderNotification; private Context mContext; private Handler mHandler; @@ -307,9 +310,10 @@ public class AccountSettingsFragment extends MailAccountPrefsFragment public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, @NonNull Preference preference) { final String key = preference.getKey(); - if (key.equals(PREFERENCE_SYNC_SETTINGS)) { + if (key.equals(PREFERENCE_SYNC_SETTINGS) || + key.equals(PREFERENCE_PER_FOLDER_NOTIFICATIONS)) { startActivity(MailboxSettings.getIntent(getActivity(), mUiAccount.fullFolderListUri, - mInboxFolder)); + mInboxFolder, key)); return true; } else { return super.onPreferenceTreeClick(preferenceScreen, preference); @@ -847,43 +851,77 @@ public class AccountSettingsFragment extends MailAccountPrefsFragment (PreferenceCategory) findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS); if (mInboxFolderPreferences != null) { - final CheckBoxPreference inboxNotify = (CheckBoxPreference) findPreference( - FolderPreferences.PreferenceKeys.NOTIFICATIONS_ENABLED); - inboxNotify.setChecked(mInboxFolderPreferences.areNotificationsEnabled()); - inboxNotify.setOnPreferenceChangeListener(this); + if (mServiceInfo.offerLookback) { + // This account supports per-folder notifications - mInboxRingtone = findPreference(FolderPreferences.PreferenceKeys.NOTIFICATION_RINGTONE); - final String ringtoneUri = mInboxFolderPreferences.getNotificationRingtoneUri(); - if (!TextUtils.isEmpty(ringtoneUri)) { - mRingtone = RingtoneManager.getRingtone(getActivity(), Uri.parse(ringtoneUri)); - } - setRingtoneSummary(); - mInboxRingtone.setOnPreferenceChangeListener(this); - mInboxRingtone.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(final Preference preference) { - showRingtonePicker(); - - return true; + // Enable per-folder notifications preference + if (mPerFolderNotification == null) { + mPerFolderNotification = new Preference(mContext); + mPerFolderNotification.setKey(PREFERENCE_PER_FOLDER_NOTIFICATIONS); + notificationsCategory.addPreference(mPerFolderNotification); } - }); + mPerFolderNotification.setTitle(R.string.folder_notify_settings_pref_title); - notificationsCategory.setEnabled(true); - - // Set the vibrator value, or hide it on devices w/o a vibrator - mInboxVibrate = (CheckBoxPreference) findPreference( - FolderPreferences.PreferenceKeys.NOTIFICATION_VIBRATE); - if (mInboxVibrate != null) { - mInboxVibrate.setChecked( - mInboxFolderPreferences.isNotificationVibrateEnabled()); - Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); - if (vibrator.hasVibrator()) { - // When the value is changed, update the setting. - mInboxVibrate.setOnPreferenceChangeListener(this); - } else { - // No vibrator present. Remove the preference altogether. + // Remove Inbox per-account preferences + final CheckBoxPreference inboxNotify = (CheckBoxPreference) findPreference( + FolderPreferences.PreferenceKeys.NOTIFICATIONS_ENABLED); + if (inboxNotify != null) { + notificationsCategory.removePreference(inboxNotify); + } + mInboxRingtone = findPreference( + FolderPreferences.PreferenceKeys.NOTIFICATION_RINGTONE); + if (mInboxRingtone != null) { + notificationsCategory.removePreference(mInboxRingtone); + } + mInboxVibrate = (CheckBoxPreference) findPreference( + FolderPreferences.PreferenceKeys.NOTIFICATION_VIBRATE); + if (mInboxVibrate != null) { notificationsCategory.removePreference(mInboxVibrate); - mInboxVibrate = null; + } + + notificationsCategory.setEnabled(true); + + } else { + final CheckBoxPreference inboxNotify = (CheckBoxPreference) findPreference( + FolderPreferences.PreferenceKeys.NOTIFICATIONS_ENABLED); + inboxNotify.setChecked(mInboxFolderPreferences.areNotificationsEnabled()); + inboxNotify.setOnPreferenceChangeListener(this); + + mInboxRingtone = findPreference( + FolderPreferences.PreferenceKeys.NOTIFICATION_RINGTONE); + final String ringtoneUri = mInboxFolderPreferences.getNotificationRingtoneUri(); + if (!TextUtils.isEmpty(ringtoneUri)) { + mRingtone = RingtoneManager.getRingtone(getActivity(), Uri.parse(ringtoneUri)); + } + setRingtoneSummary(); + mInboxRingtone.setOnPreferenceChangeListener(this); + mInboxRingtone.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(final Preference preference) { + showRingtonePicker(); + + return true; + } + }); + + notificationsCategory.setEnabled(true); + + // Set the vibrator value, or hide it on devices w/o a vibrator + mInboxVibrate = (CheckBoxPreference) findPreference( + FolderPreferences.PreferenceKeys.NOTIFICATION_VIBRATE); + if (mInboxVibrate != null) { + mInboxVibrate.setChecked( + mInboxFolderPreferences.isNotificationVibrateEnabled()); + Vibrator vibrator = (Vibrator) mContext.getSystemService( + Context.VIBRATOR_SERVICE); + if (vibrator.hasVibrator()) { + // When the value is changed, update the setting. + mInboxVibrate.setOnPreferenceChangeListener(this); + } else { + // No vibrator present. Remove the preference altogether. + notificationsCategory.removePreference(mInboxVibrate); + mInboxVibrate = null; + } } } } else { diff --git a/src/com/android/email/activity/setup/MailboxSettings.java b/src/com/android/email/activity/setup/MailboxSettings.java index 42ae407dd..d6b649a36 100644 --- a/src/com/android/email/activity/setup/MailboxSettings.java +++ b/src/com/android/email/activity/setup/MailboxSettings.java @@ -17,6 +17,7 @@ package com.android.email.activity.setup; import android.app.ActionBar; +import android.app.Activity; import android.app.LoaderManager; import android.content.ContentUris; import android.content.ContentValues; @@ -26,17 +27,29 @@ import android.content.Intent; import android.content.Loader; import android.content.res.Resources; import android.database.Cursor; +import android.media.Ringtone; +import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; +import android.os.Vibrator; import android.preference.CheckBoxPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; +import android.provider.Settings; import android.support.annotation.NonNull; +import android.support.v4.util.Pair; import android.text.TextUtils; +import android.view.LayoutInflater; import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; import com.android.email.R; import com.android.emailcommon.Logging; @@ -47,14 +60,18 @@ import com.android.emailcommon.provider.Mailbox; import com.android.emailcommon.provider.Policy; import com.android.emailcommon.utility.EmailAsyncTask; import com.android.emailcommon.utility.Utility; +import com.android.mail.preferences.FolderPreferences; import com.android.mail.providers.Folder; import com.android.mail.providers.UIProvider; import com.android.mail.ui.MailAsyncTaskLoader; import com.android.mail.utils.LogUtils; import com.google.common.base.Preconditions; +import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -70,21 +87,30 @@ import java.util.Map; * #onDestroy()}, unless it's called for configuration changes. */ public class MailboxSettings extends PreferenceActivity { + public static final String PREFERENCE_SYNC_SETTINGS = "account_sync_settings"; + public static final String PREFERENCE_PER_FOLDER_NOTIFICATIONS = + "account_per_folder_notifications"; + private static final String EXTRA_FOLDERS_URI = "FOLDERS_URI"; private static final String EXTRA_INBOX_ID = "INBOX_ID"; + private static final String EXTRA_TYPE = "TYPE"; + + private static final String EXTRA_HEADER_FOLDER_INDENT = "folder-indent"; private static final int FOLDERS_LOADER_ID = 0; private Uri mFoldersUri; private int mInboxId; - private final List mFolders = new ArrayList<>(); + private String mType; + private final List> mFolders = new ArrayList<>(); /** * Starts the activity */ - public static Intent getIntent(Context context, Uri foldersUri, Folder inbox) { + public static Intent getIntent(Context context, Uri foldersUri, Folder inbox, String type) { final Intent i = new Intent(context, MailboxSettings.class); i.putExtra(EXTRA_FOLDERS_URI, foldersUri); i.putExtra(EXTRA_INBOX_ID, inbox.id); + i.putExtra(EXTRA_TYPE, type); return i; } @@ -93,6 +119,7 @@ public class MailboxSettings extends PreferenceActivity { // This needs to happen before super.onCreate() since that calls onBuildHeaders() mInboxId = getIntent().getIntExtra(EXTRA_INBOX_ID, -1); mFoldersUri = getIntent().getParcelableExtra(EXTRA_FOLDERS_URI); + mType = getIntent().getStringExtra(EXTRA_TYPE); if (mFoldersUri != null) { getLoaderManager().initLoader(FOLDERS_LOADER_ID, null, @@ -108,6 +135,11 @@ public class MailboxSettings extends PreferenceActivity { // Hide the app icon. actionBar.setIcon(android.R.color.transparent); actionBar.setDisplayUseLogoEnabled(false); + if (mType != null && mType.equals(PREFERENCE_SYNC_SETTINGS)) { + actionBar.setTitle(getString(R.string.mailbox_settings_activity_title)); + } else if (mType != null && mType.equals(PREFERENCE_PER_FOLDER_NOTIFICATIONS)) { + actionBar.setTitle(getString(R.string.mailbox_notify_settings_activity_title)); + } } } @@ -117,25 +149,28 @@ public class MailboxSettings extends PreferenceActivity { final Header dummy = new Header(); dummy.titleRes = R.string.mailbox_name_display_inbox; dummy.fragment = MailboxSettingsFragment.class.getName(); - dummy.fragmentArguments = MailboxSettingsFragment.getArguments(mInboxId); - target.add(dummy); + dummy.fragmentArguments = MailboxSettingsFragment.getArguments(mInboxId, null); + } else { - for (final Folder f : mFolders) { + for (final Pair f : mFolders) { final Header h = new Header(); - if (!TextUtils.isEmpty(f.hierarchicalDesc)) { - h.title = f.hierarchicalDesc; - } else { - h.title = f.name; - } - h.fragment = MailboxSettingsFragment.class.getName(); - h.fragmentArguments = MailboxSettingsFragment.getArguments(f.id); - if (f.id == mInboxId) { - target.add(0, h); - } else { - target.add(h); + h.title = f.first.name; + setMailboxHeaderIcon(h, f.first); + h.extras = new Bundle(); + h.extras.putInt(EXTRA_HEADER_FOLDER_INDENT, f.second.split("\\/").length - 1); + if (mType != null && mType.equals(PREFERENCE_SYNC_SETTINGS)) { + h.fragment = MailboxSettingsFragment.class.getName(); + h.fragmentArguments = MailboxSettingsFragment.getArguments(f.first.id, mType); + } else if (mType != null && mType.equals(PREFERENCE_PER_FOLDER_NOTIFICATIONS)) { + h.fragment = MailboxNotificationsFragment.class.getName(); + h.fragmentArguments = MailboxNotificationsFragment.getArguments( + f.first, mType); } + target.add(h); } } + + setListAdapter(new MailboxHeadersAdapter(this, target)); } @Override @@ -153,6 +188,17 @@ public class MailboxSettings extends PreferenceActivity { return super.onOptionsItemSelected(item); } + private void setMailboxHeaderIcon(Header header, Folder folder) { + if (folder.isSent()) { + header.iconRes = R.drawable.ic_drawer_sent_24dp; + } else if (folder.isInbox()) { + header.iconRes = R.drawable.ic_drawer_inbox_24dp; + } else { + header.iconRes = folder.hasChildren ? R.drawable.ic_folder_parent_24dp + : R.drawable.ic_drawer_folder_24dp; + } + } + /** * Setup the entries and entry values for the sync lookback preference * @param context the caller's context @@ -190,6 +236,49 @@ public class MailboxSettings extends PreferenceActivity { pref.setSummary(pref.getEntry()); } + private static class MailboxHeadersAdapter extends ArrayAdapter
{ + private static class HeaderViewHolder { + View spacer; + ImageView icon; + TextView title; + } + + private LayoutInflater mInflater; + private int mFolderIndent; + + public MailboxHeadersAdapter(Context context, List
objects) { + super(context, 0, objects); + mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mFolderIndent = (int) context.getResources().getDimension(R.dimen.child_folder_indent); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + HeaderViewHolder holder; + View view; + + if (convertView == null) { + view = mInflater.inflate(R.layout.preference_mailbox_item, parent, false); + holder = new HeaderViewHolder(); + holder.spacer = view.findViewById(R.id.spacer); + holder.icon = (ImageView) view.findViewById(R.id.icon); + holder.title = (TextView) view.findViewById(android.R.id.title); + view.setTag(holder); + } else { + view = convertView; + holder = (HeaderViewHolder) view.getTag(); + } + + // All view fields must be updated every time, because the view may be recycled + Header header = getItem(position); + int headerIndent = header.extras.getInt(EXTRA_HEADER_FOLDER_INDENT, 0); + holder.spacer.getLayoutParams().width = mFolderIndent * headerIndent; + holder.icon.setImageResource(header.iconRes); + holder.title.setText(header.getTitle(getContext().getResources())); + return view; + } + } + private class MailboxSettingsFolderLoaderCallbacks implements LoaderManager.LoaderCallbacks { @@ -206,14 +295,69 @@ public class MailboxSettings extends PreferenceActivity { } mFolders.clear(); + // Convert the cursor to an temp array and map all the folders + Map folders = new HashMap<>(); + List tmp = new ArrayList<>(); + Folder inbox = null; + Folder sent = null; while(cursor.moveToNext()) { final Folder folder = new Folder(cursor); if (!folder.supportsCapability(UIProvider.FolderCapabilities.IS_VIRTUAL) && !folder.isTrash() && !folder.isDraft() && !folder.isOutbox()) { - mFolders.add(folder); + if (folder.id == mInboxId) { + inbox = folder; + } else if (folder.isSent()) { + sent = folder; + } + tmp.add(folder); + folders.put(folder.folderUri.fullUri, folder); } } + // Create the hierarchical paths of all the folders + int count = tmp.size(); + for (int i = 0; i < count; i++) { + Folder folder = tmp.get(i); + mFolders.add(new Pair(folder, + getHierarchicalFolder(folder, folders))); + } + + // Sort folders by hierarchical path + final String inboxFolderName = inbox.name; + final String sentFolderName = sent.name; + Collections.sort(mFolders, new Comparator>() { + private final Collator mCollator = Collator.getInstance(); + @Override + public int compare(Pair lhs, Pair rhs) { + boolean lInbox = lhs.second.startsWith(inboxFolderName); + boolean rInbox = rhs.second.startsWith(inboxFolderName); + boolean lSent = lhs.second.startsWith(sentFolderName); + boolean rSent = rhs.second.startsWith(sentFolderName); + String lParent = getHierarchicalParentFolder(lhs.second); + String rParent = getHierarchicalParentFolder(rhs.second); + if (lInbox && !rInbox) { + return -1; + } else if (!lInbox && rInbox) { + return 1; + } + if (lSent && !rSent) { + return -1; + } else if (!lSent && rSent) { + return 1; + } + if (lhs.second.startsWith(rhs.second)) { + return 1; + } + if (rhs.second.startsWith(lhs.second)) { + return -1; + } + if (lParent != null && rParent != null && lParent.equals(rParent)) { + return mCollator.compare(lhs.first.name, rhs.first.name); + } + return mCollator.compare(lhs.second, rhs.second); + } + }); + invalidateHeaders(); } @@ -221,6 +365,344 @@ public class MailboxSettings extends PreferenceActivity { public void onLoaderReset(Loader cursorLoader) { mFolders.clear(); } + + private String getHierarchicalFolder(Folder folder, Map folders) { + if (!TextUtils.isEmpty(folder.hierarchicalDesc)) { + return folder.hierarchicalDesc; + } + String name = folder.name; + Folder tmp = folder; + while (tmp != null && tmp.parent != null && !tmp.parent.toString().isEmpty()) { + tmp = folders.get(tmp.parent); + name = tmp.name + "/" + name; + } + return name; + } + + private String getHierarchicalParentFolder(String folder) { + int pos = folder.lastIndexOf("/"); + if (pos != -1) { + return folder.substring(0, pos); + } + return null; + } + } + + public static class MailboxNotificationsFragment extends PreferenceFragment { + private static final String EXTRA_MAILBOX_ID = "MailboxId"; + private static final String EXTRA_MAILBOX_PERSISTEND_ID = "MailboxPersistentId"; + private static final String EXTRA_MAILBOX_IS_INBOX = "MailboxIsInbox"; + + private static final String BUNDLE_ACCOUNT = "MailboxNotifySettings.account"; + private static final String BUNDLE_MAILBOX = "MailboxNotifySettings.mailbox"; + private static final String BUNDLE_NOTIF_ENABLED = "MailboxNotifySettings.enabled"; + private static final String BUNDLE_NOTIF_RINGTONE = "MailboxSettings.ringtone"; + private static final String BUNDLE_NOTIF_VIBRATE = "MailboxSettings.vibrate"; + + private static final String PREF_NOTIF_ENABLED_KEY = "notifications-enabled"; + private static final String PREF_NOTIF_RINGTONE_KEY = "notification-ringtone"; + private static final String PREF_NOTIF_VIBRATE_KEY = "notification-vibrate"; + + private static final int RINGTONE_REQUEST_CODE = + MailboxNotificationsFragment.class.hashCode(); + + private FolderPreferences mPreferences; + private Account mAccount; + private Mailbox mMailbox; + + private CheckBoxPreference mPrefNotifEnabled; + private Preference mPrefNotifRingtone; + private CheckBoxPreference mPrefNotifVibrate; + + private boolean mOldMailboxEnabled; + private String mOldMailboxRingtone; + private boolean mOldMailboxVibrate; + + private Uri mRingtoneUri; + private Ringtone mRingtone; + + private static Bundle getArguments(Folder folder, String type) { + final Bundle b = new Bundle(4); + b.putLong(EXTRA_MAILBOX_ID, folder.id); + b.putString(EXTRA_MAILBOX_PERSISTEND_ID, folder.persistentId); + b.putBoolean(EXTRA_MAILBOX_IS_INBOX, folder.isInbox()); + b.putString(EXTRA_TYPE, type); + return b; + } + + public MailboxNotificationsFragment() {} + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + final long mailboxId = getArguments().getLong(EXTRA_MAILBOX_ID, Mailbox.NO_MAILBOX); + final String mailboxPersistenId = getArguments().getString( + EXTRA_MAILBOX_PERSISTEND_ID, null); + final boolean mailboxIsInbox = getArguments().getBoolean(EXTRA_MAILBOX_IS_INBOX, false); + if (mailboxId == Mailbox.NO_MAILBOX || mailboxPersistenId == null) { + getActivity().finish(); + } + + addPreferencesFromResource(R.xml.mailbox_notifications_preferences); + + mPrefNotifEnabled = (CheckBoxPreference) findPreference(PREF_NOTIF_ENABLED_KEY); + mPrefNotifRingtone = findPreference(PREF_NOTIF_RINGTONE_KEY); + mPrefNotifRingtone.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + showRingtonePicker(); + return true; + } + }); + mPrefNotifVibrate = (CheckBoxPreference) findPreference(PREF_NOTIF_VIBRATE_KEY); + Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE); + if (!vibrator.hasVibrator()) { + mPrefNotifVibrate.setChecked(false); + getPreferenceScreen().removePreference(mPrefNotifVibrate); + mPrefNotifVibrate = null; + } + + if (savedInstanceState != null) { + mAccount = savedInstanceState.getParcelable(BUNDLE_ACCOUNT); + mMailbox = savedInstanceState.getParcelable(BUNDLE_MAILBOX); + mPreferences = new FolderPreferences(getActivity(), mAccount.mEmailAddress, + mailboxPersistenId, mailboxIsInbox); + + mPrefNotifEnabled.setChecked(savedInstanceState.getBoolean(BUNDLE_NOTIF_ENABLED)); + setRingtone(savedInstanceState.getString(BUNDLE_NOTIF_RINGTONE)); + if (mPrefNotifVibrate != null) { + mPrefNotifVibrate.setChecked( + savedInstanceState.getBoolean(BUNDLE_NOTIF_VIBRATE)); + } + onDataLoaded(); + } else { + // Make them disabled until we load data + enablePreferences(false); + getLoaderManager().initLoader(0, getArguments(), new MailboxLoaderCallbacks()); + } + } + + private void setRingtone(String ringtone) { + if (!TextUtils.isEmpty(ringtone)) { + mRingtoneUri = Uri.parse(ringtone); + mRingtone = RingtoneManager.getRingtone(getActivity(), mRingtoneUri); + } else { + mRingtoneUri = null; + mRingtone = null; + } + setRingtoneSummary(); + } + + private void setRingtoneSummary() { + final String summary = mRingtone != null ? mRingtone.getTitle(getActivity()) + : getString(R.string.silent_ringtone); + mPrefNotifRingtone.setSummary(summary); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == RINGTONE_REQUEST_CODE) { + if (resultCode == Activity.RESULT_OK && data != null) { + Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); + String ringtone = ""; + if (uri != null) { + ringtone = uri.toString(); + } + setRingtone(ringtone); + } + } + } + + private void enablePreferences(boolean enabled) { + mPrefNotifEnabled.setEnabled(enabled); + mPrefNotifRingtone.setEnabled(enabled); + if (mPrefNotifVibrate != null) { + mPrefNotifVibrate.setEnabled(enabled); + } + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(BUNDLE_ACCOUNT, mAccount); + outState.putParcelable(BUNDLE_MAILBOX, mMailbox); + outState.putBoolean(BUNDLE_NOTIF_ENABLED, mPrefNotifEnabled.isChecked()); + String ringtoneUri = ""; + if (mRingtoneUri != null) { + ringtoneUri = mRingtoneUri.toString(); + } + outState.putString(BUNDLE_NOTIF_RINGTONE, ringtoneUri); + outState.putBoolean(PREF_NOTIF_VIBRATE_KEY, mPrefNotifVibrate != null + ? mPrefNotifVibrate.isChecked() : false); + } + + /** + * We save all the settings in onDestroy, *unless it's for configuration changes*. + */ + @Override + public void onDestroy() { + super.onDestroy(); + if (!getActivity().isChangingConfigurations()) { + savePreferences(); + } + } + + private void loadOldPreferencesValues() { + mOldMailboxEnabled = mPreferences.areNotificationsEnabled(); + mOldMailboxRingtone = mPreferences.getNotificationRingtoneUri(); + mOldMailboxVibrate = mPreferences.isNotificationVibrateEnabled(); + } + + /** + * Shows the system ringtone picker. + */ + private void showRingtonePicker() { + Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); + final String ringtoneUri = mPreferences.getNotificationRingtoneUri(); + if (!TextUtils.isEmpty(ringtoneUri)) { + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, + Uri.parse(ringtoneUri)); + } + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, + Settings.System.DEFAULT_NOTIFICATION_URI); + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, + RingtoneManager.TYPE_NOTIFICATION); + startActivityForResult(intent, RINGTONE_REQUEST_CODE); + } + + /** + * Called when {@link #mMailbox} is loaded (either by the loader or from the saved state). + */ + private void onDataLoaded() { + Preconditions.checkNotNull(mAccount); + Preconditions.checkNotNull(mMailbox); + + // Update the title with the mailbox name. + final ActionBar actionBar = getActivity().getActionBar(); + final String mailboxName = mMailbox.mDisplayName; + if (actionBar != null) { + actionBar.setTitle(mailboxName); + actionBar.setSubtitle(getString(R.string.mailbox_notify_settings_activity_title)); + } else { + getActivity().setTitle( + getString(R.string.mailbox_notify_settings_activity_title_with_mailbox, + mailboxName)); + } + } + + /** + * Save changes to the preferences folder backend. + * + * Note it's called from {@link #onDestroy()} + */ + private void savePreferences() { + if (mPreferences == null) { + return; + } + + boolean mailboxEnabled = mPrefNotifEnabled.isChecked(); + String mailboxRingtone = ""; + if (mRingtoneUri != null) { + mailboxRingtone = mRingtoneUri.toString(); + } + boolean mailboxVibrate = mPrefNotifVibrate != null + ? mPrefNotifVibrate.isChecked() : false; + if (mailboxEnabled != mOldMailboxEnabled) { + mPreferences.setNotificationsEnabled(mailboxEnabled); + mOldMailboxEnabled = mailboxEnabled; + } + if (!mailboxRingtone.equals(mOldMailboxRingtone)) { + mPreferences.setNotificationRingtoneUri(mailboxRingtone); + mOldMailboxRingtone = mailboxRingtone; + } + if (mailboxVibrate != mOldMailboxVibrate) { + mPreferences.setNotificationVibrateEnabled(mailboxVibrate); + mOldMailboxVibrate = mailboxVibrate; + } + } + + private static class MailboxLoader extends MailAsyncTaskLoader> { + + public static final String RESULT_KEY_MAILBOX = "mailbox"; + public static final String RESULT_KEY_ACCOUNT = "account"; + + private final long mMailboxId; + + private MailboxLoader(Context context, long mailboxId) { + super(context); + mMailboxId = mailboxId; + } + + @Override + public Map loadInBackground() { + final Map result = new HashMap<>(); + + final Mailbox mailbox = Mailbox.restoreMailboxWithId(getContext(), mMailboxId); + if (mailbox == null) { + return null; + } + Account account = Account.restoreAccountWithId(getContext(), mailbox.mAccountKey); + if (account == null) { + return null; + } + result.put(RESULT_KEY_MAILBOX, mailbox); + result.put(RESULT_KEY_ACCOUNT, account); + return result; + } + + @Override + protected void onDiscardResult(Map result) {} + } + + private class MailboxLoaderCallbacks + implements LoaderManager.LoaderCallbacks> { + + private long mMailboxId; + private String mMailboxPersistentId; + private boolean mMailboxIsInbox; + + @Override + public Loader> onCreateLoader(int id, Bundle args) { + mMailboxId = getArguments().getLong(EXTRA_MAILBOX_ID, Mailbox.NO_MAILBOX); + mMailboxPersistentId = getArguments().getString(EXTRA_MAILBOX_PERSISTEND_ID, null); + mMailboxIsInbox = getArguments().getBoolean(EXTRA_MAILBOX_IS_INBOX, false); + return new MailboxLoader(getActivity(), mMailboxId); + } + + @Override + public void onLoadFinished(Loader> loader, + Map data) { + final Mailbox mailbox = (Mailbox) (data == null + ? null : data.get(MailboxLoader.RESULT_KEY_MAILBOX)); + final Account account = (Account) (data == null + ? null : data.get(MailboxLoader.RESULT_KEY_ACCOUNT)); + if (mailbox == null || account == null) { + getActivity().finish(); + return; + } + + mAccount = account; + mMailbox = mailbox; + mPreferences = new FolderPreferences(getActivity(), mAccount.mEmailAddress, + mMailboxPersistentId, mMailboxIsInbox); + loadOldPreferencesValues(); + + mPrefNotifEnabled.setChecked(mPreferences.areNotificationsEnabled()); + setRingtone(mPreferences.getNotificationRingtoneUri()); + if (mPrefNotifVibrate != null) { + mPrefNotifVibrate.setChecked(mPreferences.isNotificationVibrateEnabled()); + } + onDataLoaded(); + if (mMailbox.mType != Mailbox.TYPE_DRAFTS) { + enablePreferences(true); + } + } + + @Override + public void onLoaderReset(Loader> loader) {} + } } public static class MailboxSettingsFragment extends PreferenceFragment { @@ -241,9 +723,10 @@ public class MailboxSettings extends PreferenceActivity { private CheckBoxPreference mSyncEnabledPref; private ListPreference mSyncLookbackPref; - private static Bundle getArguments(long mailboxId) { + private static Bundle getArguments(long mailboxId, String type) { final Bundle b = new Bundle(1); b.putLong(EXTRA_MAILBOX_ID, mailboxId); + b.putString(EXTRA_TYPE, type); return b; }