Clean-up in MessageCompose, using EmailContent.Message.

Difficulties:
re-enable EmailHtmlUtil.resolveInlineImage() and
MessageCompose.loadAttachments() that operate on MIME parts.
This commit is contained in:
Mihai Preda 2009-07-17 14:58:23 -07:00
parent 852974bc0b
commit 21ace307e0
8 changed files with 247 additions and 299 deletions

View File

@ -801,7 +801,8 @@ public class FolderMessageList extends ExpandableListActivity {
}
if (folder.drafts) {
MessageCompose.actionEditDraft(this, mAccountId, message.message);
// actionEditDraft() now takes messageId only
// MessageCompose.actionEditDraft(this, mAccountId, message.message);
}
else {
ArrayList<String> folderUids = new ArrayList<String>();
@ -863,15 +864,18 @@ public class FolderMessageList extends ExpandableListActivity {
}
private void onReply(MessageInfoHolder holder) {
MessageCompose.actionReply(this, mAccountId, holder.message, false);
// now uses messageId
// MessageCompose.actionReply(this, mAccountId, holder.message, false);
}
private void onReplyAll(MessageInfoHolder holder) {
MessageCompose.actionReply(this, mAccountId, holder.message, true);
// now uses messageId
// MessageCompose.actionReply(this, mAccountId, holder.message, true);
}
private void onForward(MessageInfoHolder holder) {
MessageCompose.actionForward(this, mAccountId, holder.message);
// now uses messageId
// MessageCompose.actionForward(this, mAccountId, holder.message);
}
private void onToggleRead(MessageInfoHolder holder) {

View File

@ -37,10 +37,12 @@ import com.android.email.mail.internet.MimeUtility;
import com.android.email.mail.store.LocalStore.LocalAttachmentBody;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.MessageColumns;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@ -86,8 +88,8 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
private static final String ACTION_EDIT_DRAFT = "com.android.email.intent.action.EDIT_DRAFT";
private static final String EXTRA_ACCOUNT_ID = "account_id";
private static final String EXTRA_FOLDER = "folder";
private static final String EXTRA_MESSAGE = "message";
private static final String EXTRA_MESSAGE_ID = "message_id";
private static final String STATE_KEY_ATTACHMENTS =
"com.android.email.activity.MessageCompose.attachments";
@ -113,9 +115,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
private long mAccountId;
private Account mAccount;
private String mFolder;
private String mSourceMessageUid;
private Message mSourceMessage;
private EmailContent.Message mSourceMessage;
/**
* Indicates that the source message has been processed at least once and should not
* be processed on any subsequent loads. This protects us from adding attachments that
@ -145,6 +145,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* overwritten instead of being created anew. This property is null until the first save.
*/
private String mDraftUid;
private String mAction;
private Handler mHandler = new Handler() {
@Override
@ -208,18 +209,11 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
try {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_ACCOUNT_ID, accountId);
/*
* TODO handle drafts via role # note via string
* Is this used? Do we ever compose anywhere else but in drafts?
*/
i.putExtra(EXTRA_FOLDER, context.getString(R.string.special_mailbox_name_drafts));
context.startActivity(i);
} catch (ActivityNotFoundException anfe) {
// Swallow it - this is usually a race condition, especially under automated test.
// (The message composer might have been disabled)
if (Config.LOGD) {
Log.d(Email.LOG_TAG, anfe.toString());
}
Log.d(Email.LOG_TAG, anfe.toString());
}
}
@ -227,19 +221,12 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* Compose a new message as a reply to the given message. If replyAll is true the function
* is reply all instead of simply reply.
* @param context
* @param account
* @param message
* @param messageId
* @param replyAll
*/
public static void actionReply(
Context context,
long accountId,
Message message,
boolean replyAll) {
public static void actionReply(Context context, long messageId, boolean replyAll) {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_ACCOUNT_ID, accountId);
i.putExtra(EXTRA_FOLDER, message.getFolder().getName());
i.putExtra(EXTRA_MESSAGE, message.getUid());
i.putExtra(EXTRA_MESSAGE_ID, messageId);
if (replyAll) {
i.setAction(ACTION_REPLY_ALL);
}
@ -252,14 +239,11 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
/**
* Compose a new message as a forward of the given message.
* @param context
* @param account
* @param message
* @param messageId
*/
public static void actionForward(Context context, long accountId, Message message) {
public static void actionForward(Context context, long messageId) {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_ACCOUNT_ID, accountId);
i.putExtra(EXTRA_FOLDER, message.getFolder().getName());
i.putExtra(EXTRA_MESSAGE, message.getUid());
i.putExtra(EXTRA_MESSAGE_ID, messageId);
i.setAction(ACTION_FORWARD);
context.startActivity(i);
}
@ -270,14 +254,11 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* Save will attempt to replace the message in the given folder with the updated version.
* Discard will delete the message from the given folder.
* @param context
* @param account
* @param message
* @param messageId the message id.
*/
public static void actionEditDraft(Context context, long accountId, Message message) {
public static void actionEditDraft(Context context, long messageId) {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_ACCOUNT_ID, accountId);
i.putExtra(EXTRA_FOLDER, message.getFolder().getName());
i.putExtra(EXTRA_MESSAGE, message.getUid());
i.putExtra(EXTRA_MESSAGE_ID, messageId);
i.setAction(ACTION_EDIT_DRAFT);
context.startActivity(i);
}
@ -420,12 +401,12 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
Intent intent = getIntent();
String action = intent.getAction();
mAction = intent.getAction();
// Handle the various intents that launch the message composer
if (Intent.ACTION_VIEW.equals(action) || Intent.ACTION_SENDTO.equals(action) ||
(Intent.ACTION_SEND.equals(action))) {
if (Intent.ACTION_VIEW.equals(mAction)
|| Intent.ACTION_SENDTO.equals(mAction)
|| Intent.ACTION_SEND.equals(mAction)) {
// Check first for a valid account
mAccountId = Account.getDefaultAccountId(this);
if (mAccountId == -1) {
@ -444,27 +425,28 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
}
else {
// Otherwise, handle the internal cases (Message Composer invoked from within app)
mAccountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
long messageId = intent.getLongExtra(EXTRA_MESSAGE_ID, -1);
mSourceMessage = EmailContent.Message.restoreMessageWithId(this, messageId);
mAccountId = mSourceMessage.mAccountKey;
mAccount = Account.restoreAccountWithId(this, mAccountId);
mFolder = intent.getStringExtra(EXTRA_FOLDER);
// TODO: change sourceMessageUid to be long _id instead of String
mSourceMessageUid = intent.getStringExtra(EXTRA_MESSAGE);
}
if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action) ||
ACTION_FORWARD.equals(action) || ACTION_EDIT_DRAFT.equals(action)) {
if (ACTION_REPLY.equals(mAction) || ACTION_REPLY_ALL.equals(mAction) ||
ACTION_FORWARD.equals(mAction) || ACTION_EDIT_DRAFT.equals(mAction)) {
/*
* If we need to load the message we add ourself as a message listener here
* so we can kick it off. Normally we add in onResume but we don't
* want to reload the message every time the activity is resumed.
* There is no harm in adding twice.
*/
MessagingController.getInstance(getApplication()).addListener(mListener);
MessagingController.getInstance(getApplication()).loadMessageForView(
mAccount,
mFolder,
mSourceMessageUid,
mListener);
// TODO: signal the controller to load the message
// MessagingController.getInstance(getApplication()).addListener(mListener);
// MessagingController.getInstance(getApplication()).loadMessageForView(
// mAccount,
// mFolder,
// mSourceMessageUid,
// mListener);
}
updateTitle();
@ -590,24 +572,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
return addresses;
}
private EmailContent.Message createMessage() throws MessagingException {
EmailContent.Message message = new EmailContent.Message();
message.mTimeStamp = System.currentTimeMillis();
message.mFrom = new Address(mAccount.getEmailAddress(), mAccount.getSenderName()).pack();
message.mTo = getPackedAddresses(mToView);
message.mCc = getPackedAddresses(mCcView);
message.mBcc = getPackedAddresses(mBccView);
message.mSubject = mSubjectView.getText().toString();
// Preserve Message-ID header if found
// This makes sure that multiply-saved drafts are identified as the same message
if (mSourceMessage != null && mSourceMessage instanceof MimeMessage) {
String messageIdHeader = ((MimeMessage)mSourceMessage).getMessageId();
if (messageIdHeader != null) {
message.mMessageId = messageIdHeader;
}
}
private String buildBodyText() {
/*
* Build the Body that will contain the text of the message. We'll decide where to
* include it later.
@ -615,39 +580,61 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
String text = mMessageContentView.getText().toString();
if (mQuotedTextBar.getVisibility() == View.VISIBLE) {
String action = getIntent().getAction();
String quotedText = null;
Part part = MimeUtility.findFirstPartByMimeType(mSourceMessage,
"text/plain");
if (part != null) {
quotedText = MimeUtility.getTextFromPart(part);
}
if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) {
text += String.format(
getString(R.string.message_compose_reply_header_fmt),
Address.toString(mSourceMessage.getFrom()));
if (mQuotedTextBar.getVisibility() == View.VISIBLE && mSourceMessage != null) {
String quotedText = mSourceMessage.mText;
String fromAsString = Address.unpackToString(mSourceMessage.mFrom);
if (ACTION_REPLY.equals(mAction) || ACTION_REPLY_ALL.equals(mAction)) {
text += String.format(getString(R.string.message_compose_reply_header_fmt),
fromAsString);
if (quotedText != null) {
text += quotedText.replaceAll("(?m)^", ">");
}
}
else if (ACTION_FORWARD.equals(action)) {
} else if (ACTION_FORWARD.equals(mAction)) {
// mSourceMessage can be null during the unit-tests.
String subject = mSourceMessage.mSubject;
text += String.format(
getString(R.string.message_compose_fwd_header_fmt),
mSourceMessage.getSubject(),
Address.toString(mSourceMessage.getFrom()),
Address.toString(
mSourceMessage.getRecipients(RecipientType.TO)),
Address.toString(
mSourceMessage.getRecipients(RecipientType.CC)));
subject,
fromAsString,
Address.unpackToString(mSourceMessage.mTo),
Address.unpackToString(mSourceMessage.mCc));
if (quotedText != null) {
text += quotedText;
}
}
}
return text;
}
message.mText = text;
private ContentValues getUpdateContentValues(EmailContent.Message message) {
ContentValues values = new ContentValues();
values.put(MessageColumns.TIMESTAMP, message.mTimeStamp);
values.put(MessageColumns.FROM_LIST, message.mFrom);
values.put(MessageColumns.TO_LIST, message.mTo);
values.put(MessageColumns.CC_LIST, message.mCc);
values.put(MessageColumns.BCC_LIST, message.mBcc);
values.put(MessageColumns.SUBJECT, message.mSubject);
// TODO: write body and update TEXT_INFO
return values;
}
/**
* @param message The message to be updated. If it's null, a new message is created.
*
*/
private EmailContent.Message updateMessage(EmailContent.Message message) {
if (message == null) {
message = new EmailContent.Message();
}
message.mTimeStamp = System.currentTimeMillis();
message.mFrom = new Address(mAccount.getEmailAddress(), mAccount.getSenderName()).pack();
message.mTo = getPackedAddresses(mToView);
message.mCc = getPackedAddresses(mCcView);
message.mBcc = getPackedAddresses(mBccView);
message.mSubject = mSubjectView.getText().toString();
message.mText = buildBodyText();
message.mAccountKey = mAccountId;
// message.mFlagLoaded = EmailContent.Message.LOADED;
// TODO: add attachments (as below)
return message;
}
@ -687,25 +674,21 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
// message.setBody(body);
// }
private void sendOrSaveMessage(boolean save) {
/*
* Create the message from all the data the user has entered.
*/
EmailContent.Message message;
try {
message = createMessage();
}
catch (MessagingException me) {
Log.e(Email.LOG_TAG, "Failed to create new message for send or save.", me);
throw new RuntimeException("Failed to create a new message for send or save.", me);
}
if (save) {
/*
* Save a draft
*/
mController.saveToMailbox(message, EmailContent.Mailbox.TYPE_DRAFTS);
if (ACTION_EDIT_DRAFT.equals(mAction)) {
// The update doesn't modify the mailboxKey,
// so just keep the same mailbox which is already DRAFTS.
// TODO: move out of UI thread
EmailContent.Message message = updateMessage(mSourceMessage);
message.update(getApplication(), getUpdateContentValues(message));
} else {
EmailContent.Message message = updateMessage(null);
mController.saveToMailbox(message, EmailContent.Mailbox.TYPE_DRAFTS);
}
// if (mDraftUid != null) {
// message.setUid(mDraftUid);
@ -787,14 +770,8 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
}
private void onDiscard() {
if (mSourceMessageUid != null) {
if (ACTION_EDIT_DRAFT.equals(getIntent().getAction()) && mSourceMessageUid != null) {
MessagingController.getInstance(getApplication()).deleteMessage(
mAccount,
mFolder,
mSourceMessage,
null);
}
if (ACTION_EDIT_DRAFT.equals(getIntent().getAction()) && mSourceMessage != null) {
mController.deleteMessage(mSourceMessage.mId, mSourceMessage.mAccountKey);
}
mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT);
mDraftNeedsSaving = false;
@ -1124,158 +1101,104 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
return URLDecoder.decode(s, "UTF-8");
}
/*
* This method de-dups code from processSourceMessage().
*/
private void displayQuotedText(EmailContent.Message message) {
boolean plainTextFlag = message.mHtml == null;
String text = plainTextFlag ? message.mText : message.mHtml;
if (text != null) {
text = plainTextFlag ? EmailHtmlUtil.escapeCharacterToDisplay(text) : text;
// TODO: re-enable EmailHtmlUtil.resolveInlineImage() for HTML
// EmailHtmlUtil.resolveInlineImage(getContentResolver(), mAccount,
// text, message, 0);
mQuotedTextBar.setVisibility(View.VISIBLE);
mQuotedText.setVisibility(View.VISIBLE);
mQuotedText.loadDataWithBaseURL("email://", text, "text/html",
"utf-8", null);
}
}
/**
* Pull out the parts of the now loaded source message and apply them to the new message
* depending on the type of message being composed.
* @param message
*/
/* package */ /**
* @param message
*/
void processSourceMessage(Message message) {
/* package */
void processSourceMessage(EmailContent.Message message) {
String action = getIntent().getAction();
if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) {
try {
if (message.getSubject() != null &&
!message.getSubject().toLowerCase().startsWith("re:")) {
mSubjectView.setText("Re: " + message.getSubject());
}
else {
mSubjectView.setText(message.getSubject());
}
/*
* If a reply-to was included with the message use that, otherwise use the from
* or sender address.
*/
Address[] replyToAddresses;
if (message.getReplyTo().length > 0) {
addAddresses(mToView, replyToAddresses = message.getReplyTo());
}
else {
addAddresses(mToView, replyToAddresses = message.getFrom());
}
if (ACTION_REPLY_ALL.equals(action)) {
for (Address address : message.getRecipients(RecipientType.TO)) {
if (!address.getAddress().equalsIgnoreCase(mAccount.getEmailAddress())) {
addAddress(mToView, address.toString());
}
}
if (message.getRecipients(RecipientType.CC).length > 0) {
for (Address address : message.getRecipients(RecipientType.CC)) {
if (!Utility.arrayContains(replyToAddresses, address)) {
addAddress(mCcView, address.toString());
}
}
mCcView.setVisibility(View.VISIBLE);
}
}
Boolean plainTextFlag = false;
Part part = MimeUtility.findFirstPartByMimeType(message, "text/html");
if (part == null) {
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
plainTextFlag = true;
}
if (part != null) {
String text = MimeUtility.getTextFromPart(part);
if (text != null) {
if (!plainTextFlag) {
text = EmailHtmlUtil.resolveInlineImage(
getContentResolver(), mAccount, text, message, 0);
} else {
text = EmailHtmlUtil.escapeCharacterToDisplay(text);
}
mQuotedTextBar.setVisibility(View.VISIBLE);
mQuotedText.setVisibility(View.VISIBLE);
mQuotedText.loadDataWithBaseURL("email://", text, "text/html",
"utf-8", null);
}
}
mDraftNeedsSaving = true;
final String subject = message.mSubject;
if (ACTION_REPLY.equals(mAction) || ACTION_REPLY_ALL.equals(mAction)) {
if (subject != null && !subject.toLowerCase().startsWith("re:")) {
mSubjectView.setText("Re: " + subject);
} else {
mSubjectView.setText(subject);
}
catch (MessagingException me) {
/*
* This really should not happen at this point but if it does it's okay.
* The user can continue composing their message.
*/
/*
* If a reply-to was included with the message use that, otherwise use the from
* or sender address.
*/
Address[] replyToAddresses = Address.unpack(message.mReplyTo);
if (replyToAddresses.length == 0) {
replyToAddresses = Address.unpack(message.mFrom);
}
}
else if (ACTION_FORWARD.equals(action)) {
try {
if (message.getSubject() != null &&
!message.getSubject().toLowerCase().startsWith("fwd:")) {
mSubjectView.setText("Fwd: " + message.getSubject());
}
else {
mSubjectView.setText(message.getSubject());
}
addAddresses(mToView, replyToAddresses);
Boolean plainTextFlag = false;
Part part = MimeUtility.findFirstPartByMimeType(message, "text/html");
if (part == null) {
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
plainTextFlag = true;
}
if (part != null) {
String text = MimeUtility.getTextFromPart(part);
if (text != null) {
if (!plainTextFlag) {
text = EmailHtmlUtil.resolveInlineImage(
getContentResolver(), mAccount, text, message, 0);
} else {
text = EmailHtmlUtil.escapeCharacterToDisplay(text);
}
mQuotedTextBar.setVisibility(View.VISIBLE);
mQuotedText.setVisibility(View.VISIBLE);
mQuotedText.loadDataWithBaseURL("email://", text, "text/html",
"utf-8", null);
if (ACTION_REPLY_ALL.equals(mAction)) {
for (Address address : Address.unpack(message.mTo)) {
if (!address.getAddress().equalsIgnoreCase(mAccount.mEmailAddress)) {
addAddress(mToView, address.toString());
}
}
if (!mSourceMessageProcessed) {
if (!loadAttachments(message, 0)) {
mHandler.sendEmptyMessage(MSG_SKIPPED_ATTACHMENTS);
boolean makeCCVisible = false;
for (Address address : Address.unpack(message.mCc)) {
if (!Utility.arrayContains(replyToAddresses, address)) {
addAddress(mCcView, address.toString());
makeCCVisible = true;
}
}
}
catch (MessagingException me) {
/*
* This really should not happen at this point but if it does it's okay.
* The user can continue composing their message.
*/
}
}
else if (ACTION_EDIT_DRAFT.equals(action)) {
try {
mSubjectView.setText(message.getSubject());
addAddresses(mToView, message.getRecipients(RecipientType.TO));
if (message.getRecipients(RecipientType.CC).length > 0) {
addAddresses(mCcView, message.getRecipients(RecipientType.CC));
if (makeCCVisible) {
mCcView.setVisibility(View.VISIBLE);
}
if (message.getRecipients(RecipientType.BCC).length > 0) {
addAddresses(mBccView, message.getRecipients(RecipientType.BCC));
mBccView.setVisibility(View.VISIBLE);
}
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
if (part != null) {
String text = MimeUtility.getTextFromPart(part);
mMessageContentView.setText(text);
}
if (!mSourceMessageProcessed) {
loadAttachments(message, 0);
}
}
catch (MessagingException me) {
// TODO
displayQuotedText(message);
} else if (ACTION_FORWARD.equals(mAction)) {
mSubjectView.setText(subject != null && !subject.toLowerCase().startsWith("fwd:") ?
"Fwd: " + subject : subject);
displayQuotedText(message);
if (!mSourceMessageProcessed) {
// TODO: re-enable loadAttachments below
// if (!loadAttachments(message, 0)) {
// mHandler.sendEmptyMessage(MSG_SKIPPED_ATTACHMENTS);
// }
}
} else if (ACTION_EDIT_DRAFT.equals(mAction)) {
mSubjectView.setText(subject);
addAddresses(mToView, Address.unpack(message.mTo));
Address[] cc = Address.unpack(message.mCc);
if (cc.length > 0) {
addAddresses(mCcView, cc);
mCcView.setVisibility(View.VISIBLE);
}
Address[] bcc = Address.unpack(message.mBcc);
if (bcc.length > 0) {
addAddresses(mBccView, bcc);
mBccView.setVisibility(View.VISIBLE);
}
// TODO: why not the same text handling as in displayQuotedText() ?
mMessageContentView.setText(message.mText);
if (!mSourceMessageProcessed) {
// TODO: re-enable loadAttachments
// loadAttachments(message, 0);
}
mDraftNeedsSaving = false;
}
setNewMessageFocus();
mSourceMessageProcessed = true;
mDraftNeedsSaving = mFolder != null && !mFolder.equals(mAccount.getDraftsFolderName(this));
}
/**
@ -1316,12 +1239,13 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
@Override
public void loadMessageForViewBodyAvailable(Account account, String folder,
String uid, final Message message) {
mSourceMessage = message;
runOnUiThread(new Runnable() {
public void run() {
processSourceMessage(message);
}
});
// TODO: convert uid to EmailContent.Message and re-do what's below
// mSourceMessage = message;
// runOnUiThread(new Runnable() {
// public void run() {
// processSourceMessage(message);
// }
// });
}
@Override
@ -1330,23 +1254,5 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
// TODO show network error
}
@Override
public void messageUidChanged(Account account, String folder,String oldUid,
String newUid) {
if (account.equals(mAccount) && (folder.equals(mFolder)
|| (mFolder == null
&& folder.equals(mAccount.getDraftsFolderName(MessageCompose.this))))) {
if (oldUid.equals(mDraftUid)) {
mDraftUid = newUid;
}
if (oldUid.equals(mSourceMessageUid)) {
mSourceMessageUid = newUid;
}
if (mSourceMessage != null && (oldUid.equals(mSourceMessage.getUid()))) {
mSourceMessage.setUid(newUid);
}
}
}
}
}

View File

@ -420,8 +420,7 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
EmailContent.Mailbox mailbox = EmailContent.Mailbox.restoreMailboxWithId(this, mailboxId);
if (mailbox.mType == EmailContent.Mailbox.TYPE_DRAFTS) {
// TODO need id-based API for MessageCompose
// MessageCompose.actionEditDraft(this, messageId);
MessageCompose.actionEditDraft(this, messageId);
} else {
MessageView.actionView(this, messageId);
}

View File

@ -592,21 +592,21 @@ public class MessageView extends Activity
private void onReply() {
if (mOldMessage != null) {
MessageCompose.actionReply(this, mAccountId, mOldMessage, false);
MessageCompose.actionReply(this, mMessage.mId, false);
finish();
}
}
private void onReplyAll() {
if (mOldMessage != null) {
MessageCompose.actionReply(this, mAccountId, mOldMessage, true);
MessageCompose.actionReply(this, mMessage.mId, true);
finish();
}
}
private void onForward() {
if (mOldMessage != null) {
MessageCompose.actionForward(this, mAccountId, mOldMessage);
MessageCompose.actionForward(this, mMessage.mId);
finish();
}
}

View File

@ -177,6 +177,14 @@ public class Address {
@Override
public boolean equals(Object o) {
if (o instanceof Address) {
// It seems that the spec says that the "user" part is case-sensitive,
// while the domain part in case-insesitive.
// So foo@yahoo.com and Foo@yahoo.com are different.
// This may seem non-intuitive from the user POV, so we
// may re-consider it if it creates UI trouble.
// A problem case is "replyAll" sending to both
// a@b.c and to A@b.c, which turn out to be the same on the server.
// Leave unchanged for now (i.e. case-sensitive).
return getAddress().equals(((Address) o).getAddress());
}
return super.equals(o);
@ -295,6 +303,19 @@ public class Address {
return sb.toString();
}
/**
* Returns exactly the same result as Address.toString(Address.unpack(packedList)).
*/
public static String unpackToString(String packedList) {
return toString(unpack(packedList));
}
/**
* Returns exactly the same result as Address.pack(Address.parse(textList)).
*/
public static String parseAndPack(String textList) {
return Address.pack(Address.parse(textList));
}
/**
* Unpacks an address list previously packed with pack()
* @param addressList String with packed addresses as returned by pack()

View File

@ -35,6 +35,7 @@ public class EmailHtmlUtil {
// multiple continuous spaces.
private static final Pattern PLAIN_TEXT_TO_ESCAPE = Pattern.compile("[<>&]| {2,}|\r?\n");
//TODO: make resolveInlineImage() work in the new content provider model.
/**
* Resolve content-id reference in src attribute of img tag to AttachmentProvider's
* content uri. This method calls itself recursively at most the number of

View File

@ -20,13 +20,13 @@ import com.android.email.Email;
import com.android.email.R;
import com.android.email.EmailAddressValidator;
import com.android.email.mail.Address;
import com.android.email.mail.Message;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Message.RecipientType;
import com.android.email.mail.internet.MimeMessage;
import com.android.email.mail.internet.TextBody;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Message;
import android.content.Context;
import android.content.Intent;
@ -157,8 +157,8 @@ public class MessageComposeInstrumentationTests
}
});
message.setFrom(null);
message.setReplyTo(Address.parse(REPLYTO));
message.mFrom = null;
message.mReplyTo = Address.parseAndPack(REPLYTO);
runTestOnUiThread(new Runnable() {
public void run() {
@ -188,8 +188,8 @@ public class MessageComposeInstrumentationTests
}
});
message.setFrom(null);
message.setReplyTo(Address.parse(UTF16_REPLYTO));
message.mFrom = null;
message.mReplyTo = Address.parseAndPack(UTF16_REPLYTO);
runTestOnUiThread(new Runnable() {
public void run() {
@ -219,8 +219,8 @@ public class MessageComposeInstrumentationTests
}
});
message.setFrom(null);
message.setReplyTo(Address.parse(UTF32_REPLYTO));
message.mFrom = null;
message.mReplyTo = Address.parseAndPack(UTF32_REPLYTO);
runTestOnUiThread(new Runnable() {
public void run() {
@ -238,8 +238,7 @@ public class MessageComposeInstrumentationTests
* Subject = Fwd: Subject
* Body = empty
*/
public void testProcessSourceMessageForward() throws MessagingException, Throwable {
public void testProcessSourceMessageForward() throws MessagingException, Throwable {
final Message message = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
Intent intent = new Intent(ACTION_FORWARD);
final MessageCompose a = getActivity();
@ -280,7 +279,7 @@ public class MessageComposeInstrumentationTests
// if subject is null, then cursor should be there instead
message.setSubject("");
message.mSubject = "";
runTestOnUiThread(new Runnable() {
public void run() {
@ -316,7 +315,7 @@ public class MessageComposeInstrumentationTests
// if subject is null, then cursor should be there instead
message.setSubject("");
message.mSubject = "";
runTestOnUiThread(new Runnable() {
public void run() {
@ -352,7 +351,7 @@ public class MessageComposeInstrumentationTests
// if subject is null, then cursor should be there instead
message.setSubject("");
message.mSubject = "";
runTestOnUiThread(new Runnable() {
public void run() {
@ -553,28 +552,25 @@ public class MessageComposeInstrumentationTests
* @param content Content of the message
* @return a complete Message object
*/
private Message buildTestMessage(String to, String sender, String subject, String content)
private Message buildTestMessage(String to, String sender,
String subject, String content)
throws MessagingException {
Message message = new MimeMessage();
Message message = new Message();
if (to != null) {
Address[] addresses = Address.parse(to);
message.setRecipients(RecipientType.TO, addresses);
message.mTo = Address.parseAndPack(to);
}
if (sender != null) {
Address[] addresses = Address.parse(sender);
assertTrue("from address", addresses.length > 0);
message.setFrom(addresses[0]);
message.mFrom = addresses[0].pack();
}
if (subject != null) {
message.setSubject(subject);
}
message.mSubject = subject;
if (content != null) {
TextBody body = new TextBody(content);
message.setBody(body);
message.mText = content;
}
return message;

View File

@ -560,6 +560,27 @@ public class AddressUnitTests extends AndroidTestCase {
}
}
/**
* Tests that unpackToString() returns the same result as toString(unpack()).
*/
public void testUnpackToString() {
for (Address[] list : PACK_CASES) {
String packed = Address.pack(list);
String s1 = Address.unpackToString(packed);
String s2 = Address.toString(Address.unpack(packed));
assertEquals(s2, s2, s1);
}
}
/**
* Tests that parseAndPack() returns the same result as pack(parse()).
*/
public void testParseAndPack() {
String s1 = Address.parseAndPack(MULTI_ADDRESSES_LIST);
String s2 = Address.pack(Address.parse(MULTI_ADDRESSES_LIST));
assertEquals(s2, s1);
}
public void testSinglePack() {
Address[] addrArray = new Address[1];
for (Address address : new Address[]{PACK_ADDR_1, PACK_ADDR_2, PACK_ADDR_3}) {