messageview: add crypto info dialog

This commit is contained in:
Vincent Breitmoser 2016-04-18 19:58:01 +02:00 committed by Vincent Breitmoser
parent d92155e2b5
commit 4da1a01130
27 changed files with 726 additions and 260 deletions

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="150"
height="100"
viewBox="0 0 149.99999 99.999998"
id="svg3344"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="status_none_dots_1.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1056"
id="namedview12"
showgrid="false"
inkscape:zoom="2.18"
inkscape:cx="75"
inkscape:cy="50"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs3346" />
<metadata
id="metadata3349">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-17.144857,-22.362199)">
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4219"
cx="138.57143"
cy="106.8622"
r="13"
d="m 151.57143,106.8622 c 0,7.1797 -5.8203,13 -13,13 -7.17971,0 -13,-5.8203 -13,-13 0,-7.179704 5.82029,-13.000002 13,-13.000002 7.1797,0 13,5.820298 13,13.000002 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="150"
height="100"
viewBox="0 0 149.99999 99.999998"
id="svg3344"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="status_none_dots_2.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1056"
id="namedview2999"
showgrid="false"
inkscape:zoom="2.18"
inkscape:cx="75"
inkscape:cy="50"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs3346" />
<metadata
id="metadata3349">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-17.144857,-22.362199)">
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4219"
cx="138.57143"
cy="106.8622"
r="13"
d="m 151.57143,106.8622 c 0,7.1797 -5.8203,13 -13,13 -7.17971,0 -13,-5.8203 -13,-13 0,-7.179704 5.82029,-13.000002 13,-13.000002 7.1797,0 13,5.820298 13,13.000002 z" />
<circle
r="13"
cy="72.362198"
cx="138.57143"
id="circle4741"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 151.57143,72.362198 c 0,7.179702 -5.8203,13 -13,13 -7.17971,0 -13,-5.820298 -13,-13 0,-7.179702 5.82029,-13 13,-13 7.1797,0 13,5.820298 13,13 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="150"
height="100"
viewBox="0 0 149.99999 99.999998"
id="svg3344"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="status_none_dots_3.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1056"
id="namedview3011"
showgrid="false"
inkscape:zoom="2.18"
inkscape:cx="75"
inkscape:cy="50"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs3346" />
<metadata
id="metadata3349">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-17.144857,-22.362199)">
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4219"
cx="138.57143"
cy="106.8622"
r="13"
d="m 151.57143,106.8622 c 0,7.1797 -5.8203,13 -13,13 -7.17971,0 -13,-5.8203 -13,-13 0,-7.179704 5.82029,-13.000002 13,-13.000002 7.1797,0 13,5.820298 13,13.000002 z" />
<circle
r="13"
cy="72.362198"
cx="138.57143"
id="circle4741"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 151.57143,72.362198 c 0,7.179702 -5.8203,13 -13,13 -7.17971,0 -13,-5.820298 -13,-13 0,-7.179702 5.82029,-13 13,-13 7.1797,0 13,5.820298 13,13 z" />
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4743"
cx="138.57143"
cy="37.862198"
r="13"
d="m 151.57143,37.862198 c 0,7.179702 -5.8203,13 -13,13 -7.17971,0 -13,-5.820298 -13,-13 0,-7.179702 5.82029,-13 13,-13 7.1797,0 13,5.820298 13,13 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -18,7 +18,7 @@ inkscape -w 48 -h 48 -e "$XDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
inkscape -w 64 -h 64 -e "$XXDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
done
for NAME in "status_check_dots_1" "status_check_dots_1" "status_check_dots_3" "status_dots" "status_lock_none_dots_1" "status_lock_disabled_dots_1" "status_lock_dots_1" "status_lock_error_dots_1" "status_lock_dots_2" "status_lock_dots_3"
for NAME in "status_none_dots_1" "status_none_dots_2" "status_none_dots_3" "status_check_dots_1" "status_check_dots_1" "status_check_dots_3" "status_dots" "status_lock_none_dots_1" "status_lock_disabled_dots_1" "status_lock_dots_1" "status_lock_error_dots_1" "status_lock_dots_2" "status_lock_dots_3"
do
echo $NAME
inkscape -w 36 -h 24 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"

View file

@ -183,6 +183,7 @@ public class MessageDecryptVerifier {
return isSameMimeType(part.getMimeType(), MULTIPART_ENCRYPTED);
}
// TODO also guess by mime-type of contained part?
public static boolean isPgpMimeEncryptedOrSignedPart(Part part) {
String contentType = part.getContentType();
String protocolParameter = MimeUtility.getHeaderParameter(contentType, PROTOCOL_PARAMETER);

View file

@ -0,0 +1,166 @@
package com.fsck.k9.ui.messageview;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import com.fsck.k9.R;
import com.fsck.k9.view.MessageCryptoDisplayStatus;
public class CryptoInfoDialog extends DialogFragment {
public static final String ARG_DISPLAY_STATUS = "display_status";
private View dialogView;
private View icon1frame;
private View icon2frame;
private TextView text1;
private TextView text2;
private ImageView icon_1_1;
private ImageView icon_1_2;
private ImageView icon_1_3;
private ImageView icon_2_1;
private ImageView icon_2_2;
public static CryptoInfoDialog newInstance(MessageCryptoDisplayStatus displayStatus) {
CryptoInfoDialog frag = new CryptoInfoDialog();
Bundle args = new Bundle();
args.putString(ARG_DISPLAY_STATUS, displayStatus.toString());
frag.setArguments(args);
return frag;
}
@SuppressLint("InflateParams") // inflating without root element is fine for creating a dialog
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Builder b = new AlertDialog.Builder(getActivity());
dialogView = LayoutInflater.from(getActivity()).inflate(R.layout.message_crypto_info_dialog, null);
icon1frame = dialogView.findViewById(R.id.crypto_info_frame_1);
icon_1_1 = (ImageView) icon1frame.findViewById(R.id.crypto_info_icon_1_1);
icon_1_2 = (ImageView) icon1frame.findViewById(R.id.crypto_info_icon_1_2);
icon_1_3 = (ImageView) icon1frame.findViewById(R.id.crypto_info_icon_1_3);
text1 = (TextView) dialogView.findViewById(R.id.crypto_info_text_1);
icon2frame = dialogView.findViewById(R.id.crypto_info_frame_2);
icon_2_1 = (ImageView) icon2frame.findViewById(R.id.crypto_info_icon_2_1);
icon_2_2 = (ImageView) icon2frame.findViewById(R.id.crypto_info_icon_2_2);
text2 = (TextView) dialogView.findViewById(R.id.crypto_info_text_2);
MessageCryptoDisplayStatus displayStatus =
MessageCryptoDisplayStatus.valueOf(getArguments().getString(ARG_DISPLAY_STATUS));
setMessageForDisplayStatus(displayStatus);
b.setView(dialogView);
b.setPositiveButton(R.string.crypto_info_ok, new OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dismiss();
}
});
return b.create();
}
private void setMessageForDisplayStatus(MessageCryptoDisplayStatus displayStatus) {
if (displayStatus.textResSecond == null) {
setMessageSingleLine(displayStatus.color, displayStatus.textResFirst, displayStatus.iconResFirst, displayStatus.iconResSecond);
} else {
if (displayStatus.iconResSecond == null) {
throw new AssertionError("second icon must be non-null if second text is non-null!");
}
setMessageWithAnimation(displayStatus.color,
displayStatus.textResFirst, displayStatus.iconResFirst,
displayStatus.textResSecond, displayStatus.iconResSecond);
}
}
private void setMessageSingleLine(@ColorRes int colorres,
@StringRes int text1res, @DrawableRes int icon1res,
@DrawableRes Integer icon2res) {
@ColorInt int color = getResources().getColor(colorres);
icon_1_1.setImageResource(icon1res);
icon_1_1.setColorFilter(color);
text1.setText(text1res);
if (icon2res != null) {
icon_1_3.setImageResource(icon2res);
icon_1_3.setColorFilter(color);
icon_1_3.setVisibility(View.VISIBLE);
} else {
icon_1_3.setVisibility(View.GONE);
}
text2.setVisibility(View.GONE);
icon2frame.setVisibility(View.GONE);
}
private void setMessageWithAnimation(@ColorRes int colorres,
@StringRes int text1res, @DrawableRes int icon1res, @StringRes int text2res, @DrawableRes int icon2res) {
icon_1_1.setImageResource(icon1res);
icon_1_2.setImageResource(icon2res);
icon_1_3.setVisibility(View.GONE);
text1.setText(text1res);
icon_2_1.setImageResource(icon1res);
icon_2_2.setImageResource(icon2res);
text2.setText(text2res);
icon_1_1.setColorFilter(getResources().getColor(colorres));
icon_2_2.setColorFilter(getResources().getColor(colorres));
prepareIconAnimation();
}
private void prepareIconAnimation() {
text1.setAlpha(0.0f);
text2.setAlpha(0.0f);
dialogView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
float halfVerticalPixelDifference = (icon2frame.getY() - icon1frame.getY()) / 2.0f;
icon1frame.setTranslationY(halfVerticalPixelDifference);
icon2frame.setTranslationY(-halfVerticalPixelDifference);
icon1frame.animate().translationY(0)
.setStartDelay(400)
.setDuration(350)
.setInterpolator(new AccelerateDecelerateInterpolator())
.start();
icon2frame.animate().translationY(0)
.setStartDelay(400)
.setDuration(350)
.setInterpolator(new AccelerateDecelerateInterpolator())
.start();
text1.animate().alpha(1.0f).setStartDelay(750).start();
text2.animate().alpha(1.0f).setStartDelay(750).start();
view.removeOnLayoutChangeListener(this);
}
});
}
}

View file

@ -147,6 +147,10 @@ public class MessageTopView extends LinearLayout implements ShowPicturesControll
attachmentCallback = callback;
}
public void setOnCryptoClickListener(OnCryptoClickListener listener) {
mHeaderContainer.setOnCryptoClickListener(listener);
}
public void enableDownloadButton() {
mDownloadRemainder.setEnabled(true);
}

View file

@ -53,10 +53,11 @@ 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 com.fsck.k9.view.MessageCryptoDisplayStatus;
import com.fsck.k9.view.MessageHeader;
public class MessageViewFragment extends Fragment implements ConfirmationDialogFragmentListener,
AttachmentViewCallback, MessageCryptoCallback {
AttachmentViewCallback, OnCryptoClickListener, MessageCryptoCallback {
private static final String ARG_REFERENCE = "reference";
@ -149,6 +150,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
mMessageView = (MessageTopView) view.findViewById(R.id.message_view);
mMessageView.setAttachmentCallback(this);
mMessageView.setOnCryptoClickListener(this);
mMessageView.setOnToggleFlagClickListener(new OnClickListener() {
@Override
@ -708,6 +710,15 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
// mMessageView.refreshAttachmentThumbnail(attachment);
}
@Override
public void onCryptoClick() {
MessageCryptoDisplayStatus displayStatus =
MessageCryptoDisplayStatus.fromResultAnnotation(messageViewInfo.cryptoResultAnnotation);
CryptoInfoDialog dialog = CryptoInfoDialog.newInstance(displayStatus);
dialog.show(getFragmentManager(), "crypto_info_dialog");
}
@Override
public void startPendingIntentForCryptoHelper(IntentSender si, int requestCode, Intent fillIntent,
int flagsMask, int flagValues, int extraFlags) throws SendIntentException {

View file

@ -0,0 +1,6 @@
package com.fsck.k9.ui.messageview;
public interface OnCryptoClickListener {
void onCryptoClick();
}

View file

@ -1,8 +1,12 @@
package com.fsck.k9.view;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import com.fsck.k9.R;
import com.fsck.k9.mailstore.CryptoResultAnnotation;
import com.fsck.k9.mailstore.CryptoResultAnnotation.CryptoError;
import org.openintents.openpgp.OpenPgpDecryptionResult;
@ -10,27 +14,139 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
public enum MessageCryptoDisplayStatus {
DISABLED,
DISABLED (
R.color.openpgp_grey,
R.drawable.status_lock_disabled,
R.string.crypto_msg_disabled
),
UNENCRYPTED_SIGN_UNKNOWN,
UNENCRYPTED_SIGN_VERIFIED,
UNENCRYPTED_SIGN_UNVERIFIED,
UNENCRYPTED_SIGN_ERROR,
UNENCRYPTED_SIGN_MISMATCH,
UNENCRYPTED_SIGN_EXPIRED,
UNENCRYPTED_SIGN_REVOKED,
UNENCRYPTED_SIGN_INSECURE,
UNENCRYPTED_SIGN_UNKNOWN (
R.color.openpgp_grey,
R.drawable.status_signature_unverified_cutout, R.drawable.status_dots,
R.string.crypto_msg_signed_unencrypted, null
),
ENCRYPTED_UNSIGNED,
ENCRYPTED_SIGN_UNKNOWN,
ENCRYPTED_SIGN_VERIFIED,
ENCRYPTED_SIGN_UNVERIFIED,
ENCRYPTED_SIGN_ERROR,
ENCRYPTED_SIGN_MISMATCH,
ENCRYPTED_SIGN_EXPIRED,
ENCRYPTED_SIGN_REVOKED,
ENCRYPTED_SIGN_INSECURE,
ENCRYPTED_ERROR;
UNENCRYPTED_SIGN_VERIFIED (
R.color.openpgp_blue,
R.drawable.status_signature_verified_cutout, R.drawable.status_none_dots_3,
R.string.crypto_msg_signed_unencrypted, R.string.crypto_msg_sign_verified
),
UNENCRYPTED_SIGN_UNVERIFIED (
R.color.openpgp_orange,
R.drawable.status_signature_verified_cutout, R.drawable.status_none_dots_2,
R.string.crypto_msg_signed_unencrypted, R.string.crypto_msg_sign_unverified
),
UNENCRYPTED_SIGN_ERROR (
R.color.openpgp_red,
R.drawable.status_signature_verified_cutout, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_unencrypted, R.string.crypto_msg_sign_error
),
UNENCRYPTED_SIGN_MISMATCH (
R.color.openpgp_red,
R.drawable.status_signature_verified_cutout, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_unencrypted, R.string.crypto_msg_sign_mismatch
),
UNENCRYPTED_SIGN_EXPIRED (
R.color.openpgp_red,
R.drawable.status_signature_verified_cutout, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_unencrypted, R.string.crypto_msg_sign_expired
),
UNENCRYPTED_SIGN_REVOKED (
R.color.openpgp_red,
R.drawable.status_signature_verified_cutout, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_unencrypted, R.string.crypto_msg_sign_revoked
),
UNENCRYPTED_SIGN_INSECURE (
R.color.openpgp_red,
R.drawable.status_signature_verified_cutout, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_unencrypted, R.string.crypto_msg_sign_insecure
),
ENCRYPTED_SIGN_UNKNOWN (
R.color.openpgp_grey,
R.drawable.status_lock_opportunistic, R.drawable.status_dots,
R.string.crypto_msg_signed_encrypted, null
),
ENCRYPTED_SIGN_VERIFIED (
R.color.openpgp_green,
R.drawable.status_lock, R.drawable.status_none_dots_3,
R.string.crypto_msg_signed_encrypted, R.string.crypto_msg_sign_verified
),
ENCRYPTED_SIGN_UNVERIFIED (
R.color.openpgp_orange,
R.drawable.status_lock, R.drawable.status_none_dots_2,
R.string.crypto_msg_signed_encrypted, R.string.crypto_msg_sign_unverified
),
ENCRYPTED_SIGN_ERROR (
R.color.openpgp_red,
R.drawable.status_lock, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_encrypted, R.string.crypto_msg_sign_error
),
ENCRYPTED_SIGN_MISMATCH (
R.color.openpgp_red,
R.drawable.status_lock, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_encrypted, R.string.crypto_msg_sign_mismatch
),
ENCRYPTED_SIGN_EXPIRED (
R.color.openpgp_red,
R.drawable.status_lock, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_encrypted, R.string.crypto_msg_sign_expired
),
ENCRYPTED_SIGN_REVOKED (
R.color.openpgp_red,
R.drawable.status_lock, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_encrypted, R.string.crypto_msg_sign_revoked
),
ENCRYPTED_SIGN_INSECURE (
R.color.openpgp_red,
R.drawable.status_lock, R.drawable.status_none_dots_1,
R.string.crypto_msg_signed_encrypted, R.string.crypto_msg_sign_insecure
),
ENCRYPTED_UNSIGNED (
R.color.openpgp_red,
R.drawable.status_lock, R.drawable.status_none_dots_1,
R.string.crypto_msg_encrypted_unsigned, R.string.crypto_msg_unsigned_encrypted
),
ENCRYPTED_ERROR (
R.color.openpgp_red,
R.drawable.status_lock_error,
R.string.crypto_msg_encrypted_error
),
SIGNED_UNSUPPORTED (
R.color.openpgp_red,
R.drawable.status_signature_verified_cutout,
R.string.crypto_msg_signed_unsupported
),
;
@ColorRes public final int color;
@DrawableRes public final int iconResFirst;
@DrawableRes public final Integer iconResSecond;
@StringRes public final int textResFirst;
@StringRes public final Integer textResSecond;
MessageCryptoDisplayStatus(@ColorRes int color, @DrawableRes int iconResFirst, @DrawableRes Integer iconResSecond,
@StringRes int textResFirst, @StringRes Integer textResSecond) {
this.color = color;
this.iconResFirst = iconResFirst;
this.iconResSecond = iconResSecond;
this.textResFirst = textResFirst;
this.textResSecond = textResSecond;
}
MessageCryptoDisplayStatus(@ColorRes int color, @DrawableRes int iconResFirst, @StringRes int textResFirst) {
this.color = color;
this.iconResFirst = iconResFirst;
this.iconResSecond = null;
this.textResFirst = textResFirst;
this.textResSecond = null;
}
@NonNull
public static MessageCryptoDisplayStatus fromResultAnnotation(CryptoResultAnnotation cryptoResult) {

View file

@ -2,22 +2,21 @@ package com.fsck.k9.view;
import android.content.Context;
import android.support.annotation.ColorInt;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.fsck.k9.R;
public class MessageCryptoStatusView extends ToolableViewAnimator {
private static final int STATUS_DISABLED = 0;
private static final int STATUS_SIGN_3_OK = 1;
private static final int STATUS_SIGN_2_WARNING = 2;
private static final int STATUS_SIGN_1_ERROR = 3;
private static final int STATUS_SIGN_0_UNKNOWN = 4;
private static final int STATUS_LOCK_3_OK = 5;
private static final int STATUS_LOCK_2_WARNING = 6;
private static final int STATUS_LOCK_1_ERROR = 7;
private static final int STATUS_LOCK_0_UNKNOWN = 8;
private static final int STATUS_LOCK_UNKNOWN = 9;
private static final int STATUS_LOCK_ERROR = 10;
public class MessageCryptoStatusView extends FrameLayout {
private ImageView iconSingle;
private ImageView iconCombinedFirst;
private ImageView iconCombinedSecond;
private ImageView iconDotsBackground;
public MessageCryptoStatusView(Context context) {
super(context);
@ -31,49 +30,36 @@ public class MessageCryptoStatusView extends ToolableViewAnimator {
super(context, attrs, defStyleAttr);
}
public void setCryptoDisplayStatus(MessageCryptoDisplayStatus displayStatus) {
int whichChild = displayStatusToChildIndex(displayStatus);
setDisplayedChild(whichChild);
@Override
protected void onFinishInflate() {
super.onFinishInflate();
iconSingle = (ImageView) findViewById(R.id.crypto_status_single);
iconCombinedFirst = (ImageView) findViewById(R.id.crypto_status_combined_1);
iconCombinedSecond = (ImageView) findViewById(R.id.crypto_status_combined_2);
iconDotsBackground = (ImageView) findViewById(R.id.crypto_status_dots_bg);
}
private int displayStatusToChildIndex(MessageCryptoDisplayStatus displayStatus) {
switch (displayStatus) {
case DISABLED:
return STATUS_DISABLED;
public void setCryptoDisplayStatus(MessageCryptoDisplayStatus displayStatus) {
@ColorInt int color = getResources().getColor(displayStatus.color);
case UNENCRYPTED_SIGN_UNKNOWN:
return STATUS_SIGN_0_UNKNOWN;
case UNENCRYPTED_SIGN_VERIFIED:
return STATUS_SIGN_3_OK;
case UNENCRYPTED_SIGN_UNVERIFIED:
return STATUS_SIGN_2_WARNING;
case UNENCRYPTED_SIGN_ERROR:
return STATUS_SIGN_1_ERROR;
case UNENCRYPTED_SIGN_MISMATCH:
case UNENCRYPTED_SIGN_EXPIRED:
case UNENCRYPTED_SIGN_REVOKED:
case UNENCRYPTED_SIGN_INSECURE:
return STATUS_SIGN_1_ERROR;
if (displayStatus.iconResSecond != null) {
iconCombinedFirst.setVisibility(View.VISIBLE);
iconCombinedSecond.setVisibility(View.VISIBLE);
iconDotsBackground.setVisibility(View.VISIBLE);
iconSingle.setVisibility(View.GONE);
case ENCRYPTED_SIGN_UNKNOWN:
return STATUS_LOCK_0_UNKNOWN;
case ENCRYPTED_SIGN_VERIFIED:
return STATUS_LOCK_3_OK;
case ENCRYPTED_SIGN_UNVERIFIED:
return STATUS_LOCK_2_WARNING;
case ENCRYPTED_SIGN_ERROR:
case ENCRYPTED_SIGN_MISMATCH:
case ENCRYPTED_SIGN_EXPIRED:
case ENCRYPTED_SIGN_REVOKED:
case ENCRYPTED_SIGN_INSECURE:
return STATUS_LOCK_1_ERROR;
iconCombinedFirst.setImageResource(displayStatus.iconResFirst);
iconCombinedFirst.setColorFilter(color);
iconCombinedSecond.setImageResource(displayStatus.iconResSecond);
iconCombinedSecond.setColorFilter(color);
} else {
iconCombinedFirst.setVisibility(View.GONE);
iconCombinedSecond.setVisibility(View.GONE);
iconDotsBackground.setVisibility(View.GONE);
iconSingle.setVisibility(View.VISIBLE);
case ENCRYPTED_ERROR:
return STATUS_LOCK_ERROR;
case ENCRYPTED_UNSIGNED:
return STATUS_LOCK_UNKNOWN;
iconSingle.setImageResource(displayStatus.iconResFirst);
iconSingle.setColorFilter(color);
}
throw new AssertionError("all cases must be handled, this is a bug!");
}
}

View file

@ -42,6 +42,7 @@ 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;
public class MessageHeader extends LinearLayout implements OnClickListener, OnLongClickListener {
@ -72,6 +73,7 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
private QuickContactBadge mContactBadge;
private OnLayoutChangedListener mOnLayoutChangedListener;
private OnCryptoClickListener onCryptoClickListener;
/**
* Pair class is only available since API Level 5, so we need
@ -133,6 +135,7 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
mCcView.setOnLongClickListener(this);
mCryptoStatusIcon = (MessageCryptoStatusView) findViewById(R.id.crypto_status_icon);
mCryptoStatusIcon.setOnClickListener(this);
mMessageHelper = MessageHelper.getInstance(mContext);
@ -150,6 +153,11 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
case R.id.cc: {
expand((TextView)view, ((TextView)view).getEllipsize() != null);
layoutChanged();
break;
}
case R.id.crypto_status_icon: {
onCryptoClickListener.onCryptoClick();
break;
}
}
}
@ -492,4 +500,8 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
public void showSubjectLine() {
mSubjectView.setVisibility(VISIBLE);
}
public void setOnCryptoClickListener(OnCryptoClickListener onCryptoClickListener) {
this.onCryptoClickListener = onCryptoClickListener;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="24dp"
android:orientation="vertical"
android:layout_gravity="center_horizontal">
<FrameLayout
android:layout_width="36dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignBottom="@+id/crypto_info_text_1"
android:id="@+id/crypto_info_frame_1"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_info_icon_1_1"
tools:src="@drawable/status_signature_verified_cutout"
tools:tint="@color/openpgp_blue"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_info_icon_1_2"
android:alpha="0.05"
tools:src="@drawable/status_none_dots_3"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_info_icon_1_3"
/>
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/crypto_info_frame_1"
android:layout_marginBottom="12dp"
android:layout_marginLeft="20dp"
android:minLines="2"
android:gravity="center_vertical"
android:id="@+id/crypto_info_text_1"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Signed, but not encrypted."
/>
<FrameLayout
android:layout_width="36dp"
android:layout_height="wrap_content"
android:layout_below="@+id/crypto_info_text_1"
android:layout_alignBottom="@+id/crypto_info_text_2"
android:id="@+id/crypto_info_frame_2"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_info_icon_2_1"
android:alpha="0.05"
tools:src="@drawable/status_signature_verified_cutout"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_info_icon_2_2"
tools:src="@drawable/status_none_dots_3"
tools:tint="@color/openpgp_blue"
/>
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/crypto_info_text_1"
android:layout_toRightOf="@+id/crypto_info_frame_2"
android:layout_marginLeft="20dp"
android:id="@+id/crypto_info_text_2"
android:minLines="2"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Signed by trusted key."
/>
</RelativeLayout>

View file

@ -6,208 +6,46 @@
android:layout_width="36dp"
android:layout_height="32dp"
android:visibility="gone"
custom:previewInitialChild="9"
custom:previewInitialChild="0"
android:background="@drawable/selectable_item_background"
tools:showIn="@layout/message_view_header"
tools:visibility="visible">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/status_lock_disabled"
android:tint="@color/openpgp_grey"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_check_dots_3"
android:tint="@color/openpgp_blue"
/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_check_dots_2"
android:tint="@color/openpgp_orange"
/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_check_dots_1"
android:tint="@color/openpgp_red"
/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_signature_unverified_cutout"
android:tint="@color/openpgp_grey"
/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_lock_dots_3"
android:tint="@color/openpgp_green"
/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_lock_dots_2"
android:tint="@color/openpgp_orange"
/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_lock_dots_1"
android:tint="@color/openpgp_red"
/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:src="@drawable/status_lock_opportunistic"
android:tint="@color/openpgp_grey"
/>
</FrameLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/status_lock_opportunistic"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_status_dots_bg"
android:src="@drawable/status_dots"
android:tint="@color/openpgp_grey"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_status_combined_2"
tools:src="@drawable/status_none_dots_1"
tools:tint="@color/openpgp_blue"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:id="@+id/crypto_status_combined_1"
tools:src="@drawable/status_signature_verified_cutout"
tools:tint="@color/openpgp_blue"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/status_lock_disabled"
android:tint="@color/openpgp_red"
android:id="@+id/crypto_status_single"
android:visibility="gone"
tools:src="@drawable/status_signature_verified_cutout"
tools:tint="@color/openpgp_blue"
/>
</com.fsck.k9.view.MessageCryptoStatusView>

View file

@ -1164,4 +1164,25 @@ Please submit bug reports, contribute new features and ask questions at
<string name="openpgp_inline_disable">Disable</string>
<string name="openpgp_inline_keep_enabled">Keep Enabled</string>
<string name="crypto_msg_disabled">Message is not encrypted</string>
<string name="crypto_msg_encrypted_error">Message is encrypted, but there was an error decrypting.</string>
<string name="crypto_msg_signed_unsupported">Message is signed, but with an unsupported format.</string>
<string name="crypto_msg_signed_unencrypted">Message is signed, but not encrypted.</string>
<string name="crypto_msg_encrypted_unsigned">Message was encrypted, but not signed.</string>
<string name="crypto_msg_sign_unknown">Signature made by unknown key.</string>
<string name="crypto_msg_sign_verified">Signature made by trusted key.</string>
<string name="crypto_msg_sign_unverified">Signature made by trusted key.</string>
<string name="crypto_msg_sign_error">Signature contained an error.</string>
<string name="crypto_msg_sign_mismatch">Signature made by wrong key.</string>
<string name="crypto_msg_sign_expired">Signature made by expired key.</string>
<string name="crypto_msg_sign_revoked">Signature made by revoked key.</string>
<string name="crypto_msg_sign_insecure">Signature made by insecure key.</string>
<string name="crypto_msg_signed_encrypted">Message is signed and encrypted.</string>
<string name="crypto_msg_unsigned_encrypted">There is no signature, this message may have been intercepted.</string>
<string name="crypto_info_ok">OK</string>
</resources>