commit
df761b9344
16 changed files with 238 additions and 152 deletions
|
@ -113,8 +113,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
public static final String ACTION_EDIT_DRAFT = "com.fsck.k9.intent.action.EDIT_DRAFT";
|
||||
|
||||
public static final String EXTRA_ACCOUNT = "account";
|
||||
public static final String EXTRA_MESSAGE_BODY = "messageBody";
|
||||
public static final String EXTRA_MESSAGE_REFERENCE = "message_reference";
|
||||
public static final String EXTRA_MESSAGE_DECRYPTION_RESULT = "message_decryption_result";
|
||||
|
||||
private static final String STATE_KEY_SOURCE_MESSAGE_PROCED =
|
||||
"com.fsck.k9.activity.MessageCompose.stateKeySourceMessageProced";
|
||||
|
@ -133,7 +133,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
|
||||
private static final int MSG_PROGRESS_ON = 1;
|
||||
private static final int MSG_PROGRESS_OFF = 2;
|
||||
private static final int MSG_SKIPPED_ATTACHMENTS = 3;
|
||||
public static final int MSG_SAVED_DRAFT = 4;
|
||||
private static final int MSG_DISCARDED_DRAFT = 5;
|
||||
|
||||
|
@ -278,12 +277,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
case MSG_PROGRESS_OFF:
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
break;
|
||||
case MSG_SKIPPED_ATTACHMENTS:
|
||||
Toast.makeText(
|
||||
MessageCompose.this,
|
||||
getString(R.string.message_compose_attachments_skipped_toast),
|
||||
Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case MSG_SAVED_DRAFT:
|
||||
mDraftId = (Long) msg.obj;
|
||||
Toast.makeText(
|
||||
|
@ -373,10 +366,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
EolConvertingEditText upperSignature = (EolConvertingEditText)findViewById(R.id.upper_signature);
|
||||
EolConvertingEditText lowerSignature = (EolConvertingEditText)findViewById(R.id.lower_signature);
|
||||
|
||||
String sourceMessageBody = intent.getStringExtra(EXTRA_MESSAGE_BODY);
|
||||
|
||||
QuotedMessageMvpView quotedMessageMvpView = new QuotedMessageMvpView(this);
|
||||
quotedMessagePresenter = new QuotedMessagePresenter(this, quotedMessageMvpView, mAccount, sourceMessageBody);
|
||||
quotedMessagePresenter = new QuotedMessagePresenter(this, quotedMessageMvpView, mAccount);
|
||||
attachmentPresenter = new AttachmentPresenter(getApplicationContext(), attachmentMvpView, getLoaderManager());
|
||||
|
||||
mMessageContentView = (EolConvertingEditText)findViewById(R.id.message_content);
|
||||
|
@ -474,7 +465,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
messageLoaderHelper = new MessageLoaderHelper(this, getLoaderManager(), getFragmentManager(),
|
||||
messageLoaderCallbacks);
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_ON);
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(mMessageReference);
|
||||
|
||||
Parcelable cachedDecryptionResult = intent.getParcelableExtra(EXTRA_MESSAGE_DECRYPTION_RESULT);
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(mMessageReference, cachedDecryptionResult);
|
||||
}
|
||||
|
||||
if (mAction != Action.EDIT_DRAFT) {
|
||||
|
@ -1139,30 +1132,30 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
throw new IllegalStateException("tried to edit quoted message with no referenced message");
|
||||
}
|
||||
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(mMessageReference);
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(mMessageReference, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull out the parts of the now loaded source message and apply them to the new message
|
||||
* depending on the type of message being composed.
|
||||
*
|
||||
* @param message
|
||||
* @param messageViewInfo
|
||||
* The source message used to populate the various text fields.
|
||||
*/
|
||||
private void processSourceMessage(LocalMessage message) {
|
||||
private void processSourceMessage(MessageViewInfo messageViewInfo) {
|
||||
try {
|
||||
switch (mAction) {
|
||||
case REPLY:
|
||||
case REPLY_ALL: {
|
||||
processMessageToReplyTo(message);
|
||||
processMessageToReplyTo(messageViewInfo);
|
||||
break;
|
||||
}
|
||||
case FORWARD: {
|
||||
processMessageToForward(message);
|
||||
processMessageToForward(messageViewInfo);
|
||||
break;
|
||||
}
|
||||
case EDIT_DRAFT: {
|
||||
processDraftMessage(message);
|
||||
processDraftMessage(messageViewInfo);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -1184,7 +1177,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
updateMessageFormat();
|
||||
}
|
||||
|
||||
private void processMessageToReplyTo(Message message) throws MessagingException {
|
||||
private void processMessageToReplyTo(MessageViewInfo messageViewInfo) throws MessagingException {
|
||||
Message message = messageViewInfo.message;
|
||||
|
||||
if (message.getSubject() != null) {
|
||||
final String subject = PREFIX.matcher(message.getSubject()).replaceFirst("");
|
||||
|
||||
|
@ -1221,7 +1216,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
}
|
||||
|
||||
// Quote the message and setup the UI.
|
||||
quotedMessagePresenter.initFromReplyToMessage(message, mAction);
|
||||
quotedMessagePresenter.initFromReplyToMessage(messageViewInfo, mAction);
|
||||
|
||||
if (mAction == Action.REPLY || mAction == Action.REPLY_ALL) {
|
||||
Identity useIdentity = IdentityHelper.getRecipientIdentityFromMessage(mAccount, message);
|
||||
|
@ -1233,7 +1228,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
|
||||
}
|
||||
|
||||
private void processMessageToForward(Message message) throws MessagingException {
|
||||
private void processMessageToForward(MessageViewInfo messageViewInfo) throws MessagingException {
|
||||
Message message = messageViewInfo.message;
|
||||
|
||||
String subject = message.getSubject();
|
||||
if (subject != null && !subject.toLowerCase(Locale.US).startsWith("fwd:")) {
|
||||
mSubjectView.setText("Fwd: " + subject);
|
||||
|
@ -1255,16 +1252,12 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
}
|
||||
|
||||
// Quote the message and setup the UI.
|
||||
quotedMessagePresenter.processMessageToForward(message);
|
||||
|
||||
if (!mSourceMessageProcessed) {
|
||||
if (message.isSet(Flag.X_DOWNLOADED_PARTIAL) || !attachmentPresenter.loadAttachments(message, 0)) {
|
||||
mHandler.sendEmptyMessage(MSG_SKIPPED_ATTACHMENTS);
|
||||
}
|
||||
}
|
||||
quotedMessagePresenter.processMessageToForward(messageViewInfo);
|
||||
attachmentPresenter.processMessageToForward(messageViewInfo);
|
||||
}
|
||||
|
||||
private void processDraftMessage(LocalMessage message) throws MessagingException {
|
||||
private void processDraftMessage(MessageViewInfo messageViewInfo) throws MessagingException {
|
||||
Message message = messageViewInfo.message;
|
||||
mDraftId = MessagingController.getInstance(getApplication()).getId(message);
|
||||
mSubjectView.setText(message.getSubject());
|
||||
|
||||
|
@ -1301,7 +1294,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
newIdentity.setSignature(k9identity.get(IdentityField.SIGNATURE));
|
||||
mSignatureChanged = true;
|
||||
} else {
|
||||
newIdentity.setSignatureUse(message.getFolder().getSignatureUse());
|
||||
if (message instanceof LocalMessage) {
|
||||
newIdentity.setSignatureUse(((LocalMessage) message).getFolder().getSignatureUse());
|
||||
}
|
||||
newIdentity.setSignature(mIdentity.getSignature());
|
||||
}
|
||||
|
||||
|
@ -1341,7 +1336,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
updateSignature();
|
||||
updateFrom();
|
||||
|
||||
quotedMessagePresenter.processDraftMessage(message, k9identity);
|
||||
quotedMessagePresenter.processDraftMessage(messageViewInfo, k9identity);
|
||||
}
|
||||
|
||||
static class SendMessageTask extends AsyncTask<Void, Void, Void> {
|
||||
|
@ -1524,14 +1519,14 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
}
|
||||
}
|
||||
|
||||
public void loadLocalMessageForDisplay(LocalMessage message, Action action) {
|
||||
public void loadLocalMessageForDisplay(MessageViewInfo messageViewInfo, Action action) {
|
||||
// We check to see if we've previously processed the source message since this
|
||||
// could be called when switching from HTML to text replies. If that happens, we
|
||||
// only want to update the UI with quoted text (which picks the appropriate
|
||||
// part).
|
||||
if (mSourceMessageProcessed) {
|
||||
try {
|
||||
quotedMessagePresenter.populateUIWithQuotedMessage(message, true, action);
|
||||
quotedMessagePresenter.populateUIWithQuotedMessage(messageViewInfo, true, action);
|
||||
} catch (MessagingException e) {
|
||||
// Hm, if we couldn't populate the UI after source reprocessing, let's just delete it?
|
||||
quotedMessagePresenter.showOrHideQuotedText(QuotedTextMode.HIDE);
|
||||
|
@ -1539,7 +1534,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
}
|
||||
updateMessageFormat();
|
||||
} else {
|
||||
processSourceMessage(message);
|
||||
processSourceMessage(messageViewInfo);
|
||||
mSourceMessageProcessed = true;
|
||||
}
|
||||
}
|
||||
|
@ -1559,7 +1554,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
@Override
|
||||
public void onMessageViewInfoLoadFinished(LocalMessage localMessage, MessageViewInfo messageViewInfo) {
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
|
||||
loadLocalMessageForDisplay(localMessage, mAction);
|
||||
loadLocalMessageForDisplay(messageViewInfo, mAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1731,6 +1726,12 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
public void performSaveAfterChecks() {
|
||||
MessageCompose.this.performSaveAfterChecks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMissingAttachmentsPartialMessageWarning() {
|
||||
Toast.makeText(MessageCompose.this,
|
||||
getString(R.string.message_compose_attachments_skipped_toast), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import android.content.res.Configuration;
|
|||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -53,7 +54,6 @@ import com.fsck.k9.search.SearchSpecification;
|
|||
import com.fsck.k9.search.SearchSpecification.Attribute;
|
||||
import com.fsck.k9.search.SearchSpecification.SearchCondition;
|
||||
import com.fsck.k9.search.SearchSpecification.SearchField;
|
||||
import com.fsck.k9.ui.messageview.CryptoInfoDialog.OnClickShowCryptoKeyListener;
|
||||
import com.fsck.k9.ui.messageview.MessageViewFragment;
|
||||
import com.fsck.k9.ui.messageview.MessageViewFragment.MessageViewFragmentListener;
|
||||
import com.fsck.k9.view.MessageHeader;
|
||||
|
@ -1210,17 +1210,32 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
|
|||
|
||||
@Override
|
||||
public void onForward(LocalMessage message) {
|
||||
MessageActions.actionForward(this, message, null);
|
||||
onForward(message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onForward(LocalMessage message, Parcelable decryptionResultForReply) {
|
||||
MessageActions.actionForward(this, message, decryptionResultForReply);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReply(LocalMessage message) {
|
||||
MessageActions.actionReply(this, message, false, null);
|
||||
onReply(message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReply(LocalMessage message, Parcelable decryptionResultForReply) {
|
||||
MessageActions.actionReply(this, message, false, decryptionResultForReply);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplyAll(LocalMessage message) {
|
||||
MessageActions.actionReply(this, message, true, null);
|
||||
onReplyAll(message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplyAll(LocalMessage message, Parcelable decryptionResultForReply) {
|
||||
MessageActions.actionReply(this, message, true, decryptionResultForReply);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.content.Intent;
|
|||
import android.content.IntentSender;
|
||||
import android.content.Loader;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
|
@ -28,6 +29,7 @@ import com.fsck.k9.ui.crypto.MessageCryptoCallback;
|
|||
import com.fsck.k9.ui.crypto.MessageCryptoHelper;
|
||||
import com.fsck.k9.ui.message.LocalMessageExtractorLoader;
|
||||
import com.fsck.k9.ui.message.LocalMessageLoader;
|
||||
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
||||
|
||||
|
||||
/** This class is responsible for loading a message start to finish, and
|
||||
|
@ -83,6 +85,7 @@ public class MessageLoaderHelper {
|
|||
|
||||
private LocalMessage localMessage;
|
||||
private MessageCryptoAnnotations messageCryptoAnnotations;
|
||||
private OpenPgpDecryptionResult cachedDecryptionResult;
|
||||
|
||||
private MessageCryptoHelper messageCryptoHelper;
|
||||
|
||||
|
@ -99,10 +102,18 @@ public class MessageLoaderHelper {
|
|||
// public interface
|
||||
|
||||
@UiThread
|
||||
public void asyncStartOrResumeLoadingMessage(MessageReference messageReference) {
|
||||
public void asyncStartOrResumeLoadingMessage(MessageReference messageReference, Parcelable cachedDecryptionResult) {
|
||||
this.messageReference = messageReference;
|
||||
this.account = Preferences.getPreferences(context).getAccount(messageReference.getAccountUuid());
|
||||
|
||||
if (cachedDecryptionResult != null) {
|
||||
if (cachedDecryptionResult instanceof OpenPgpDecryptionResult) {
|
||||
this.cachedDecryptionResult = (OpenPgpDecryptionResult) cachedDecryptionResult;
|
||||
} else {
|
||||
Log.e(K9.LOG_TAG, "Got decryption result of unknown type - ignoring");
|
||||
}
|
||||
}
|
||||
|
||||
startOrResumeLocalMessageLoader();
|
||||
}
|
||||
|
||||
|
@ -248,7 +259,8 @@ public class MessageLoaderHelper {
|
|||
messageCryptoHelper = new MessageCryptoHelper(context, account.getOpenPgpProvider());
|
||||
retainCryptoHelperFragment.setData(messageCryptoHelper);
|
||||
}
|
||||
messageCryptoHelper.asyncStartOrResumeProcessingMessage(localMessage, messageCryptoCallback);
|
||||
messageCryptoHelper.asyncStartOrResumeProcessingMessage(
|
||||
localMessage, messageCryptoCallback, cachedDecryptionResult);
|
||||
}
|
||||
|
||||
private void cancelAndClearCryptoOperation() {
|
||||
|
|
|
@ -21,11 +21,14 @@ import com.fsck.k9.activity.loader.AttachmentContentLoader;
|
|||
import com.fsck.k9.activity.loader.AttachmentInfoLoader;
|
||||
import com.fsck.k9.activity.misc.Attachment;
|
||||
import com.fsck.k9.activity.misc.Attachment.LoadingState;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Multipart;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
import com.fsck.k9.mailstore.LocalBodyPart;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo;
|
||||
import com.fsck.k9.provider.AttachmentProvider;
|
||||
|
||||
|
||||
|
@ -130,31 +133,74 @@ public class AttachmentPresenter {
|
|||
addAttachment(uri, null);
|
||||
}
|
||||
|
||||
public void addAttachment(Uri uri, String contentType) {
|
||||
int loaderId = getNextFreeLoaderId();
|
||||
Attachment attachment = Attachment.createAttachment(uri, loaderId, contentType);
|
||||
public void addAttachment(AttachmentViewInfo attachmentViewInfo) {
|
||||
if (attachments.containsKey(attachmentViewInfo.uri)) {
|
||||
throw new IllegalStateException("Received the same attachmentViewInfo twice!");
|
||||
}
|
||||
|
||||
int loaderId = getNextFreeLoaderId();
|
||||
Attachment attachment = Attachment.createAttachment(
|
||||
attachmentViewInfo.uri, loaderId, attachmentViewInfo.mimeType);
|
||||
attachment = attachment.deriveWithMetadataLoaded(
|
||||
attachmentViewInfo.mimeType, attachmentViewInfo.displayName, attachmentViewInfo.size);
|
||||
|
||||
addAttachmentAndStartLoader(attachment);
|
||||
}
|
||||
|
||||
public void addAttachment(Uri uri, String contentType) {
|
||||
if (attachments.containsKey(uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
attachments.put(uri, attachment);
|
||||
int loaderId = getNextFreeLoaderId();
|
||||
Attachment attachment = Attachment.createAttachment(uri, loaderId, contentType);
|
||||
|
||||
addAttachmentAndStartLoader(attachment);
|
||||
}
|
||||
|
||||
public void processMessageToForward(MessageViewInfo messageViewInfo) {
|
||||
if (messageViewInfo.message.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
|
||||
attachmentMvpView.showMissingAttachmentsPartialMessageWarning();
|
||||
return;
|
||||
}
|
||||
|
||||
for (AttachmentViewInfo attachmentViewInfo : messageViewInfo.attachments) {
|
||||
if (attachmentViewInfo.firstClassAttachment) {
|
||||
addAttachment(attachmentViewInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addAttachmentAndStartLoader(Attachment attachment) {
|
||||
attachments.put(attachment.uri, attachment);
|
||||
attachmentMvpView.addAttachmentView(attachment);
|
||||
|
||||
initAttachmentInfoLoader(attachment);
|
||||
if (attachment.state == LoadingState.URI_ONLY) {
|
||||
initAttachmentInfoLoader(attachment);
|
||||
} else if (attachment.state == LoadingState.METADATA) {
|
||||
initAttachmentContentLoader(attachment);
|
||||
} else {
|
||||
throw new IllegalStateException("Attachment can only be added in URI_ONLY or METADATA state!");
|
||||
}
|
||||
}
|
||||
|
||||
private void initAttachmentInfoLoader(Attachment attachment) {
|
||||
if (attachment.state != LoadingState.URI_ONLY) {
|
||||
throw new IllegalStateException("initAttachmentInfoLoader can only be called for URI_ONLY state!");
|
||||
}
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(LOADER_ARG_ATTACHMENT, attachment.uri);
|
||||
|
||||
loaderManager.initLoader(attachment.loaderId, bundle, mAttachmentInfoLoaderCallback);
|
||||
}
|
||||
|
||||
private void initAttachmentContentLoader(Attachment attachment) {
|
||||
if (attachment.state != LoadingState.METADATA) {
|
||||
throw new IllegalStateException("initAttachmentContentLoader can only be called for METADATA state!");
|
||||
}
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(LOADER_ARG_ATTACHMENT, attachment.uri);
|
||||
|
||||
loaderManager.initLoader(attachment.loaderId, bundle, mAttachmentContentLoaderCallback);
|
||||
}
|
||||
|
||||
|
@ -364,5 +410,6 @@ public class AttachmentPresenter {
|
|||
void performSendAfterChecks();
|
||||
void performSaveAfterChecks();
|
||||
|
||||
void showMissingAttachmentsPartialMessageWarning();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.fsck.k9.activity.compose;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.Preferences;
|
||||
|
@ -28,15 +29,11 @@ public class MessageActions {
|
|||
/**
|
||||
* Get intent for composing a new message as a reply to the given message. If replyAll is true
|
||||
* the function is reply all instead of simply reply.
|
||||
* @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message
|
||||
*/
|
||||
public static Intent getActionReplyIntent(
|
||||
Context context,
|
||||
LocalMessage message,
|
||||
boolean replyAll,
|
||||
String messageBody) {
|
||||
Context context, LocalMessage message, boolean replyAll, Parcelable decryptionResult) {
|
||||
Intent i = new Intent(context, MessageCompose.class);
|
||||
i.putExtra(MessageCompose.EXTRA_MESSAGE_BODY, messageBody);
|
||||
i.putExtra(MessageCompose.EXTRA_MESSAGE_DECRYPTION_RESULT, decryptionResult);
|
||||
i.putExtra(MessageCompose.EXTRA_MESSAGE_REFERENCE, message.makeMessageReference());
|
||||
if (replyAll) {
|
||||
i.setAction(MessageCompose.ACTION_REPLY_ALL);
|
||||
|
@ -58,27 +55,19 @@ public class MessageActions {
|
|||
/**
|
||||
* Compose a new message as a reply to the given message. If replyAll is true the function
|
||||
* is reply all instead of simply reply.
|
||||
* @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message
|
||||
*/
|
||||
public static void actionReply(
|
||||
Context context,
|
||||
LocalMessage message,
|
||||
boolean replyAll,
|
||||
String messageBody) {
|
||||
context.startActivity(getActionReplyIntent(context, message, replyAll, messageBody));
|
||||
Context context, LocalMessage message, boolean replyAll, Parcelable decryptionResult) {
|
||||
context.startActivity(getActionReplyIntent(context, message, replyAll, decryptionResult));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a new message as a forward of the given message.
|
||||
* @param messageBody optional, for decrypted messages, null if it should be grabbed from the given message
|
||||
*/
|
||||
public static void actionForward(
|
||||
Context context,
|
||||
LocalMessage message,
|
||||
String messageBody) {
|
||||
public static void actionForward(Context context, LocalMessage message, Parcelable decryptionResult) {
|
||||
Intent i = new Intent(context, MessageCompose.class);
|
||||
i.putExtra(MessageCompose.EXTRA_MESSAGE_BODY, messageBody);
|
||||
i.putExtra(MessageCompose.EXTRA_MESSAGE_REFERENCE, message.makeMessageReference());
|
||||
i.putExtra(MessageCompose.EXTRA_MESSAGE_DECRYPTION_RESULT, decryptionResult);
|
||||
i.setAction(MessageCompose.ACTION_FORWARD);
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
|
|
@ -191,12 +191,12 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
outState.putBoolean(STATE_KEY_CRYPTO_ENABLE_PGP_INLINE, cryptoEnablePgpInline);
|
||||
}
|
||||
|
||||
public void initFromDraftMessage(LocalMessage message) {
|
||||
public void initFromDraftMessage(Message message) {
|
||||
initRecipientsFromDraftMessage(message);
|
||||
initPgpInlineFromDraftMessage(message);
|
||||
}
|
||||
|
||||
private void initRecipientsFromDraftMessage(LocalMessage message) {
|
||||
private void initRecipientsFromDraftMessage(Message message) {
|
||||
addToAddresses(message.getRecipients(RecipientType.TO));
|
||||
|
||||
Address[] ccRecipients = message.getRecipients(RecipientType.CC);
|
||||
|
@ -206,7 +206,7 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
addBccAddresses(bccRecipients);
|
||||
}
|
||||
|
||||
private void initPgpInlineFromDraftMessage(LocalMessage message) {
|
||||
private void initPgpInlineFromDraftMessage(Message message) {
|
||||
cryptoEnablePgpInline = message.isSet(Flag.X_DRAFT_OPENPGP_INLINE);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,19 +75,17 @@ public class QuotedMessageHelper {
|
|||
InsertableHtmlContent insertable = findInsertionPoints(messageBody);
|
||||
|
||||
String sentDate = getSentDateText(resources, originalMessage);
|
||||
String fromAddress = Address.toString(originalMessage.getFrom());
|
||||
if (quoteStyle == QuoteStyle.PREFIX) {
|
||||
StringBuilder header = new StringBuilder(QUOTE_BUFFER_LENGTH);
|
||||
header.append("<div class=\"gmail_quote\">");
|
||||
if (sentDate.length() != 0) {
|
||||
header.append(HtmlConverter.textToHtmlFragment(String.format(
|
||||
resources.getString(R.string.message_compose_reply_header_fmt_with_date),
|
||||
sentDate,
|
||||
Address.toString(originalMessage.getFrom()))
|
||||
resources.getString(R.string.message_compose_reply_header_fmt_with_date), sentDate, fromAddress)
|
||||
));
|
||||
} else {
|
||||
header.append(HtmlConverter.textToHtmlFragment(String.format(
|
||||
resources.getString(R.string.message_compose_reply_header_fmt),
|
||||
Address.toString(originalMessage.getFrom()))
|
||||
resources.getString(R.string.message_compose_reply_header_fmt), fromAddress)
|
||||
));
|
||||
}
|
||||
header.append("<blockquote class=\"gmail_quote\" " +
|
||||
|
@ -102,9 +100,9 @@ public class QuotedMessageHelper {
|
|||
StringBuilder header = new StringBuilder();
|
||||
header.append("<div style='font-size:10.0pt;font-family:\"Tahoma\",\"sans-serif\";padding:3.0pt 0in 0in 0in'>\r\n");
|
||||
header.append("<hr style='border:none;border-top:solid #E1E1E1 1.0pt'>\r\n"); // This gets converted into a horizontal line during html to text conversion.
|
||||
if (originalMessage.getFrom() != null && Address.toString(originalMessage.getFrom()).length() != 0) {
|
||||
if (originalMessage.getFrom() != null && fromAddress.length() != 0) {
|
||||
header.append("<b>").append(resources.getString(R.string.message_compose_quote_header_from)).append("</b> ")
|
||||
.append(HtmlConverter.textToHtmlFragment(Address.toString(originalMessage.getFrom())))
|
||||
.append(HtmlConverter.textToHtmlFragment(fromAddress))
|
||||
.append("<br>\r\n");
|
||||
}
|
||||
if (sentDate.length() != 0) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.annotation.WorkerThread;
|
||||
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.helper.HtmlConverter;
|
||||
|
@ -44,6 +45,7 @@ public class MessageViewInfoExtractor {
|
|||
|
||||
private MessageViewInfoExtractor() { }
|
||||
|
||||
@WorkerThread
|
||||
public static MessageViewInfo extractMessageForView(Context context,
|
||||
Message message, MessageCryptoAnnotations annotations) throws MessagingException {
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import android.net.Uri;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
import android.support.annotation.WorkerThread;
|
||||
|
||||
import com.fsck.k9.Globals;
|
||||
import com.fsck.k9.K9;
|
||||
|
@ -40,7 +41,9 @@ public class AttachmentInfoExtractor {
|
|||
this.context = context;
|
||||
}
|
||||
|
||||
public List<AttachmentViewInfo> extractAttachmentInfos(List<Part> attachmentParts) throws MessagingException {
|
||||
@WorkerThread
|
||||
public List<AttachmentViewInfo> extractAttachmentInfos(List<Part> attachmentParts)
|
||||
throws MessagingException {
|
||||
|
||||
List<AttachmentViewInfo> attachments = new ArrayList<>();
|
||||
for (Part part : attachmentParts) {
|
||||
|
@ -50,6 +53,7 @@ public class AttachmentInfoExtractor {
|
|||
return attachments;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public AttachmentViewInfo extractAttachmentInfo(Part part) throws MessagingException {
|
||||
Uri uri;
|
||||
long size;
|
||||
|
@ -93,6 +97,7 @@ public class AttachmentInfoExtractor {
|
|||
return extractAttachmentInfo(part, Uri.EMPTY, AttachmentViewInfo.UNKNOWN_SIZE);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private AttachmentViewInfo extractAttachmentInfo(Part part, Uri uri, long size) throws MessagingException {
|
||||
boolean firstClassAttachment = true;
|
||||
|
||||
|
@ -128,6 +133,7 @@ public class AttachmentInfoExtractor {
|
|||
return new AttachmentViewInfo(mimeType, name, attachmentSize, uri, firstClassAttachment, part);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private long extractAttachmentSize(String contentDisposition, long size) {
|
||||
if (size != AttachmentViewInfo.UNKNOWN_SIZE) {
|
||||
return size;
|
||||
|
|
|
@ -15,13 +15,12 @@ import com.fsck.k9.activity.MessageCompose;
|
|||
import com.fsck.k9.activity.MessageCompose.Action;
|
||||
import com.fsck.k9.helper.HtmlConverter;
|
||||
import com.fsck.k9.helper.QuotedMessageHelper;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MessageExtractor;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mailstore.AttachmentResolver;
|
||||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo;
|
||||
import com.fsck.k9.message.IdentityField;
|
||||
import com.fsck.k9.message.InsertableHtmlContent;
|
||||
import com.fsck.k9.message.MessageBuilder;
|
||||
|
@ -46,33 +45,17 @@ public class QuotedMessagePresenter {
|
|||
private QuoteStyle quoteStyle;
|
||||
private boolean forcePlainText;
|
||||
|
||||
/**
|
||||
* "Original" message body
|
||||
*
|
||||
* <p>
|
||||
* The contents of this string will be used instead of the body of a referenced message when
|
||||
* replying to or forwarding a message.<br>
|
||||
* Right now this is only used when replying to a signed or encrypted message. It then contains
|
||||
* the stripped/decrypted body of that message.
|
||||
* </p>
|
||||
* <p><strong>Note:</strong>
|
||||
* When this field is not {@code null} we assume that the message we are composing right now
|
||||
* should be encrypted.
|
||||
* </p>
|
||||
*/
|
||||
private String sourceMessageBody;
|
||||
|
||||
private SimpleMessageFormat quotedTextFormat;
|
||||
private InsertableHtmlContent quotedHtmlContent;
|
||||
private Account account;
|
||||
|
||||
|
||||
public QuotedMessagePresenter(MessageCompose messageCompose, QuotedMessageMvpView quotedMessageMvpView,
|
||||
Account account, String sourceMessageBody) {
|
||||
public QuotedMessagePresenter(
|
||||
MessageCompose messageCompose, QuotedMessageMvpView quotedMessageMvpView, Account account) {
|
||||
this.messageCompose = messageCompose;
|
||||
this.resources = messageCompose.getResources();
|
||||
this.view = quotedMessageMvpView;
|
||||
this.sourceMessageBody = sourceMessageBody;
|
||||
onSwitchAccount(account);
|
||||
|
||||
quotedTextMode = QuotedTextMode.NONE;
|
||||
|
@ -96,7 +79,7 @@ public class QuotedMessagePresenter {
|
|||
* @param showQuotedText
|
||||
* {@code true} if the quoted text should be shown, {@code false} otherwise.
|
||||
*/
|
||||
public void populateUIWithQuotedMessage(Message sourceMessage, boolean showQuotedText, Action action)
|
||||
public void populateUIWithQuotedMessage(MessageViewInfo messageViewInfo, boolean showQuotedText, Action action)
|
||||
throws MessagingException {
|
||||
MessageFormat origMessageFormat = account.getMessageFormat();
|
||||
|
||||
|
@ -107,18 +90,15 @@ public class QuotedMessagePresenter {
|
|||
// Figure out which message format to use for the quoted text by looking if the source
|
||||
// message contains a text/html part. If it does, we use that.
|
||||
quotedTextFormat =
|
||||
(MimeUtility.findFirstPartByMimeType(sourceMessage, "text/html") == null) ?
|
||||
(MimeUtility.findFirstPartByMimeType(messageViewInfo.rootPart, "text/html") == null) ?
|
||||
SimpleMessageFormat.TEXT : SimpleMessageFormat.HTML;
|
||||
} else {
|
||||
quotedTextFormat = SimpleMessageFormat.HTML;
|
||||
}
|
||||
|
||||
// TODO -- I am assuming that sourceMessageBody will always be a text part. Is this a safe assumption?
|
||||
|
||||
// Handle the original message in the reply
|
||||
// If we already have sourceMessageBody, use that. It's pre-populated if we've got crypto going on.
|
||||
String content = sourceMessageBody != null ? sourceMessageBody :
|
||||
QuotedMessageHelper.getBodyTextFromMessage(sourceMessage, quotedTextFormat);
|
||||
String content = QuotedMessageHelper.getBodyTextFromMessage(messageViewInfo.rootPart, quotedTextFormat);
|
||||
|
||||
if (quotedTextFormat == SimpleMessageFormat.HTML) {
|
||||
// Strip signature.
|
||||
|
@ -129,15 +109,15 @@ public class QuotedMessagePresenter {
|
|||
|
||||
// Add the HTML reply header to the top of the content.
|
||||
quotedHtmlContent = QuotedMessageHelper.quoteOriginalHtmlMessage(
|
||||
resources, sourceMessage, content, quoteStyle);
|
||||
resources, messageViewInfo.message, content, quoteStyle);
|
||||
|
||||
// Load the message with the reply header. TODO replace with MessageViewInfo data
|
||||
view.setQuotedHtml(quotedHtmlContent.getQuotedContent(),
|
||||
AttachmentResolver.createFromPart(sourceMessage));
|
||||
AttachmentResolver.createFromPart(messageViewInfo.rootPart));
|
||||
|
||||
// TODO: Also strip the signature from the text/plain part
|
||||
view.setQuotedText(QuotedMessageHelper.quoteOriginalTextMessage(resources, sourceMessage,
|
||||
QuotedMessageHelper.getBodyTextFromMessage(sourceMessage, SimpleMessageFormat.TEXT),
|
||||
view.setQuotedText(QuotedMessageHelper.quoteOriginalTextMessage(resources, messageViewInfo.message,
|
||||
QuotedMessageHelper.getBodyTextFromMessage(messageViewInfo.rootPart, SimpleMessageFormat.TEXT),
|
||||
quoteStyle, account.getQuotePrefix()));
|
||||
|
||||
} else if (quotedTextFormat == SimpleMessageFormat.TEXT) {
|
||||
|
@ -146,7 +126,7 @@ public class QuotedMessagePresenter {
|
|||
}
|
||||
|
||||
view.setQuotedText(QuotedMessageHelper.quoteOriginalTextMessage(
|
||||
resources, sourceMessage, content, quoteStyle, account.getQuotePrefix()));
|
||||
resources, messageViewInfo.message, content, quoteStyle, account.getQuotePrefix()));
|
||||
}
|
||||
|
||||
if (showQuotedText) {
|
||||
|
@ -186,17 +166,17 @@ public class QuotedMessagePresenter {
|
|||
(QuotedTextMode) savedInstanceState.getSerializable(STATE_KEY_QUOTED_TEXT_MODE));
|
||||
}
|
||||
|
||||
public void processMessageToForward(Message message) throws MessagingException {
|
||||
public void processMessageToForward(MessageViewInfo messageViewInfo) throws MessagingException {
|
||||
quoteStyle = QuoteStyle.HEADER;
|
||||
populateUIWithQuotedMessage(message, true, Action.FORWARD);
|
||||
populateUIWithQuotedMessage(messageViewInfo, true, Action.FORWARD);
|
||||
}
|
||||
|
||||
public void initFromReplyToMessage(Message message, Action action)
|
||||
public void initFromReplyToMessage(MessageViewInfo messageViewInfo, Action action)
|
||||
throws MessagingException {
|
||||
populateUIWithQuotedMessage(message, account.isDefaultQuotedTextShown(), action);
|
||||
populateUIWithQuotedMessage(messageViewInfo, account.isDefaultQuotedTextShown(), action);
|
||||
}
|
||||
|
||||
public void processDraftMessage(LocalMessage message, Map<IdentityField, String> k9identity)
|
||||
public void processDraftMessage(MessageViewInfo messageViewInfo, Map<IdentityField, String> k9identity)
|
||||
throws MessagingException {
|
||||
quoteStyle = k9identity.get(IdentityField.QUOTE_STYLE) != null
|
||||
? QuoteStyle.valueOf(k9identity.get(IdentityField.QUOTE_STYLE))
|
||||
|
@ -255,7 +235,7 @@ public class QuotedMessagePresenter {
|
|||
// composition window. If that's the case, try and convert it to text to
|
||||
// match the behavior in text mode.
|
||||
view.setMessageContentCharacters(
|
||||
QuotedMessageHelper.getBodyTextFromMessage(message, SimpleMessageFormat.TEXT));
|
||||
QuotedMessageHelper.getBodyTextFromMessage(messageViewInfo.message, SimpleMessageFormat.TEXT));
|
||||
forcePlainText = true;
|
||||
|
||||
showOrHideQuotedText(quotedMode);
|
||||
|
@ -263,7 +243,7 @@ public class QuotedMessagePresenter {
|
|||
}
|
||||
|
||||
if (messageFormat == MessageFormat.HTML) {
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
Part part = MimeUtility.findFirstPartByMimeType(messageViewInfo.message, "text/html");
|
||||
if (part != null) { // Shouldn't happen if we were the one who saved it.
|
||||
quotedTextFormat = SimpleMessageFormat.HTML;
|
||||
String text = MessageExtractor.getTextFromPart(part);
|
||||
|
@ -298,15 +278,15 @@ public class QuotedMessagePresenter {
|
|||
}
|
||||
// TODO replace with MessageViewInfo data
|
||||
view.setQuotedHtml(quotedHtmlContent.getQuotedContent(),
|
||||
AttachmentResolver.createFromPart(message));
|
||||
AttachmentResolver.createFromPart(messageViewInfo.rootPart));
|
||||
}
|
||||
}
|
||||
if (bodyPlainOffset != null && bodyPlainLength != null) {
|
||||
processSourceMessageText(message, bodyPlainOffset, bodyPlainLength, false);
|
||||
processSourceMessageText(messageViewInfo.rootPart, bodyPlainOffset, bodyPlainLength, false);
|
||||
}
|
||||
} else if (messageFormat == MessageFormat.TEXT) {
|
||||
quotedTextFormat = SimpleMessageFormat.TEXT;
|
||||
processSourceMessageText(message, bodyOffset, bodyLength, true);
|
||||
processSourceMessageText(messageViewInfo.rootPart, bodyOffset, bodyLength, true);
|
||||
} else {
|
||||
Log.e(K9.LOG_TAG, "Unhandled message format.");
|
||||
}
|
||||
|
@ -324,14 +304,13 @@ public class QuotedMessagePresenter {
|
|||
/**
|
||||
* Pull out the parts of the now loaded source message and apply them to the new message
|
||||
* depending on the type of message being composed.
|
||||
* @param message Source message
|
||||
* @param bodyOffset Insertion point for reply.
|
||||
* @param bodyLength Length of reply.
|
||||
* @param viewMessageContent Update mMessageContentView or not.
|
||||
*/
|
||||
private void processSourceMessageText(Message message, int bodyOffset, int bodyLength, boolean viewMessageContent)
|
||||
private void processSourceMessageText(Part rootMessagePart, int bodyOffset, int bodyLength, boolean viewMessageContent)
|
||||
throws MessagingException {
|
||||
Part textPart = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
Part textPart = MimeUtility.findFirstPartByMimeType(rootMessagePart, "text/plain");
|
||||
if (textPart == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.app.Activity;
|
|||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.util.Log;
|
||||
|
@ -69,6 +70,7 @@ public class MessageCryptoHelper {
|
|||
private MessageCryptoCallback callback;
|
||||
|
||||
private LocalMessage currentMessage;
|
||||
private OpenPgpDecryptionResult cachedDecryptionResult;
|
||||
private MessageCryptoAnnotations queuedResult;
|
||||
private PendingIntent queuedPendingIntent;
|
||||
|
||||
|
@ -95,7 +97,8 @@ public class MessageCryptoHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public void asyncStartOrResumeProcessingMessage(LocalMessage message, MessageCryptoCallback callback) {
|
||||
public void asyncStartOrResumeProcessingMessage(LocalMessage message, MessageCryptoCallback callback,
|
||||
OpenPgpDecryptionResult cachedDecryptionResult) {
|
||||
if (this.currentMessage != null) {
|
||||
reattachCallback(message, callback);
|
||||
return;
|
||||
|
@ -103,6 +106,7 @@ public class MessageCryptoHelper {
|
|||
|
||||
this.messageAnnotations = new MessageCryptoAnnotations();
|
||||
this.currentMessage = message;
|
||||
this.cachedDecryptionResult = cachedDecryptionResult;
|
||||
this.callback = callback;
|
||||
|
||||
runFirstPass();
|
||||
|
@ -229,18 +233,26 @@ public class MessageCryptoHelper {
|
|||
Intent decryptIntent = userInteractionResultIntent;
|
||||
userInteractionResultIntent = null;
|
||||
if (decryptIntent == null) {
|
||||
decryptIntent = new Intent();
|
||||
decryptIntent = getDecryptionIntent();
|
||||
}
|
||||
decryptVerify(decryptIntent);
|
||||
}
|
||||
|
||||
private void decryptVerify(Intent intent) {
|
||||
intent.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||
@NonNull
|
||||
private Intent getDecryptionIntent() {
|
||||
Intent decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||
|
||||
Address[] from = currentMessage.getFrom();
|
||||
if (from.length > 0) {
|
||||
intent.putExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS, from[0].getAddress());
|
||||
decryptIntent.putExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS, from[0].getAddress());
|
||||
}
|
||||
|
||||
decryptIntent.putExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT, cachedDecryptionResult);
|
||||
|
||||
return decryptIntent;
|
||||
}
|
||||
|
||||
private void decryptVerify(Intent intent) {
|
||||
try {
|
||||
CryptoPartType cryptoPartType = currentCryptoPart.type;
|
||||
switch (cryptoPartType) {
|
||||
|
|
|
@ -4,6 +4,7 @@ package com.fsck.k9.ui.message;
|
|||
import android.content.AsyncTaskLoader;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
|
@ -45,6 +46,7 @@ public class LocalMessageExtractorLoader extends AsyncTaskLoader<MessageViewInfo
|
|||
}
|
||||
|
||||
@Override
|
||||
@WorkerThread
|
||||
public MessageViewInfo loadInBackground() {
|
||||
try {
|
||||
return MessageViewInfoExtractor.extractMessageForView(getContext(), message, annotations);
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.content.IntentSender;
|
|||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.util.Log;
|
||||
|
@ -201,6 +202,13 @@ public class MessageCryptoPresenter implements OnCryptoClickListener {
|
|||
messageCryptoMvpView.redisplayMessage();
|
||||
}
|
||||
|
||||
public Parcelable getDecryptionResultForReply() {
|
||||
if (cryptoResultAnnotation != null && cryptoResultAnnotation.isOpenPgpResult()) {
|
||||
return cryptoResultAnnotation.getOpenPgpDecryptionResult();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Drawable getOpenPgpApiProviderIcon(Context context, Account account) {
|
||||
try {
|
||||
|
|
|
@ -16,6 +16,7 @@ import android.content.IntentSender.SendIntentException;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.ContextThemeWrapper;
|
||||
|
@ -203,7 +204,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
}
|
||||
|
||||
mAccount = Preferences.getPreferences(getApplicationContext()).getAccount(mMessageReference.getAccountUuid());
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(messageReference);
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(messageReference, null);
|
||||
|
||||
mFragmentListener.updateMenu();
|
||||
}
|
||||
|
@ -319,19 +320,19 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
|
||||
public void onReply() {
|
||||
if (mMessage != null) {
|
||||
mFragmentListener.onReply(mMessage);
|
||||
mFragmentListener.onReply(mMessage, messageCryptoPresenter.getDecryptionResultForReply());
|
||||
}
|
||||
}
|
||||
|
||||
public void onReplyAll() {
|
||||
if (mMessage != null) {
|
||||
mFragmentListener.onReplyAll(mMessage);
|
||||
mFragmentListener.onReplyAll(mMessage, messageCryptoPresenter.getDecryptionResultForReply());
|
||||
}
|
||||
}
|
||||
|
||||
public void onForward() {
|
||||
if (mMessage != null) {
|
||||
mFragmentListener.onForward(mMessage);
|
||||
mFragmentListener.onForward(mMessage, messageCryptoPresenter.getDecryptionResultForReply());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -690,15 +691,15 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
}
|
||||
|
||||
public interface MessageViewFragmentListener {
|
||||
public void onForward(LocalMessage mMessage);
|
||||
public void disableDeleteAction();
|
||||
public void onReplyAll(LocalMessage mMessage);
|
||||
public void onReply(LocalMessage mMessage);
|
||||
public void displayMessageSubject(String title);
|
||||
public void setProgress(boolean b);
|
||||
public void showNextMessageOrReturn();
|
||||
public void messageHeaderViewAvailable(MessageHeader messageHeaderView);
|
||||
public void updateMenu();
|
||||
void onForward(LocalMessage mMessage, Parcelable decryptionResultForReply);
|
||||
void disableDeleteAction();
|
||||
void onReplyAll(LocalMessage mMessage, Parcelable decryptionResultForReply);
|
||||
void onReply(LocalMessage mMessage, Parcelable decryptionResultForReply);
|
||||
void displayMessageSubject(String title);
|
||||
void setProgress(boolean b);
|
||||
void showNextMessageOrReturn();
|
||||
void messageHeaderViewAvailable(MessageHeader messageHeaderView);
|
||||
void updateMenu();
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
|
|
|
@ -25,7 +25,7 @@ public class OpenPgpDecryptionResult implements Parcelable {
|
|||
* old versions of the protocol (and thus old versions of this class), we need a versioning
|
||||
* system for the parcels sent between the clients and the providers.
|
||||
*/
|
||||
public static final int PARCELABLE_VERSION = 1;
|
||||
public static final int PARCELABLE_VERSION = 2;
|
||||
|
||||
// content not encrypted
|
||||
public static final int RESULT_NOT_ENCRYPTED = -1;
|
||||
|
@ -34,26 +34,33 @@ public class OpenPgpDecryptionResult implements Parcelable {
|
|||
// encrypted
|
||||
public static final int RESULT_ENCRYPTED = 1;
|
||||
|
||||
int result;
|
||||
public final int result;
|
||||
public final byte[] sessionKey;
|
||||
public final byte[] decryptedSessionKey;
|
||||
|
||||
public int getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(int result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public OpenPgpDecryptionResult() {
|
||||
|
||||
}
|
||||
|
||||
public OpenPgpDecryptionResult(int result) {
|
||||
this.result = result;
|
||||
this.sessionKey = null;
|
||||
this.decryptedSessionKey = null;
|
||||
}
|
||||
|
||||
public OpenPgpDecryptionResult(int result, byte[] sessionKey, byte[] decryptedSessionKey) {
|
||||
this.result = result;
|
||||
if ((sessionKey == null) != (decryptedSessionKey == null)) {
|
||||
throw new AssertionError("sessionkey must be null iff decryptedSessionKey is null");
|
||||
}
|
||||
this.sessionKey = sessionKey;
|
||||
this.decryptedSessionKey = decryptedSessionKey;
|
||||
}
|
||||
|
||||
public OpenPgpDecryptionResult(OpenPgpDecryptionResult b) {
|
||||
this.result = b.result;
|
||||
this.sessionKey = b.sessionKey;
|
||||
this.decryptedSessionKey = b.decryptedSessionKey;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
|
@ -73,6 +80,9 @@ public class OpenPgpDecryptionResult implements Parcelable {
|
|||
int startPosition = dest.dataPosition();
|
||||
// version 1
|
||||
dest.writeInt(result);
|
||||
// version 2
|
||||
dest.writeByteArray(sessionKey);
|
||||
dest.writeByteArray(decryptedSessionKey);
|
||||
// Go back and write the size
|
||||
int parcelableSize = dest.dataPosition() - startPosition;
|
||||
dest.setDataPosition(sizePosition);
|
||||
|
@ -82,12 +92,15 @@ public class OpenPgpDecryptionResult implements Parcelable {
|
|||
|
||||
public static final Creator<OpenPgpDecryptionResult> CREATOR = new Creator<OpenPgpDecryptionResult>() {
|
||||
public OpenPgpDecryptionResult createFromParcel(final Parcel source) {
|
||||
source.readInt(); // parcelableVersion
|
||||
int version = source.readInt(); // parcelableVersion
|
||||
int parcelableSize = source.readInt();
|
||||
int startPosition = source.dataPosition();
|
||||
|
||||
OpenPgpDecryptionResult vr = new OpenPgpDecryptionResult();
|
||||
vr.result = source.readInt();
|
||||
int result = source.readInt();
|
||||
byte[] sessionKey = version > 1 ? source.createByteArray() : null;
|
||||
byte[] decryptedSessionKey = version > 1 ? source.createByteArray() : null;
|
||||
|
||||
OpenPgpDecryptionResult vr = new OpenPgpDecryptionResult(result, sessionKey, decryptedSessionKey);
|
||||
|
||||
// skip over all fields added in future versions of this parcel
|
||||
source.setDataPosition(startPosition + parcelableSize);
|
||||
|
|
|
@ -258,6 +258,7 @@ public class OpenPgpApi {
|
|||
public static final String RESULT_INTENT = "intent";
|
||||
|
||||
// DECRYPT_VERIFY
|
||||
public static final String EXTRA_DECRYPTION_RESULT = "decryption_result";
|
||||
public static final String EXTRA_DETACHED_SIGNATURE = "detached_signature";
|
||||
public static final String EXTRA_PROGRESS_MESSENGER = "progress_messenger";
|
||||
public static final String EXTRA_DATA_LENGTH = "data_length";
|
||||
|
|
Loading…
Reference in a new issue