mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-27 11:42:16 -05:00
Merge pull request #468
Extract a TextBodyBuilder class Conflicts: src/com/fsck/k9/activity/MessageCompose.java
This commit is contained in:
commit
95f33c38fe
@ -50,3 +50,8 @@ android {
|
|||||||
exclude 'META-INF/NOTICE'
|
exclude 'META-INF/NOTICE'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task testsOnJVM(type :GradleBuild, dependsOn: assemble) {
|
||||||
|
buildFile = 'tests-on-jvm/build.gradle'
|
||||||
|
tasks = ['test']
|
||||||
|
}
|
||||||
|
@ -12,7 +12,7 @@ import java.io.Serializable;
|
|||||||
*
|
*
|
||||||
* TODO: This container should also have a text part, along with its insertion point. Or maybe a generic InsertableContent and maintain one each for Html and Text?
|
* TODO: This container should also have a text part, along with its insertion point. Or maybe a generic InsertableContent and maintain one each for Html and Text?
|
||||||
*/
|
*/
|
||||||
class InsertableHtmlContent implements Serializable {
|
public class InsertableHtmlContent implements Serializable {
|
||||||
private static final long serialVersionUID = 2397327034L;
|
private static final long serialVersionUID = 2397327034L;
|
||||||
// Default to a headerInsertionPoint at the beginning of the message.
|
// Default to a headerInsertionPoint at the beginning of the message.
|
||||||
private int headerInsertionPoint = 0;
|
private int headerInsertionPoint = 0;
|
||||||
|
@ -88,6 +88,7 @@ import com.fsck.k9.mail.Part;
|
|||||||
import com.fsck.k9.mail.internet.MimeBodyPart;
|
import com.fsck.k9.mail.internet.MimeBodyPart;
|
||||||
import com.fsck.k9.mail.internet.MimeHeader;
|
import com.fsck.k9.mail.internet.MimeHeader;
|
||||||
import com.fsck.k9.mail.internet.MimeMessage;
|
import com.fsck.k9.mail.internet.MimeMessage;
|
||||||
|
import com.fsck.k9.mail.internet.TextBodyBuilder;
|
||||||
import com.fsck.k9.mail.internet.MimeMultipart;
|
import com.fsck.k9.mail.internet.MimeMultipart;
|
||||||
import com.fsck.k9.mail.internet.MimeUtility;
|
import com.fsck.k9.mail.internet.MimeUtility;
|
||||||
import com.fsck.k9.mail.internet.TextBody;
|
import com.fsck.k9.mail.internet.TextBody;
|
||||||
@ -111,6 +112,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -381,36 +383,36 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(android.os.Message msg) {
|
public void handleMessage(android.os.Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case MSG_PROGRESS_ON:
|
case MSG_PROGRESS_ON:
|
||||||
setSupportProgressBarIndeterminateVisibility(true);
|
setSupportProgressBarIndeterminateVisibility(true);
|
||||||
break;
|
break;
|
||||||
case MSG_PROGRESS_OFF:
|
case MSG_PROGRESS_OFF:
|
||||||
setSupportProgressBarIndeterminateVisibility(false);
|
setSupportProgressBarIndeterminateVisibility(false);
|
||||||
break;
|
break;
|
||||||
case MSG_SKIPPED_ATTACHMENTS:
|
case MSG_SKIPPED_ATTACHMENTS:
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
MessageCompose.this,
|
MessageCompose.this,
|
||||||
getString(R.string.message_compose_attachments_skipped_toast),
|
getString(R.string.message_compose_attachments_skipped_toast),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
break;
|
break;
|
||||||
case MSG_SAVED_DRAFT:
|
case MSG_SAVED_DRAFT:
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
MessageCompose.this,
|
MessageCompose.this,
|
||||||
getString(R.string.message_saved_toast),
|
getString(R.string.message_saved_toast),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
break;
|
break;
|
||||||
case MSG_DISCARDED_DRAFT:
|
case MSG_DISCARDED_DRAFT:
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
MessageCompose.this,
|
MessageCompose.this,
|
||||||
getString(R.string.message_discarded_toast),
|
getString(R.string.message_discarded_toast),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
break;
|
break;
|
||||||
case MSG_PERFORM_STALLED_ACTION:
|
case MSG_PERFORM_STALLED_ACTION:
|
||||||
performStalledAction();
|
performStalledAction();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
super.handleMessage(msg);
|
super.handleMessage(msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -560,8 +562,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
mMessageReference = intent.getParcelableExtra(EXTRA_MESSAGE_REFERENCE);
|
mMessageReference = intent.getParcelableExtra(EXTRA_MESSAGE_REFERENCE);
|
||||||
mSourceMessageBody = intent.getStringExtra(EXTRA_MESSAGE_BODY);
|
mSourceMessageBody = intent.getStringExtra(EXTRA_MESSAGE_BODY);
|
||||||
|
|
||||||
if (K9.DEBUG && mSourceMessageBody != null)
|
if (K9.DEBUG && mSourceMessageBody != null) {
|
||||||
Log.d(K9.LOG_TAG, "Composing message with explicitly specified message body.");
|
Log.d(K9.LOG_TAG, "Composing message with explicitly specified message body.");
|
||||||
|
}
|
||||||
|
|
||||||
final String accountUuid = (mMessageReference != null) ?
|
final String accountUuid = (mMessageReference != null) ?
|
||||||
mMessageReference.accountUuid :
|
mMessageReference.accountUuid :
|
||||||
@ -1350,136 +1353,56 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
* original message.
|
* original message.
|
||||||
*/
|
*/
|
||||||
private TextBody buildText(boolean isDraft, SimpleMessageFormat messageFormat) {
|
private TextBody buildText(boolean isDraft, SimpleMessageFormat messageFormat) {
|
||||||
// The length of the formatted version of the user-supplied text/reply
|
String messageText = mMessageContentView.getCharacters();
|
||||||
int composedMessageLength;
|
|
||||||
|
|
||||||
// The offset of the user-supplied text/reply in the final text body
|
TextBodyBuilder textBodyBuilder = new TextBodyBuilder(messageText);
|
||||||
int composedMessageOffset;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find out if we need to include the original message as quoted text.
|
* Find out if we need to include the original message as quoted text.
|
||||||
*
|
*
|
||||||
* We include the quoted text in the body if the user didn't choose to hide it. We always
|
* We include the quoted text in the body if the user didn't choose to
|
||||||
* include the quoted text when we're saving a draft. That's so the user is able to
|
* hide it. We always include the quoted text when we're saving a draft.
|
||||||
* "un-hide" the quoted text if (s)he opens a saved draft.
|
* That's so the user is able to "un-hide" the quoted text if (s)he
|
||||||
|
* opens a saved draft.
|
||||||
*/
|
*/
|
||||||
boolean includeQuotedText = (mQuotedTextMode.equals(QuotedTextMode.SHOW) || isDraft);
|
boolean includeQuotedText = (isDraft || mQuotedTextMode == QuotedTextMode.SHOW);
|
||||||
|
boolean isReplyAfterQuote = (mQuoteStyle == QuoteStyle.PREFIX && mAccount.isReplyAfterQuote());
|
||||||
|
|
||||||
// Reply after quote makes no sense for HEADER style replies
|
textBodyBuilder.setIncludeQuotedText(false);
|
||||||
boolean replyAfterQuote = (mQuoteStyle == QuoteStyle.HEADER) ?
|
if (includeQuotedText) {
|
||||||
false : mAccount.isReplyAfterQuote();
|
if (messageFormat == SimpleMessageFormat.HTML && mQuotedHtmlContent != null) {
|
||||||
|
textBodyBuilder.setIncludeQuotedText(true);
|
||||||
boolean signatureBeforeQuotedText = mAccount.isSignatureBeforeQuotedText();
|
textBodyBuilder.setQuotedTextHtml(mQuotedHtmlContent);
|
||||||
|
textBodyBuilder.setReplyAfterQuote(isReplyAfterQuote);
|
||||||
// Get the user-supplied text
|
|
||||||
String text = mMessageContentView.getCharacters();
|
|
||||||
|
|
||||||
// Handle HTML separate from the rest of the text content
|
|
||||||
if (messageFormat == SimpleMessageFormat.HTML) {
|
|
||||||
|
|
||||||
// Do we have to modify an existing message to include our reply?
|
|
||||||
if (includeQuotedText && mQuotedHtmlContent != null) {
|
|
||||||
if (K9.DEBUG) {
|
|
||||||
Log.d(K9.LOG_TAG, "insertable: " + mQuotedHtmlContent.toDebugString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isDraft) {
|
|
||||||
// Append signature to the reply
|
|
||||||
if (replyAfterQuote || signatureBeforeQuotedText) {
|
|
||||||
text = appendSignature(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the text to HTML
|
|
||||||
text = HtmlConverter.textToHtmlFragment(text);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the insertion location based upon our reply after quote setting.
|
|
||||||
* Additionally, add some extra separators between the composed message and quoted
|
|
||||||
* message depending on the quote location. We only add the extra separators when
|
|
||||||
* we're sending, that way when we load a draft, we don't have to know the length
|
|
||||||
* of the separators to remove them before editing.
|
|
||||||
*/
|
|
||||||
if (replyAfterQuote) {
|
|
||||||
mQuotedHtmlContent.setInsertionLocation(
|
|
||||||
InsertableHtmlContent.InsertionLocation.AFTER_QUOTE);
|
|
||||||
if (!isDraft) {
|
|
||||||
text = "<br clear=\"all\">" + text;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mQuotedHtmlContent.setInsertionLocation(
|
|
||||||
InsertableHtmlContent.InsertionLocation.BEFORE_QUOTE);
|
|
||||||
if (!isDraft) {
|
|
||||||
text += "<br><br>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isDraft) {
|
|
||||||
// Place signature immediately after the quoted text
|
|
||||||
if (!(replyAfterQuote || signatureBeforeQuotedText)) {
|
|
||||||
mQuotedHtmlContent.insertIntoQuotedFooter(getSignatureHtml());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mQuotedHtmlContent.setUserContent(text);
|
|
||||||
|
|
||||||
// Save length of the body and its offset. This is used when thawing drafts.
|
|
||||||
composedMessageLength = text.length();
|
|
||||||
composedMessageOffset = mQuotedHtmlContent.getInsertionPoint();
|
|
||||||
text = mQuotedHtmlContent.toString();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// There is no text to quote so simply append the signature if available
|
|
||||||
if (!isDraft) {
|
|
||||||
text = appendSignature(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the text to HTML
|
|
||||||
text = HtmlConverter.textToHtmlFragment(text);
|
|
||||||
|
|
||||||
//TODO: Wrap this in proper HTML tags
|
|
||||||
|
|
||||||
composedMessageLength = text.length();
|
|
||||||
composedMessageOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Capture composed message length before we start attaching quoted parts and signatures.
|
|
||||||
composedMessageLength = text.length();
|
|
||||||
composedMessageOffset = 0;
|
|
||||||
|
|
||||||
if (!isDraft) {
|
|
||||||
// Append signature to the text/reply
|
|
||||||
if (replyAfterQuote || signatureBeforeQuotedText) {
|
|
||||||
text = appendSignature(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String quotedText = mQuotedText.getCharacters();
|
String quotedText = mQuotedText.getCharacters();
|
||||||
if (includeQuotedText && quotedText.length() > 0) {
|
if (messageFormat == SimpleMessageFormat.TEXT && quotedText.length() > 0) {
|
||||||
if (replyAfterQuote) {
|
textBodyBuilder.setIncludeQuotedText(true);
|
||||||
composedMessageOffset = quotedText.length() + "\r\n".length();
|
textBodyBuilder.setQuotedText(quotedText);
|
||||||
text = quotedText + "\r\n" + text;
|
textBodyBuilder.setReplyAfterQuote(isReplyAfterQuote);
|
||||||
} else {
|
|
||||||
text += "\r\n\r\n" + quotedText.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isDraft) {
|
|
||||||
// Place signature immediately after the quoted text
|
|
||||||
if (!(replyAfterQuote || signatureBeforeQuotedText)) {
|
|
||||||
text = appendSignature(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextBody body = new TextBody(text);
|
textBodyBuilder.setInsertSeparator(!isDraft);
|
||||||
body.setComposedMessageLength(composedMessageLength);
|
|
||||||
body.setComposedMessageOffset(composedMessageOffset);
|
|
||||||
|
|
||||||
|
boolean useSignature = (!isDraft && mIdentity.getSignatureUse());
|
||||||
|
if (useSignature) {
|
||||||
|
textBodyBuilder.setAppendSignature(true);
|
||||||
|
textBodyBuilder.setSignature(mSignatureView.getCharacters());
|
||||||
|
textBodyBuilder.setSignatureBeforeQuotedText(mAccount.isSignatureBeforeQuotedText());
|
||||||
|
} else {
|
||||||
|
textBodyBuilder.setAppendSignature(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBody body;
|
||||||
|
if (messageFormat == SimpleMessageFormat.HTML) {
|
||||||
|
body = textBodyBuilder.buildTextHtml();
|
||||||
|
} else {
|
||||||
|
body = textBodyBuilder.buildTextPlain();
|
||||||
|
}
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the final message to be sent (or saved). If there is another message quoted in this one, it will be baked
|
* Build the final message to be sent (or saved). If there is another message quoted in this one, it will be baked
|
||||||
* into the final message here.
|
* into the final message here.
|
||||||
@ -1628,8 +1551,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
* title*3="isn't it!"
|
* title*3="isn't it!"
|
||||||
*/
|
*/
|
||||||
bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, String.format(Locale.US,
|
bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, String.format(Locale.US,
|
||||||
"attachment;\r\n filename=\"%s\";\r\n size=%d",
|
"attachment;\r\n filename=\"%s\";\r\n size=%d",
|
||||||
attachment.name, attachment.size));
|
attachment.name, attachment.size));
|
||||||
|
|
||||||
mp.addBodyPart(bp);
|
mp.addBodyPart(bp);
|
||||||
}
|
}
|
||||||
@ -1762,8 +1685,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
private Map<IdentityField, String> parseIdentityHeader(final String identityString) {
|
private Map<IdentityField, String> parseIdentityHeader(final String identityString) {
|
||||||
Map<IdentityField, String> identity = new HashMap<IdentityField, String>();
|
Map<IdentityField, String> identity = new HashMap<IdentityField, String>();
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Decoding identity: " + identityString);
|
Log.d(K9.LOG_TAG, "Decoding identity: " + identityString);
|
||||||
|
}
|
||||||
|
|
||||||
if (identityString == null || identityString.length() < 1) {
|
if (identityString == null || identityString.length() < 1) {
|
||||||
return identity;
|
return identity;
|
||||||
@ -1781,8 +1705,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Decoded identity: " + identity.toString());
|
Log.d(K9.LOG_TAG, "Decoded identity: " + identity.toString());
|
||||||
|
}
|
||||||
|
|
||||||
// Sanity check our Integers so that recipients of this result don't have to.
|
// Sanity check our Integers so that recipients of this result don't have to.
|
||||||
for (IdentityField key : IdentityField.getIntegerFields()) {
|
for (IdentityField key : IdentityField.getIntegerFields()) {
|
||||||
@ -1797,8 +1722,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
} else {
|
} else {
|
||||||
// Legacy identity
|
// Legacy identity
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Got a saved legacy identity: " + identityString);
|
Log.d(K9.LOG_TAG, "Got a saved legacy identity: " + identityString);
|
||||||
|
}
|
||||||
StringTokenizer tokenizer = new StringTokenizer(identityString, ":", false);
|
StringTokenizer tokenizer = new StringTokenizer(identityString, ":", false);
|
||||||
|
|
||||||
// First item is the body length. We use this to separate the composed reply from the quoted text.
|
// First item is the body length. We use this to separate the composed reply from the quoted text.
|
||||||
@ -1827,35 +1753,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
return identity;
|
return identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String appendSignature(String originalText) {
|
|
||||||
String text = originalText;
|
|
||||||
if (mIdentity.getSignatureUse()) {
|
|
||||||
String signature = mSignatureView.getCharacters();
|
|
||||||
|
|
||||||
if (signature != null && !signature.contentEquals("")) {
|
|
||||||
text += "\r\n" + signature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an HTML version of the signature in the #mSignatureView, if any.
|
|
||||||
* @return HTML version of signature.
|
|
||||||
*/
|
|
||||||
private String getSignatureHtml() {
|
|
||||||
String signature = "";
|
|
||||||
if (mIdentity.getSignatureUse()) {
|
|
||||||
signature = mSignatureView.getCharacters();
|
|
||||||
if(!StringUtils.isNullOrEmpty(signature)) {
|
|
||||||
signature = HtmlConverter.textToHtmlFragment("\r\n" + signature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendMessage() {
|
private void sendMessage() {
|
||||||
new SendMessageTask().execute();
|
new SendMessageTask().execute();
|
||||||
}
|
}
|
||||||
@ -1929,18 +1826,18 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
}
|
}
|
||||||
emailsArray = emails.toArray(new String[emails.size()]);
|
emailsArray = emails.toArray(new String[emails.size()]);
|
||||||
}
|
}
|
||||||
if (mEncryptCheckbox.isChecked() && mCryptoSignatureCheckbox.isChecked()) {
|
if (mEncryptCheckbox.isChecked() && mCryptoSignatureCheckbox.isChecked()) {
|
||||||
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
||||||
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, emailsArray);
|
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, emailsArray);
|
||||||
executeOpenPgpMethod(intent);
|
executeOpenPgpMethod(intent);
|
||||||
} else if (mCryptoSignatureCheckbox.isChecked()) {
|
} else if (mCryptoSignatureCheckbox.isChecked()) {
|
||||||
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN);
|
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN);
|
||||||
executeOpenPgpMethod(intent);
|
executeOpenPgpMethod(intent);
|
||||||
} else if (mEncryptCheckbox.isChecked()) {
|
} else if (mEncryptCheckbox.isChecked()) {
|
||||||
Intent intent = new Intent(OpenPgpApi.ACTION_ENCRYPT);
|
Intent intent = new Intent(OpenPgpApi.ACTION_ENCRYPT);
|
||||||
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, emailsArray);
|
intent.putExtra(OpenPgpApi.EXTRA_USER_IDS, emailsArray);
|
||||||
executeOpenPgpMethod(intent);
|
executeOpenPgpMethod(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// onSend() is called again in SignEncryptCallback and with
|
// onSend() is called again in SignEncryptCallback and with
|
||||||
// encryptedData set in pgpData!
|
// encryptedData set in pgpData!
|
||||||
@ -1988,8 +1885,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
sendMessage();
|
sendMessage();
|
||||||
|
|
||||||
if (mMessageReference != null && mMessageReference.flag != null) {
|
if (mMessageReference != null && mMessageReference.flag != null) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Setting referenced message (" + mMessageReference.folderName + ", " + mMessageReference.uid + ") flag to " + mMessageReference.flag);
|
Log.d(K9.LOG_TAG, "Setting referenced message (" + mMessageReference.folderName + ", " + mMessageReference.uid + ") flag to " + mMessageReference.flag);
|
||||||
|
}
|
||||||
|
|
||||||
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
||||||
final String folderName = mMessageReference.folderName;
|
final String folderName = mMessageReference.folderName;
|
||||||
@ -2049,8 +1947,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
final String output = os.toString("UTF-8");
|
final String output = os.toString("UTF-8");
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length
|
Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length +
|
||||||
+ " str=" + output);
|
" str=" + output);
|
||||||
|
|
||||||
mPgpData.setEncryptedData(output);
|
mPgpData.setEncryptedData(output);
|
||||||
onSend();
|
onSend();
|
||||||
@ -2382,71 +2280,72 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultCode != RESULT_OK)
|
if (resultCode != RESULT_OK) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case ACTIVITY_REQUEST_PICK_ATTACHMENT:
|
case ACTIVITY_REQUEST_PICK_ATTACHMENT:
|
||||||
addAttachmentsFromResultIntent(data);
|
addAttachmentsFromResultIntent(data);
|
||||||
mDraftNeedsSaving = true;
|
mDraftNeedsSaving = true;
|
||||||
break;
|
break;
|
||||||
case CONTACT_PICKER_TO:
|
case CONTACT_PICKER_TO:
|
||||||
case CONTACT_PICKER_CC:
|
case CONTACT_PICKER_CC:
|
||||||
case CONTACT_PICKER_BCC:
|
case CONTACT_PICKER_BCC:
|
||||||
ContactItem contact = mContacts.extractInfoFromContactPickerIntent(data);
|
ContactItem contact = mContacts.extractInfoFromContactPickerIntent(data);
|
||||||
if (contact == null) {
|
if (contact == null) {
|
||||||
Toast.makeText(this, getString(R.string.error_contact_address_not_found), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, getString(R.string.error_contact_address_not_found), Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (contact.emailAddresses.size() > 1) {
|
if (contact.emailAddresses.size() > 1) {
|
||||||
Intent i = new Intent(this, EmailAddressList.class);
|
Intent i = new Intent(this, EmailAddressList.class);
|
||||||
i.putExtra(EmailAddressList.EXTRA_CONTACT_ITEM, contact);
|
i.putExtra(EmailAddressList.EXTRA_CONTACT_ITEM, contact);
|
||||||
|
|
||||||
|
if (requestCode == CONTACT_PICKER_TO) {
|
||||||
|
startActivityForResult(i, CONTACT_PICKER_TO2);
|
||||||
|
} else if (requestCode == CONTACT_PICKER_CC) {
|
||||||
|
startActivityForResult(i, CONTACT_PICKER_CC2);
|
||||||
|
} else if (requestCode == CONTACT_PICKER_BCC) {
|
||||||
|
startActivityForResult(i, CONTACT_PICKER_BCC2);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (K9.DEBUG) {
|
||||||
|
List<String> emails = contact.emailAddresses;
|
||||||
|
for (int i = 0; i < emails.size(); i++) {
|
||||||
|
Log.v(K9.LOG_TAG, "email[" + i + "]: " + emails.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String email = contact.emailAddresses.get(0);
|
||||||
if (requestCode == CONTACT_PICKER_TO) {
|
if (requestCode == CONTACT_PICKER_TO) {
|
||||||
startActivityForResult(i, CONTACT_PICKER_TO2);
|
addAddress(mToView, new Address(email, ""));
|
||||||
} else if (requestCode == CONTACT_PICKER_CC) {
|
} else if (requestCode == CONTACT_PICKER_CC) {
|
||||||
startActivityForResult(i, CONTACT_PICKER_CC2);
|
addAddress(mCcView, new Address(email, ""));
|
||||||
} else if (requestCode == CONTACT_PICKER_BCC) {
|
} else if (requestCode == CONTACT_PICKER_BCC) {
|
||||||
startActivityForResult(i, CONTACT_PICKER_BCC2);
|
addAddress(mBccView, new Address(email, ""));
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (K9.DEBUG) {
|
|
||||||
List<String> emails = contact.emailAddresses;
|
break;
|
||||||
for (int i = 0; i < emails.size(); i++) {
|
case CONTACT_PICKER_TO2:
|
||||||
Log.v(K9.LOG_TAG, "email[" + i + "]: " + emails.get(i));
|
case CONTACT_PICKER_CC2:
|
||||||
|
case CONTACT_PICKER_BCC2:
|
||||||
|
String emailAddr = data.getStringExtra(EmailAddressList.EXTRA_EMAIL_ADDRESS);
|
||||||
|
if (requestCode == CONTACT_PICKER_TO2) {
|
||||||
|
addAddress(mToView, new Address(emailAddr, ""));
|
||||||
|
} else if (requestCode == CONTACT_PICKER_CC2) {
|
||||||
|
addAddress(mCcView, new Address(emailAddr, ""));
|
||||||
|
} else if (requestCode == CONTACT_PICKER_BCC2) {
|
||||||
|
addAddress(mBccView, new Address(emailAddr, ""));
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
|
||||||
|
|
||||||
String email = contact.emailAddresses.get(0);
|
|
||||||
if (requestCode == CONTACT_PICKER_TO) {
|
|
||||||
addAddress(mToView, new Address(email, ""));
|
|
||||||
} else if (requestCode == CONTACT_PICKER_CC) {
|
|
||||||
addAddress(mCcView, new Address(email, ""));
|
|
||||||
} else if (requestCode == CONTACT_PICKER_BCC) {
|
|
||||||
addAddress(mBccView, new Address(email, ""));
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
case CONTACT_PICKER_TO2:
|
|
||||||
case CONTACT_PICKER_CC2:
|
|
||||||
case CONTACT_PICKER_BCC2:
|
|
||||||
String emailAddr = data.getStringExtra(EmailAddressList.EXTRA_EMAIL_ADDRESS);
|
|
||||||
if (requestCode == CONTACT_PICKER_TO2) {
|
|
||||||
addAddress(mToView, new Address(emailAddr, ""));
|
|
||||||
} else if (requestCode == CONTACT_PICKER_CC2) {
|
|
||||||
addAddress(mCcView, new Address(emailAddr, ""));
|
|
||||||
} else if (requestCode == CONTACT_PICKER_BCC2) {
|
|
||||||
addAddress(mBccView, new Address(emailAddr, ""));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2563,39 +2462,39 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
switch (view.getId()) {
|
switch (view.getId()) {
|
||||||
case R.id.attachment_delete:
|
case R.id.attachment_delete:
|
||||||
/*
|
/*
|
||||||
* The view is the delete button, and we have previously set the tag of
|
* The view is the delete button, and we have previously set the tag of
|
||||||
* the delete button to the view that owns it. We don't use parent because the
|
* the delete button to the view that owns it. We don't use parent because the
|
||||||
* view is very complex and could change in the future.
|
* view is very complex and could change in the future.
|
||||||
*/
|
*/
|
||||||
mAttachments.removeView((View) view.getTag());
|
mAttachments.removeView((View) view.getTag());
|
||||||
mDraftNeedsSaving = true;
|
mDraftNeedsSaving = true;
|
||||||
break;
|
break;
|
||||||
case R.id.quoted_text_show:
|
case R.id.quoted_text_show:
|
||||||
showOrHideQuotedText(QuotedTextMode.SHOW);
|
showOrHideQuotedText(QuotedTextMode.SHOW);
|
||||||
updateMessageFormat();
|
updateMessageFormat();
|
||||||
mDraftNeedsSaving = true;
|
mDraftNeedsSaving = true;
|
||||||
break;
|
break;
|
||||||
case R.id.quoted_text_delete:
|
case R.id.quoted_text_delete:
|
||||||
showOrHideQuotedText(QuotedTextMode.HIDE);
|
showOrHideQuotedText(QuotedTextMode.HIDE);
|
||||||
updateMessageFormat();
|
updateMessageFormat();
|
||||||
mDraftNeedsSaving = true;
|
mDraftNeedsSaving = true;
|
||||||
break;
|
break;
|
||||||
case R.id.quoted_text_edit:
|
case R.id.quoted_text_edit:
|
||||||
mForcePlainText = true;
|
mForcePlainText = true;
|
||||||
if (mMessageReference != null) { // shouldn't happen...
|
if (mMessageReference != null) { // shouldn't happen...
|
||||||
// TODO - Should we check if mSourceMessageBody is already present and bypass the MessagingController call?
|
// TODO - Should we check if mSourceMessageBody is already present and bypass the MessagingController call?
|
||||||
MessagingController.getInstance(getApplication()).addListener(mListener);
|
MessagingController.getInstance(getApplication()).addListener(mListener);
|
||||||
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
||||||
final String folderName = mMessageReference.folderName;
|
final String folderName = mMessageReference.folderName;
|
||||||
final String sourceMessageUid = mMessageReference.uid;
|
final String sourceMessageUid = mMessageReference.uid;
|
||||||
MessagingController.getInstance(getApplication()).loadMessageForView(account, folderName, sourceMessageUid, null);
|
MessagingController.getInstance(getApplication()).loadMessageForView(account, folderName, sourceMessageUid, null);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.identity:
|
case R.id.identity:
|
||||||
showDialog(DIALOG_CHOOSE_IDENTITY);
|
showDialog(DIALOG_CHOOSE_IDENTITY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2642,36 +2541,36 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.send:
|
case R.id.send:
|
||||||
mPgpData.setEncryptionKeys(null);
|
mPgpData.setEncryptionKeys(null);
|
||||||
onSend();
|
onSend();
|
||||||
break;
|
break;
|
||||||
case R.id.save:
|
case R.id.save:
|
||||||
if (mEncryptCheckbox.isChecked()) {
|
if (mEncryptCheckbox.isChecked()) {
|
||||||
showDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
showDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
||||||
} else {
|
} else {
|
||||||
onSave();
|
onSave();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.discard:
|
case R.id.discard:
|
||||||
onDiscard();
|
onDiscard();
|
||||||
break;
|
break;
|
||||||
case R.id.add_cc_bcc:
|
case R.id.add_cc_bcc:
|
||||||
onAddCcBcc();
|
onAddCcBcc();
|
||||||
break;
|
break;
|
||||||
case R.id.add_attachment:
|
case R.id.add_attachment:
|
||||||
onAddAttachment();
|
onAddAttachment();
|
||||||
break;
|
break;
|
||||||
case R.id.add_attachment_image:
|
case R.id.add_attachment_image:
|
||||||
onAddAttachment2("image/*");
|
onAddAttachment2("image/*");
|
||||||
break;
|
break;
|
||||||
case R.id.add_attachment_video:
|
case R.id.add_attachment_video:
|
||||||
onAddAttachment2("video/*");
|
onAddAttachment2("video/*");
|
||||||
break;
|
break;
|
||||||
case R.id.read_receipt:
|
case R.id.read_receipt:
|
||||||
onReadReceipt();
|
onReadReceipt();
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2769,94 +2668,94 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(int id) {
|
public Dialog onCreateDialog(int id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE:
|
case DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE:
|
||||||
return new AlertDialog.Builder(this)
|
return new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.save_or_discard_draft_message_dlg_title)
|
.setTitle(R.string.save_or_discard_draft_message_dlg_title)
|
||||||
.setMessage(R.string.save_or_discard_draft_message_instructions_fmt)
|
.setMessage(R.string.save_or_discard_draft_message_instructions_fmt)
|
||||||
.setPositiveButton(R.string.save_draft_action, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.save_draft_action, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
dismissDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
|
dismissDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
|
||||||
onSave();
|
onSave();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.discard_action, new DialogInterface.OnClickListener() {
|
.setNegativeButton(R.string.discard_action, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
dismissDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
|
dismissDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
|
||||||
onDiscard();
|
onDiscard();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
case DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED:
|
case DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED:
|
||||||
return new AlertDialog.Builder(this)
|
return new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.refuse_to_save_draft_marked_encrypted_dlg_title)
|
.setTitle(R.string.refuse_to_save_draft_marked_encrypted_dlg_title)
|
||||||
.setMessage(R.string.refuse_to_save_draft_marked_encrypted_instructions_fmt)
|
.setMessage(R.string.refuse_to_save_draft_marked_encrypted_instructions_fmt)
|
||||||
.setNeutralButton(R.string.okay_action, new DialogInterface.OnClickListener() {
|
.setNeutralButton(R.string.okay_action, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
dismissDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
dismissDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
case DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY:
|
case DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY:
|
||||||
return new AlertDialog.Builder(this)
|
return new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.continue_without_public_key_dlg_title)
|
.setTitle(R.string.continue_without_public_key_dlg_title)
|
||||||
.setMessage(R.string.continue_without_public_key_instructions_fmt)
|
.setMessage(R.string.continue_without_public_key_instructions_fmt)
|
||||||
.setPositiveButton(R.string.continue_action, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.continue_action, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||||
mContinueWithoutPublicKey = true;
|
mContinueWithoutPublicKey = true;
|
||||||
onSend();
|
onSend();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.back_action, new DialogInterface.OnClickListener() {
|
.setNegativeButton(R.string.back_action, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||||
mContinueWithoutPublicKey = false;
|
mContinueWithoutPublicKey = false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
case DIALOG_CONFIRM_DISCARD_ON_BACK:
|
case DIALOG_CONFIRM_DISCARD_ON_BACK:
|
||||||
return new AlertDialog.Builder(this)
|
return new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.confirm_discard_draft_message_title)
|
.setTitle(R.string.confirm_discard_draft_message_title)
|
||||||
.setMessage(R.string.confirm_discard_draft_message)
|
.setMessage(R.string.confirm_discard_draft_message)
|
||||||
.setPositiveButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
dismissDialog(DIALOG_CONFIRM_DISCARD_ON_BACK);
|
dismissDialog(DIALOG_CONFIRM_DISCARD_ON_BACK);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.discard_action, new DialogInterface.OnClickListener() {
|
.setNegativeButton(R.string.discard_action, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
dismissDialog(DIALOG_CONFIRM_DISCARD_ON_BACK);
|
dismissDialog(DIALOG_CONFIRM_DISCARD_ON_BACK);
|
||||||
Toast.makeText(MessageCompose.this,
|
Toast.makeText(MessageCompose.this,
|
||||||
getString(R.string.message_discarded_toast),
|
getString(R.string.message_discarded_toast),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
onDiscard();
|
onDiscard();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
case DIALOG_CHOOSE_IDENTITY:
|
case DIALOG_CHOOSE_IDENTITY:
|
||||||
Context context = new ContextThemeWrapper(this,
|
Context context = new ContextThemeWrapper(this,
|
||||||
(K9.getK9Theme() == K9.Theme.LIGHT) ?
|
(K9.getK9Theme() == K9.Theme.LIGHT) ?
|
||||||
R.style.Theme_K9_Dialog_Light :
|
R.style.Theme_K9_Dialog_Light :
|
||||||
R.style.Theme_K9_Dialog_Dark);
|
R.style.Theme_K9_Dialog_Dark);
|
||||||
Builder builder = new AlertDialog.Builder(context);
|
Builder builder = new AlertDialog.Builder(context);
|
||||||
builder.setTitle(R.string.send_as);
|
builder.setTitle(R.string.send_as);
|
||||||
final IdentityAdapter adapter = new IdentityAdapter(context);
|
final IdentityAdapter adapter = new IdentityAdapter(context);
|
||||||
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
|
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
IdentityContainer container = (IdentityContainer) adapter.getItem(which);
|
IdentityContainer container = (IdentityContainer) adapter.getItem(which);
|
||||||
onAccountChosen(container.account, container.identity);
|
onAccountChosen(container.account, container.identity);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
return super.onCreateDialog(id);
|
return super.onCreateDialog(id);
|
||||||
}
|
}
|
||||||
@ -2993,8 +2892,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "could not get Message-ID.");
|
Log.d(K9.LOG_TAG, "could not get Message-ID.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quote the message and setup the UI.
|
// Quote the message and setup the UI.
|
||||||
@ -3387,10 +3287,10 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
List<Integer> start = new ArrayList<Integer>();
|
List<Integer> start = new ArrayList<Integer>();
|
||||||
List<Integer> end = new ArrayList<Integer>();
|
List<Integer> end = new ArrayList<Integer>();
|
||||||
|
|
||||||
while(blockquoteStart.find()) {
|
while (blockquoteStart.find()) {
|
||||||
start.add(blockquoteStart.start());
|
start.add(blockquoteStart.start());
|
||||||
}
|
}
|
||||||
while(blockquoteEnd.find()) {
|
while (blockquoteEnd.find()) {
|
||||||
end.add(blockquoteEnd.start());
|
end.add(blockquoteEnd.start());
|
||||||
}
|
}
|
||||||
if (start.size() != end.size()) {
|
if (start.size() != end.size()) {
|
||||||
@ -3405,8 +3305,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < start.size() - 1; i++) {
|
for (int i = 0; i < start.size() - 1; i++) {
|
||||||
// within blockquotes.
|
// within blockquotes.
|
||||||
if (end.get(i) < start.get(i+1)) {
|
if (end.get(i) < start.get(i + 1)) {
|
||||||
dashSignatureHtml.region(end.get(i), start.get(i+1));
|
dashSignatureHtml.region(end.get(i), start.get(i + 1));
|
||||||
if (dashSignatureHtml.find()) {
|
if (dashSignatureHtml.find()) {
|
||||||
content = content.substring(0, dashSignatureHtml.start());
|
content = content.substring(0, dashSignatureHtml.start());
|
||||||
break;
|
break;
|
||||||
@ -3493,30 +3393,34 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
// HTML takes precedence, then text.
|
// HTML takes precedence, then text.
|
||||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||||
if (part != null) {
|
if (part != null) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: HTML requested, HTML found.");
|
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: HTML requested, HTML found.");
|
||||||
|
}
|
||||||
return MimeUtility.getTextFromPart(part);
|
return MimeUtility.getTextFromPart(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||||
if (part != null) {
|
if (part != null) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: HTML requested, text found.");
|
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: HTML requested, text found.");
|
||||||
|
}
|
||||||
return HtmlConverter.textToHtml(MimeUtility.getTextFromPart(part));
|
return HtmlConverter.textToHtml(MimeUtility.getTextFromPart(part));
|
||||||
}
|
}
|
||||||
} else if (format == SimpleMessageFormat.TEXT) {
|
} else if (format == SimpleMessageFormat.TEXT) {
|
||||||
// Text takes precedence, then html.
|
// Text takes precedence, then html.
|
||||||
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||||
if (part != null) {
|
if (part != null) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: Text requested, text found.");
|
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: Text requested, text found.");
|
||||||
|
}
|
||||||
return MimeUtility.getTextFromPart(part);
|
return MimeUtility.getTextFromPart(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||||
if (part != null) {
|
if (part != null) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: Text requested, HTML found.");
|
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: Text requested, HTML found.");
|
||||||
|
}
|
||||||
return HtmlConverter.htmlToText(MimeUtility.getTextFromPart(part));
|
return HtmlConverter.htmlToText(MimeUtility.getTextFromPart(part));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3583,8 +3487,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
hasBodyTag = true;
|
hasBodyTag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Open: hasHtmlTag:" + hasHtmlTag + " hasHeadTag:" + hasHeadTag + " hasBodyTag:" + hasBodyTag);
|
Log.d(K9.LOG_TAG, "Open: hasHtmlTag:" + hasHtmlTag + " hasHeadTag:" + hasHeadTag + " hasBodyTag:" + hasBodyTag);
|
||||||
|
}
|
||||||
|
|
||||||
// Given our inspections, let's figure out where to start our content.
|
// Given our inspections, let's figure out where to start our content.
|
||||||
// This is the ideal case -- there's a BODY tag and we insert ourselves just after it.
|
// This is the ideal case -- there's a BODY tag and we insert ourselves just after it.
|
||||||
@ -3635,8 +3540,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||||||
hasBodyEndTag = true;
|
hasBodyEndTag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Close: hasHtmlEndTag:" + hasHtmlEndTag + " hasBodyEndTag:" + hasBodyEndTag);
|
Log.d(K9.LOG_TAG, "Close: hasHtmlEndTag:" + hasHtmlEndTag + " hasBodyEndTag:" + hasBodyEndTag);
|
||||||
|
}
|
||||||
|
|
||||||
// Now figure out where to put our footer.
|
// Now figure out where to put our footer.
|
||||||
// This is the ideal case -- there's a BODY tag and we insert ourselves just before it.
|
// This is the ideal case -- there's a BODY tag and we insert ourselves just before it.
|
||||||
|
242
src/com/fsck/k9/mail/internet/TextBodyBuilder.java
Normal file
242
src/com/fsck/k9/mail/internet/TextBodyBuilder.java
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
package com.fsck.k9.mail.internet;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.fsck.k9.K9;
|
||||||
|
import com.fsck.k9.activity.InsertableHtmlContent;
|
||||||
|
import com.fsck.k9.helper.HtmlConverter;
|
||||||
|
import com.fsck.k9.helper.StringUtils;
|
||||||
|
import com.fsck.k9.mail.Body;
|
||||||
|
|
||||||
|
public class TextBodyBuilder {
|
||||||
|
private boolean mIncludeQuotedText = true;
|
||||||
|
private boolean mReplyAfterQuote = false;
|
||||||
|
private boolean mSignatureBeforeQuotedText = false;
|
||||||
|
private boolean mInsertSeparator = false;
|
||||||
|
private boolean mAppendSignature = true;
|
||||||
|
|
||||||
|
private String mMessageContent;
|
||||||
|
private String mSignature;
|
||||||
|
private String mQuotedText;
|
||||||
|
private InsertableHtmlContent mQuotedTextHtml;
|
||||||
|
|
||||||
|
public TextBodyBuilder(String messageContent) {
|
||||||
|
mMessageContent = messageContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the {@link Body} that will contain the text of the message.
|
||||||
|
*
|
||||||
|
* @return {@link TextBody} instance that contains the entered text and
|
||||||
|
* possibly the quoted original message.
|
||||||
|
*/
|
||||||
|
public TextBody buildTextHtml() {
|
||||||
|
// The length of the formatted version of the user-supplied text/reply
|
||||||
|
int composedMessageLength;
|
||||||
|
|
||||||
|
// The offset of the user-supplied text/reply in the final text body
|
||||||
|
int composedMessageOffset;
|
||||||
|
|
||||||
|
// Get the user-supplied text
|
||||||
|
String text = mMessageContent;
|
||||||
|
|
||||||
|
// Do we have to modify an existing message to include our reply?
|
||||||
|
if (mIncludeQuotedText) {
|
||||||
|
InsertableHtmlContent quotedHtmlContent = getQuotedTextHtml();
|
||||||
|
|
||||||
|
if (K9.DEBUG) {
|
||||||
|
Log.d(K9.LOG_TAG, "insertable: " + quotedHtmlContent.toDebugString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAppendSignature) {
|
||||||
|
// Append signature to the reply
|
||||||
|
if (mReplyAfterQuote || mSignatureBeforeQuotedText) {
|
||||||
|
text += getSignature();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the text to HTML
|
||||||
|
text = textToHtmlFragment(text);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the insertion location based upon our reply after quote
|
||||||
|
* setting. Additionally, add some extra separators between the
|
||||||
|
* composed message and quoted message depending on the quote
|
||||||
|
* location. We only add the extra separators when we're
|
||||||
|
* sending, that way when we load a draft, we don't have to know
|
||||||
|
* the length of the separators to remove them before editing.
|
||||||
|
*/
|
||||||
|
if (mReplyAfterQuote) {
|
||||||
|
quotedHtmlContent.setInsertionLocation(
|
||||||
|
InsertableHtmlContent.InsertionLocation.AFTER_QUOTE);
|
||||||
|
if (mInsertSeparator) {
|
||||||
|
text = "<br clear=\"all\">" + text;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quotedHtmlContent.setInsertionLocation(
|
||||||
|
InsertableHtmlContent.InsertionLocation.BEFORE_QUOTE);
|
||||||
|
if (mInsertSeparator) {
|
||||||
|
text += "<br><br>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAppendSignature) {
|
||||||
|
// Place signature immediately after the quoted text
|
||||||
|
if (!(mReplyAfterQuote || mSignatureBeforeQuotedText)) {
|
||||||
|
quotedHtmlContent.insertIntoQuotedFooter(getSignatureHtml());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quotedHtmlContent.setUserContent(text);
|
||||||
|
|
||||||
|
// Save length of the body and its offset. This is used when thawing drafts.
|
||||||
|
composedMessageLength = text.length();
|
||||||
|
composedMessageOffset = quotedHtmlContent.getInsertionPoint();
|
||||||
|
text = quotedHtmlContent.toString();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// There is no text to quote so simply append the signature if available
|
||||||
|
if (mAppendSignature) {
|
||||||
|
text += getSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the text to HTML
|
||||||
|
text = textToHtmlFragment(text);
|
||||||
|
|
||||||
|
//TODO: Wrap this in proper HTML tags
|
||||||
|
|
||||||
|
composedMessageLength = text.length();
|
||||||
|
composedMessageOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBody body = new TextBody(text);
|
||||||
|
body.setComposedMessageLength(composedMessageLength);
|
||||||
|
body.setComposedMessageOffset(composedMessageOffset);
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the {@link Body} that will contain the text of the message.
|
||||||
|
*
|
||||||
|
* @return {@link TextBody} instance that contains the entered text and
|
||||||
|
* possibly the quoted original message.
|
||||||
|
*/
|
||||||
|
public TextBody buildTextPlain() {
|
||||||
|
// The length of the formatted version of the user-supplied text/reply
|
||||||
|
int composedMessageLength;
|
||||||
|
|
||||||
|
// The offset of the user-supplied text/reply in the final text body
|
||||||
|
int composedMessageOffset;
|
||||||
|
|
||||||
|
// Get the user-supplied text
|
||||||
|
String text = mMessageContent;
|
||||||
|
|
||||||
|
// Capture composed message length before we start attaching quoted parts and signatures.
|
||||||
|
composedMessageLength = text.length();
|
||||||
|
composedMessageOffset = 0;
|
||||||
|
|
||||||
|
// Do we have to modify an existing message to include our reply?
|
||||||
|
if (mIncludeQuotedText) {
|
||||||
|
String quotedText = getQuotedText();
|
||||||
|
|
||||||
|
if (mAppendSignature) {
|
||||||
|
// Append signature to the text/reply
|
||||||
|
if (mReplyAfterQuote || mSignatureBeforeQuotedText) {
|
||||||
|
text += getSignature();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mReplyAfterQuote) {
|
||||||
|
composedMessageOffset = quotedText.length() + "\r\n".length();
|
||||||
|
text = quotedText + "\r\n" + text;
|
||||||
|
} else {
|
||||||
|
text += "\r\n\r\n" + quotedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAppendSignature) {
|
||||||
|
// Place signature immediately after the quoted text
|
||||||
|
if (!(mReplyAfterQuote || mSignatureBeforeQuotedText)) {
|
||||||
|
text += getSignature();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There is no text to quote so simply append the signature if available
|
||||||
|
if (mAppendSignature) {
|
||||||
|
// Append signature to the text/reply
|
||||||
|
text += getSignature();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBody body = new TextBody(text);
|
||||||
|
body.setComposedMessageLength(composedMessageLength);
|
||||||
|
body.setComposedMessageOffset(composedMessageOffset);
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSignature() {
|
||||||
|
String signature = "";
|
||||||
|
if (!StringUtils.isNullOrEmpty(mSignature)) {
|
||||||
|
signature = "\r\n" + mSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSignatureHtml() {
|
||||||
|
String signature = "";
|
||||||
|
if (!StringUtils.isNullOrEmpty(mSignature)) {
|
||||||
|
signature = textToHtmlFragment("\r\n" + mSignature);
|
||||||
|
}
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getQuotedText() {
|
||||||
|
String quotedText = "";
|
||||||
|
if (!StringUtils.isNullOrEmpty(mQuotedText)) {
|
||||||
|
quotedText = mQuotedText;
|
||||||
|
}
|
||||||
|
return quotedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InsertableHtmlContent getQuotedTextHtml() {
|
||||||
|
return mQuotedTextHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String textToHtmlFragment(String text) {
|
||||||
|
return HtmlConverter.textToHtmlFragment(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignature(String signature) {
|
||||||
|
mSignature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIncludeQuotedText(boolean includeQuotedText) {
|
||||||
|
mIncludeQuotedText = includeQuotedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQuotedText(String quotedText) {
|
||||||
|
mQuotedText = quotedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQuotedTextHtml(InsertableHtmlContent quotedTextHtml) {
|
||||||
|
mQuotedTextHtml = quotedTextHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInsertSeparator(boolean insertSeparator) {
|
||||||
|
mInsertSeparator = insertSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignatureBeforeQuotedText(boolean signatureBeforeQuotedText) {
|
||||||
|
mSignatureBeforeQuotedText = signatureBeforeQuotedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReplyAfterQuote(boolean replyAfterQuote) {
|
||||||
|
mReplyAfterQuote = replyAfterQuote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppendSignature(boolean appendSignature) {
|
||||||
|
mAppendSignature = appendSignature;
|
||||||
|
}
|
||||||
|
}
|
5
tests-on-jvm/src/com/fsck/k9/K9.java
Normal file
5
tests-on-jvm/src/com/fsck/k9/K9.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.fsck.k9;
|
||||||
|
|
||||||
|
public class K9 {
|
||||||
|
public static boolean DEBUG = false;
|
||||||
|
}
|
@ -0,0 +1,328 @@
|
|||||||
|
package com.fsck.k9.mail.internet;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.experimental.theories.*;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import com.fsck.k9.Account.QuoteStyle;
|
||||||
|
import com.fsck.k9.activity.InsertableHtmlContent;
|
||||||
|
|
||||||
|
class TestingTextBodyBuilder extends TextBodyBuilder {
|
||||||
|
|
||||||
|
public TestingTextBodyBuilder(boolean includeQuotedText,
|
||||||
|
boolean isDraft,
|
||||||
|
QuoteStyle quoteStyle,
|
||||||
|
boolean replyAfterQuote,
|
||||||
|
boolean signatureBeforeQuotedText,
|
||||||
|
boolean useSignature,
|
||||||
|
String messageText,
|
||||||
|
String signatureText) {
|
||||||
|
super(messageText);
|
||||||
|
|
||||||
|
includeQuotedText = (isDraft || includeQuotedText);
|
||||||
|
if (includeQuotedText) {
|
||||||
|
this.setIncludeQuotedText(true);
|
||||||
|
this.setReplyAfterQuote(quoteStyle == QuoteStyle.PREFIX && replyAfterQuote);
|
||||||
|
} else {
|
||||||
|
this.setIncludeQuotedText(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setInsertSeparator(!isDraft);
|
||||||
|
|
||||||
|
useSignature = (!isDraft && useSignature);
|
||||||
|
if (useSignature) {
|
||||||
|
this.setAppendSignature(true);
|
||||||
|
this.setSignature(signatureText);
|
||||||
|
this.setSignatureBeforeQuotedText(signatureBeforeQuotedText);
|
||||||
|
} else {
|
||||||
|
this.setAppendSignature(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HtmlConverter depends on Android.
|
||||||
|
// So we use dummy method for tests.
|
||||||
|
@Override
|
||||||
|
public String textToHtmlFragment(String text) {
|
||||||
|
return "<html>" + text + "</html>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RunWith(Theories.class)
|
||||||
|
public class TextBodyBuilderTest {
|
||||||
|
|
||||||
|
@DataPoints
|
||||||
|
public static boolean[] BOOLEANS = { true, false };
|
||||||
|
|
||||||
|
@DataPoints
|
||||||
|
public static QuoteStyle[] QUOTESTYLES = { QuoteStyle.PREFIX, QuoteStyle.HEADER };
|
||||||
|
|
||||||
|
@Theory
|
||||||
|
public void testBuildTextPlain(boolean includeQuotedText,
|
||||||
|
QuoteStyle quoteStyle,
|
||||||
|
boolean isReplyAfterQuote,
|
||||||
|
boolean isSignatureUse,
|
||||||
|
boolean isSignatureBeforeQuotedText,
|
||||||
|
boolean isDraft) {
|
||||||
|
|
||||||
|
String expectedText;
|
||||||
|
int expectedMessageLength;
|
||||||
|
int expectedMessagePosition;
|
||||||
|
|
||||||
|
// 1.quoted text
|
||||||
|
// 2.message content
|
||||||
|
// 3.signature
|
||||||
|
if (quoteStyle == QuoteStyle.PREFIX && isReplyAfterQuote) {
|
||||||
|
String expectedQuotedText = "";
|
||||||
|
|
||||||
|
if (isDraft || includeQuotedText) {
|
||||||
|
expectedQuotedText = "quoted text" + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedText = expectedQuotedText;
|
||||||
|
|
||||||
|
expectedText += "message content";
|
||||||
|
|
||||||
|
if (!isDraft && isSignatureUse) {
|
||||||
|
expectedText += "\r\n" + "signature";
|
||||||
|
}
|
||||||
|
expectedMessageLength = "message content".length();
|
||||||
|
expectedMessagePosition = expectedQuotedText.length();
|
||||||
|
}
|
||||||
|
// 1.message content
|
||||||
|
// 2.signature
|
||||||
|
// 3.quoted text
|
||||||
|
else if (isSignatureBeforeQuotedText) {
|
||||||
|
expectedText = "message content";
|
||||||
|
|
||||||
|
if (!isDraft && isSignatureUse) {
|
||||||
|
expectedText += "\r\n" + "signature";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDraft || includeQuotedText) {
|
||||||
|
expectedText += "\r\n\r\nquoted text";
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedMessageLength = "message content".length();
|
||||||
|
expectedMessagePosition = 0;
|
||||||
|
}
|
||||||
|
// 1.message content
|
||||||
|
// 2.quoted text
|
||||||
|
// 3.signature
|
||||||
|
else {
|
||||||
|
expectedText = "message content";
|
||||||
|
|
||||||
|
if (isDraft || includeQuotedText) {
|
||||||
|
expectedText += "\r\n\r\nquoted text";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isDraft && isSignatureUse) {
|
||||||
|
expectedText += "\r\n" + "signature";
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedMessageLength = "message content".length();
|
||||||
|
expectedMessagePosition = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String quotedText = "quoted text";
|
||||||
|
String messageText = "message content";
|
||||||
|
String signatureText = "signature";
|
||||||
|
|
||||||
|
TestingTextBodyBuilder textBodyBuilder = new TestingTextBodyBuilder(
|
||||||
|
includeQuotedText,
|
||||||
|
isDraft,
|
||||||
|
quoteStyle,
|
||||||
|
isReplyAfterQuote,
|
||||||
|
isSignatureBeforeQuotedText,
|
||||||
|
isSignatureUse,
|
||||||
|
messageText,
|
||||||
|
signatureText
|
||||||
|
);
|
||||||
|
textBodyBuilder.setQuotedText(quotedText);
|
||||||
|
TextBody textBody = textBodyBuilder.buildTextPlain();
|
||||||
|
|
||||||
|
assertThat(textBody, instanceOf(TextBody.class));
|
||||||
|
assertThat(textBody.getText(), is(expectedText));
|
||||||
|
assertThat(textBody.getComposedMessageLength(), is(expectedMessageLength));
|
||||||
|
assertThat(textBody.getComposedMessageOffset(), is(expectedMessagePosition));
|
||||||
|
assertThat(textBody.getText().substring(expectedMessagePosition, expectedMessagePosition + expectedMessageLength),
|
||||||
|
is("message content"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate expected HtmlContent debug string
|
||||||
|
*
|
||||||
|
* @param expectedText
|
||||||
|
* @param quotedContent
|
||||||
|
* @param footerInsertionPoint
|
||||||
|
* @param isBefore
|
||||||
|
* @param userContent
|
||||||
|
* @param compiledResult
|
||||||
|
* @return expected string
|
||||||
|
*
|
||||||
|
* @see InsertableHtmlContent#toDebugString()
|
||||||
|
*/
|
||||||
|
public String makeExpectedHtmlContent(String expectedText, String quotedContent,
|
||||||
|
int footerInsertionPoint, boolean isBefore,
|
||||||
|
String userContent, String compiledResult) {
|
||||||
|
String expectedHtmlContent = "InsertableHtmlContent{"
|
||||||
|
+ "headerInsertionPoint=0,"
|
||||||
|
+ " footerInsertionPoint=" + footerInsertionPoint + ","
|
||||||
|
+ " insertionLocation=" + (isBefore ? "BEFORE_QUOTE" : "AFTER_QUOTE") + ","
|
||||||
|
+ " quotedContent=" + quotedContent + ","
|
||||||
|
+ " userContent=" + userContent + ","
|
||||||
|
+ " compiledResult=" + compiledResult
|
||||||
|
+ "}";
|
||||||
|
return expectedHtmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Theory
|
||||||
|
public void testBuildTextHtml(boolean includeQuotedText,
|
||||||
|
QuoteStyle quoteStyle,
|
||||||
|
boolean isReplyAfterQuote,
|
||||||
|
boolean isSignatureUse,
|
||||||
|
boolean isSignatureBeforeQuotedText,
|
||||||
|
boolean isDraft) {
|
||||||
|
String expectedText;
|
||||||
|
int expectedMessageLength;
|
||||||
|
int expectedMessagePosition = 0;
|
||||||
|
String expectedHtmlContent;
|
||||||
|
|
||||||
|
String expectedPrefix = "";
|
||||||
|
|
||||||
|
if (includeQuotedText && quoteStyle == QuoteStyle.PREFIX && isReplyAfterQuote && !isDraft) {
|
||||||
|
expectedPrefix = "<br clear=\"all\">";
|
||||||
|
}
|
||||||
|
String expectedPostfix = "";
|
||||||
|
if (!isDraft && includeQuotedText) {
|
||||||
|
expectedPostfix = "<br><br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1.quoted text
|
||||||
|
// 2.message content
|
||||||
|
// 3.signature
|
||||||
|
if (quoteStyle == QuoteStyle.PREFIX && isReplyAfterQuote) {
|
||||||
|
expectedText = expectedPrefix
|
||||||
|
+ "<html>message content";
|
||||||
|
if (!isDraft && isSignatureUse) {
|
||||||
|
expectedText += "\r\n" + "signature";
|
||||||
|
}
|
||||||
|
expectedText += "</html>";
|
||||||
|
expectedMessageLength = expectedText.length();
|
||||||
|
String quotedContent = "quoted text";
|
||||||
|
|
||||||
|
if (isDraft || includeQuotedText) {
|
||||||
|
expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
expectedText,
|
||||||
|
expectedText + quotedContent);
|
||||||
|
expectedText += quotedContent;
|
||||||
|
} else {
|
||||||
|
expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
quotedContent);
|
||||||
|
// expectedText += quotedContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 1.message content
|
||||||
|
// 2.signature
|
||||||
|
// 3.quoted text
|
||||||
|
else if (isSignatureBeforeQuotedText) {
|
||||||
|
expectedText = expectedPrefix
|
||||||
|
+ "<html>message content";
|
||||||
|
if (!isDraft && isSignatureUse) {
|
||||||
|
expectedText += "\r\n" + "signature";
|
||||||
|
}
|
||||||
|
expectedText += "</html>";
|
||||||
|
expectedText += expectedPostfix;
|
||||||
|
|
||||||
|
expectedMessageLength = expectedText.length();
|
||||||
|
String quotedContent = "quoted text";
|
||||||
|
|
||||||
|
if (isDraft || includeQuotedText) {
|
||||||
|
expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
expectedText,
|
||||||
|
expectedText + quotedContent);
|
||||||
|
expectedText += quotedContent;
|
||||||
|
} else {
|
||||||
|
expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
quotedContent);
|
||||||
|
// expectedText += quotedContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 1.message content
|
||||||
|
// 2.quoted text
|
||||||
|
// 3.signature
|
||||||
|
else {
|
||||||
|
String expectedSignature = "";
|
||||||
|
|
||||||
|
expectedText = expectedPrefix
|
||||||
|
+ "<html>message content";
|
||||||
|
|
||||||
|
if (!isDraft && isSignatureUse) {
|
||||||
|
if (!includeQuotedText) {
|
||||||
|
expectedText += "\r\n" + "signature";
|
||||||
|
} else {
|
||||||
|
expectedSignature = "<html>\r\nsignature</html>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expectedText += "</html>";
|
||||||
|
expectedText += expectedPostfix;
|
||||||
|
|
||||||
|
expectedMessageLength = expectedText.length();
|
||||||
|
String quotedContent = "quoted text";
|
||||||
|
|
||||||
|
if (isDraft || includeQuotedText) {
|
||||||
|
expectedHtmlContent = makeExpectedHtmlContent(expectedText, expectedSignature + quotedContent,
|
||||||
|
expectedSignature.length(),
|
||||||
|
true,
|
||||||
|
expectedText,
|
||||||
|
expectedText + expectedSignature + quotedContent);
|
||||||
|
expectedText += expectedSignature + quotedContent;
|
||||||
|
} else {
|
||||||
|
expectedHtmlContent = makeExpectedHtmlContent(expectedText, quotedContent,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
quotedContent);
|
||||||
|
// expectedText += quotedContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertableHtmlContent insertableHtmlContent = new InsertableHtmlContent();
|
||||||
|
|
||||||
|
String quotedText = "quoted text";
|
||||||
|
insertableHtmlContent.setQuotedContent(new StringBuilder(quotedText));
|
||||||
|
String messageText = "message content";
|
||||||
|
String signatureText = "signature";
|
||||||
|
|
||||||
|
TestingTextBodyBuilder textBodyBuilder = new TestingTextBodyBuilder(
|
||||||
|
includeQuotedText,
|
||||||
|
isDraft,
|
||||||
|
quoteStyle,
|
||||||
|
isReplyAfterQuote,
|
||||||
|
isSignatureBeforeQuotedText,
|
||||||
|
isSignatureUse,
|
||||||
|
messageText,
|
||||||
|
signatureText
|
||||||
|
);
|
||||||
|
textBodyBuilder.setQuotedTextHtml(insertableHtmlContent);
|
||||||
|
TextBody textBody = textBodyBuilder.buildTextHtml();
|
||||||
|
|
||||||
|
assertThat(textBody, instanceOf(TextBody.class));
|
||||||
|
assertThat(textBody.getText(), is(expectedText));
|
||||||
|
assertThat(textBody.getComposedMessageLength(), is(expectedMessageLength));
|
||||||
|
assertThat(textBody.getComposedMessageOffset(), is(expectedMessagePosition));
|
||||||
|
assertThat(insertableHtmlContent.toDebugString(), is(expectedHtmlContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user