Don't save empty drafts.
Note: all unicode sending unit tests are broken due to chip issues. I've filed a separate bug on that. Bug: 5012204 Change-Id: I17392f65e5bd8349780b79d9cbe10492d8e7a7d9
This commit is contained in:
parent
1086830bae
commit
0796b8aa61
|
@ -198,6 +198,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
private Controller mController;
|
private Controller mController;
|
||||||
private boolean mDraftNeedsSaving;
|
private boolean mDraftNeedsSaving;
|
||||||
private boolean mMessageLoaded;
|
private boolean mMessageLoaded;
|
||||||
|
private boolean mInitiallyEmpty;
|
||||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||||
|
|
||||||
private AccountSpecifier mAddressAdapterTo;
|
private AccountSpecifier mAddressAdapterTo;
|
||||||
|
@ -215,7 +216,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged(CharSequence s, int start,
|
public void onTextChanged(CharSequence s, int start,
|
||||||
int before, int count) {
|
int before, int count) {
|
||||||
setDraftNeedsSaving(true);
|
setMessageChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -394,7 +395,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
|| Intent.ACTION_SEND.equals(mAction)
|
|| Intent.ACTION_SEND.equals(mAction)
|
||||||
|| Intent.ACTION_SEND_MULTIPLE.equals(mAction)) {
|
|| Intent.ACTION_SEND_MULTIPLE.equals(mAction)) {
|
||||||
initFromIntent(intent);
|
initFromIntent(intent);
|
||||||
setDraftNeedsSaving(true);
|
setMessageChanged(true);
|
||||||
setMessageLoaded(true);
|
setMessageLoaded(true);
|
||||||
} else if (ACTION_REPLY.equals(mAction)
|
} else if (ACTION_REPLY.equals(mAction)
|
||||||
|| ACTION_REPLY_ALL.equals(mAction)
|
|| ACTION_REPLY_ALL.equals(mAction)
|
||||||
|
@ -527,16 +528,36 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
if (mMessageLoaded != isLoaded) {
|
if (mMessageLoaded != isLoaded) {
|
||||||
mMessageLoaded = isLoaded;
|
mMessageLoaded = isLoaded;
|
||||||
addListeners();
|
addListeners();
|
||||||
|
mInitiallyEmpty = areViewsEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDraftNeedsSaving(boolean needsSaving) {
|
private void setMessageChanged(boolean messageChanged) {
|
||||||
|
boolean needsSaving = messageChanged && !(mInitiallyEmpty && areViewsEmpty());
|
||||||
|
|
||||||
if (mDraftNeedsSaving != needsSaving) {
|
if (mDraftNeedsSaving != needsSaving) {
|
||||||
mDraftNeedsSaving = needsSaving;
|
mDraftNeedsSaving = needsSaving;
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether or not all text fields are empty (i.e. the entire compose message is empty)
|
||||||
|
*/
|
||||||
|
private boolean areViewsEmpty() {
|
||||||
|
return (mToView.length() == 0)
|
||||||
|
&& (mCcView.length() == 0)
|
||||||
|
&& (mBccView.length() == 0)
|
||||||
|
&& (mSubjectView.length() == 0)
|
||||||
|
&& isBodyEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBodyEmpty() {
|
||||||
|
return (mMessageContentView.length() == 0)
|
||||||
|
|| mMessageContentView.getText()
|
||||||
|
.toString().equals("\n" + getAccountSignature(mAccount));
|
||||||
|
}
|
||||||
|
|
||||||
public void setFocusShifter(int fromViewId, final int targetViewId) {
|
public void setFocusShifter(int fromViewId, final int targetViewId) {
|
||||||
View label = findViewById(fromViewId); // xlarge only
|
View label = findViewById(fromViewId); // xlarge only
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
|
@ -796,7 +817,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
showCcBccFieldsIfFilled();
|
showCcBccFieldsIfFilled();
|
||||||
setNewMessageFocus();
|
setNewMessageFocus();
|
||||||
}
|
}
|
||||||
setDraftNeedsSaving(false);
|
setMessageChanged(false);
|
||||||
|
|
||||||
// The quoted text must always be restored.
|
// The quoted text must always be restored.
|
||||||
displayQuotedText(message.mTextReply, message.mHtmlReply);
|
displayQuotedText(message.mTextReply, message.mHtmlReply);
|
||||||
|
@ -842,7 +863,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
if (processSourceMessageAttachments(
|
if (processSourceMessageAttachments(
|
||||||
mAttachments, mSourceAttachments, true)) {
|
mAttachments, mSourceAttachments, true)) {
|
||||||
updateAttachmentUi();
|
updateAttachmentUi();
|
||||||
setDraftNeedsSaving(true);
|
setMessageChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1334,7 +1355,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
if (!mDraftNeedsSaving) {
|
if (!mDraftNeedsSaving) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setDraftNeedsSaving(false);
|
setMessageChanged(false);
|
||||||
sendOrSaveMessage(false);
|
sendOrSaveMessage(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1365,7 +1386,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
sendOrSaveMessage(true);
|
sendOrSaveMessage(true);
|
||||||
setDraftNeedsSaving(false);
|
setMessageChanged(false);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1404,7 +1425,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
mController.deleteMessage(mDraft.mId);
|
mController.deleteMessage(mDraft.mId);
|
||||||
}
|
}
|
||||||
Utility.showToast(MessageCompose.this, R.string.message_discarded_toast);
|
Utility.showToast(MessageCompose.this, R.string.message_discarded_toast);
|
||||||
setDraftNeedsSaving(false);
|
setMessageChanged(false);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1557,7 +1578,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addAttachmentFromUri(data.getData());
|
addAttachmentFromUri(data.getData());
|
||||||
setDraftNeedsSaving(true);
|
setMessageChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean includeQuotedText() {
|
private boolean includeQuotedText() {
|
||||||
|
@ -1580,7 +1601,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
mQuotedText.setVisibility(mIncludeQuotedTextCheckBox.isChecked()
|
mQuotedText.setVisibility(mIncludeQuotedTextCheckBox.isChecked()
|
||||||
? View.VISIBLE : View.GONE);
|
? View.VISIBLE : View.GONE);
|
||||||
if (updateNeedsSaving) {
|
if (updateNeedsSaving) {
|
||||||
setDraftNeedsSaving(true);
|
setMessageChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1589,7 +1610,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
Attachment attachment = (Attachment) attachmentView.getTag();
|
Attachment attachment = (Attachment) attachmentView.getTag();
|
||||||
deleteAttachment(mAttachments, attachment);
|
deleteAttachment(mAttachments, attachment);
|
||||||
updateAttachmentUi();
|
updateAttachmentUi();
|
||||||
setDraftNeedsSaving(true);
|
setMessageChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1690,7 +1711,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||||
// if that's the case, and the attachments will be processed when they load.
|
// if that's the case, and the attachments will be processed when they load.
|
||||||
if (processSourceMessageAttachments(mAttachments, mSourceAttachments, isForward())) {
|
if (processSourceMessageAttachments(mAttachments, mSourceAttachments, isForward())) {
|
||||||
updateAttachmentUi();
|
updateAttachmentUi();
|
||||||
setDraftNeedsSaving(true);
|
setMessageChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateActionSelector();
|
updateActionSelector();
|
||||||
|
|
|
@ -617,7 +617,7 @@ public class MessageComposeTests
|
||||||
*
|
*
|
||||||
* In this case, we're doing a "reply all"
|
* In this case, we're doing a "reply all"
|
||||||
* The user is CC2 (a "cc" recipient)
|
* The user is CC2 (a "cc" recipient)
|
||||||
* The to should be: FROM,
|
* The to should be: FROM,
|
||||||
* The cc should be: TO1, TO2, CC1 and CC3 (CC2 is our account's email address)
|
* The cc should be: TO1, TO2, CC1 and CC3 (CC2 is our account's email address)
|
||||||
*/
|
*/
|
||||||
public void testReplyAllAddresses2() throws Throwable {
|
public void testReplyAllAddresses2() throws Throwable {
|
||||||
|
@ -1001,60 +1001,6 @@ public class MessageComposeTests
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for the comma-inserting logic. The logic is applied equally to To: Cc: and Bcc:
|
|
||||||
* but we only run the full set on To:
|
|
||||||
*/
|
|
||||||
public void testCommaInserting() throws Throwable {
|
|
||||||
if (!TestUtils.isScreenOnAndNotLocked(mContext)) {
|
|
||||||
Log.w(Logging.LOG_TAG, "SKIP testCommaInserting: Screen off or locked");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// simple appending cases
|
|
||||||
checkCommaInsert("a", "", false);
|
|
||||||
checkCommaInsert("a@", "", false);
|
|
||||||
checkCommaInsert("a@b", "", false);
|
|
||||||
checkCommaInsert("a@b.", "", true); // non-optimal, but matches current implementation
|
|
||||||
checkCommaInsert("a@b.c", "", true);
|
|
||||||
|
|
||||||
// confirm works properly for internal editing
|
|
||||||
checkCommaInsert("me@foo.com, you", " they@bar.com", false);
|
|
||||||
checkCommaInsert("me@foo.com, you@", "they@bar.com", false);
|
|
||||||
checkCommaInsert("me@foo.com, you@bar", " they@bar.com", false);
|
|
||||||
checkCommaInsert("me@foo.com, you@bar.", " they@bar.com", true); // non-optimal
|
|
||||||
checkCommaInsert("me@foo.com, you@bar.com", " they@bar.com", true);
|
|
||||||
|
|
||||||
// check a couple of multi-period cases
|
|
||||||
checkCommaInsert("me.myself@foo", "", false);
|
|
||||||
checkCommaInsert("me.myself@foo.com", "", true);
|
|
||||||
checkCommaInsert("me@foo.co.uk", "", true);
|
|
||||||
|
|
||||||
// cases that should not append because there's already a comma
|
|
||||||
checkCommaInsert("a@b.c,", "", false);
|
|
||||||
checkCommaInsert("me@foo.com, you@bar.com,", " they@bar.com", false);
|
|
||||||
checkCommaInsert("me.myself@foo.com,", "", false);
|
|
||||||
checkCommaInsert("me@foo.co.uk,", "", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check comma insertion logic for a single try on the To: field
|
|
||||||
*/
|
|
||||||
private void checkCommaInsert(final String before, final String after, boolean expectComma)
|
|
||||||
throws Throwable {
|
|
||||||
String expect = new String(before + (expectComma ? ", " : " ") + after);
|
|
||||||
|
|
||||||
runTestOnUiThread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
mToView.setText(before + after);
|
|
||||||
mToView.setSelection(before.length());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
getInstrumentation().sendStringSync(" ");
|
|
||||||
String result = mToView.getText().toString();
|
|
||||||
assertEquals(expect, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int sAttachmentId = 1;
|
private static int sAttachmentId = 1;
|
||||||
private Attachment makeAttachment(String filename) {
|
private Attachment makeAttachment(String filename) {
|
||||||
Attachment a = new Attachment();
|
Attachment a = new Attachment();
|
||||||
|
|
Loading…
Reference in New Issue