Reimplement QuickResponse support

b/8622751

Change-Id: Id079efcf34dce15b5f5057f937582c0e198d3d50
This commit is contained in:
Tony Mantler 2013-08-14 11:05:19 -07:00
parent 2127d4dd09
commit c6953b7755
13 changed files with 309 additions and 347 deletions

View File

@ -78,7 +78,7 @@
<meta-data android:name="android.app.default_searchable"
android:value="com.android.email2.ui.MailActivityEmail" />
<activity
android:name="com.android.mail.compose.ComposeActivity"
android:name="com.android.email.activity.ComposeActivityEmail"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light">
<intent-filter>
@ -132,6 +132,9 @@
</intent-filter>
</activity>
<activity-alias android:name="com.android.mail.compose.ComposeActivity"
android:targetActivity="com.android.email.activity.ComposeActivityEmail"/>
<activity
android:name=".activity.EventViewer"
android:label="@string/app_name"

View File

@ -1589,16 +1589,6 @@ public abstract class EmailContent {
static final String ACCOUNT_KEY = "accountKey";
}
public static final int QUICK_RESPONSE_COLUMN_ID = 0;
public static final int QUICK_RESPONSE_COLUMN_TEXT = 1;
public static final int QUICK_RESPONSE_COLUMN_ACCOUNT = 2;
public static final String [] QUICK_RESPONSE_PROJECTION = new String [] {
QuickResponseColumns.ID,
QuickResponseColumns.TEXT,
QuickResponseColumns.ACCOUNT_KEY
};
public interface MailboxColumns {
public static final String ID = "_id";
// The display name of this mailbox [INDEX]

View File

@ -17,23 +17,16 @@
package com.android.emailcommon.provider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.emailcommon.provider.EmailContent.QuickResponseColumns;
import com.google.common.base.Objects;
/**
* A user-modifiable message that may be quickly inserted into the body while user is composing
* a message. Tied to a specific account.
*/
public final class QuickResponse extends EmailContent
implements QuickResponseColumns, Parcelable {
public abstract class QuickResponse extends EmailContent
implements QuickResponseColumns {
public static final String TABLE_NAME = "QuickResponse";
public static Uri CONTENT_URI;
public static Uri ACCOUNT_ID_URI;
@ -42,178 +35,4 @@ public final class QuickResponse extends EmailContent
CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/quickresponse");
ACCOUNT_ID_URI = Uri.parse(EmailContent.CONTENT_URI + "/quickresponse/account");
}
private String mText;
private long mAccountKey;
private static final int CONTENT_ID_COLUMN = 0;
private static final int CONTENT_QUICK_RESPONSE_COLUMN = 1;
private static final int CONTENT_ACCOUNT_KEY_COLUMN = 2;
public static final String[] CONTENT_PROJECTION = new String[] {
RECORD_ID,
QuickResponseColumns.TEXT,
QuickResponseColumns.ACCOUNT_KEY
};
/**
* Creates an empty QuickResponse. Restore should be called after.
*/
private QuickResponse() {
// empty
}
/**
* Constructor used by CREATOR for parceling.
*/
private QuickResponse(Parcel in) {
mBaseUri = CONTENT_URI;
mId = in.readLong();
mText = in.readString();
mAccountKey = in.readLong();
}
/**
* Creates QuickResponse associated with a particular account using the given string.
*/
public QuickResponse(long accountKey, String quickResponse) {
mBaseUri = CONTENT_URI;
mAccountKey = accountKey;
mText = quickResponse;
}
/**
* @see com.android.emailcommon.provider.EmailContent#restore(android.database.Cursor)
*/
@Override
public void restore(Cursor cursor) {
mBaseUri = CONTENT_URI;
mId = cursor.getLong(CONTENT_ID_COLUMN);
mText = cursor.getString(CONTENT_QUICK_RESPONSE_COLUMN);
mAccountKey = cursor.getLong(CONTENT_ACCOUNT_KEY_COLUMN);
}
/**
* @see com.android.emailcommon.provider.EmailContent#toContentValues()
*/
@Override
public ContentValues toContentValues() {
ContentValues values = new ContentValues();
values.put(QuickResponseColumns.TEXT, mText);
values.put(QuickResponseColumns.ACCOUNT_KEY, mAccountKey);
return values;
}
@Override
public String toString() {
return mText;
}
/**
* Given an array of QuickResponses, returns the an array of the String values
* corresponding to each QuickResponse.
*/
public static String[] getQuickResponseStrings(QuickResponse[] quickResponses) {
int count = quickResponses.length;
String[] quickResponseStrings = new String[count];
for (int i = 0; i < count; i++) {
quickResponseStrings[i] = quickResponses[i].toString();
}
return quickResponseStrings;
}
/**
* @param context
* @param accountId
* @return array of QuickResponses for the account with id accountId
*/
public static QuickResponse[] restoreQuickResponsesWithAccountId(Context context,
long accountId) {
Uri uri = ContentUris.withAppendedId(ACCOUNT_ID_URI, accountId);
Cursor c = context.getContentResolver().query(uri, CONTENT_PROJECTION,
null, null, null);
try {
int count = c.getCount();
QuickResponse[] quickResponses = new QuickResponse[count];
for (int i = 0; i < count; ++i) {
c.moveToNext();
QuickResponse quickResponse = new QuickResponse();
quickResponse.restore(c);
quickResponses[i] = quickResponse;
}
return quickResponses;
} finally {
c.close();
}
}
/**
* Returns the base URI for this QuickResponse
*/
public Uri getBaseUri() {
return mBaseUri;
}
/**
* Returns the unique id for this QuickResponse
*/
public long getId() {
return mId;
}
@Override
public boolean equals(Object objectThat) {
if (this == objectThat) return true;
if (!(objectThat instanceof QuickResponse)) return false;
QuickResponse that = (QuickResponse) objectThat;
return
mText.equals(that.mText) &&
mId == that.mId &&
mAccountKey == that.mAccountKey;
}
@Override
public int hashCode() {
return Objects.hashCode(mId, mText, mAccountKey);
}
/**
* Implements Parcelable. Not used.
*/
@Override
public int describeContents() {
return 0;
}
/**
* Implements Parcelable.
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
// mBaseUri is not parceled
dest.writeLong(mId);
dest.writeString(mText);
dest.writeLong(mAccountKey);
}
/**
* Implements Parcelable
*/
public static final Parcelable.Creator<QuickResponse> CREATOR
= new Parcelable.Creator<QuickResponse>() {
@Override
public QuickResponse createFromParcel(Parcel in) {
return new QuickResponse(in);
}
@Override
public QuickResponse[] newArray(int size) {
return new QuickResponse[size];
}
};
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 Google Inc.
Licensed to 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/insert_quick_response_menu_item"
android:title="@string/message_compose_insert_quick_response_menu_title"/>
</menu>

View File

@ -312,6 +312,8 @@
<!-- Title for dialog containing list of quick responses that user may insert
into message body. [CHAR_LIMIT=30] -->
<string name="message_compose_insert_quick_response_list_title">Insert quick response</string>
<!-- Menu item for inserting quick responses into email compose activity. [CHAR_LIMIT=30] -->
<string name="message_compose_insert_quick_response_menu_title">Insert quick response</string>
<!-- Display name for composed message, indicating the destination of the message.
e.g. "John and 2 others" -->
<string name="message_compose_display_name"><xliff:g id="name" example="John">%1$s</xliff:g> and <xliff:g id="number" example="27">%2$d</xliff:g> others</string>

View File

@ -0,0 +1,65 @@
/**
* Copyright (c) 2013, Google Inc.
*
* 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;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import com.android.email.R;
import com.android.mail.compose.ComposeActivity;
public class ComposeActivityEmail extends ComposeActivity
implements InsertQuickResponseDialog.Callback {
static final String insertQuickResponseDialogTag = "insertQuickResponseDialog";
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.email_compose_menu_extras, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.insert_quick_response_menu_item) {
InsertQuickResponseDialog dialog = InsertQuickResponseDialog.newInstance(null,
mReplyFromAccount.account);
dialog.show(getFragmentManager(), insertQuickResponseDialogTag);
}
return super.onOptionsItemSelected(item);
}
public void onQuickResponseSelected(CharSequence quickResponse) {
final int selEnd = mBodyView.getSelectionEnd();
final int selStart = mBodyView.getSelectionStart();
if (selEnd >= 0 && selStart >= 0) {
final SpannableStringBuilder messageBody =
new SpannableStringBuilder(mBodyView.getText());
final int replaceStart = selStart < selEnd ? selStart : selEnd;
final int replaceEnd = selStart < selEnd ? selEnd : selStart;
messageBody.replace(replaceStart, replaceEnd, quickResponse);
mBodyView.setText(messageBody);
mBodyView.setSelection(replaceStart + quickResponse.length());
} else {
mBodyView.append(quickResponse);
mBodyView.setSelection(mBodyView.getText().length());
}
}
}

View File

@ -17,30 +17,31 @@
package com.android.email.activity;
import com.android.email.R;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.mail.providers.Account;
import com.android.mail.providers.UIProvider;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.Context;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
/**
* Dialog which lists QuickResponses for the specified account. On user selection, will call
* Callback.onQuickResponseSelected() with the selected QuickResponse text.
*/
public class InsertQuickResponseDialog extends DialogFragment
implements DialogInterface.OnClickListener, OnItemClickListener {
private ListView mQuickResponsesView;
private EmailAsyncTask.Tracker mTaskTracker;
public class InsertQuickResponseDialog extends DialogFragment {
// Key for the Account object in the arguments bundle
private static final String ACCOUNT_KEY = "account";
@ -94,49 +95,59 @@ public class InsertQuickResponseDialog extends DialogFragment
// Now that Callback implementation is verified, build the dialog
final Context context = getActivity();
final SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),
R.layout.quick_response_item, null,
new String[] {UIProvider.QuickResponseColumns.TEXT},
new int[] {R.id.quick_response_text}, 0);
final ListView listView = new ListView(context);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Cursor c = (Cursor) listView.getItemAtPosition(position);
final String quickResponseText =
c.getString(c.getColumnIndex(UIProvider.QuickResponseColumns.TEXT));
getCallback().onQuickResponseSelected(quickResponseText);
dismiss();
}
});
final Account account = getArguments().getParcelable(ACCOUNT_KEY);
getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), account.quickResponseUri,
UIProvider.QUICK_RESPONSE_PROJECTION, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
});
final AlertDialog.Builder b = new AlertDialog.Builder(context);
mQuickResponsesView = new ListView(context);
Account account = (Account) getArguments().getParcelable(ACCOUNT_KEY);
mTaskTracker = new EmailAsyncTask.Tracker();
// TODO: fix everything
//new QuickResponseFinder(mTaskTracker, account.mId, mQuickResponsesView,
// context, null, this, false).executeParallel();
b.setTitle(getResources()
.getString(R.string.message_compose_insert_quick_response_list_title))
.setView(mQuickResponsesView)
.setNegativeButton(R.string.cancel_action, this);
.setView(listView)
.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
return b.create();
}
@Override
public void onDestroy() {
mTaskTracker.cancellAllInterrupt();
super.onDestroy();
}
/**
* Implements OnItemClickListener.
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
getCallback().onQuickResponseSelected(
mQuickResponsesView.getItemAtPosition(position).toString());
dismiss();
}
/**
* Implements DialogInterface.OnClickListener
*/
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_NEGATIVE) {
dialog.cancel();
}
}
private Callback getCallback() {
Fragment targetFragment = getTargetFragment();
if (targetFragment != null) {

View File

@ -599,7 +599,7 @@ public class AccountSettings extends PreferenceActivity implements FeedbackEnabl
AccountSettings.this.onSettingsChanged(account, preference, value);
}
@Override
public void onEditQuickResponses(Account account) {
public void onEditQuickResponses(com.android.mail.providers.Account account) {
AccountSettings.this.onEditQuickResponses(account);
}
@Override
@ -667,7 +667,7 @@ public class AccountSettings extends PreferenceActivity implements FeedbackEnabl
/**
* Dispatch to edit quick responses.
*/
public void onEditQuickResponses(Account account) {
public void onEditQuickResponses(com.android.mail.providers.Account account) {
try {
Bundle args = new Bundle();
args.putParcelable(QUICK_RESPONSE_ACCOUNT_KEY, account);

View File

@ -18,16 +18,13 @@ package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.Account;
import com.android.mail.utils.LogUtils;
import com.android.mail.providers.Account;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.Utils;
import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.ContentUris;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
@ -38,7 +35,6 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
@ -58,7 +54,6 @@ import android.widget.TextView;
*/
public class AccountSettingsEditQuickResponsesFragment extends Fragment {
private Account mAccount;
private SimpleCursorAdapter mAdapter;
private static final String BUNDLE_KEY_ACTIVITY_TITLE
= "AccountSettingsEditQuickResponsesFragment.title";
@ -80,31 +75,30 @@ public class AccountSettingsEditQuickResponsesFragment extends Fragment {
getActivity().setTitle(savedInstanceState.getString(BUNDLE_KEY_ACTIVITY_TITLE));
}
mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.quick_response_item, null,
new String [] {EmailContent.QuickResponseColumns.TEXT},
new int [] {R.id.quick_response_text}, 0);
final SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),
R.layout.quick_response_item, null,
new String[] {UIProvider.QuickResponseColumns.TEXT},
new int[] {R.id.quick_response_text}, 0);
final ListView listView = UiUtilities.getView(getView(),
R.id.account_settings_quick_responses_list);
listView.setAdapter(mAdapter);
listView.setAdapter(adapter);
getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
final Uri baseUri = Uri.parse(EmailContent.CONTENT_URI + "/quickresponse/account");
final Uri uri = ContentUris.withAppendedId(baseUri, mAccount.getId());
return new CursorLoader(getActivity(), uri, EmailContent.QUICK_RESPONSE_PROJECTION,
null, null, null);
return new CursorLoader(getActivity(), mAccount.quickResponseUri,
UIProvider.QUICK_RESPONSE_PROJECTION, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
adapter.swapCursor(null);
}
});
}
@ -116,9 +110,6 @@ public class AccountSettingsEditQuickResponsesFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
LogUtils.d(Logging.LOG_TAG, "AccountSettingsEditQuickResponsesFragment onCreate");
}
super.onCreate(savedInstanceState);
Bundle args = getArguments();
@ -130,9 +121,6 @@ public class AccountSettingsEditQuickResponsesFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
LogUtils.d(Logging.LOG_TAG, "AccountSettingsEditQuickResponsesFragment onCreateView");
}
final View view = inflater.inflate(R.layout.account_settings_edit_quick_responses_fragment,
container, false);
@ -145,12 +133,11 @@ public class AccountSettingsEditQuickResponsesFragment extends Fragment {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Cursor c = (Cursor) listView.getItemAtPosition(position);
final int quickResponseId = c.getInt(EmailContent.QUICK_RESPONSE_COLUMN_ID);
final String quickResponseText =
c.getString(EmailContent.QUICK_RESPONSE_COLUMN_TEXT);
final Uri baseUri = Uri.parse(EmailContent.CONTENT_URI + "/quickresponse");
final Uri uri = ContentUris.withAppendedId(baseUri, quickResponseId);
EditQuickResponseDialog.newInstance(quickResponseText, uri, mAccount.getId(), false)
c.getString(c.getColumnIndex(UIProvider.QuickResponseColumns.TEXT));
final Uri uri = Utils.getValidUri(
c.getString(c.getColumnIndex(UIProvider.QuickResponseColumns.URI)));
EditQuickResponseDialog.newInstance(quickResponseText, uri, false)
.show(getFragmentManager(), null);
}
});
@ -166,8 +153,7 @@ public class AccountSettingsEditQuickResponsesFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create_new) {
final Uri baseUri = Uri.parse(EmailContent.CONTENT_URI + "/quickresponse");
EditQuickResponseDialog.newInstance(null, baseUri, mAccount.getId(), true)
EditQuickResponseDialog.newInstance(null, mAccount.quickResponseUri, true)
.show(getFragmentManager(), null);
return true;
}

View File

@ -65,6 +65,8 @@ import com.android.mail.utils.LogUtils;
import com.android.mail.utils.NotificationUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* Fragment containing the main logic for account settings. This also calls out to other
@ -123,8 +125,14 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
private CheckBoxPreference mSyncEmail;
private Context mContext;
/**
* mAccount is email-specific, transition to using mUiAccount instead
*/
@Deprecated
private Account mAccount;
private boolean mAccountDirty;
private com.android.mail.providers.Account mUiAccount;
private Callback mCallback = EmptyCallback.INSTANCE;
private boolean mStarted;
private boolean mLoaded;
@ -146,7 +154,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
*/
public interface Callback {
public void onSettingsChanged(Account account, String preference, Object value);
public void onEditQuickResponses(Account account);
public void onEditQuickResponses(com.android.mail.providers.Account account);
public void onIncomingSettings(Account account);
public void onOutgoingSettings(Account account);
public void abandonEdit();
@ -155,7 +163,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
private static class EmptyCallback implements Callback {
public static final Callback INSTANCE = new EmptyCallback();
@Override public void onSettingsChanged(Account account, String preference, Object value) {}
@Override public void onEditQuickResponses(Account account) {}
@Override public void onEditQuickResponses(com.android.mail.providers.Account account) {}
@Override public void onIncomingSettings(Account account) {}
@Override public void onOutgoingSettings(Account account) {}
@Override public void abandonEdit() {}
@ -436,10 +444,13 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
/**
* Async task to load account in order to view/edit it
*/
private class LoadAccountTask extends AsyncTask<Long, Void, Account> {
private class LoadAccountTask extends AsyncTask<Long, Void, Map<String, Object>> {
static final String ACCOUNT_KEY = "account";
static final String UI_ACCOUNT_KEY = "uiAccount";
@Override
protected Account doInBackground(Long... params) {
long accountId = params[0];
protected Map<String, Object> doInBackground(Long... params) {
final long accountId = params[0];
Account account = Account.restoreAccountWithId(mContext, accountId);
if (account != null) {
account.mHostAuthRecv =
@ -450,12 +461,34 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
account = null;
}
}
return account;
final Cursor accountCursor = mContext.getContentResolver().query(EmailProvider
.uiUri("uiaccount", accountId), UIProvider.ACCOUNTS_PROJECTION, null,
null, null);
final com.android.mail.providers.Account uiAccount;
try {
if (accountCursor != null && accountCursor.moveToFirst()) {
uiAccount = new com.android.mail.providers.Account(accountCursor);
} else {
uiAccount = null;
}
} finally {
if (accountCursor != null) {
accountCursor.close();
}
}
final Map<String, Object> map = new HashMap<String, Object>(2);
map.put(ACCOUNT_KEY, account);
map.put(UI_ACCOUNT_KEY, uiAccount);
return map;
}
@Override
protected void onPostExecute(Account account) {
protected void onPostExecute(Map<String, Object> map) {
if (!isCancelled()) {
final Account account = (Account) map.get(ACCOUNT_KEY);
if (account == null) {
mSaveOnExit = false;
mCallback.abandonEdit();
@ -465,6 +498,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
loadSettings();
}
}
mUiAccount = (com.android.mail.providers.Account) map.get(UI_ACCOUNT_KEY);
}
}
}
@ -517,32 +551,17 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
/**
* Loads settings that are dependent on a {@link com.android.mail.providers.Account}, which
* must be obtained off the main thread. This will also call {@link #loadMainThreadSettings()}.
* must be obtained off the main thread.
*/
private void loadSettingsOffMainThread() {
new Thread(new Runnable() {
@Override
public void run() {
final Cursor accountCursor = mContext.getContentResolver().query(EmailProvider
.uiUri("uiaccount", mAccount.mId), UIProvider.ACCOUNTS_PROJECTION, null,
null, null);
if (accountCursor == null) {
if (mUiAccount == null) {
return;
}
final com.android.mail.providers.Account account;
try {
if (accountCursor.moveToFirst()) {
account = new com.android.mail.providers.Account(accountCursor);
} else {
return;
}
} finally {
accountCursor.close();
}
final Cursor folderCursor = mContext.getContentResolver().query(
account.settings.defaultInbox, UIProvider.FOLDERS_PROJECTION, null, null,
mUiAccount.settings.defaultInbox, UIProvider.FOLDERS_PROJECTION, null, null,
null);
if (folderCursor == null) {
return;
@ -559,9 +578,9 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
folderCursor.close();
}
mAccountPreferences = new AccountPreferences(mContext, account.name);
mAccountPreferences = new AccountPreferences(mContext, mUiAccount.name);
mInboxFolderPreferences =
new FolderPreferences(mContext, account.name, folder, true);
new FolderPreferences(mContext, mUiAccount.name, folder, true);
NotificationUtils.moveNotificationSetting(
mAccountPreferences, mInboxFolderPreferences);
@ -637,7 +656,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
@Override
public boolean onPreferenceClick(Preference preference) {
mAccountDirty = true;
mCallback.onEditQuickResponses(mAccount);
mCallback.onEditQuickResponses(mUiAccount);
return true;
}
});

View File

@ -17,15 +17,12 @@
package com.android.email.activity.setup;
import com.android.email.R;
import com.android.emailcommon.provider.QuickResponse;
import com.android.emailcommon.provider.EmailContent.QuickResponseColumns;
import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.mail.providers.UIProvider;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
@ -45,7 +42,6 @@ public class EditQuickResponseDialog extends DialogFragment {
private static final String QUICK_RESPONSE_STRING = "quick_response_edited_string";
private static final String QUICK_RESPONSE_CONTENT_URI = "quick_response_content_uri";
private static final String QUICK_RESPONSE_CREATE = "quick_response_create";
private static final String ACCOUNT_ID = "accountId";
// Public no-args constructor needed for fragment re-instantiation
public EditQuickResponseDialog() {}
@ -54,17 +50,16 @@ public class EditQuickResponseDialog extends DialogFragment {
* Creates a new dialog to edit an existing QuickResponse or create a new
* one.
*
* @param baseUri - The content Uri QuickResponse which the user is editing;
* @param accountId - The accountId for the account which holds this QuickResponse
* @param baseUri - The content Uri QuickResponse which the user is editing
* or the content Uri for creating a new QuickResponse
* @param create - True if this is a new QuickResponse
*/
public static EditQuickResponseDialog newInstance(String text,
Uri baseUri, long accountId, boolean create) {
Uri baseUri, boolean create) {
final EditQuickResponseDialog dialog = new EditQuickResponseDialog();
Bundle args = new Bundle(4);
args.putString(QUICK_RESPONSE_STRING, text);
args.putLong(ACCOUNT_ID, accountId);
args.putParcelable(QUICK_RESPONSE_CONTENT_URI, baseUri);
args.putBoolean(QUICK_RESPONSE_CREATE, create);
@ -74,7 +69,6 @@ public class EditQuickResponseDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final long accountId = getArguments().getLong(ACCOUNT_ID);
final Uri uri = getArguments().getParcelable(QUICK_RESPONSE_CONTENT_URI);
final boolean create = getArguments().getBoolean(QUICK_RESPONSE_CREATE);
@ -114,9 +108,8 @@ public class EditQuickResponseDialog extends DialogFragment {
@Override
public void onClick(DialogInterface dialog, int which) {
final String text = mQuickResponseEditText.getText().toString();
final ContentValues values = new ContentValues(2);
values.put(QuickResponseColumns.ACCOUNT_KEY, accountId);
values.put(QuickResponseColumns.TEXT, text);
final ContentValues values = new ContentValues(1);
values.put(UIProvider.QuickResponseColumns.TEXT, text);
if (create) {
getActivity().getContentResolver().insert(uri, values);

View File

@ -49,6 +49,7 @@ import android.provider.BaseColumns;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Base64;
import android.util.SparseArray;
import com.android.common.content.ProjectionMap;
import com.android.email.Preferences;
@ -88,7 +89,6 @@ import com.android.mail.providers.Folder;
import com.android.mail.providers.FolderList;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.AccountCapabilities;
import com.android.mail.providers.UIProvider.AccountColumns.SettingsColumns;
import com.android.mail.providers.UIProvider.AccountCursorExtraKeys;
import com.android.mail.providers.UIProvider.ConversationPriority;
import com.android.mail.providers.UIProvider.ConversationSendingState;
@ -112,6 +112,7 @@ import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -231,31 +232,28 @@ public class EmailProvider extends ContentProvider {
private static final int UI_DEFAULT_RECENT_FOLDERS = UI_BASE + 16;
private static final int UI_ALL_FOLDERS = UI_BASE + 17;
// MUST ALWAYS EQUAL THE LAST OF THE PREVIOUS BASE CONSTANTS
private static final int LAST_EMAIL_PROVIDER_DB_BASE = UI_BASE;
// DO NOT CHANGE BODY_BASE!!
private static final int BODY_BASE = LAST_EMAIL_PROVIDER_DB_BASE + 0x1000;
private static final int BODY_BASE = 0xA000;
private static final int BODY = BODY_BASE;
private static final int BODY_ID = BODY_BASE + 1;
private static final int BASE_SHIFT = 12; // 12 bits to the base type: 0, 0x1000, 0x2000, etc.
// TABLE_NAMES MUST remain in the order of the BASE constants above (e.g. ACCOUNT_BASE = 0x0000,
// MESSAGE_BASE = 0x1000, etc.)
private static final String[] TABLE_NAMES = {
Account.TABLE_NAME,
Mailbox.TABLE_NAME,
Message.TABLE_NAME,
Attachment.TABLE_NAME,
HostAuth.TABLE_NAME,
Message.UPDATED_TABLE_NAME,
Message.DELETED_TABLE_NAME,
Policy.TABLE_NAME,
QuickResponse.TABLE_NAME,
null, // UI
Body.TABLE_NAME,
};
private static final SparseArray<String> TABLE_NAMES;
static {
SparseArray<String> array = new SparseArray<String>(11);
array.put(ACCOUNT_BASE >> BASE_SHIFT, Account.TABLE_NAME);
array.put(MAILBOX_BASE >> BASE_SHIFT, Mailbox.TABLE_NAME);
array.put(MESSAGE_BASE >> BASE_SHIFT, Message.TABLE_NAME);
array.put(ATTACHMENT_BASE >> BASE_SHIFT, Attachment.TABLE_NAME);
array.put(HOSTAUTH_BASE >> BASE_SHIFT, HostAuth.TABLE_NAME);
array.put(UPDATED_MESSAGE_BASE >> BASE_SHIFT, Message.UPDATED_TABLE_NAME);
array.put(DELETED_MESSAGE_BASE >> BASE_SHIFT, Message.DELETED_TABLE_NAME);
array.put(POLICY_BASE >> BASE_SHIFT, Policy.TABLE_NAME);
array.put(QUICK_RESPONSE_BASE >> BASE_SHIFT, QuickResponse.TABLE_NAME);
array.put(UI_BASE >> BASE_SHIFT, null);
array.put(BODY_BASE >> BASE_SHIFT, Body.TABLE_NAME);
TABLE_NAMES = array;
}
private static UriMatcher sURIMatcher = null;
@ -503,7 +501,7 @@ public class EmailProvider extends ContentProvider {
boolean messageDeletion = false;
ContentResolver resolver = context.getContentResolver();
String tableName = TABLE_NAMES[table];
String tableName = TABLE_NAMES.valueAt(table);
int result = -1;
try {
@ -749,7 +747,7 @@ public class EmailProvider extends ContentProvider {
case HOSTAUTH:
case POLICY:
case QUICK_RESPONSE:
longId = db.insert(TABLE_NAMES[table], "foo", values);
longId = db.insert(TABLE_NAMES.valueAt(table), "foo", values);
resultUri = ContentUris.withAppendedId(uri, longId);
switch(match) {
case MESSAGE:
@ -793,6 +791,10 @@ public class EmailProvider extends ContentProvider {
break;
}
break;
case QUICK_RESPONSE_ACCOUNT_ID:
longId = Long.parseLong(uri.getPathSegments().get(2));
values.put(EmailContent.QuickResponseColumns.ACCOUNT_KEY, longId);
return insert(QuickResponse.CONTENT_URI, values);
case MAILBOX_ID:
// This implies adding a message to a mailbox
// Hmm, a problem here is that we can't link the account as well, so it must be
@ -812,7 +814,7 @@ public class EmailProvider extends ContentProvider {
values.put(MailboxColumns.ACCOUNT_KEY, longId);
return insert(Mailbox.CONTENT_URI, values); // Recurse
case ATTACHMENTS_MESSAGE_ID:
longId = db.insert(TABLE_NAMES[table], "foo", values);
longId = db.insert(TABLE_NAMES.valueAt(table), "foo", values);
resultUri = ContentUris.withAppendedId(Attachment.CONTENT_URI, longId);
break;
default:
@ -1038,7 +1040,7 @@ public class EmailProvider extends ContentProvider {
String limit = uri.getQueryParameter(EmailContent.PARAMETER_LIMIT);
String id;
String tableName = TABLE_NAMES[table];
String tableName = TABLE_NAMES.valueAt(table);
try {
switch (match) {
@ -1103,10 +1105,12 @@ public class EmailProvider extends ContentProvider {
case ACCOUNT:
case HOSTAUTH:
case POLICY:
case QUICK_RESPONSE:
c = db.query(tableName, projection,
selection, selectionArgs, null, null, sortOrder, limit);
break;
case QUICK_RESPONSE:
c = uiQuickResponse(projection);
break;
case BODY_ID:
case MESSAGE_ID:
case DELETED_MESSAGE_ID:
@ -1116,11 +1120,14 @@ public class EmailProvider extends ContentProvider {
case ACCOUNT_ID:
case HOSTAUTH_ID:
case POLICY_ID:
case QUICK_RESPONSE_ID:
id = uri.getPathSegments().get(1);
c = db.query(tableName, projection, whereWithId(id, selection),
selectionArgs, null, null, sortOrder, limit);
break;
case QUICK_RESPONSE_ID:
id = uri.getPathSegments().get(1);
c = uiQuickResponseId(projection, id);
break;
case ATTACHMENTS_MESSAGE_ID:
// All attachments for the given message
id = uri.getPathSegments().get(2);
@ -1131,9 +1138,7 @@ public class EmailProvider extends ContentProvider {
case QUICK_RESPONSE_ACCOUNT_ID:
// All quick responses for the given account
id = uri.getPathSegments().get(2);
c = db.query(QuickResponse.TABLE_NAME, projection,
whereWith(QuickResponse.ACCOUNT_KEY + "=" + id, selection),
selectionArgs, null, null, sortOrder);
c = uiQuickResponseAccount(projection, id);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
@ -1385,7 +1390,7 @@ public class EmailProvider extends ContentProvider {
values.remove(MailboxColumns.MESSAGE_COUNT);
}
String tableName = TABLE_NAMES[table];
String tableName = TABLE_NAMES.valueAt(table);
String id = "0";
try {
@ -2027,6 +2032,20 @@ public class EmailProvider extends ContentProvider {
}
private static ProjectionMap sAccountListMap;
private static ProjectionMap getQuickResponseMap() {
if (sQuickResponseMap == null) {
sQuickResponseMap = ProjectionMap.builder()
.add(UIProvider.QuickResponseColumns.TEXT,
EmailContent.QuickResponseColumns.TEXT)
.add(UIProvider.QuickResponseColumns.URI,
"'" + combinedUriString("quickresponse", "") + "'||"
+ EmailContent.QuickResponseColumns.ID)
.build();
}
return sQuickResponseMap;
}
private static ProjectionMap sQuickResponseMap;
/**
* The "ORDER BY" clause for top level folders
*/
@ -2514,6 +2533,7 @@ public class EmailProvider extends ContentProvider {
* Generate a "single account" SQLite query, given a projection from UnifiedEmail
*
* @param uiProjection as passed from UnifiedEmail
* @param id account row ID
* @return the SQLite query to be executed on the EmailProvider database
*/
private String genQueryAccount(String[] uiProjection, String id) {
@ -2641,6 +2661,10 @@ public class EmailProvider extends ContentProvider {
if (projectionColumns.contains(UIProvider.AccountColumns.SYNC_AUTHORITY)) {
values.put(UIProvider.AccountColumns.SYNC_AUTHORITY, EmailContent.AUTHORITY);
}
if (projectionColumns.contains(UIProvider.AccountColumns.QUICK_RESPONSE_URI)) {
values.put(UIProvider.AccountColumns.QUICK_RESPONSE_URI,
combinedUriString("quickresponse/account", id));
}
final StringBuilder sb = genSelect(getAccountListMap(getContext()), uiProjection, values);
sb.append(" FROM " + Account.TABLE_NAME + " WHERE " + AccountColumns.ID + "=?");
@ -2926,11 +2950,9 @@ public class EmailProvider extends ContentProvider {
db.rawQuery("select _id from " + Account.TABLE_NAME, new String[0]);
final MatrixCursor mc;
try {
int numAccounts = accountIdCursor.getCount();
boolean combinedAccount = false;
if (numAccounts > 1) {
if (accountIdCursor.getCount() > 1) {
combinedAccount = true;
numAccounts++;
}
final Bundle extras = new Bundle();
// Email always returns the accurate number of accounts
@ -2963,6 +2985,35 @@ public class EmailProvider extends ContentProvider {
return mc;
}
private Cursor uiQuickResponseAccount(String[] uiProjection, String account) {
final Context context = getContext();
final SQLiteDatabase db = getDatabase(context);
final StringBuilder sb = genSelect(getQuickResponseMap(), uiProjection);
sb.append(" FROM " + QuickResponse.TABLE_NAME);
sb.append(" WHERE " + QuickResponse.ACCOUNT_KEY + "=?");
final String query = sb.toString();
return db.rawQuery(query, new String[] {account});
}
private Cursor uiQuickResponseId(String[] uiProjection, String id) {
final Context context = getContext();
final SQLiteDatabase db = getDatabase(context);
final StringBuilder sb = genSelect(getQuickResponseMap(), uiProjection);
sb.append(" FROM " + QuickResponse.TABLE_NAME);
sb.append(" WHERE " + QuickResponse.ID + "=?");
final String query = sb.toString();
return db.rawQuery(query, new String[] {id});
}
private Cursor uiQuickResponse(String[] uiProjection) {
final Context context = getContext();
final SQLiteDatabase db = getDatabase(context);
final StringBuilder sb = genSelect(getQuickResponseMap(), uiProjection);
sb.append(" FROM " + QuickResponse.TABLE_NAME);
final String query = sb.toString();
return db.rawQuery(query, new String[0]);
}
/**
* Generate the "attachment list" SQLite query, given a projection from UnifiedEmail
*

View File

@ -45,7 +45,8 @@ public class QuickResponseTests extends ProviderTestCase2<EmailProvider> {
ContentCache.invalidateAllCaches();
}
public void testParcelling() {
// This class no longer has any content
public void brokenTestParcelling() {
QuickResponse original = new QuickResponse(7, "quick response text");
Parcel p = Parcel.obtain();