Custom froms.
DO NOT WANT.
First revision. It works! And it sends mail...so that's good.
Change-Id: I9e77df792d57dfc09442b711710b387b5e1e6d10
diff --git a/res/layout/custom_from_dropdown_item.xml b/res/layout/custom_from_dropdown_item.xml
new file mode 100644
index 0000000..75408ed
--- /dev/null
+++ b/res/layout/custom_from_dropdown_item.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:paddingLeft="24dip"
+ android:layout_gravity="center_vertical"
+ android:paddingTop="10dip"
+ android:paddingBottom="10dip">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content">
+
+ <TextView
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/custom_from_account_label"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+ <TextView
+ android:id="@+id/spinner_account_name"
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/spinner_account_address"
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+</LinearLayout>
diff --git a/res/layout/custom_from_item.xml b/res/layout/custom_from_item.xml
new file mode 100644
index 0000000..ccffd48
--- /dev/null
+++ b/res/layout/custom_from_item.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent">
+
+ <TextView android:id="@+id/spinner_account_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="6dip"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+ <TextView android:id="@+id/spinner_account_address"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="6dip"
+ android:singleLine="true"
+ android:ellipsize="end"/>
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c135e5c..6ec2fe3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -96,6 +96,8 @@
<string name="message_discarded">Message discarded.</string>
<!-- Formatting string for the user's signaure. [CHAR LIMIT=10] -->
<string name="signature">\n\n<xliff:g id="signature">%s</xliff:g></string>
+ <!-- Shown in the from dropdown in front of custom from addresses. [CHAR LIMIT=15] -->
+ <string name="custom_from_account_label">Send mail as:</string>
<!-- Menu item: send this message -->
<string name="send">Send</string>
diff --git a/src/com/android/mail/compose/ComposeActivity.java b/src/com/android/mail/compose/ComposeActivity.java
index 6744fb8..a6c0744 100644
--- a/src/com/android/mail/compose/ComposeActivity.java
+++ b/src/com/android/mail/compose/ComposeActivity.java
@@ -45,7 +45,6 @@
import android.text.TextWatcher;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -71,6 +70,7 @@
import com.android.mail.providers.Attachment;
import com.android.mail.providers.Message;
import com.android.mail.providers.MessageModification;
+import com.android.mail.providers.ReplyFromAccount;
import com.android.mail.providers.Settings;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.DraftType;
@@ -178,6 +178,7 @@
private CcBccView mCcBccView;
private AttachmentsView mAttachmentsView;
private Account mAccount;
+ private ReplyFromAccount mReplyFromAccount;
private Settings mCachedSettings;
private Rfc822Validator mValidator;
private TextView mSubject;
@@ -415,10 +416,12 @@
}
private void initFromSpinner(int action) {
+ mReplyFromAccount = new ReplyFromAccount(mAccount, mAccount.uri, mAccount.name,
+ mAccount.name, true, false);
if (action == COMPOSE ||
(action == EDIT_DRAFT
&& mDraft.draftType == UIProvider.DraftType.COMPOSE)) {
- mFromSpinner.setCurrentAccount(mAccount);
+ mFromSpinner.setCurrentAccount(mReplyFromAccount);
mFromSpinner.asyncInitFromSpinner();
boolean showSpinner = mFromSpinner.getCount() > 1;
// If there is only 1 account, just show that account.
@@ -432,7 +435,7 @@
mFromStatic.setVisibility(View.VISIBLE);
mFromStaticText.setText(mAccount.name);
mFromSpinnerWrapper.setVisibility(View.GONE);
- mFromSpinner.setCurrentAccount(mAccount);
+ mFromSpinner.setCurrentAccount(mReplyFromAccount);
}
}
@@ -1125,7 +1128,7 @@
public void run() {
final SendOrSaveMessage sendOrSaveMessage = mSendOrSaveMessage;
- final Account selectedAccount = sendOrSaveMessage.mSelectedAccount;
+ final ReplyFromAccount selectedAccount = sendOrSaveMessage.mAccount;
Message message = mSendOrSaveCallback.getMessage();
long messageId = message != null ? message.id : UIProvider.INVALID_MESSAGE_ID;
// If a previous draft has been saved, in an account that is different
@@ -1136,8 +1139,8 @@
ContentResolver resolver = mContext.getContentResolver();
ContentValues values = new ContentValues();
values.put(BaseColumns._ID, messageId);
- if (selectedAccount.expungeMessageUri != null) {
- resolver.update(selectedAccount.expungeMessageUri, values, null,
+ if (selectedAccount.account.expungeMessageUri != null) {
+ resolver.update(selectedAccount.account.expungeMessageUri, values, null,
null);
} else {
// TODO(mindyp) delete the conversation.
@@ -1155,9 +1158,10 @@
sendOrSaveMessage.mValues, null, null);
} else {
ContentResolver resolver = mContext.getContentResolver();
- Uri messageUri = resolver.insert(
- sendOrSaveMessage.mSave ? selectedAccount.saveDraftUri
- : selectedAccount.sendMessageUri, sendOrSaveMessage.mValues);
+ Uri messageUri = resolver
+ .insert(sendOrSaveMessage.mSave ? selectedAccount.account.saveDraftUri
+ : selectedAccount.account.sendMessageUri,
+ sendOrSaveMessage.mValues);
if (sendOrSaveMessage.mSave && messageUri != null) {
Cursor messageCursor = resolver.query(messageUri,
UIProvider.MESSAGE_PROJECTION, null, null, null);
@@ -1196,17 +1200,15 @@
private String mSignature;
/*package*/ static class SendOrSaveMessage {
- final Account mAccount;
- final Account mSelectedAccount;
+ final ReplyFromAccount mAccount;
final ContentValues mValues;
final String mRefMessageId;
final boolean mSave;
final int mRequestId;
- public SendOrSaveMessage(Account account, Account selectedAccount, ContentValues values,
+ public SendOrSaveMessage(ReplyFromAccount account, ContentValues values,
String refMessageId, boolean save) {
mAccount = account;
- mSelectedAccount = selectedAccount;
mValues = values;
mRefMessageId = refMessageId;
mSave = save;
@@ -1500,12 +1502,11 @@
}
/* package */
- static int sendOrSaveInternal(Context context, final Account account,
- final Account selectedAccount, String fromAddress, final Spanned body,
- final String[] to, final String[] cc, final String[] bcc, final String subject,
- final CharSequence quotedText, final List<Attachment> attachments,
- final Message refMessage, SendOrSaveCallback callback, Handler handler, boolean save,
- int composeMode) {
+ static int sendOrSaveInternal(Context context, final ReplyFromAccount replyFromAccount,
+ String fromAddress, final Spanned body, final String[] to, final String[] cc,
+ final String[] bcc, final String subject, final CharSequence quotedText,
+ final List<Attachment> attachments, final Message refMessage,
+ SendOrSaveCallback callback, Handler handler, boolean save, int composeMode) {
ContentValues values = new ContentValues();
String refMessageId = refMessage != null ? refMessage.uri.toString() : "";
@@ -1514,6 +1515,8 @@
MessageModification.putCcAddresses(values, cc);
MessageModification.putBccAddresses(values, bcc);
+ MessageModification.putCustomFromAddress(values, replyFromAccount.address);
+
MessageModification.putSubject(values, subject);
String htmlBody = Html.toHtml(body);
boolean includeQuotedText = !TextUtils.isEmpty(quotedText);
@@ -1566,7 +1569,7 @@
MessageModification.putRefMessageId(values, refMessageId);
}
- SendOrSaveMessage sendOrSaveMessage = new SendOrSaveMessage(account, selectedAccount,
+ SendOrSaveMessage sendOrSaveMessage = new SendOrSaveMessage(replyFromAccount,
values, refMessageId, save);
SendOrSaveTask sendOrSaveTask = new SendOrSaveTask(context, sendOrSaveMessage, callback);
@@ -1667,12 +1670,12 @@
};
// Get the selected account if the from spinner has been setup.
- Account selectedAccount = mAccount;
+ ReplyFromAccount selectedAccount = mReplyFromAccount;
String fromAddress = selectedAccount.name;
if (selectedAccount == null || fromAddress == null) {
// We don't have either the selected account or from address,
// use mAccount.
- selectedAccount = mAccount;
+ selectedAccount = mReplyFromAccount;
fromAddress = mAccount.name;
}
@@ -1683,7 +1686,7 @@
mSendSaveTaskHandler = new Handler(handlerThread.getLooper());
}
- mRequestId = sendOrSaveInternal(this, mAccount, selectedAccount, fromAddress, body, to, cc,
+ mRequestId = sendOrSaveInternal(this, mReplyFromAccount, fromAddress, body, to, cc,
bcc, mSubject.getText().toString(), mQuotedTextView.getQuotedTextIfIncluded(),
mAttachmentsView.getAttachments(), mRefMessage, callback,
mSendSaveTaskHandler, save, mComposeMode);
@@ -1691,7 +1694,7 @@
if (mRecipient != null && mRecipient.equals(mAccount.name)) {
mRecipient = selectedAccount.name;
}
- mAccount = selectedAccount;
+ mAccount = selectedAccount.account;
// Don't display the toast if the user is just changing the orientation,
// but we still need to save the draft to the cursor because this is how we restore
@@ -1873,9 +1876,9 @@
@Override
public void onAccountChanged() {
- Account selectedAccountInfo = mFromSpinner.getCurrentAccount();
- if (!mAccount.equals(selectedAccountInfo)) {
- mAccount = selectedAccountInfo;
+ mReplyFromAccount = mFromSpinner.getCurrentAccount();
+ if (!mAccount.equals(mReplyFromAccount.account)) {
+ mAccount = mReplyFromAccount.account;
mCachedSettings = null;
getLoaderManager().restartLoader(ACCOUNT_SETTINGS_LOADER, null, this);
// TODO: handle discarding attachments when switching accounts.
diff --git a/src/com/android/mail/compose/FromAddressSpinner.java b/src/com/android/mail/compose/FromAddressSpinner.java
index 712d92a..da25bca 100644
--- a/src/com/android/mail/compose/FromAddressSpinner.java
+++ b/src/com/android/mail/compose/FromAddressSpinner.java
@@ -16,6 +16,7 @@
package com.android.mail.compose;
import android.content.Context;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
@@ -23,13 +24,20 @@
import android.widget.Spinner;
import com.android.mail.providers.Account;
+import com.android.mail.providers.ReplyFromAccount;
import com.android.mail.utils.AccountUtils;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
import java.util.List;
public class FromAddressSpinner extends Spinner implements OnItemSelectedListener {
private List<Account> mAccounts;
- private Account mAccount;
+ private ReplyFromAccount mAccount;
+ private List<ReplyFromAccount> mReplyFromAccounts;
private OnAccountChangedListener mAccountChangedListener;
public FromAddressSpinner(Context context) {
@@ -40,18 +48,18 @@
super(context, set);
}
- public void setCurrentAccount(Account account) {
+ public void setCurrentAccount(ReplyFromAccount account) {
mAccount = account;
}
- public Account getCurrentAccount() {
+ public ReplyFromAccount getCurrentAccount() {
return mAccount;
}
public void asyncInitFromSpinner() {
Account[] result = AccountUtils.getSyncingAccounts(getContext());
- mAccounts = AccountUtils
- .mergeAccountLists(mAccounts, result, true /* prioritizeAccountList */);
+ mAccounts = AccountUtils.mergeAccountLists(mAccounts, result,
+ true /* prioritizeAccountList */);
initFromSpinner();
}
@@ -66,12 +74,39 @@
FromAddressSpinnerAdapter adapter = new FromAddressSpinnerAdapter(getContext());
int currentAccountIndex = 0;
- currentAccountIndex = adapter.addAccounts(mAccount, mAccounts);
+ mReplyFromAccounts = new ArrayList<ReplyFromAccount>();
+ for (Account account : mAccounts) {
+ ReplyFromAccount replyFrom = new ReplyFromAccount(account, account.uri, account.name,
+ account.name, false, false);
+ if (replyFrom != null) {
+ mReplyFromAccounts.add(replyFrom);
+ }
+ if (!TextUtils.isEmpty(account.accountFromAddresses)) {
+ // Parse and create an entry for each.
+ try {
+ JSONArray accounts = new JSONArray(account.accountFromAddresses);
+ JSONObject accountString;
+ for (int i = 0; i < accounts.length(); i++) {
+ accountString = (JSONObject) accounts.get(i);
+ ReplyFromAccount a = ReplyFromAccount.deserialize(account, accountString);
+ if (a != null) {
+ mReplyFromAccounts.add(a);
+ }
+ }
+ } catch (JSONException e) {
+
+ }
+ }
+ }
+ currentAccountIndex = adapter.addAccounts(mAccount, mReplyFromAccounts);
setAdapter(adapter);
setSelection(currentAccountIndex, false);
setOnItemSelectedListener(this);
- mAccount = mAccounts.get(currentAccountIndex);
+ if (currentAccountIndex >= mReplyFromAccounts.size()) {
+ currentAccountIndex = 0;
+ }
+ mAccount = mReplyFromAccounts.get(currentAccountIndex);
}
public void setOnAccountChangedListener(OnAccountChangedListener listener) {
@@ -80,7 +115,7 @@
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- Account selection = (Account) getItemAtPosition(position);
+ ReplyFromAccount selection = (ReplyFromAccount) getItemAtPosition(position);
if (!selection.name.equals(mAccount.name)) {
mAccount = selection;
mAccountChangedListener.onAccountChanged();
diff --git a/src/com/android/mail/compose/FromAddressSpinnerAdapter.java b/src/com/android/mail/compose/FromAddressSpinnerAdapter.java
index db02501..448a750 100644
--- a/src/com/android/mail/compose/FromAddressSpinnerAdapter.java
+++ b/src/com/android/mail/compose/FromAddressSpinnerAdapter.java
@@ -24,6 +24,7 @@
import com.android.mail.R;
import com.android.mail.providers.Account;
+import com.android.mail.providers.ReplyFromAccount;
import java.util.List;
@@ -33,7 +34,7 @@
*
* @author mindyp@google.com
*/
-public class FromAddressSpinnerAdapter extends ArrayAdapter<Account> {
+public class FromAddressSpinnerAdapter extends ArrayAdapter<ReplyFromAccount> {
public static int REAL_ACCOUNT = 2;
public static int ACCOUNT_DISPLAY = 0;
@@ -56,29 +57,30 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- Account fromItem = getItem(position);
- View fromEntry = getInflater().inflate(R.layout.from_item, null);
- ((TextView) fromEntry.findViewById(R.id.spinner_account_name))
- .setText(fromItem.name);
+ ReplyFromAccount fromItem = getItem(position);
+ int res = fromItem.isCustomFrom ? R.layout.custom_from_item : R.layout.from_item;
+ View fromEntry = getInflater().inflate(res, null);
+ ((TextView) fromEntry.findViewById(R.id.spinner_account_name)).setText(fromItem.name);
return fromEntry;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
- Account fromItem = getItem(position);
- View fromEntry = getInflater().inflate(R.layout.from_dropdown_item, null);
- TextView acctName = ((TextView) fromEntry.
- findViewById(R.id.spinner_account_name));
+ ReplyFromAccount fromItem = getItem(position);
+ int res = fromItem.isCustomFrom ? R.layout.custom_from_dropdown_item
+ : R.layout.from_dropdown_item;
+ View fromEntry = getInflater().inflate(res, null);
+ TextView acctName = ((TextView) fromEntry.findViewById(R.id.spinner_account_name));
acctName.setText(fromItem.name);
return fromEntry;
}
- public int addAccounts(Account selectedAccount,
- List<Account> replyFromAccounts) {
+ public int addAccounts(ReplyFromAccount selectedAccount,
+ List<ReplyFromAccount> replyFromAccounts) {
int currentIndex = 0;
int currentAccountIndex = 0;
// Get the position of the current account
- for (Account account : replyFromAccounts) {
+ for (ReplyFromAccount account : replyFromAccounts) {
// Add the account to the Adapter
add(account);
// See if we have located the selected account.
diff --git a/src/com/android/mail/providers/Account.java b/src/com/android/mail/providers/Account.java
index 0bce93d..66ae656 100644
--- a/src/com/android/mail/providers/Account.java
+++ b/src/com/android/mail/providers/Account.java
@@ -17,6 +17,7 @@
package com.android.mail.providers;
import com.android.mail.utils.LogUtils;
+import com.android.mail.utils.Utils;
import android.database.Cursor;
import android.net.Uri;
@@ -60,10 +61,9 @@
public final Uri searchUri;
/**
- * The content provider uri that can be queried to access the from addresses
- * for this account.
+ * The custom from addresses for this account or null if there are none.
*/
- public final Uri accountFromAddressesUri;
+ public final String accountFromAddresses;
/**
* The content provider uri that can be used to save (insert) new draft
@@ -148,8 +148,8 @@
json.put(UIProvider.AccountColumns.CAPABILITIES, capabilities);
json.put(UIProvider.AccountColumns.FOLDER_LIST_URI, folderListUri);
json.put(UIProvider.AccountColumns.SEARCH_URI, searchUri);
- json.put(UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES_URI,
- accountFromAddressesUri);
+ json.put(UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES,
+ accountFromAddresses);
json.put(UIProvider.AccountColumns.SAVE_DRAFT_URI, saveDraftUri);
json.put(UIProvider.AccountColumns.SEND_MAIL_URI, sendMessageUri);
json.put(UIProvider.AccountColumns.EXPUNGE_MESSAGE_URI, expungeMessageUri);
@@ -200,9 +200,7 @@
* @return a valid URI, possibly {@link android.net.Uri#EMPTY}
*/
private static Uri getValidUri(String uri) {
- if (uri == JSONObject.NULL)
- return Uri.EMPTY;
- return Uri.parse(uri);
+ return Utils.getValidUri(uri);
}
/**
@@ -226,8 +224,7 @@
capabilities = Integer.valueOf(json.getInt(UIProvider.AccountColumns.CAPABILITIES));
folderListUri = getValidUri(json.optString(UIProvider.AccountColumns.FOLDER_LIST_URI));
searchUri = getValidUri(json.optString(UIProvider.AccountColumns.SEARCH_URI));
- accountFromAddressesUri = getValidUri(json
- .optString(UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES_URI));
+ accountFromAddresses = UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES;
saveDraftUri = getValidUri(json.optString(UIProvider.AccountColumns.SAVE_DRAFT_URI));
sendMessageUri = getValidUri(json.optString(UIProvider.AccountColumns.SEND_MAIL_URI));
expungeMessageUri = getValidUri(json
@@ -254,7 +251,7 @@
capabilities = in.readInt();
folderListUri = in.readParcelable(null);
searchUri = in.readParcelable(null);
- accountFromAddressesUri = in.readParcelable(null);
+ accountFromAddresses = in.readString();
saveDraftUri = in.readParcelable(null);
sendMessageUri = in.readParcelable(null);
expungeMessageUri = in.readParcelable(null);
@@ -271,10 +268,8 @@
public Account(Cursor cursor) {
super(cursor.getString(UIProvider.ACCOUNT_NAME_COLUMN), "unknown");
- String fromAddresses = cursor
- .getString(UIProvider.ACCOUNT_FROM_ADDRESSES_URI_COLUMN);
- accountFromAddressesUri = !TextUtils.isEmpty(fromAddresses) ? Uri.parse(fromAddresses)
- : null;
+ accountFromAddresses = cursor
+ .getString(UIProvider.ACCOUNT_FROM_ADDRESSES_COLUMN);
capabilities = cursor.getInt(UIProvider.ACCOUNT_CAPABILITIES_COLUMN);
providerVersion = cursor.getInt(UIProvider.ACCOUNT_PROVIDER_VERISON_COLUMN);
uri = Uri.parse(cursor.getString(UIProvider.ACCOUNT_URI_COLUMN));
@@ -341,7 +336,7 @@
dest.writeInt(capabilities);
dest.writeParcelable(folderListUri, 0);
dest.writeParcelable(searchUri, 0);
- dest.writeParcelable(accountFromAddressesUri, 0);
+ dest.writeString(accountFromAddresses);
dest.writeParcelable(saveDraftUri, 0);
dest.writeParcelable(sendMessageUri, 0);
dest.writeParcelable(expungeMessageUri, 0);
@@ -373,7 +368,7 @@
sb.append(",type=");
sb.append(type);
sb.append(",accountFromAddressUri=");
- sb.append(accountFromAddressesUri);
+ sb.append(accountFromAddresses);
sb.append(",capabilities=");
sb.append(capabilities);
sb.append(",providerVersion=");
@@ -426,7 +421,7 @@
Objects.equal(uri, other.uri) &&
Objects.equal(folderListUri, other.folderListUri) &&
Objects.equal(searchUri, other.searchUri) &&
- Objects.equal(accountFromAddressesUri, other.accountFromAddressesUri) &&
+ Objects.equal(accountFromAddresses, other.accountFromAddresses) &&
Objects.equal(saveDraftUri, other.saveDraftUri) &&
Objects.equal(sendMessageUri, other.sendMessageUri) &&
Objects.equal(expungeMessageUri, other.expungeMessageUri) &&
@@ -444,7 +439,7 @@
@Override
public int hashCode() {
return super.hashCode() ^ Objects.hashCode(name, type, capabilities, providerVersion,
- uri, folderListUri, searchUri, accountFromAddressesUri, saveDraftUri,
+ uri, folderListUri, searchUri, accountFromAddresses, saveDraftUri,
sendMessageUri, expungeMessageUri, undoUri, settingsIntentUri, settingsQueryUri,
helpIntentUri, sendFeedbackIntentUri, syncStatus, composeIntentUri, mimeType,
recentFolderListUri);
diff --git a/src/com/android/mail/providers/MailAppProvider.java b/src/com/android/mail/providers/MailAppProvider.java
index 62473fd..88a0802 100644
--- a/src/com/android/mail/providers/MailAppProvider.java
+++ b/src/com/android/mail/providers/MailAppProvider.java
@@ -203,8 +203,8 @@
} else if (TextUtils.equals(column, UIProvider.AccountColumns.SEARCH_URI)) {
builder.add(account.searchUri);
} else if (TextUtils.equals(column,
- UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES_URI)) {
- builder.add(account.accountFromAddressesUri);
+ UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES)) {
+ builder.add(account.accountFromAddresses);
} else if (TextUtils.equals(column, UIProvider.AccountColumns.SAVE_DRAFT_URI)) {
builder.add(account.saveDraftUri);
} else if (TextUtils.equals(column, UIProvider.AccountColumns.SEND_MAIL_URI)) {
diff --git a/src/com/android/mail/providers/MessageModification.java b/src/com/android/mail/providers/MessageModification.java
index b7bc6bf..fde9e94 100644
--- a/src/com/android/mail/providers/MessageModification.java
+++ b/src/com/android/mail/providers/MessageModification.java
@@ -72,6 +72,17 @@
}
/**
+ * Sets the custom from address for a message, we only set this if its different than the
+ * default adress for the account.
+ *
+ * @param values the ContentValues that will be used to create or update the message
+ * @param customFromAddress from address
+ */
+ public static void putCustomFromAddress(ContentValues values, String customFromAddress) {
+ values.put(MessageColumns.CUSTOM_FROM_ADDRESS, customFromAddress);
+ }
+
+ /**
* Saves a flag indicating the message is forwarded. Only valid for drafts
* not yet sent to / retrieved from server.
* @param values the ContentValues that will be used to create or update the
diff --git a/src/com/android/mail/providers/ReplyFromAccount.java b/src/com/android/mail/providers/ReplyFromAccount.java
new file mode 100644
index 0000000..bc27b3b
--- /dev/null
+++ b/src/com/android/mail/providers/ReplyFromAccount.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2012, 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.mail.providers;
+
+import android.net.Uri;
+
+import com.android.mail.utils.LogUtils;
+import com.android.mail.utils.Utils;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.Serializable;
+import java.util.regex.Pattern;
+
+public class ReplyFromAccount implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private static final String LOG_TAG = new LogUtils().getLogTag();
+ private static final String BASE_ACCOUNT_URI = "baseAccountUri";
+ private static final String ADDRESS_STRING = "address";
+ private static final String NAME_STRING = "name";
+ private static final String IS_DEFAULT = "isDefault";
+ private static final String IS_CUSTOM_FROM = "isCustom";
+
+ public Account account;
+ Uri baseAccountUri;
+ public String address;
+ public String name;
+ public boolean isDefault;
+ public boolean isCustomFrom;
+
+ public ReplyFromAccount(Account account, Uri baseAccountUri, String address, String name,
+ boolean isDefault, boolean isCustom) {
+ this.account = account;
+ this.baseAccountUri = baseAccountUri;
+ this.address = address;
+ this.name = name;
+ this.isDefault = isDefault;
+ this.isCustomFrom = isCustom;
+ }
+
+ public JSONObject serialize() {
+ JSONObject json = new JSONObject();
+ try {
+ json.put(BASE_ACCOUNT_URI, baseAccountUri);
+ json.put(ADDRESS_STRING, address);
+ json.put(NAME_STRING, name);
+ json.put(IS_DEFAULT, isDefault);
+ json.put(IS_CUSTOM_FROM, isCustomFrom);
+ } catch (JSONException e) {
+ LogUtils.wtf(LOG_TAG, e, "Could not serialize account with name " + name);
+ }
+ return json;
+ }
+
+ public static ReplyFromAccount deserialize(Account account, JSONObject json) {
+ ReplyFromAccount replyFromAccount = null;
+ try {
+ Uri uri = Utils.getValidUri(json.getString(BASE_ACCOUNT_URI));
+ String addressString = json.getString(ADDRESS_STRING);
+ String nameString = json.getString(NAME_STRING);
+ boolean isDefault = json.getBoolean(IS_DEFAULT);
+ boolean isCustomFrom = json.getBoolean(IS_CUSTOM_FROM);
+ replyFromAccount = new ReplyFromAccount(account, uri, addressString, nameString,
+ isDefault, isCustomFrom);
+ } catch (JSONException e) {
+ LogUtils.wtf(LOG_TAG, e, "Could not deserialize replyfromaccount");
+ }
+ return replyFromAccount;
+ }
+}
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index 3b7666c..97c27bc 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -93,7 +93,7 @@
AccountColumns.CAPABILITIES,
AccountColumns.FOLDER_LIST_URI,
AccountColumns.SEARCH_URI,
- AccountColumns.ACCOUNT_FROM_ADDRESSES_URI,
+ AccountColumns.ACCOUNT_FROM_ADDRESSES,
AccountColumns.SAVE_DRAFT_URI,
AccountColumns.SEND_MAIL_URI,
AccountColumns.EXPUNGE_MESSAGE_URI,
@@ -115,7 +115,7 @@
public static final int ACCOUNT_CAPABILITIES_COLUMN = 4;
public static final int ACCOUNT_FOLDER_LIST_URI_COLUMN = 5;
public static final int ACCOUNT_SEARCH_URI_COLUMN = 6;
- public static final int ACCOUNT_FROM_ADDRESSES_URI_COLUMN = 7;
+ public static final int ACCOUNT_FROM_ADDRESSES_COLUMN = 7;
public static final int ACCOUNT_SAVE_DRAFT_URI_COLUMN = 8;
public static final int ACCOUNT_SEND_MESSAGE_URI_COLUMN = 9;
public static final int ACCOUNT_EXPUNGE_MESSAGE_URI_COLUMN = 10;
@@ -266,10 +266,10 @@
public static final String SEARCH_URI = "searchUri";
/**
- * This string column contains the content provider uri that can be queried to access the
- * from addresses for this account.
+ * This string column contains a json array of json objects representing
+ * custom from addresses for this account or null if there are none.
*/
- public static final String ACCOUNT_FROM_ADDRESSES_URI = "accountFromAddressesUri";
+ public static final String ACCOUNT_FROM_ADDRESSES = "accountFromAddresses";
/**
* This string column contains the content provider uri that can be used to save (insert)
@@ -801,7 +801,8 @@
MessageColumns.READ,
MessageColumns.STARRED,
MessageColumns.QUOTE_START_POS,
- MessageColumns.ATTACHMENTS
+ MessageColumns.ATTACHMENTS,
+ MessageColumns.CUSTOM_FROM_ADDRESS
};
/** Separates attachment info parts in strings in a message. */
@@ -840,6 +841,7 @@
public static final int MESSAGE_STARRED_COLUMN = 26;
public static final int QUOTED_TEXT_OFFSET_COLUMN = 27;
public static final int MESSAGE_ATTACHMENTS_COLUMN = 28;
+ public static final int MESSAGE_CUSTOM_FROM_ADDRESS_COLUMN = 29;
public static final class CursorStatus {
@@ -1018,6 +1020,7 @@
* This string columns contains a JSON array of serialized {@link Attachment} objects.
*/
public static final String ATTACHMENTS = "attachments";
+ public static final String CUSTOM_FROM_ADDRESS = "customFrom";
private MessageColumns() {}
}
diff --git a/src/com/android/mail/providers/protos/mock/MockUiProvider.java b/src/com/android/mail/providers/protos/mock/MockUiProvider.java
index 67312b2..cb1ebbc 100644
--- a/src/com/android/mail/providers/protos/mock/MockUiProvider.java
+++ b/src/com/android/mail/providers/protos/mock/MockUiProvider.java
@@ -24,10 +24,12 @@
import android.os.Parcel;
import android.provider.BaseColumns;
import android.text.Html;
+import android.text.TextUtils;
import com.android.mail.providers.Account;
import com.android.mail.providers.Folder;
import com.android.mail.providers.MailAppProvider;
+import com.android.mail.providers.ReplyFromAccount;
import com.android.mail.providers.UIProvider.AccountCapabilities;
import com.android.mail.providers.UIProvider.AccountColumns;
import com.android.mail.providers.UIProvider.AttachmentColumns;
@@ -43,6 +45,9 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.json.JSONArray;
+
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -311,10 +316,18 @@
AccountCapabilities.LOCAL_SEARCH |
AccountCapabilities.THREADED_CONVERSATIONS |
AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV));
+ JSONArray replyFroms = new JSONArray();
+ ArrayList<ReplyFromAccount> list = new ArrayList<ReplyFromAccount>();
+ list.add(new ReplyFromAccount(null, Uri.parse(accountUri), "customAddress1@custom.com",
+ "Custom1", false, true));
+ list.add(new ReplyFromAccount(null, Uri.parse(accountUri), "customAddress2@custom.com",
+ "Custom2", false, true));
+ for (ReplyFromAccount a : list) {
+ replyFroms.put(a.serialize());
+ }
+ accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES, replyFroms.toString());
accountMap.put(AccountColumns.FOLDER_LIST_URI, Uri.parse(accountUri + "/folders"));
accountMap.put(AccountColumns.SEARCH_URI, Uri.parse(accountUri + "/search"));
- accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES_URI,
- Uri.parse(accountUri + "/fromAddresses"));
accountMap.put(AccountColumns.SAVE_DRAFT_URI, Uri.parse(accountUri + "/saveDraft"));
accountMap.put(AccountColumns.SEND_MAIL_URI, Uri.parse(accountUri + "/sendMail"));
accountMap.put(AccountColumns.EXPUNGE_MESSAGE_URI,
@@ -327,6 +340,7 @@
accountMap.put(AccountColumns.COMPOSE_URI, Uri.parse(accountUri + "/compose"));
accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI,
Uri.parse(accountUri + "/recentFolderListUri"));
+ accountMap.put(AccountColumns.MIME_TYPE, "account/mock");
if (cacheMap) {
addAccountInfoToAccountCache(accountMap);
}
@@ -412,7 +426,7 @@
dest.writeInt((Integer) accountInfo.get(AccountColumns.CAPABILITIES));
dest.writeParcelable((Uri) accountInfo.get(AccountColumns.FOLDER_LIST_URI), 0);
dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SEARCH_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.ACCOUNT_FROM_ADDRESSES_URI), 0);
+ dest.writeString((String) accountInfo.get(AccountColumns.ACCOUNT_FROM_ADDRESSES));
dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SAVE_DRAFT_URI), 0);
dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SEND_MAIL_URI), 0);
dest.writeParcelable((Uri) accountInfo.get(AccountColumns.EXPUNGE_MESSAGE_URI), 0);
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index 11d992f..b68db34 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -51,6 +51,8 @@
import com.android.mail.providers.Folder;
import com.android.mail.providers.UIProvider.EditSettingsExtras;
+import org.json.JSONObject;
+
import java.util.Locale;
import java.util.Map;
@@ -836,4 +838,17 @@
}
item.setVisible(shouldShow);
}
+
+ /**
+ * Parse a string (possibly null or empty) into a URI. If the string is null
+ * or empty, null is returned back. Otherwise an empty URI is returned.
+ *
+ * @param uri
+ * @return a valid URI, possibly {@link android.net.Uri#EMPTY}
+ */
+ public static Uri getValidUri(String uri) {
+ if (uri == JSONObject.NULL)
+ return Uri.EMPTY;
+ return Uri.parse(uri);
+ }
}
diff --git a/tests/src/com/android/mail/providers/AccountTests.java b/tests/src/com/android/mail/providers/AccountTests.java
index 6beb009..dfeadd6 100644
--- a/tests/src/com/android/mail/providers/AccountTests.java
+++ b/tests/src/com/android/mail/providers/AccountTests.java
@@ -42,7 +42,7 @@
intent.putExtra(Utils.EXTRA_ACCOUNT, account);
Account outAccount = (Account) intent.getParcelableExtra(Utils.EXTRA_ACCOUNT);
assertEquals(outAccount.name, account.name);
- assertEquals(outAccount.accountFromAddressesUri, account.accountFromAddressesUri);
+ assertEquals(outAccount.accountFromAddresses, account.accountFromAddresses);
assertEquals(outAccount.capabilities, account.capabilities);
assertEquals(outAccount.providerVersion, account.providerVersion);
assertEquals(outAccount.uri, account.uri);