From c6953b77552d4cb71776cf0537dc226029381628 Mon Sep 17 00:00:00 2001 From: Tony Mantler Date: Wed, 14 Aug 2013 11:05:19 -0700 Subject: [PATCH] Reimplement QuickResponse support b/8622751 Change-Id: Id079efcf34dce15b5f5057f937582c0e198d3d50 --- AndroidManifest.xml | 5 +- .../emailcommon/provider/EmailContent.java | 10 - .../emailcommon/provider/QuickResponse.java | 185 +----------------- res/menu/email_compose_menu_extras.xml | 22 +++ res/values/strings.xml | 2 + .../email/activity/ComposeActivityEmail.java | 65 ++++++ .../activity/InsertQuickResponseDialog.java | 99 +++++----- .../email/activity/setup/AccountSettings.java | 4 +- ...untSettingsEditQuickResponsesFragment.java | 48 ++--- .../setup/AccountSettingsFragment.java | 75 ++++--- .../setup/EditQuickResponseDialog.java | 19 +- .../android/email/provider/EmailProvider.java | 119 +++++++---- .../provider/QuickResponseTests.java | 3 +- 13 files changed, 309 insertions(+), 347 deletions(-) create mode 100644 res/menu/email_compose_menu_extras.xml create mode 100644 src/com/android/email/activity/ComposeActivityEmail.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index fa4479a23..7e9d3316c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -78,7 +78,7 @@ @@ -132,6 +132,9 @@ + + CREATOR - = new Parcelable.Creator() { - @Override - public QuickResponse createFromParcel(Parcel in) { - return new QuickResponse(in); - } - - @Override - public QuickResponse[] newArray(int size) { - return new QuickResponse[size]; - } - }; - } \ No newline at end of file diff --git a/res/menu/email_compose_menu_extras.xml b/res/menu/email_compose_menu_extras.xml new file mode 100644 index 000000000..99aa6a8e1 --- /dev/null +++ b/res/menu/email_compose_menu_extras.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 9bc440f88..1ac212698 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -312,6 +312,8 @@ Insert quick response + + Insert quick response %1$s and %2$d others diff --git a/src/com/android/email/activity/ComposeActivityEmail.java b/src/com/android/email/activity/ComposeActivityEmail.java new file mode 100644 index 000000000..16373d0b0 --- /dev/null +++ b/src/com/android/email/activity/ComposeActivityEmail.java @@ -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()); + } + } +} diff --git a/src/com/android/email/activity/InsertQuickResponseDialog.java b/src/com/android/email/activity/InsertQuickResponseDialog.java index 111db424e..cf7773301 100644 --- a/src/com/android/email/activity/InsertQuickResponseDialog.java +++ b/src/com/android/email/activity/InsertQuickResponseDialog.java @@ -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() { + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new CursorLoader(getActivity(), account.quickResponseUri, + UIProvider.QUICK_RESPONSE_PROJECTION, null, null, null); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + adapter.swapCursor(data); + } + + @Override + public void onLoaderReset(Loader 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) { diff --git a/src/com/android/email/activity/setup/AccountSettings.java b/src/com/android/email/activity/setup/AccountSettings.java index bf85c83fb..2bd6c3025 100644 --- a/src/com/android/email/activity/setup/AccountSettings.java +++ b/src/com/android/email/activity/setup/AccountSettings.java @@ -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); diff --git a/src/com/android/email/activity/setup/AccountSettingsEditQuickResponsesFragment.java b/src/com/android/email/activity/setup/AccountSettingsEditQuickResponsesFragment.java index 9806187b8..873f673e0 100644 --- a/src/com/android/email/activity/setup/AccountSettingsEditQuickResponsesFragment.java +++ b/src/com/android/email/activity/setup/AccountSettingsEditQuickResponsesFragment.java @@ -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() { @Override public Loader 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 loader, Cursor data) { - mAdapter.swapCursor(data); + adapter.swapCursor(data); } @Override public void onLoaderReset(Loader 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; } diff --git a/src/com/android/email/activity/setup/AccountSettingsFragment.java b/src/com/android/email/activity/setup/AccountSettingsFragment.java index d8db49099..14c276876 100644 --- a/src/com/android/email/activity/setup/AccountSettingsFragment.java +++ b/src/com/android/email/activity/setup/AccountSettingsFragment.java @@ -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 { + private class LoadAccountTask extends AsyncTask> { + 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 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 map = new HashMap(2); + map.put(ACCOUNT_KEY, account); + map.put(UI_ACCOUNT_KEY, uiAccount); + return map; } @Override - protected void onPostExecute(Account account) { + protected void onPostExecute(Map 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; } }); diff --git a/src/com/android/email/activity/setup/EditQuickResponseDialog.java b/src/com/android/email/activity/setup/EditQuickResponseDialog.java index 07db2584c..7c8891b52 100644 --- a/src/com/android/email/activity/setup/EditQuickResponseDialog.java +++ b/src/com/android/email/activity/setup/EditQuickResponseDialog.java @@ -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); diff --git a/src/com/android/email/provider/EmailProvider.java b/src/com/android/email/provider/EmailProvider.java index cef470958..f08e04e35 100644 --- a/src/com/android/email/provider/EmailProvider.java +++ b/src/com/android/email/provider/EmailProvider.java @@ -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 TABLE_NAMES; + static { + SparseArray array = new SparseArray(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 * diff --git a/tests/src/com/android/emailcommon/provider/QuickResponseTests.java b/tests/src/com/android/emailcommon/provider/QuickResponseTests.java index f94136d78..9e0b6d5b5 100644 --- a/tests/src/com/android/emailcommon/provider/QuickResponseTests.java +++ b/tests/src/com/android/emailcommon/provider/QuickResponseTests.java @@ -45,7 +45,8 @@ public class QuickResponseTests extends ProviderTestCase2 { 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();