Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df761b93 authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #1501 from k9mail/decrypted-reply

Decrypted reply
parents a58ca462 19cd7b99
Loading
Loading
Loading
Loading
+36 −35
Original line number Diff line number Diff line
@@ -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();
        }
    };

}
+19 −4
Original line number Diff line number Diff line
@@ -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
+14 −2
Original line number Diff line number Diff line
@@ -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() {
+52 −5
Original line number Diff line number Diff line
@@ -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(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;
        }

        int loaderId = getNextFreeLoaderId();
        Attachment attachment = Attachment.createAttachment(uri, loaderId, contentType);

        if (attachments.containsKey(uri)) {
        addAttachmentAndStartLoader(attachment);
    }

    public void processMessageToForward(MessageViewInfo messageViewInfo) {
        if (messageViewInfo.message.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
            attachmentMvpView.showMissingAttachmentsPartialMessageWarning();
            return;
        }

        attachments.put(uri, attachment);
        for (AttachmentViewInfo attachmentViewInfo : messageViewInfo.attachments) {
            if (attachmentViewInfo.firstClassAttachment) {
                addAttachment(attachmentViewInfo);
            }
        }
    }

    private void addAttachmentAndStartLoader(Attachment attachment) {
        attachments.put(attachment.uri, attachment);
        attachmentMvpView.addAttachmentView(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();
    }
}
+7 −18
Original line number Diff line number Diff line
@@ -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);
    }
Loading