package com.fsck.k9.ui.messageview;
import android.animation.Animator;
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;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.fsck.k9.Account;
import com.fsck.k9.Account.ShowPictures;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.mail.Address;
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.MessageHeader;
import com.fsck.k9.view.ThemeUtils;
import com.fsck.k9.view.ToolableViewAnimator;
import org.openintents.openpgp.OpenPgpError;
public class MessageTopView extends LinearLayout {
public static final int PROGRESS_MAX = 1000;
public static final int PROGRESS_MAX_WITH_MARGIN = 950;
public static final int PROGRESS_STEP_DURATION = 180;
private ToolableViewAnimator viewAnimator;
private ProgressBar progressBar;
private TextView progressText;
private MessageHeader mHeaderContainer;
private LayoutInflater mInflater;
private ViewGroup containerView;
private Button mDownloadRemainder;
private AttachmentViewCallback attachmentCallback;
private Button showPicturesButton;
private boolean isShowingProgress;
private MessageCryptoPresenter messageCryptoPresenter;
public MessageTopView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onFinishInflate() {
super.onFinishInflate();
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
// mHeaderContainer.setOnLayoutChangedListener(this);
mInflater = LayoutInflater.from(getContext());
viewAnimator = (ToolableViewAnimator) findViewById(R.id.message_layout_animator);
progressBar = (ProgressBar) findViewById(R.id.message_progress);
progressText = (TextView) findViewById(R.id.message_progress_text);
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
mDownloadRemainder.setVisibility(View.GONE);
showPicturesButton = (Button) findViewById(R.id.show_pictures);
setShowPicturesButtonListener();
containerView = (ViewGroup) findViewById(R.id.message_container);
hideHeaderView();
}
private void setShowPicturesButtonListener() {
showPicturesButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showPicturesInAllContainerViews();
}
});
}
private void showPicturesInAllContainerViews() {
View messageContainerViewCandidate = containerView.getChildAt(0);
if (messageContainerViewCandidate instanceof MessageContainerView) {
((MessageContainerView) messageContainerViewCandidate).showPictures();
}
hideShowPicturesButton();
}
private void resetAndPrepareMessageView(MessageViewInfo messageViewInfo) {
mDownloadRemainder.setVisibility(View.GONE);
containerView.removeAllViews();
setShowDownloadButton(messageViewInfo);
}
public void showMessage(Account account, MessageViewInfo messageViewInfo) {
resetAndPrepareMessageView(messageViewInfo);
ShowPictures showPicturesSetting = account.getShowPictures();
boolean automaticallyLoadPictures =
shouldAutomaticallyLoadPictures(showPicturesSetting, messageViewInfo.message);
MessageContainerView view = (MessageContainerView) mInflater.inflate(R.layout.message_container,
containerView, false);
containerView.addView(view);
boolean hideUnsignedTextDivider = !K9.getOpenPgpSupportSignOnly();
view.displayMessageViewContainer(messageViewInfo, new OnRenderingFinishedListener() {
@Override
public void onLoadFinished() {
displayViewOnLoadFinished(true);
}
}, automaticallyLoadPictures, hideUnsignedTextDivider, attachmentCallback);
if (view.hasHiddenExternalImages()) {
showShowPicturesButton();
}
}
public void showMessageCryptoWarning(final MessageViewInfo messageViewInfo, Drawable providerIcon,
@StringRes int warningTextRes, boolean showDetailButton) {
resetAndPrepareMessageView(messageViewInfo);
View view = mInflater.inflate(R.layout.message_content_crypto_warning, containerView, false);
setCryptoProviderIcon(providerIcon, view);
View detailButton = view.findViewById(R.id.crypto_warning_details);
if(showDetailButton) {
detailButton.setVisibility(View.VISIBLE);
detailButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
messageCryptoPresenter.onClickShowCryptoWarningDetails();
}
});
} else {
detailButton.setVisibility(View.GONE);
}
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);
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);
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();
if (openPgpError != null) {
String errorText = openPgpError.getMessage();
cryptoErrorText.setText(errorText);
}
containerView.addView(view);
displayViewOnLoadFinished(false);
}
public void showMessageCryptoCancelledView(MessageViewInfo messageViewInfo, Drawable providerIcon) {
resetAndPrepareMessageView(messageViewInfo);
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) {
messageCryptoPresenter.onClickRetryCryptoOperation();
}
});
containerView.addView(view);
displayViewOnLoadFinished(false);
}
public void showCryptoProviderNotConfigured(final MessageViewInfo messageViewInfo) {
resetAndPrepareMessageView(messageViewInfo);
View view = mInflater.inflate(R.layout.message_content_crypto_no_provider, containerView, false);
view.findViewById(R.id.crypto_settings).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
messageCryptoPresenter.onClickConfigureProvider();
}
});
containerView.addView(view);
displayViewOnLoadFinished(false);
}
private void setCryptoProviderIcon(Drawable openPgpApiProviderIcon, View view) {
ImageView cryptoProviderIcon = (ImageView) view.findViewById(R.id.crypto_error_icon);
if (openPgpApiProviderIcon != null) {
cryptoProviderIcon.setImageDrawable(openPgpApiProviderIcon);
} else {
cryptoProviderIcon.setImageResource(R.drawable.status_lock_error);
cryptoProviderIcon.setColorFilter(ThemeUtils.getStyledColor(getContext(), R.attr.openpgp_red));
}
}
/**
* Fetch the message header view. This is not the same as the message headers; this is the View shown at the top
* of messages.
* @return MessageHeader View.
*/
public MessageHeader getMessageHeaderView() {
return mHeaderContainer;
}
public void setHeaders(final Message message, Account account) {
mHeaderContainer.populate(message, account);
mHeaderContainer.setVisibility(View.VISIBLE);
}
public void setOnToggleFlagClickListener(OnClickListener listener) {
mHeaderContainer.setOnFlagListener(listener);
}
public void showAllHeaders() {
mHeaderContainer.onShowAdditionalHeaders();
}
public boolean additionalHeadersVisible() {
return mHeaderContainer.additionalHeadersVisible();
}
private void hideHeaderView() {
mHeaderContainer.setVisibility(View.GONE);
}
public void setOnDownloadButtonClickListener(OnClickListener listener) {
mDownloadRemainder.setOnClickListener(listener);
}
public void setAttachmentCallback(AttachmentViewCallback callback) {
attachmentCallback = callback;
}
public void setMessageCryptoPresenter(MessageCryptoPresenter messageCryptoPresenter) {
this.messageCryptoPresenter = messageCryptoPresenter;
mHeaderContainer.setOnCryptoClickListener(messageCryptoPresenter);
}
public void enableDownloadButton() {
mDownloadRemainder.setEnabled(true);
}
public void disableDownloadButton() {
mDownloadRemainder.setEnabled(false);
}
private void setShowDownloadButton(MessageViewInfo messageViewInfo) {
if (messageViewInfo.isMessageIncomplete) {
mDownloadRemainder.setEnabled(true);
mDownloadRemainder.setVisibility(View.VISIBLE);
} else {
mDownloadRemainder.setVisibility(View.GONE);
}
}
private void showShowPicturesButton() {
showPicturesButton.setVisibility(View.VISIBLE);
}
private void hideShowPicturesButton() {
showPicturesButton.setVisibility(View.GONE);
}
private boolean shouldAutomaticallyLoadPictures(ShowPictures showPicturesSetting, Message message) {
return showPicturesSetting == ShowPictures.ALWAYS || shouldShowPicturesFromSender(showPicturesSetting, message);
}
private boolean shouldShowPicturesFromSender(ShowPictures showPicturesSetting, Message message) {
if (showPicturesSetting != ShowPictures.ONLY_FROM_CONTACTS) {
return false;
}
String senderEmailAddress = getSenderEmailAddress(message);
if (senderEmailAddress == null) {
return false;
}
Contacts contacts = Contacts.getInstance(getContext());
return contacts.isInContacts(senderEmailAddress);
}
private String getSenderEmailAddress(Message message) {
Address[] from = message.getFrom();
if (from == null || from.length == 0) {
return null;
}
return from[0].getAddress();
}
public void displayViewOnLoadFinished(boolean finishProgressBar) {
if (!finishProgressBar || !isShowingProgress) {
viewAnimator.setDisplayedChild(2);
return;
}
ObjectAnimator animator = ObjectAnimator.ofInt(
progressBar, "progress", progressBar.getProgress(), PROGRESS_MAX);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
viewAnimator.setDisplayedChild(2);
}
});
animator.setDuration(PROGRESS_STEP_DURATION);
animator.start();
}
public void setToLoadingState() {
viewAnimator.setDisplayedChild(0);
progressBar.setProgress(0);
isShowingProgress = false;
}
public void setLoadingProgress(int progress, int max) {
if (!isShowingProgress) {
viewAnimator.setDisplayedChild(1);
isShowingProgress = true;
return;
}
int newPosition = (int) (progress / (float) max * PROGRESS_MAX_WITH_MARGIN);
int currentPosition = progressBar.getProgress();
if (newPosition > currentPosition) {
ObjectAnimator.ofInt(progressBar, "progress", currentPosition, newPosition)
.setDuration(PROGRESS_STEP_DURATION).start();
} else {
progressBar.setProgress(newPosition);
}
}
}