478 lines
19 KiB
Java
478 lines
19 KiB
Java
/*
|
|
* Copyright (C) 2011 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.email.activity.setup;
|
|
|
|
import android.app.ActionBar;
|
|
import android.app.LoaderManager;
|
|
import android.content.ContentUris;
|
|
import android.content.ContentValues;
|
|
import android.content.Context;
|
|
import android.content.CursorLoader;
|
|
import android.content.Intent;
|
|
import android.content.Loader;
|
|
import android.content.res.Resources;
|
|
import android.database.Cursor;
|
|
import android.net.Uri;
|
|
import android.os.Bundle;
|
|
import android.preference.CheckBoxPreference;
|
|
import android.preference.ListPreference;
|
|
import android.preference.Preference;
|
|
import android.preference.Preference.OnPreferenceChangeListener;
|
|
import android.preference.PreferenceActivity;
|
|
import android.preference.PreferenceFragment;
|
|
import android.support.annotation.NonNull;
|
|
import android.text.TextUtils;
|
|
import android.view.MenuItem;
|
|
|
|
import com.android.email.R;
|
|
import com.android.emailcommon.Logging;
|
|
import com.android.emailcommon.provider.Account;
|
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
|
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
|
|
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.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.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* "Mailbox settings" activity.
|
|
*
|
|
* It's used to update per-mailbox sync settings. It normally updates Mailbox settings, unless
|
|
* the target mailbox is Inbox, in which case it updates Account settings instead.
|
|
*
|
|
* All changes made by the user will not be immediately saved to the database, as changing the
|
|
* sync window may result in removal of messages. Instead, we only save to the database in {@link
|
|
* #onDestroy()}, unless it's called for configuration changes.
|
|
*/
|
|
public class MailboxSettings extends PreferenceActivity {
|
|
private static final String EXTRA_FOLDERS_URI = "FOLDERS_URI";
|
|
private static final String EXTRA_INBOX_ID = "INBOX_ID";
|
|
|
|
private static final int FOLDERS_LOADER_ID = 0;
|
|
private Uri mFoldersUri;
|
|
private int mInboxId;
|
|
private final List<Folder> mFolders = new ArrayList<>();
|
|
|
|
/**
|
|
* Starts the activity
|
|
*/
|
|
public static Intent getIntent(Context context, Uri foldersUri, Folder inbox) {
|
|
final Intent i = new Intent(context, MailboxSettings.class);
|
|
i.putExtra(EXTRA_FOLDERS_URI, foldersUri);
|
|
i.putExtra(EXTRA_INBOX_ID, inbox.id);
|
|
return i;
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
// This needs to happen before super.onCreate() since that calls onBuildHeaders()
|
|
mInboxId = getIntent().getIntExtra(EXTRA_INBOX_ID, -1);
|
|
mFoldersUri = getIntent().getParcelableExtra(EXTRA_FOLDERS_URI);
|
|
|
|
if (mFoldersUri != null) {
|
|
getLoaderManager().initLoader(FOLDERS_LOADER_ID, null,
|
|
new MailboxSettingsFolderLoaderCallbacks());
|
|
}
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
// Always show "app up" as we expect our parent to be an Email activity.
|
|
ActionBar actionBar = getActionBar();
|
|
if (actionBar != null) {
|
|
actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);
|
|
// Hide the app icon.
|
|
actionBar.setIcon(android.R.color.transparent);
|
|
actionBar.setDisplayUseLogoEnabled(false);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onBuildHeaders(List<Header> target) {
|
|
if (mFolders.isEmpty()) {
|
|
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);
|
|
} else {
|
|
for (final Folder 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected boolean isValidFragment(String fragmentName) {
|
|
// Activity is not exported
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
if (item.getItemId() == android.R.id.home) {
|
|
onBackPressed();
|
|
return true;
|
|
}
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
|
|
/**
|
|
* Setup the entries and entry values for the sync lookback preference
|
|
* @param context the caller's context
|
|
* @param pref a ListPreference to be set up
|
|
* @param maxLookback The maximum lookback allowed, or 0 if no max.
|
|
* @param showWithDefault Whether to show the version with default, or without.
|
|
*/
|
|
public static void setupLookbackPreferenceOptions(final Context context,
|
|
final ListPreference pref, final int maxLookback, final boolean showWithDefault) {
|
|
final Resources resources = context.getResources();
|
|
// Load the complete list of entries/values
|
|
CharSequence[] entries;
|
|
CharSequence[] values;
|
|
final int offset;
|
|
if (showWithDefault) {
|
|
entries = resources.getTextArray(
|
|
R.array.account_settings_mail_window_entries_with_default);
|
|
values = resources.getTextArray(
|
|
R.array.account_settings_mail_window_values_with_default);
|
|
offset = 1;
|
|
} else {
|
|
entries = resources.getTextArray(R.array.account_settings_mail_window_entries);
|
|
values = resources.getTextArray(R.array.account_settings_mail_window_values);
|
|
offset = 0;
|
|
}
|
|
// If we have a maximum lookback policy, enforce it
|
|
if (maxLookback > 0) {
|
|
final int size = maxLookback + offset;
|
|
entries = Arrays.copyOf(entries, size);
|
|
values = Arrays.copyOf(values, size);
|
|
}
|
|
// Set up the preference
|
|
pref.setEntries(entries);
|
|
pref.setEntryValues(values);
|
|
pref.setSummary(pref.getEntry());
|
|
}
|
|
|
|
private class MailboxSettingsFolderLoaderCallbacks
|
|
implements LoaderManager.LoaderCallbacks<Cursor> {
|
|
|
|
@Override
|
|
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
|
|
return new CursorLoader(MailboxSettings.this, mFoldersUri,
|
|
UIProvider.FOLDERS_PROJECTION, null, null, null);
|
|
}
|
|
|
|
@Override
|
|
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
|
|
if (cursor == null) {
|
|
return;
|
|
}
|
|
mFolders.clear();
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
invalidateHeaders();
|
|
}
|
|
|
|
@Override
|
|
public void onLoaderReset(Loader<Cursor> cursorLoader) {
|
|
mFolders.clear();
|
|
}
|
|
}
|
|
|
|
public static class MailboxSettingsFragment extends PreferenceFragment {
|
|
private static final String EXTRA_MAILBOX_ID = "MailboxId";
|
|
|
|
private static final String BUNDLE_MAILBOX = "MailboxSettings.mailbox";
|
|
private static final String BUNDLE_MAX_LOOKBACK = "MailboxSettings.maxLookback";
|
|
private static final String BUNDLE_SYNC_ENABLED_VALUE = "MailboxSettings.syncEnabled";
|
|
private static final String BUNDLE_SYNC_WINDOW_VALUE = "MailboxSettings.syncWindow";
|
|
|
|
private static final String PREF_SYNC_ENABLED_KEY = "sync_enabled";
|
|
private static final String PREF_SYNC_WINDOW_KEY = "sync_window";
|
|
|
|
private Mailbox mMailbox;
|
|
/** The maximum lookback allowed for this mailbox, or 0 if no max. */
|
|
private int mMaxLookback;
|
|
|
|
private CheckBoxPreference mSyncEnabledPref;
|
|
private ListPreference mSyncLookbackPref;
|
|
|
|
private static Bundle getArguments(long mailboxId) {
|
|
final Bundle b = new Bundle(1);
|
|
b.putLong(EXTRA_MAILBOX_ID, mailboxId);
|
|
return b;
|
|
}
|
|
|
|
public MailboxSettingsFragment() {}
|
|
|
|
@Override
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
super.onActivityCreated(savedInstanceState);
|
|
final long mailboxId = getArguments().getLong(EXTRA_MAILBOX_ID, Mailbox.NO_MAILBOX);
|
|
if (mailboxId == Mailbox.NO_MAILBOX) {
|
|
getActivity().finish();
|
|
}
|
|
|
|
addPreferencesFromResource(R.xml.mailbox_preferences);
|
|
|
|
mSyncEnabledPref = (CheckBoxPreference) findPreference(PREF_SYNC_ENABLED_KEY);
|
|
mSyncLookbackPref = (ListPreference) findPreference(PREF_SYNC_WINDOW_KEY);
|
|
|
|
mSyncLookbackPref.setOnPreferenceChangeListener(mPreferenceChanged);
|
|
|
|
if (savedInstanceState != null) {
|
|
mMailbox = savedInstanceState.getParcelable(BUNDLE_MAILBOX);
|
|
mMaxLookback = savedInstanceState.getInt(BUNDLE_MAX_LOOKBACK);
|
|
mSyncEnabledPref
|
|
.setChecked(savedInstanceState.getBoolean(BUNDLE_SYNC_ENABLED_VALUE));
|
|
mSyncLookbackPref.setValue(savedInstanceState.getString(BUNDLE_SYNC_WINDOW_VALUE));
|
|
onDataLoaded();
|
|
} else {
|
|
// Make them disabled until we load data
|
|
enablePreferences(false);
|
|
getLoaderManager().initLoader(0, getArguments(), new MailboxLoaderCallbacks());
|
|
}
|
|
}
|
|
|
|
private void enablePreferences(boolean enabled) {
|
|
mSyncEnabledPref.setEnabled(enabled);
|
|
mSyncLookbackPref.setEnabled(enabled);
|
|
}
|
|
|
|
@Override
|
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
|
super.onSaveInstanceState(outState);
|
|
outState.putParcelable(BUNDLE_MAILBOX, mMailbox);
|
|
outState.putInt(BUNDLE_MAX_LOOKBACK, mMaxLookback);
|
|
outState.putBoolean(BUNDLE_SYNC_ENABLED_VALUE, mSyncEnabledPref.isChecked());
|
|
outState.putString(BUNDLE_SYNC_WINDOW_VALUE, mSyncLookbackPref.getValue());
|
|
}
|
|
|
|
/**
|
|
* We save all the settings in onDestroy, *unless it's for configuration changes*.
|
|
*/
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
if (!getActivity().isChangingConfigurations()) {
|
|
saveToDatabase();
|
|
}
|
|
}
|
|
|
|
private static class MailboxLoader extends MailAsyncTaskLoader<Map<String, Object>> {
|
|
/** Projection for loading an account's policy key. */
|
|
private static final String[] POLICY_KEY_PROJECTION =
|
|
{ AccountColumns.POLICY_KEY };
|
|
private static final int POLICY_KEY_COLUMN = 0;
|
|
|
|
/** Projection for loading the max email lookback. */
|
|
private static final String[] MAX_EMAIL_LOOKBACK_PROJECTION =
|
|
{ Policy.MAX_EMAIL_LOOKBACK };
|
|
private static final int MAX_EMAIL_LOOKBACK_COLUMN = 0;
|
|
|
|
public static final String RESULT_KEY_MAILBOX = "mailbox";
|
|
public static final String RESULT_KEY_MAX_LOOKBACK = "maxLookback";
|
|
|
|
private final long mMailboxId;
|
|
|
|
private MailboxLoader(Context context, long mailboxId) {
|
|
super(context);
|
|
mMailboxId = mailboxId;
|
|
}
|
|
|
|
@Override
|
|
public Map<String, Object> loadInBackground() {
|
|
final Map<String, Object> result = new HashMap<>();
|
|
|
|
final Mailbox mailbox = Mailbox.restoreMailboxWithId(getContext(), mMailboxId);
|
|
result.put(RESULT_KEY_MAILBOX, mailbox);
|
|
result.put(RESULT_KEY_MAX_LOOKBACK, 0);
|
|
|
|
if (mailbox == null) {
|
|
return result;
|
|
}
|
|
|
|
// Get the max lookback from our policy, if we have one.
|
|
final Long policyKey = Utility.getFirstRowLong(getContext(),
|
|
ContentUris.withAppendedId(Account.CONTENT_URI, mailbox.mAccountKey),
|
|
POLICY_KEY_PROJECTION, null, null, null, POLICY_KEY_COLUMN);
|
|
if (policyKey == null) {
|
|
// No policy, nothing to look up.
|
|
return result;
|
|
}
|
|
|
|
final int maxLookback = Utility.getFirstRowInt(getContext(),
|
|
ContentUris.withAppendedId(Policy.CONTENT_URI, policyKey),
|
|
MAX_EMAIL_LOOKBACK_PROJECTION, null, null, null,
|
|
MAX_EMAIL_LOOKBACK_COLUMN, 0);
|
|
result.put(RESULT_KEY_MAX_LOOKBACK, maxLookback);
|
|
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
protected void onDiscardResult(Map<String, Object> result) {}
|
|
}
|
|
|
|
private class MailboxLoaderCallbacks
|
|
implements LoaderManager.LoaderCallbacks<Map<String, Object>> {
|
|
@Override
|
|
public Loader<Map<String, Object>> onCreateLoader(int id, Bundle args) {
|
|
final long mailboxId = args.getLong(EXTRA_MAILBOX_ID);
|
|
return new MailboxLoader(getActivity(), mailboxId);
|
|
}
|
|
|
|
@Override
|
|
public void onLoadFinished(Loader<Map<String, Object>> loader,
|
|
Map<String, Object> data) {
|
|
final Mailbox mailbox = (Mailbox)
|
|
(data == null ? null : data.get(MailboxLoader.RESULT_KEY_MAILBOX));
|
|
if (mailbox == null) {
|
|
getActivity().finish();
|
|
return;
|
|
}
|
|
|
|
mMailbox = mailbox;
|
|
mMaxLookback = (Integer) data.get(MailboxLoader.RESULT_KEY_MAX_LOOKBACK);
|
|
|
|
mSyncEnabledPref.setChecked(mMailbox.mSyncInterval != 0);
|
|
mSyncLookbackPref.setValue(String.valueOf(mMailbox.mSyncLookback));
|
|
onDataLoaded();
|
|
if (mMailbox.mType != Mailbox.TYPE_DRAFTS) {
|
|
enablePreferences(true);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onLoaderReset(Loader<Map<String, Object>> loader) {}
|
|
}
|
|
|
|
/**
|
|
* Called when {@link #mMailbox} is loaded (either by the loader or from the saved state).
|
|
*/
|
|
private void onDataLoaded() {
|
|
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_settings_activity_title));
|
|
} else {
|
|
getActivity().setTitle(
|
|
getString(R.string.mailbox_settings_activity_title_with_mailbox,
|
|
mailboxName));
|
|
}
|
|
|
|
MailboxSettings.setupLookbackPreferenceOptions(getActivity(), mSyncLookbackPref,
|
|
mMaxLookback, true);
|
|
}
|
|
|
|
|
|
private final OnPreferenceChangeListener mPreferenceChanged =
|
|
new OnPreferenceChangeListener() {
|
|
@Override
|
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
mSyncLookbackPref.setValue((String) newValue);
|
|
mSyncLookbackPref.setSummary(mSyncLookbackPref.getEntry());
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Save changes to the database.
|
|
*
|
|
* Note it's called from {@link #onDestroy()}, which is called on the UI thread where we're
|
|
* not allowed to touch the database, so it uses {@link EmailAsyncTask} to do the save on a
|
|
* bg thread. This unfortunately means there's a chance that the app gets killed before the
|
|
* save is finished.
|
|
*/
|
|
private void saveToDatabase() {
|
|
if (mMailbox == null) {
|
|
// We haven't loaded yet, nothing to save.
|
|
return;
|
|
}
|
|
final int syncInterval = mSyncEnabledPref.isChecked() ? 1 : 0;
|
|
final int syncLookback = Integer.valueOf(mSyncLookbackPref.getValue());
|
|
|
|
final boolean syncIntervalChanged = syncInterval != mMailbox.mSyncInterval;
|
|
final boolean syncLookbackChanged = syncLookback != mMailbox.mSyncLookback;
|
|
|
|
// Only save if a preference has changed value.
|
|
if (!syncIntervalChanged && !syncLookbackChanged) {
|
|
return;
|
|
}
|
|
|
|
LogUtils.i(Logging.LOG_TAG, "Saving mailbox settings...");
|
|
enablePreferences(false);
|
|
|
|
final long id = mMailbox.mId;
|
|
final Context context = getActivity().getApplicationContext();
|
|
|
|
new EmailAsyncTask<Void, Void, Void> (null /* no cancel */) {
|
|
@Override
|
|
protected Void doInBackground(Void... params) {
|
|
final ContentValues cv = new ContentValues(2);
|
|
final Uri uri;
|
|
if (syncIntervalChanged) {
|
|
cv.put(MailboxColumns.SYNC_INTERVAL, syncInterval);
|
|
}
|
|
if (syncLookbackChanged) {
|
|
cv.put(MailboxColumns.SYNC_LOOKBACK, syncLookback);
|
|
}
|
|
uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, id);
|
|
context.getContentResolver().update(uri, cv, null, null);
|
|
|
|
LogUtils.i(Logging.LOG_TAG, "Saved: " + uri);
|
|
return null;
|
|
}
|
|
}.executeSerial((Void [])null);
|
|
}
|
|
}
|
|
}
|