Merge "Support compose with quoted html." into jb-ub-mail-ur10
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 265b7b9..3c470ad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -76,6 +76,8 @@
<string name="reply_attribution">On <xliff:g id="date">%s</xliff:g>, <xliff:g id="person">%s</xliff:g> wrote:</string>
<!-- Compose screen, displayed at the top of a message being forwarded. Please preserve the HTML entities (surrounded by & and ;). [CHAR LIMIT=1000] -->
<string name="forward_attribution">---------- Forwarded message ----------<br>From: <xliff:g id="from">%1$s</xliff:g><br>Date: <xliff:g id="date">%2$s</xliff:g><br>Subject: <xliff:g id="subject">%3$s</xliff:g><br>To: <xliff:g id="to">%4$s</xliff:g><br></string>
+ <!-- Compose screen, displayed at the top of a message being forwarded. [CHAR LIMIT=100]-->
+ <string name="forward_attribution_no_headers">---------- Forwarded message ----------</string>
<!-- Compose screen, displayed at the top of a message being forwarded if there are any email addresses in the CC list. Please preserve the HTML entities (surrounded by & and ;). [CHAR LIMIT=1000]-->
<string name="cc_attribution">Cc: <xliff:g id="cc">%1$s</xliff:g><br></string>
<!-- Dialog text: select the type of an attachment while composing [CHAR LIMIT=100]-->
diff --git a/src/com/android/mail/compose/ComposeActivity.java b/src/com/android/mail/compose/ComposeActivity.java
index 3f7da5b..c80799d 100644
--- a/src/com/android/mail/compose/ComposeActivity.java
+++ b/src/com/android/mail/compose/ComposeActivity.java
@@ -34,6 +34,7 @@
import android.content.Intent;
import android.content.Loader;
import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -123,11 +124,11 @@
LoaderManager.LoaderCallbacks<Cursor>, TextView.OnEditorActionListener,
FeedbackEnabledActivity {
// Identifiers for which type of composition this is
- protected static final int COMPOSE = -1;
- protected static final int REPLY = 0;
- protected static final int REPLY_ALL = 1;
- protected static final int FORWARD = 2;
- protected static final int EDIT_DRAFT = 3;
+ public static final int COMPOSE = -1;
+ public static final int REPLY = 0;
+ public static final int REPLY_ALL = 1;
+ public static final int FORWARD = 2;
+ public static final int EDIT_DRAFT = 3;
// Integer extra holding one of the above compose action
protected static final String EXTRA_ACTION = "action";
@@ -145,6 +146,11 @@
private static final String EXTRA_BODY = "body";
+ /**
+ * Expected to be html formatted text.
+ */
+ private static final String EXTRA_QUOTED_TEXT = "quotedText";
+
protected static final String EXTRA_FROM_ACCOUNT_STRING = "fromAccountString";
private static final String EXTRA_ATTACHMENT_PREVIEWS = "attachmentPreviews";
@@ -155,7 +161,8 @@
private static final String EXTRA_BCC = "bcc";
// List of all the fields
- static final String[] ALL_EXTRAS = { EXTRA_SUBJECT, EXTRA_BODY, EXTRA_TO, EXTRA_CC, EXTRA_BCC };
+ static final String[] ALL_EXTRAS = { EXTRA_SUBJECT, EXTRA_BODY, EXTRA_TO, EXTRA_CC, EXTRA_BCC,
+ EXTRA_QUOTED_TEXT };
private static SendOrSaveCallback sTestSendOrSaveCallback = null;
// Map containing information about requests to create new messages, and the id of the
@@ -284,21 +291,29 @@
* Can be called from a non-UI thread.
*/
public static void editDraft(Context launcher, Account account, Message message) {
- launch(launcher, account, message, EDIT_DRAFT, null, null);
+ launch(launcher, account, message, EDIT_DRAFT, null, null, null, null);
}
/**
* Can be called from a non-UI thread.
*/
public static void compose(Context launcher, Account account) {
- launch(launcher, account, null, COMPOSE, null, null);
+ launch(launcher, account, null, COMPOSE, null, null, null, null);
}
/**
* Can be called from a non-UI thread.
*/
public static void composeToAddress(Context launcher, Account account, String toAddress) {
- launch(launcher, account, null, COMPOSE, toAddress, null);
+ launch(launcher, account, null, COMPOSE, toAddress, null, null, null);
+ }
+
+ /**
+ * Can be called from a non-UI thread.
+ */
+ public static void composeWithQuotedText(Context launcher, Account account,
+ String quotedText, String subject) {
+ launch(launcher, account, null, COMPOSE, null, null, quotedText, subject);
}
/**
@@ -340,30 +355,31 @@
* Can be called from a non-UI thread.
*/
public static void reply(Context launcher, Account account, Message message) {
- launch(launcher, account, message, REPLY, null, null);
+ launch(launcher, account, message, REPLY, null, null, null, null);
}
/**
* Can be called from a non-UI thread.
*/
public static void replyAll(Context launcher, Account account, Message message) {
- launch(launcher, account, message, REPLY_ALL, null, null);
+ launch(launcher, account, message, REPLY_ALL, null, null, null, null);
}
/**
* Can be called from a non-UI thread.
*/
public static void forward(Context launcher, Account account, Message message) {
- launch(launcher, account, message, FORWARD, null, null);
+ launch(launcher, account, message, FORWARD, null, null, null, null);
}
public static void reportRenderingFeedback(Context launcher, Account account, Message message,
String body) {
- launch(launcher, account, message, FORWARD, "android-gmail-readability@google.com", body);
+ launch(launcher, account, message, FORWARD,
+ "android-gmail-readability@google.com", body, null, null);
}
private static void launch(Context launcher, Account account, Message message, int action,
- String toAddress, String body) {
+ String toAddress, String body, String quotedText, String subject) {
Intent intent = new Intent(launcher, ComposeActivity.class);
intent.putExtra(EXTRA_FROM_EMAIL_TASK, true);
intent.putExtra(EXTRA_ACTION, action);
@@ -379,6 +395,12 @@
if (body != null) {
intent.putExtra(EXTRA_BODY, body);
}
+ if (quotedText != null) {
+ intent.putExtra(EXTRA_QUOTED_TEXT, quotedText);
+ }
+ if (subject != null) {
+ intent.putExtra(EXTRA_SUBJECT, subject);
+ }
launcher.startActivity(intent);
}
@@ -398,6 +420,7 @@
Message message;
ArrayList<AttachmentPreview> previews;
mShowQuotedText = false;
+ CharSequence quotedText = null;
int action;
// Check for any of the possibly supplied accounts.;
Account account = null;
@@ -408,6 +431,7 @@
previews = savedState.getParcelableArrayList(EXTRA_ATTACHMENT_PREVIEWS);
mRefMessage = (Message) savedState.getParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE);
+ quotedText = savedState.getCharSequence(EXTRA_QUOTED_TEXT);
} else {
account = obtainAccount(intent);
action = intent.getIntExtra(EXTRA_ACTION, COMPOSE);
@@ -460,6 +484,11 @@
initQuotedTextFromRefMessage(mRefMessage, action);
showCcBcc(savedState);
mShowQuotedText = message.appendRefMessageContent;
+ // if we should be showing quoted text but mRefMessage is null
+ // and we have some quotedText, display that
+ if (mShowQuotedText && quotedText != null && mRefMessage == null) {
+ initQuotedText(quotedText, false /* shouldQuoteText */);
+ }
} else if (action == EDIT_DRAFT) {
initFromDraftMessage(message);
boolean showBcc = !TextUtils.isEmpty(message.getBcc());
@@ -589,9 +618,6 @@
private void finishSetup(int action, Intent intent, Bundle savedInstanceState) {
setFocus(action);
- if (action == COMPOSE) {
- mQuotedTextView.setVisibility(View.GONE);
- }
// Don't bother with the intent if we have procured a message from the
// intent already.
if (!hadSavedInstanceStateMessage(savedInstanceState)) {
@@ -797,6 +823,10 @@
if (mRefMessage != null) {
state.putParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE, mRefMessage);
+ } else if (message.appendRefMessageContent) {
+ // If we have no ref message but should be appending
+ // ref message content, we have orphaned quoted text. Save it.
+ state.putCharSequence(EXTRA_QUOTED_TEXT, mQuotedTextView.getQuotedTextIfIncluded());
}
state.putBoolean(EXTRA_SHOW_CC, mCcBccView.isCcVisible());
state.putBoolean(EXTRA_SHOW_BCC, mCcBccView.isBccVisible());
@@ -1292,6 +1322,8 @@
mSubject.setText(value);
} else if (EXTRA_BODY.equals(extra)) {
setBody(value, true /* with signature */);
+ } else if (EXTRA_QUOTED_TEXT.equals(extra)) {
+ initQuotedText(value, true /* shouldQuoteText */);
}
}
}
@@ -1302,9 +1334,12 @@
if (text != null) {
setBody(text, true /* with signature */);
}
+
+ // TODO - support EXTRA_HTML_TEXT
}
}
+
@VisibleForTesting
protected String decodeEmailInUri(String s) throws UnsupportedEncodingException {
// TODO: handle the case where there are spaces in the display name as
@@ -1501,6 +1536,10 @@
}
}
+ private void initQuotedText(CharSequence quotedText, boolean shouldQuoteText) {
+ mQuotedTextView.setQuotedTextFromHtml(quotedText, shouldQuoteText);
+ mShowQuotedText = true;
+ }
private void initQuotedTextFromRefMessage(Message refMessage, int action) {
if (mRefMessage != null && (action == REPLY || action == REPLY_ALL || action == FORWARD)) {
@@ -1744,16 +1783,19 @@
mAccount.getReplyFroms());
}
- private void setSubject(Message refMessage, int action) {
- String subject = refMessage.subject;
+ /**
+ * Returns a formatted subject string with the appropriate prefix for the action type.
+ * E.g., "FWD: " is prepended if action is {@link ComposeActivity#FORWARD}.
+ */
+ public static String buildFormattedSubject(Resources res, String subject, int action) {
String prefix;
String correctedSubject = null;
if (action == ComposeActivity.COMPOSE) {
prefix = "";
} else if (action == ComposeActivity.FORWARD) {
- prefix = getString(R.string.forward_subject_label);
+ prefix = res.getString(R.string.forward_subject_label);
} else {
- prefix = getString(R.string.reply_subject_label);
+ prefix = res.getString(R.string.reply_subject_label);
}
// Don't duplicate the prefix
@@ -1761,10 +1803,15 @@
&& subject.toLowerCase().startsWith(prefix.toLowerCase())) {
correctedSubject = subject;
} else {
- correctedSubject = String
- .format(getString(R.string.formatted_subject), prefix, subject);
+ correctedSubject = String.format(
+ res.getString(R.string.formatted_subject), prefix, subject);
}
- mSubject.setText(correctedSubject);
+
+ return correctedSubject;
+ }
+
+ private void setSubject(Message refMessage, int action) {
+ mSubject.setText(buildFormattedSubject(getResources(), refMessage.subject, action));
}
private void initRecipients() {
@@ -2085,7 +2132,7 @@
}
/**
- * Use the {@link ContentResolver#call()} method to send or save the message.
+ * Use the {@link ContentResolver#call} method to send or save the message.
*
* If this was successful, this method will return an non-null Bundle instance
*/
diff --git a/src/com/android/mail/compose/QuotedTextView.java b/src/com/android/mail/compose/QuotedTextView.java
index bb9ac75..8ebac6f 100644
--- a/src/com/android/mail/compose/QuotedTextView.java
+++ b/src/com/android/mail/compose/QuotedTextView.java
@@ -248,7 +248,7 @@
public void setQuotedText(int action, Message refMessage, boolean allow) {
setVisibility(View.VISIBLE);
String htmlText = getHtmlText(refMessage);
- StringBuffer quotedText = new StringBuffer();
+ StringBuilder quotedText = new StringBuilder();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
Date date = new Date(refMessage.dateReceivedMs);
Resources resources = getContext().getResources();
@@ -299,6 +299,26 @@
allowRespondInline(true);
}
+ public void setQuotedTextFromHtml(CharSequence htmlText, boolean shouldQuoteText) {
+ setVisibility(VISIBLE);
+ if (shouldQuoteText) {
+ final StringBuilder quotedText = new StringBuilder();
+ final Resources resources = getContext().getResources();
+ quotedText.append(sQuoteBegin);
+ quotedText.append(
+ String.format(resources.getString(R.string.forward_attribution_no_headers)));
+ quotedText.append(HEADER_SEPARATOR);
+ quotedText.append(BLOCKQUOTE_BEGIN);
+ quotedText.append(htmlText);
+ quotedText.append(BLOCKQUOTE_END);
+ quotedText.append(QUOTE_END);
+ setQuotedText(quotedText);
+ } else {
+ setQuotedText(htmlText);
+ }
+ findViewById(R.id.divider_bar).setVisibility(GONE);
+ findViewById(R.id.quoted_text_button_bar).setVisibility(GONE);
+ }
/**
* Set quoted text. Some use cases may not want to display the check box (i.e. forwarding) so
* allow control of that.
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index 9aadf87..6013769 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -2108,7 +2108,8 @@
private static boolean getShouldAllowDrawerPull(final int viewMode) {
// if search list/conv mode, disable drawer pull
// allow drawer pull everywhere except conversation mode where the list is hidden
- return !ViewMode.isSearchMode(viewMode) && !(ViewMode.isConversationMode(viewMode));
+ return !ViewMode.isSearchMode(viewMode) && !ViewMode.isConversationMode(viewMode) &&
+ !ViewMode.isAdMode(viewMode);
// TODO(ath): get this to work to allow drawer pull in 2-pane conv mode.
/* && !isConversationListVisible() */