MessageCompose:

- set displayName for composed messages (from To:)
- set FLAG_LOADED
- do the save & send in an AsyncTask
- some clean-up
This commit is contained in:
Mihai Preda 2009-07-29 15:10:50 +02:00
parent b9f5134672
commit 2917e895c7
5 changed files with 273 additions and 268 deletions

View File

@ -198,6 +198,9 @@
<string name="message_compose_attachments_skipped_toast">Some attachments cannot be forwarded because they have not downloaded.</string>
<!-- Toast that appears when an attachment is too big to send. -->
<string name="message_compose_attachment_size">File too large to attach.</string>
<!-- Display name for composed message, indicating the destination of the message.
e.g. "John and 2 others" -->
<string name="message_compose_display_name">%s and %d others</string>
<!-- Label for To field in read message view -->
<string name="message_view_to_label">To:</string>
<!-- Label for CC field in read message view -->

View File

@ -205,21 +205,16 @@ public class Controller {
/**
* Saves the message to a mailbox of given type.
* This is a synchronous operation taking place in the same thread as the caller.
* Upon return the message.mId is set.
* @param message the message (must have the mAccountId set).
* @param mailboxType the mailbox type (e.g. Mailbox.TYPE_DRAFTS).
* TODO: UI feedback.
* TODO: use AsyncTask instead of Thread
*/
public void saveToMailbox(final EmailContent.Message message, final int mailboxType) {
new Thread() {
@Override
public void run() {
long accountId = message.mAccountKey;
long mailboxId = findOrCreateMailboxOfType(accountId, mailboxType);
message.mMailboxKey = mailboxId;
message.save(mContext);
}
}.start();
long accountId = message.mAccountKey;
long mailboxId = findOrCreateMailboxOfType(accountId, mailboxType);
message.mMailboxKey = mailboxId;
message.save(mContext);
}
/**

View File

@ -237,10 +237,6 @@ public class Email extends Application {
* The calls to log() must be guarded with "if (Email.LOGD)" for performance reasons.
*/
public static void log(String message) {
if (!Email.LOGD) {
// somebody called log() without the guard.
throw new IllegalStateException("Must guard with \"if (Email.LOGD)\"");
}
Log.d(LOG_TAG, message);
}
}

View File

@ -89,7 +89,6 @@ 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_MESSAGE_ID = "message_id";
private static final String STATE_KEY_ATTACHMENTS =
@ -109,13 +108,18 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
private static final int MSG_PROGRESS_OFF = 2;
private static final int MSG_UPDATE_TITLE = 3;
private static final int MSG_SKIPPED_ATTACHMENTS = 4;
private static final int MSG_SAVED_DRAFT = 5;
private static final int MSG_DISCARDED_DRAFT = 6;
private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1;
private Account mAccount;
private Message mSourceMessage;
// mDraft is null until the first save, afterwards it contains the last saved version.
private Message mDraft;
// mSource is only set for REPLY, REPLY_ALL and FORWARD, and contains the source message.
private Message mSource;
/**
* 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
@ -137,14 +141,8 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
private WebView mQuotedText;
private Controller mController;
private boolean mDraftNeedsSaving = false;
/**
* The draft uid of this message. This is used when saving drafts so that the same draft is
* overwritten instead of being created anew. This property is null until the first save.
*/
private String mDraftUid;
private Listener mListener = new Listener();
private boolean mDraftNeedsSaving;
private Handler mHandler = new Handler() {
@Override
@ -165,12 +163,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
getString(R.string.message_compose_attachments_skipped_toast),
Toast.LENGTH_LONG).show();
break;
case MSG_SAVED_DRAFT:
Toast.makeText(
MessageCompose.this,
getString(R.string.message_saved_toast),
Toast.LENGTH_LONG).show();
break;
case MSG_DISCARDED_DRAFT:
Toast.makeText(
MessageCompose.this,
@ -184,10 +176,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
}
};
private Listener mListener = new Listener();
private EmailAddressAdapter mAddressAdapter;
private Validator mAddressValidator;
/**
* Encapsulates known information about a single attachment.
*/
@ -212,7 +200,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
} catch (ActivityNotFoundException anfe) {
// Swallow it - this is usually a race condition, especially under automated test.
// (The message composer might have been disabled)
Log.d(Email.LOG_TAG, anfe.toString());
Email.log(anfe.toString());
}
}
@ -224,15 +212,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* @param replyAll
*/
public static void actionReply(Context context, long messageId, boolean replyAll) {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_MESSAGE_ID, messageId);
if (replyAll) {
i.setAction(ACTION_REPLY_ALL);
}
else {
i.setAction(ACTION_REPLY);
}
context.startActivity(i);
startActivityWithMessage(context, replyAll ? ACTION_REPLY_ALL : ACTION_REPLY, messageId);
}
/**
@ -241,10 +221,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* @param messageId
*/
public static void actionForward(Context context, long messageId) {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_MESSAGE_ID, messageId);
i.setAction(ACTION_FORWARD);
context.startActivity(i);
startActivityWithMessage(context, ACTION_FORWARD, messageId);
}
/**
@ -256,140 +233,24 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* @param messageId the message id.
*/
public static void actionEditDraft(Context context, long messageId) {
startActivityWithMessage(context, ACTION_EDIT_DRAFT, messageId);
}
private static void startActivityWithMessage(Context context, String action, long messageId) {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_MESSAGE_ID, messageId);
i.setAction(ACTION_EDIT_DRAFT);
i.setAction(action);
context.startActivity(i);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.message_compose);
mController = Controller.getInstance(getApplication());
initViews();
mAddressAdapter = new EmailAddressAdapter(this);
mAddressValidator = new EmailAddressValidator();
mToView = (MultiAutoCompleteTextView)findViewById(R.id.to);
mCcView = (MultiAutoCompleteTextView)findViewById(R.id.cc);
mBccView = (MultiAutoCompleteTextView)findViewById(R.id.bcc);
mSubjectView = (EditText)findViewById(R.id.subject);
mMessageContentView = (EditText)findViewById(R.id.message_content);
mSendButton = (Button)findViewById(R.id.send);
mDiscardButton = (Button)findViewById(R.id.discard);
mSaveButton = (Button)findViewById(R.id.save);
mAttachments = (LinearLayout)findViewById(R.id.attachments);
mQuotedTextBar = findViewById(R.id.quoted_text_bar);
mQuotedTextDelete = (ImageButton)findViewById(R.id.quoted_text_delete);
mQuotedText = (WebView)findViewById(R.id.quoted_text);
TextWatcher watcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start,
int before, int after) { }
public void onTextChanged(CharSequence s, int start,
int before, int count) {
mDraftNeedsSaving = true;
}
public void afterTextChanged(android.text.Editable s) { }
};
/**
* Implements special address cleanup rules:
* The first space key entry following an "@" symbol that is followed by any combination
* of letters and symbols, including one+ dots and zero commas, should insert an extra
* comma (followed by the space).
*/
InputFilter recipientFilter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
int dstart, int dend) {
// quick check - did they enter a single space?
if (end-start != 1 || source.charAt(start) != ' ') {
return null;
}
// determine if the characters before the new space fit the pattern
// follow backwards and see if we find a comma, dot, or @
int scanBack = dstart;
boolean dotFound = false;
while (scanBack > 0) {
char c = dest.charAt(--scanBack);
switch (c) {
case '.':
dotFound = true; // one or more dots are req'd
break;
case ',':
return null;
case '@':
if (!dotFound) {
return null;
}
// we have found a comma-insert case. now just do it
// in the least expensive way we can.
if (source instanceof Spanned) {
SpannableStringBuilder sb = new SpannableStringBuilder(",");
sb.append(source);
return sb;
} else {
return ", ";
}
default:
// just keep going
}
}
// no termination cases were found, so don't edit the input
return null;
}
};
InputFilter[] recipientFilters = new InputFilter[] { recipientFilter };
mToView.addTextChangedListener(watcher);
mCcView.addTextChangedListener(watcher);
mBccView.addTextChangedListener(watcher);
mSubjectView.addTextChangedListener(watcher);
mMessageContentView.addTextChangedListener(watcher);
// NOTE: assumes no other filters are set
mToView.setFilters(recipientFilters);
mCcView.setFilters(recipientFilters);
mBccView.setFilters(recipientFilters);
/*
* We set this to invisible by default. Other methods will turn it back on if it's
* needed.
*/
mQuotedTextBar.setVisibility(View.GONE);
mQuotedText.setVisibility(View.GONE);
mQuotedTextDelete.setOnClickListener(this);
mToView.setAdapter(mAddressAdapter);
mToView.setTokenizer(new Rfc822Tokenizer());
mToView.setValidator(mAddressValidator);
mCcView.setAdapter(mAddressAdapter);
mCcView.setTokenizer(new Rfc822Tokenizer());
mCcView.setValidator(mAddressValidator);
mBccView.setAdapter(mAddressAdapter);
mBccView.setTokenizer(new Rfc822Tokenizer());
mBccView.setValidator(mAddressValidator);
mSendButton.setOnClickListener(this);
mDiscardButton.setOnClickListener(this);
mSaveButton.setOnClickListener(this);
mSubjectView.setOnFocusChangeListener(this);
if (savedInstanceState != null) {
/*
* This data gets used in onCreate, so grab it here instead of onRestoreIntstanceState
@ -400,7 +261,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
Intent intent = getIntent();
final String action = intent.getAction();
mSourceMessage = null;
// Handle the various intents that launch the message composer
if (Intent.ACTION_VIEW.equals(action)
@ -412,7 +272,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
// There are no accounts set up. This should not have happened. Prompt the
// user to set up an account as an acceptable bailout.
AccountFolderList.actionShowAccounts(this);
mDraftNeedsSaving = false;
finish();
return;
} else {
@ -439,16 +298,8 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* want to reload the message every time the activity is resumed.
* There is no harm in adding twice.
*/
// TODO: signal the controller to load the message
// MessagingController.getInstance(getApplication()).addListener(mListener);
// MessagingController.getInstance(getApplication()).loadMessageForView(
// mAccount,
// mFolder,
// mSourceMessageUid,
// mListener);
}
updateTitle();
}
@ -500,7 +351,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
outState.putBoolean(STATE_KEY_QUOTED_TEXT_SHOWN,
mQuotedTextBar.getVisibility() == View.VISIBLE);
outState.putBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, mSourceMessageProcessed);
outState.putString(STATE_KEY_DRAFT_UID, mDraftUid);
// outState.putString(STATE_KEY_DRAFT_UID, mDraftUid);
}
@Override
@ -522,10 +373,130 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
View.VISIBLE : View.GONE);
mQuotedText.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ?
View.VISIBLE : View.GONE);
mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID);
// mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID);
mDraftNeedsSaving = false;
}
private void initViews() {
mToView = (MultiAutoCompleteTextView)findViewById(R.id.to);
mCcView = (MultiAutoCompleteTextView)findViewById(R.id.cc);
mBccView = (MultiAutoCompleteTextView)findViewById(R.id.bcc);
mSubjectView = (EditText)findViewById(R.id.subject);
mMessageContentView = (EditText)findViewById(R.id.message_content);
mSendButton = (Button)findViewById(R.id.send);
mDiscardButton = (Button)findViewById(R.id.discard);
mSaveButton = (Button)findViewById(R.id.save);
mAttachments = (LinearLayout)findViewById(R.id.attachments);
mQuotedTextBar = findViewById(R.id.quoted_text_bar);
mQuotedTextDelete = (ImageButton)findViewById(R.id.quoted_text_delete);
mQuotedText = (WebView)findViewById(R.id.quoted_text);
TextWatcher watcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start,
int before, int after) { }
public void onTextChanged(CharSequence s, int start,
int before, int count) {
mDraftNeedsSaving = true;
}
public void afterTextChanged(android.text.Editable s) { }
};
/**
* Implements special address cleanup rules:
* The first space key entry following an "@" symbol that is followed by any combination
* of letters and symbols, including one+ dots and zero commas, should insert an extra
* comma (followed by the space).
*/
InputFilter recipientFilter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
int dstart, int dend) {
// quick check - did they enter a single space?
if (end-start != 1 || source.charAt(start) != ' ') {
return null;
}
// determine if the characters before the new space fit the pattern
// follow backwards and see if we find a comma, dot, or @
int scanBack = dstart;
boolean dotFound = false;
while (scanBack > 0) {
char c = dest.charAt(--scanBack);
switch (c) {
case '.':
dotFound = true; // one or more dots are req'd
break;
case ',':
return null;
case '@':
if (!dotFound) {
return null;
}
// we have found a comma-insert case. now just do it
// in the least expensive way we can.
if (source instanceof Spanned) {
SpannableStringBuilder sb = new SpannableStringBuilder(",");
sb.append(source);
return sb;
} else {
return ", ";
}
default:
// just keep going
}
}
// no termination cases were found, so don't edit the input
return null;
}
};
InputFilter[] recipientFilters = new InputFilter[] { recipientFilter };
mToView.addTextChangedListener(watcher);
mCcView.addTextChangedListener(watcher);
mBccView.addTextChangedListener(watcher);
mSubjectView.addTextChangedListener(watcher);
mMessageContentView.addTextChangedListener(watcher);
// NOTE: assumes no other filters are set
mToView.setFilters(recipientFilters);
mCcView.setFilters(recipientFilters);
mBccView.setFilters(recipientFilters);
/*
* We set this to invisible by default. Other methods will turn it back on if it's
* needed.
*/
mQuotedTextBar.setVisibility(View.GONE);
mQuotedText.setVisibility(View.GONE);
mQuotedTextDelete.setOnClickListener(this);
EmailAddressAdapter addressAdapter = new EmailAddressAdapter(this);
EmailAddressValidator addressValidator = new EmailAddressValidator();
mToView.setAdapter(addressAdapter);
mToView.setTokenizer(new Rfc822Tokenizer());
mToView.setValidator(addressValidator);
mCcView.setAdapter(addressAdapter);
mCcView.setTokenizer(new Rfc822Tokenizer());
mCcView.setValidator(addressValidator);
mBccView.setAdapter(addressAdapter);
mBccView.setTokenizer(new Rfc822Tokenizer());
mBccView.setValidator(addressValidator);
mSendButton.setOnClickListener(this);
mDiscardButton.setOnClickListener(this);
mSaveButton.setOnClickListener(this);
mSubjectView.setOnFocusChangeListener(this);
}
// TODO: is there any way to unify this with MessageView.LoadMessageTask?
private class LoadMessageTask extends AsyncTask<Long, Void, Object[]> {
@Override
@ -540,9 +511,19 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
protected void onPostExecute(Object[] messageAndAccount) {
final Message message = (Message) messageAndAccount[0];
final Account account = (Account) messageAndAccount[1];
mSourceMessage = message;
final String action = getIntent().getAction();
if (ACTION_EDIT_DRAFT.equals(action)) {
mDraft = message;
} else if (ACTION_REPLY.equals(action)
|| ACTION_REPLY_ALL.equals(action)
|| ACTION_FORWARD.equals(action)) {
mSource = message;
} else if (Email.LOGD) {
Email.log("Action " + action + " has unexpected EXTRA_MESSAGE_ID");
}
mAccount = account;
processSourceMessage(message);
processSourceMessage(message, mAccount);
}
}
@ -592,7 +573,10 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
return addresses;
}
private String buildBodyText() {
/*
* Takes care to append source info and text in a REPLY or FORWARD situation.
*/
private String buildBodyText(Message sourceMessage) {
/*
* Build the Body that will contain the text of the message. We'll decide where to
* include it later.
@ -600,9 +584,9 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
final String action = getIntent().getAction();
String text = mMessageContentView.getText().toString();
if (mQuotedTextBar.getVisibility() == View.VISIBLE && mSourceMessage != null) {
String quotedText = mSourceMessage.mText;
String fromAsString = Address.unpackToString(mSourceMessage.mFrom);
if (mQuotedTextBar.getVisibility() == View.VISIBLE && sourceMessage != null) {
String quotedText = sourceMessage.mText;
String fromAsString = Address.unpackToString(sourceMessage.mFrom);
if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) {
text += String.format(getString(R.string.message_compose_reply_header_fmt),
fromAsString);
@ -610,14 +594,13 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
text += quotedText.replaceAll("(?m)^", ">");
}
} else if (ACTION_FORWARD.equals(action)) {
// mSourceMessage can be null during the unit-tests.
String subject = mSourceMessage.mSubject;
String subject = sourceMessage.mSubject;
text += String.format(
getString(R.string.message_compose_fwd_header_fmt),
subject,
fromAsString,
Address.unpackToString(mSourceMessage.mTo),
Address.unpackToString(mSourceMessage.mCc));
Address.unpackToString(sourceMessage.mTo),
Address.unpackToString(sourceMessage.mCc));
if (quotedText != null) {
text += quotedText;
}
@ -634,30 +617,56 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
values.put(MessageColumns.CC_LIST, message.mCc);
values.put(MessageColumns.BCC_LIST, message.mBcc);
values.put(MessageColumns.SUBJECT, message.mSubject);
values.put(MessageColumns.DISPLAY_NAME, message.mDisplayName);
values.put(MessageColumns.FLAG_LOADED, message.mFlagLoaded);
// 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.
*
/*
* Computes a short string indicating the destination of the message based on To, Cc, Bcc.
* If only one address appears, returns the friendly form of that address.
* Otherwise returns the friendly form of the first address appended with "and N others".
*/
private Message updateMessage(Message message) {
if (message == null) {
message = new Message();
private String makeDisplayName(String packedTo, String packedCc, String packedBcc) {
Address first = null;
int nRecipients = 0;
for (String packed: new String[] {packedTo, packedCc, packedBcc}) {
Address[] addresses = Address.unpack(packed);
nRecipients += addresses.length;
if (first == null && addresses.length > 0) {
first = addresses[0];
}
}
if (nRecipients == 0) {
return "";
}
String friendly = first.toFriendly();
if (nRecipients == 1) {
return friendly;
}
return this.getString(R.string.message_compose_display_name, friendly, nRecipients - 1);
}
/**
* @param message The message to be updated.
* @param account the account (used to obtain From: address).
* @param bodyText the body text.
*/
private void updateMessage(Message message, Account account, String bodyText) {
message.mTimeStamp = System.currentTimeMillis();
message.mFrom = new Address(mAccount.getEmailAddress(), mAccount.getSenderName()).pack();
message.mFrom = new Address(account.getEmailAddress(), account.getSenderName()).pack();
message.mTo = getPackedAddresses(mToView);
message.mCc = getPackedAddresses(mCcView);
message.mBcc = getPackedAddresses(mBccView);
message.mSubject = mSubjectView.getText().toString();
message.mText = buildBodyText();
message.mAccountKey = mAccount.mId;
// message.mFlagLoaded = Message.LOADED;
message.mText = bodyText;
message.mAccountKey = account.mId;
message.mDisplayName = makeDisplayName(message.mTo, message.mCc, message.mBcc);
message.mFlagLoaded = Message.LOADED;
// TODO: add attachments (as below)
return message;
}
// TextBody body = new TextBody(text);
// if (mAttachments.getChildCount() > 0) {
// /*
@ -695,50 +704,54 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
// }
/**
* Send a message:
* save to Drafts and invoke Controller.sendMessage().
* Send or save a message:
* - out of the UI thread
* - write to Drafts
* - if send, invoke Controller.sendMessage()
* - when operation is complete, display toast
*/
private void sendMessage() {
Message message = saveMessage();
mController.sendMessage(message.mId, message.mAccountKey);
}
/**
* Save a draft
* @return the id of the saved message.
*/
private Message saveMessage() {
final String action = getIntent().getAction();
Message message;
if (ACTION_EDIT_DRAFT.equals(action)) {
// The update doesn't modify the mailboxKey,
// so just keep the same mailbox which is already DRAFTS.
// TODO: move out of UI thread
message = updateMessage(mSourceMessage);
message.update(getApplication(), getUpdateContentValues(message));
} else {
message = updateMessage(null);
mController.saveToMailbox(message, EmailContent.Mailbox.TYPE_DRAFTS);
private void sendOrSaveMessage(final boolean send) {
if (mDraft == null) {
mDraft = new Message();
}
// if (mDraftUid != null) {
// message.setUid(mDraftUid);
// }
// else if (ACTION_EDIT_DRAFT.equals(getIntent().getAction())) {
// /*
// * We're saving a previously saved draft, so update the new message's uid
// * to the old message's uid.
// */
// message.setUid(mSourceMessageUid);
// }
// MessagingController.getInstance(getApplication()).saveDraft(mAccount, message);
// mDraftUid = message.getUid();
// Don't display the toast if the user is just changing the orientation
if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
mHandler.sendEmptyMessage(MSG_SAVED_DRAFT);
}
return message;
updateMessage(mDraft, mAccount, buildBodyText(mSource));
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
final String action = getIntent().getAction();
if (mDraft.isSaved()) {
mDraft.update(getApplication(), getUpdateContentValues(mDraft));
} else {
// saveToMailbox() is synchronous (in this same thread)
// so that mDraft.mId is set upon return
// (needed by the sendMessage() that happens afterwards).
mController.saveToMailbox(mDraft, EmailContent.Mailbox.TYPE_DRAFTS);
}
return null;
}
@Override
protected void onPostExecute(Void dummy) {
if (send) {
mController.sendMessage(mDraft.mId, mDraft.mAccountKey);
// Decide whether we need to show a Toast with something like
// "Message saved to Outbox for sending"
// or whether just the dismissing of the composing activity is enough feedback
// After a send it's no longer a draft; null it here just to be sure,
// although MessageCompose should just finish() anyway.
mDraft = null;
} else {
// Don't display the toast if the user is just changing the orientation
if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
Toast.makeText(MessageCompose.this, getString(R.string.message_saved_toast),
Toast.LENGTH_LONG).show();
}
}
}
}.execute();
}
private void saveIfNeeded() {
@ -746,7 +759,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
return;
}
mDraftNeedsSaving = false;
saveMessage();
sendOrSaveMessage(false);
}
/**
@ -774,15 +787,15 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
Toast.makeText(this, getString(R.string.message_compose_error_no_recipients),
Toast.LENGTH_LONG).show();
} else {
sendMessage();
sendOrSaveMessage(true);
mDraftNeedsSaving = false;
finish();
}
}
private void onDiscard() {
if (ACTION_EDIT_DRAFT.equals(getIntent().getAction()) && mSourceMessage != null) {
mController.deleteMessage(mSourceMessage.mId, mSourceMessage.mAccountKey);
if (mDraft != null) {
mController.deleteMessage(mDraft.mId, mDraft.mAccountKey);
}
mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT);
mDraftNeedsSaving = false;
@ -1112,9 +1125,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
return URLDecoder.decode(s, "UTF-8");
}
/*
* This method de-dups code from processSourceMessage().
*/
// used by processSourceMessage()
private void displayQuotedText(Message message) {
boolean plainTextFlag = message.mHtml == null;
String text = plainTextFlag ? message.mText : message.mHtml;
@ -1136,7 +1147,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
* @param message
*/
/* package */
void processSourceMessage(Message message) {
void processSourceMessage(Message message, Account account) {
final String action = getIntent().getAction();
mDraftNeedsSaving = true;
final String subject = message.mSubject;
@ -1159,7 +1170,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
if (ACTION_REPLY_ALL.equals(action)) {
for (Address address : Address.unpack(message.mTo)) {
if (!address.getAddress().equalsIgnoreCase(mAccount.mEmailAddress)) {
if (!address.getAddress().equalsIgnoreCase(account.mEmailAddress)) {
addAddress(mToView, address.toString());
}
}

View File

@ -151,7 +151,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(SENDER + ", ", null, null, "Re: " + SUBJECT, null);
checkFocused(mMessageView);
}
@ -163,7 +163,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
resetViews();
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(REPLYTO + ", ", null, null, "Re: " + SUBJECT, null);
checkFocused(mMessageView);
}
@ -182,7 +182,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF16_SENDER + ", ", null, null, "Re: " + UTF16_SUBJECT, null);
checkFocused(mMessageView);
}
@ -194,7 +194,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
resetViews();
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF16_REPLYTO + ", ", null, null, "Re: " + UTF16_SUBJECT, null);
checkFocused(mMessageView);
}
@ -213,7 +213,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF32_SENDER + ", ", null, null, "Re: " + UTF32_SUBJECT, null);
checkFocused(mMessageView);
}
@ -225,7 +225,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
resetViews();
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF32_REPLYTO + ", ", null, null, "Re: " + UTF32_SUBJECT, null);
checkFocused(mMessageView);
}
@ -246,7 +246,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(null, null, null, "Fwd: " + SUBJECT, null);
checkFocused(mToView);
}
@ -271,7 +271,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(RECIPIENT_TO + ", ", null, null, SUBJECT, BODY);
checkFocused(mMessageView);
}
@ -284,7 +284,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
resetViews();
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(RECIPIENT_TO + ", ", null, null, null, BODY);
checkFocused(mSubjectView);
}
@ -306,7 +306,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF16_RECIPIENT_TO + ", ",
null, null, UTF16_SUBJECT, UTF16_BODY);
checkFocused(mMessageView);
@ -320,7 +320,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
resetViews();
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF16_RECIPIENT_TO + ", ", null, null, null, UTF16_BODY);
checkFocused(mSubjectView);
}
@ -342,7 +342,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF32_RECIPIENT_TO + ", ",
null, null, UTF32_SUBJECT, UTF32_BODY);
checkFocused(mMessageView);
@ -356,7 +356,7 @@ public class MessageComposeInstrumentationTests
runTestOnUiThread(new Runnable() {
public void run() {
resetViews();
a.processSourceMessage(message);
a.processSourceMessage(message, null);
checkFields(UTF32_RECIPIENT_TO + ", ", null, null, null, UTF32_BODY);
checkFocused(mSubjectView);
}