Merge "Cleanups to how "save draft" state is handled."
diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java
index 1e28806..b182c2f 100644
--- a/src/com/android/email/activity/MessageCompose.java
+++ b/src/com/android/email/activity/MessageCompose.java
@@ -174,9 +174,6 @@
private EmailAddressAdapter mAddressAdapterCc;
private EmailAddressAdapter mAddressAdapterBcc;
- /** Whether the save command should be enabled. */
- private boolean mSaveEnabled;
-
private static Intent getBaseIntent(Context context) {
Intent i = new Intent(context, MessageCompose.class);
i.putExtra(EXTRA_FROM_WITHIN_APP, true);
@@ -306,15 +303,14 @@
mController = Controller.getInstance(getApplication());
initViews();
- setDraftNeedsSaving(false);
- long draftId = -1;
+ long draftId = Message.NOT_SAVED;
long existingSaveTaskId = -1;
if (savedInstanceState != null) {
// This data gets used in onCreate, so grab it here instead of onRestoreInstanceState
mSourceMessageProcessed =
savedInstanceState.getBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, false);
- draftId = savedInstanceState.getLong(STATE_KEY_DRAFT_ID, -1);
+ draftId = savedInstanceState.getLong(STATE_KEY_DRAFT_ID, Message.NOT_SAVED);
existingSaveTaskId = savedInstanceState.getLong(STATE_KEY_REQUEST_ID, -1);
}
@@ -325,7 +321,7 @@
Intent intent = getIntent();
mAction = intent.getAction();
- if (draftId != -1) {
+ if (draftId != Message.NOT_SAVED) {
// this means that we saved the draft earlier,
// so now we need to disregard the intent action and do
// EDIT_DRAFT instead.
@@ -345,9 +341,10 @@
mSourceMessageProcessed = true;
} else {
// Otherwise, handle the internal cases (Message Composer invoked from within app)
- long messageId = draftId != -1 ? draftId : intent.getLongExtra(EXTRA_MESSAGE_ID, -1);
+ long messageId = (draftId != Message.NOT_SAVED)
+ ? draftId : intent.getLongExtra(EXTRA_MESSAGE_ID, -1);
SendOrSaveMessageTask saveTask = sActiveSaveTasks.get(existingSaveTaskId);
- if ((messageId != -1) || (saveTask != null)) {
+ if ((messageId != Message.NOT_SAVED) || (saveTask != null)) {
new LoadMessageTask(messageId, saveTask).executeParallel();
} else {
setAccount(intent);
@@ -359,6 +356,22 @@
mSourceMessageProcessed = true;
}
}
+
+ // Attach the text listeners late, since any population of data from Intent/saved instances
+ // are uninteresting and should be ignored.
+ initListeners();
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ if (savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN)) {
+ showCcBccFields();
+ }
+ mQuotedTextBar.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN)
+ ? View.VISIBLE : View.GONE);
+ mQuotedText.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN)
+ ? View.VISIBLE : View.GONE);
}
// needed for unit tests
@@ -421,7 +434,7 @@
super.onSaveInstanceState(outState);
long draftId = mDraft.mId;
- if (draftId != -1) {
+ if (draftId != Message.NOT_SAVED) {
outState.putLong(STATE_KEY_DRAFT_ID, draftId);
}
outState.putBoolean(STATE_KEY_CC_SHOWN, mCcBccContainer.getVisibility() == View.VISIBLE);
@@ -434,18 +447,6 @@
outState.putLong(STATE_KEY_REQUEST_ID, mLastSaveTaskId);
}
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- if (savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN)) {
- showCcBccFields();
- }
- mQuotedTextBar.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN)
- ? View.VISIBLE : View.GONE);
- mQuotedText.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN)
- ? View.VISIBLE : View.GONE);
- }
-
/**
* @return true if the activity was opened by the email app itself.
*/
@@ -455,9 +456,10 @@
}
private void setDraftNeedsSaving(boolean needsSaving) {
- mDraftNeedsSaving = needsSaving;
- mSaveEnabled = needsSaving;
- invalidateOptionsMenu();
+ if (mDraftNeedsSaving != needsSaving) {
+ mDraftNeedsSaving = needsSaving;
+ invalidateOptionsMenu();
+ }
}
public void setFocusShifter(int fromViewId, final int targetViewId) {
@@ -473,6 +475,59 @@
}
}
+ /**
+ * An {@link InputFilter} that 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).
+ */
+ @VisibleForTesting
+ static final InputFilter RECIPIENT_FILTER = new InputFilter() {
+ @Override
+ 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;
+ }
+ };
+
private void initViews() {
mFromView = UiUtilities.getView(this, R.id.from);
mToView = UiUtilities.getView(this, R.id.to);
@@ -487,76 +542,7 @@
mIncludeQuotedTextCheckBox = UiUtilities.getView(this, R.id.include_quoted_text);
mQuotedText = UiUtilities.getView(this, 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) {
- setDraftNeedsSaving(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);
+ InputFilter[] recipientFilters = new InputFilter[] { RECIPIENT_FILTER };
// NOTE: assumes no other filters are set
mToView.setFilters(recipientFilters);
@@ -605,6 +591,26 @@
mToView.requestFocus();
}
+ private void initListeners() {
+ final 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) {
+ setDraftNeedsSaving(true);
+ }
+
+ public void afterTextChanged(android.text.Editable s) { }
+ };
+
+ mToView.addTextChangedListener(watcher);
+ mCcView.addTextChangedListener(watcher);
+ mBccView.addTextChangedListener(watcher);
+ mSubjectView.addTextChangedListener(watcher);
+ mMessageContentView.addTextChangedListener(watcher);
+ }
+
/**
* Set up address auto-completion adapters.
*/
@@ -1351,7 +1357,7 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- menu.findItem(R.id.save).setEnabled(mSaveEnabled);
+ menu.findItem(R.id.save).setEnabled(mDraftNeedsSaving);
return true;
}
@@ -1457,7 +1463,6 @@
// Finally - expose fields that were filled in but are normally hidden, and set focus
showCcBccFieldsIfFilled();
setNewMessageFocus();
- setDraftNeedsSaving(false);
}
/**