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

Commit 1bae6816 authored by Vincent Breitmoser's avatar Vincent Breitmoser
Browse files

messageview: move more control flow for display of crypto data into MessageCryptoPresenter

parent fccb4a4b
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -106,6 +106,18 @@ public class MessageLoaderHelper {
        startOrResumeLocalMessageLoader();
    }

    @UiThread
    public void asyncReloadMessage() {
        startOrResumeLocalMessageLoader();
    }

    @UiThread
    public void asyncRestartMessageCryptoProcessing() {
        cancelAndClearCryptoOperation();
        cancelAndClearDecodeLoader();
        startOrResumeCryptoOperation();
    }

    /** Cancels all loading processes, prevents future callbacks, and destroys all loading state. */
    @UiThread
    public void onDestroy() {
@@ -136,13 +148,6 @@ public class MessageLoaderHelper {
        startDownloadingMessageBody(true);
    }

    @UiThread
    public void restartMessageCryptoProcessing() {
        cancelAndClearCryptoOperation();
        cancelAndClearDecodeLoader();
        startOrResumeCryptoOperation();
    }

    @UiThread
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        messageCryptoHelper.onActivityResult(requestCode, resultCode, data);
+113 −12
Original line number Diff line number Diff line
@@ -8,11 +8,15 @@ import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.util.Log;

import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.mailstore.CryptoResultAnnotation;
import com.fsck.k9.mailstore.MessageViewInfo;
import com.fsck.k9.view.MessageCryptoDisplayStatus;

@@ -21,33 +25,125 @@ public class MessageCryptoPresenter implements OnCryptoClickListener {
    public static final int REQUEST_CODE_UNKNOWN_KEY = 123;


    // injected state
    private final MessageCryptoMvpView messageCryptoMvpView;


    private MessageViewInfo messageViewInfo;
    // persistent state
    private boolean overrideCryptoWarning;


    public MessageCryptoPresenter(MessageCryptoMvpView messageCryptoMvpView) {
    // transient state
    private CryptoResultAnnotation cryptoResultAnnotation;


    public MessageCryptoPresenter(Bundle savedInstanceState, MessageCryptoMvpView messageCryptoMvpView) {
        this.messageCryptoMvpView = messageCryptoMvpView;

        if (savedInstanceState != null) {
            overrideCryptoWarning = savedInstanceState.getBoolean("overrideCryptoWarning");
        }
    }

    public void onSaveInstanceState(Bundle outState) {
        outState.putBoolean("overrideCryptoWarning", overrideCryptoWarning);
    }

    public void setMessageViewInfo(MessageViewInfo messageViewInfo) {
        this.messageViewInfo = messageViewInfo;
    public boolean maybeHandleShowMessage(MessageTopView messageView, Account account, MessageViewInfo messageViewInfo) {
        this.cryptoResultAnnotation = messageViewInfo.cryptoResultAnnotation;

        MessageCryptoDisplayStatus displayStatus =
                MessageCryptoDisplayStatus.fromResultAnnotation(messageViewInfo.cryptoResultAnnotation);
        if (displayStatus == MessageCryptoDisplayStatus.DISABLED) {
            return false;
        }

        messageView.getMessageHeaderView().setCryptoStatus(displayStatus);

        switch (displayStatus) {
            case UNENCRYPTED_SIGN_REVOKED:
            case ENCRYPTED_SIGN_REVOKED: {
                showMessageCryptoWarning(messageView, account, messageViewInfo,
                        R.string.messageview_crypto_warning_revoked);
                break;
            }
            case UNENCRYPTED_SIGN_EXPIRED:
            case ENCRYPTED_SIGN_EXPIRED: {
                showMessageCryptoWarning(messageView, account, messageViewInfo,
                        R.string.messageview_crypto_warning_expired);
                break;
            }
            case UNENCRYPTED_SIGN_INSECURE:
            case ENCRYPTED_SIGN_INSECURE: {
                showMessageCryptoWarning(messageView, account, messageViewInfo,
                        R.string.messageview_crypto_warning_insecure);
                break;
            }
            case UNENCRYPTED_SIGN_ERROR:
            case ENCRYPTED_SIGN_ERROR: {
                showMessageCryptoWarning(messageView, account, messageViewInfo,
                        R.string.messageview_crypto_warning_error);
                break;
            }

            case CANCELLED: {
                Drawable providerIcon = getOpenPgpApiProviderIcon(messageView.getContext(), account);
                messageView.showMessageCryptoCancelledView(messageViewInfo, providerIcon);
                break;
            }

            case INCOMPLETE_ENCRYPTED: {
                Drawable providerIcon = getOpenPgpApiProviderIcon(messageView.getContext(), account);
                messageView.showMessageEncryptedButIncomplete(messageViewInfo, providerIcon);
                break;
            }

            case ENCRYPTED_ERROR:
            case UNSUPPORTED_ENCRYPTED: {
                Drawable providerIcon = getOpenPgpApiProviderIcon(messageView.getContext(), account);
                messageView.showMessageCryptoErrorView(messageViewInfo, providerIcon);
                break;
            }

            case INCOMPLETE_SIGNED:
            case UNSUPPORTED_SIGNED:
            default: {
                messageView.showMessage(account, messageViewInfo);
                break;
            }

            case LOADING: {
                throw new IllegalStateException("Displaying message while in loading state!");
            }
        }

        return true;
    }

    private void showMessageCryptoWarning(MessageTopView messageView, Account account,
            MessageViewInfo messageViewInfo, @StringRes int warningStringRes) {
        if (overrideCryptoWarning) {
            messageView.showMessage(account, messageViewInfo);
            return;
        }
        Drawable providerIcon = getOpenPgpApiProviderIcon(messageView.getContext(), account);
        messageView.showMessageCryptoWarning(messageViewInfo, providerIcon, warningStringRes);
    }


    @Override
    public void onCryptoClick() {
        if (messageViewInfo == null) {
        if (cryptoResultAnnotation == null) {
            return;
        }
        MessageCryptoDisplayStatus displayStatus =
                MessageCryptoDisplayStatus.fromResultAnnotation(messageViewInfo.cryptoResultAnnotation);
                MessageCryptoDisplayStatus.fromResultAnnotation(cryptoResultAnnotation);
        switch (displayStatus) {
            case LOADING:
                // no need to do anything, there is a progress bar...
                break;
            case UNENCRYPTED_SIGN_UNKNOWN:
                launchPendingIntent(messageViewInfo);
                launchPendingIntent(cryptoResultAnnotation);
                break;
            default:
                displayCryptoInfoDialog(displayStatus);
@@ -72,9 +168,9 @@ public class MessageCryptoPresenter implements OnCryptoClickListener {
        messageCryptoMvpView.showCryptoInfoDialog(displayStatus);
    }

    private void launchPendingIntent(MessageViewInfo messageViewInfo) {
    private void launchPendingIntent(CryptoResultAnnotation cryptoResultAnnotation) {
        try {
            PendingIntent pendingIntent = messageViewInfo.cryptoResultAnnotation.getOpenPgpPendingIntent();
            PendingIntent pendingIntent = cryptoResultAnnotation.getOpenPgpPendingIntent();
            if (pendingIntent != null) {
                messageCryptoMvpView.startPendingIntentForCryptoPresenter(
                        pendingIntent.getIntentSender(), REQUEST_CODE_UNKNOWN_KEY, null, 0, 0, 0);
@@ -86,7 +182,7 @@ public class MessageCryptoPresenter implements OnCryptoClickListener {

    public void onClickShowCryptoKey() {
        try {
            PendingIntent pendingIntent = messageViewInfo.cryptoResultAnnotation.getOpenPgpPendingIntent();
            PendingIntent pendingIntent = cryptoResultAnnotation.getOpenPgpPendingIntent();
            if (pendingIntent != null) {
                messageCryptoMvpView.startPendingIntentForCryptoPresenter(
                        pendingIntent.getIntentSender(), null, null, 0, 0, 0);
@@ -100,9 +196,13 @@ public class MessageCryptoPresenter implements OnCryptoClickListener {
        messageCryptoMvpView.restartMessageCryptoProcessing();
    }

    public void onClickShowMessageOverrideWarning() {
        overrideCryptoWarning = true;
        messageCryptoMvpView.redisplayMessage();
    }

    @Nullable
    // TODO this isn't really very presenter-like, but it works for now
    public static Drawable getOpenPgpApiProviderIcon(Context context, Account account) {
    private static Drawable getOpenPgpApiProviderIcon(Context context, Account account) {
        try {
            String openPgpProvider = account.getOpenPgpProvider();
            if (Account.NO_OPENPGP_PROVIDER.equals(openPgpProvider)) {
@@ -115,6 +215,7 @@ public class MessageCryptoPresenter implements OnCryptoClickListener {
    }

    public interface MessageCryptoMvpView {
        void redisplayMessage();
        void restartMessageCryptoProcessing();

        void startPendingIntentForCryptoPresenter(IntentSender si, Integer requestCode, Intent fillIntent,
+43 −66
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.StringRes;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -25,7 +26,6 @@ import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mailstore.MessageViewInfo;
import com.fsck.k9.ui.messageview.MessageContainerView.OnRenderingFinishedListener;
import com.fsck.k9.view.MessageCryptoDisplayStatus;
import com.fsck.k9.view.MessageHeader;
import com.fsck.k9.view.ToolableViewAnimator;
import org.openintents.openpgp.OpenPgpError;
@@ -97,63 +97,15 @@ public class MessageTopView extends LinearLayout {
        hideShowPicturesButton();
    }

    public void resetView() {
    private void resetAndPrepareMessageView(Message message) {
        mDownloadRemainder.setVisibility(View.GONE);
        containerView.removeAllViews();
        setShowDownloadButton(message);
    }

    public void setMessage(Account account, MessageViewInfo messageViewInfo) {
        resetView();
    public void showMessage(Account account, MessageViewInfo messageViewInfo) {
        resetAndPrepareMessageView(messageViewInfo.message);

        setShowDownloadButton(messageViewInfo.message);

        MessageCryptoDisplayStatus displayStatus =
                MessageCryptoDisplayStatus.fromResultAnnotation(messageViewInfo.cryptoResultAnnotation);
        mHeaderContainer.setCryptoStatus(displayStatus);

        switch (displayStatus) {
            case DISABLED:
            case INCOMPLETE_SIGNED:
            case UNSUPPORTED_SIGNED:
            default: {
                // in most cases, we simply display the message
                showMessageContentView(account, messageViewInfo);
                break;
            }

            case CANCELLED: {
                showMessageCryptoCancelledView(account);
                break;
            }

            case INCOMPLETE_ENCRYPTED: {
                showEncryptedButIncompleteView(account);
                break;
            }

            case ENCRYPTED_ERROR:
            case UNSUPPORTED_ENCRYPTED: {
                showMessageCryptoErrorView(account, messageViewInfo);
                break;
            }

            case LOADING: {
                throw new IllegalStateException("Displaying message while in loading state!");
            }
        }
    }

    private void showEncryptedButIncompleteView(Account account) {
        View view = mInflater.inflate(R.layout.message_content_crypto_incomplete, containerView, false);

        ImageView cryptoProviderIcon = (ImageView) view.findViewById(R.id.crypto_error_icon);
        setCryptoProviderIcon(account, cryptoProviderIcon);

        containerView.addView(view);
        displayViewOnLoadFinished(false);
    }

    private void showMessageContentView(Account account, MessageViewInfo messageViewInfo) {
        ShowPictures showPicturesSetting = account.getShowPictures();
        boolean automaticallyLoadPictures =
                shouldAutomaticallyLoadPictures(showPicturesSetting, messageViewInfo.message);
@@ -174,11 +126,39 @@ public class MessageTopView extends LinearLayout {
        }
    }

    private void showMessageCryptoErrorView(Account account, MessageViewInfo messageViewInfo) {
        View view = mInflater.inflate(R.layout.message_content_crypto_error, containerView, false);
    public void showMessageCryptoWarning(final MessageViewInfo messageViewInfo, Drawable providerIcon,
            @StringRes int warningTextRes) {
        resetAndPrepareMessageView(messageViewInfo.message);
        View view = mInflater.inflate(R.layout.message_content_crypto_warning, containerView, false);
        setCryptoProviderIcon(providerIcon, view);

        ImageView cryptoProviderIcon = (ImageView) view.findViewById(R.id.crypto_error_icon);
        setCryptoProviderIcon(account, cryptoProviderIcon);
        view.findViewById(R.id.crypto_warning_override).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                messageCryptoPresenter.onClickShowMessageOverrideWarning();
            }
        });

        TextView warningText = (TextView) view.findViewById(R.id.crypto_warning_text);
        warningText.setText(warningTextRes);

        containerView.addView(view);
        displayViewOnLoadFinished(false);
    }

    public void showMessageEncryptedButIncomplete(MessageViewInfo messageViewInfo, Drawable providerIcon) {
        resetAndPrepareMessageView(messageViewInfo.message);
        View view = mInflater.inflate(R.layout.message_content_crypto_incomplete, containerView, false);
        setCryptoProviderIcon(providerIcon, view);

        containerView.addView(view);
        displayViewOnLoadFinished(false);
    }

    public void showMessageCryptoErrorView(MessageViewInfo messageViewInfo, Drawable providerIcon) {
        resetAndPrepareMessageView(messageViewInfo.message);
        View view = mInflater.inflate(R.layout.message_content_crypto_error, containerView, false);
        setCryptoProviderIcon(providerIcon, view);

        TextView cryptoErrorText = (TextView) view.findViewById(R.id.crypto_error_text);
        OpenPgpError openPgpError = messageViewInfo.cryptoResultAnnotation.getOpenPgpError();
@@ -191,8 +171,11 @@ public class MessageTopView extends LinearLayout {
        displayViewOnLoadFinished(false);
    }

    private void showMessageCryptoCancelledView(Account account) {
    public void showMessageCryptoCancelledView(MessageViewInfo messageViewInfo, Drawable providerIcon) {
        resetAndPrepareMessageView(messageViewInfo.message);
        View view = mInflater.inflate(R.layout.message_content_crypto_cancelled, containerView, false);
        setCryptoProviderIcon(providerIcon, view);

        view.findViewById(R.id.crypto_cancelled_retry).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
@@ -200,15 +183,12 @@ public class MessageTopView extends LinearLayout {
            }
        });

        ImageView cryptoProviderIcon = (ImageView) view.findViewById(R.id.crypto_error_icon);
        setCryptoProviderIcon(account, cryptoProviderIcon);

        containerView.addView(view);
        displayViewOnLoadFinished(false);
    }

    private void setCryptoProviderIcon(Account account, ImageView cryptoProviderIcon) {
        Drawable openPgpApiProviderIcon = MessageCryptoPresenter.getOpenPgpApiProviderIcon(getContext(), account);
    private void setCryptoProviderIcon(Drawable openPgpApiProviderIcon, View view) {
        ImageView cryptoProviderIcon = (ImageView) view.findViewById(R.id.crypto_error_icon);
        if (openPgpApiProviderIcon != null) {
            cryptoProviderIcon.setImageDrawable(openPgpApiProviderIcon);
        } else {
@@ -228,9 +208,6 @@ public class MessageTopView extends LinearLayout {

    public void setHeaders(final Message message, Account account) {
        mHeaderContainer.populate(message, account);
        if (account.isOpenPgpProviderConfigured()) {
            mHeaderContainer.setCryptoStatus(MessageCryptoDisplayStatus.LOADING);
        }
        mHeaderContainer.setVisibility(View.VISIBLE);
    }

+25 −6
Original line number Diff line number Diff line
@@ -127,12 +127,19 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
        Context context = getActivity().getApplicationContext();
        mController = MessagingController.getInstance(context);
        downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        messageCryptoPresenter = new MessageCryptoPresenter(messageCryptoMvpView);
        messageCryptoPresenter = new MessageCryptoPresenter(savedInstanceState, messageCryptoMvpView);
        messageLoaderHelper =
                new MessageLoaderHelper(context, getLoaderManager(), getFragmentManager(), messageLoaderCallbacks);
        mInitialized = true;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        messageCryptoPresenter.onSaveInstanceState(outState);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
@@ -234,12 +241,19 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
    }

    private void showMessage(MessageViewInfo messageViewInfo) {
        messageCryptoPresenter.setMessageViewInfo(messageViewInfo);
        mMessageView.setMessage(mAccount, messageViewInfo);
        boolean handledByCryptoPresenter = messageCryptoPresenter.maybeHandleShowMessage(
                mMessageView, mAccount, messageViewInfo);
        if (!handledByCryptoPresenter) {
            mMessageView.showMessage(mAccount, messageViewInfo);
            mMessageView.getMessageHeaderView().setCryptoStatusDisabled();
        }
    }

    private void displayMessageHeader(LocalMessage message) {
    private void displayHeaderForLoadingMessage(LocalMessage message) {
        mMessageView.setHeaders(message, mAccount);
        if (mAccount.isOpenPgpProviderConfigured()) {
            mMessageView.getMessageHeaderView().setCryptoStatusLoading();
        }
        displayMessageSubject(getSubjectForMessage(message));
        mFragmentListener.updateMenu();
    }
@@ -638,6 +652,11 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
    }

    private MessageCryptoMvpView messageCryptoMvpView = new MessageCryptoMvpView() {
        @Override
        public void redisplayMessage() {
            messageLoaderHelper.asyncReloadMessage();
        }

        @Override
        public void startPendingIntentForCryptoPresenter(IntentSender si, Integer requestCode, Intent fillIntent,
                int flagsMask, int flagValues, int extraFlags) throws SendIntentException {
@@ -661,7 +680,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
        @Override
        public void restartMessageCryptoProcessing() {
            mMessageView.setToLoadingState();
            messageLoaderHelper.restartMessageCryptoProcessing();
            messageLoaderHelper.asyncRestartMessageCryptoProcessing();
        }
    };

@@ -692,7 +711,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
        public void onMessageDataLoadFinished(LocalMessage message) {
            mMessage = message;

            displayMessageHeader(message);
            displayHeaderForLoadingMessage(message);
            mMessageView.setToLoadingState();
        }

+11 −1
Original line number Diff line number Diff line
package com.fsck.k9.view;


import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -41,7 +42,6 @@ import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mailstore.CryptoResultAnnotation;
import com.fsck.k9.ui.messageview.OnCryptoClickListener;


@@ -342,6 +342,16 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
        }
    }

    public void setCryptoStatusLoading() {
        mCryptoStatusIcon.setVisibility(View.VISIBLE);
        mCryptoStatusIcon.setCryptoDisplayStatus(MessageCryptoDisplayStatus.LOADING);
    }

    public void setCryptoStatusDisabled() {
        mCryptoStatusIcon.setVisibility(View.VISIBLE);
        mCryptoStatusIcon.setCryptoDisplayStatus(MessageCryptoDisplayStatus.DISABLED);
    }

    public void setCryptoStatus(MessageCryptoDisplayStatus displayStatus) {
        mCryptoStatusIcon.setVisibility(View.VISIBLE);
        mCryptoStatusIcon.setCryptoDisplayStatus(displayStatus);
Loading