1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-23 18:02:15 -05:00

Merge pull request #535

This commit is contained in:
cketti 2015-01-28 17:42:34 +01:00
commit 4827b4c437
74 changed files with 1031 additions and 262 deletions

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>lock-closed</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="lock-closed" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M81.502,45.132 L79.577,45.132 L79.577,29.479 C79.479,10.285 66.387,-0.164 50.476,-0.164 C34.57,-0.164 20.304,10.782 20.801,29.479 L20.785,45.112 C20.785,45.112 21.025,45.133 19.825,45.133 C18.555,45.133 10.185,46.606 10.185,54.069 L10.185,89.893 C10.185,97.852 19.605,99.836 19.825,99.836 L81.027,99.836 C81.247,99.836 90.181,98.843 90.181,89.893 L90.181,54.564 C90.182,46.109 81.727,45.132 81.502,45.132 L81.502,45.132 Z M59.334,86.055 L41.061,86.055 L46.024,71.489 C43.904,70.077 42.496,67.623 42.496,64.824 C42.496,60.44 45.938,56.886 50.183,56.886 C54.428,56.886 57.87,60.443 57.87,64.824 C57.87,67.619 56.466,70.077 54.348,71.485 L59.334,86.055 L59.334,86.055 Z M34.261,45.132 L34.277,29.686 C34.277,19.737 40.348,11.783 50.183,11.783 C59.924,11.783 66.088,18.741 66.088,29.686 L66.098,45.132 L34.261,45.132 L34.261,45.132 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>lock-error</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="lock-error" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M80.459,45.474 L78.533,45.474 L78.533,29.826 C78.435,10.633 65.344,0.183 49.433,0.183 C33.527,0.183 19.265,11.128 19.761,29.826 L19.745,45.454 C19.745,45.454 19.985,45.475 18.784,45.475 C17.514,45.475 9.145,46.946 9.145,54.407 L9.145,90.228 C9.145,98.187 18.565,100.171 18.784,100.171 L79.984,100.171 C80.203,100.171 89.138,99.178 89.138,90.228 L89.138,54.901 C89.139,46.452 80.684,45.474 80.459,45.474 L80.459,45.474 Z M33.234,30.033 C33.234,20.084 39.304,12.131 49.14,12.131 C58.881,12.131 65.045,19.088 65.045,30.033 L65.055,45.474 L33.218,45.474 L33.234,30.033 L33.234,30.033 Z M59.4033767,90.873 L48.4582822,79.9279055 L38.2296593,90.3644491 L31.6365,83.7568884 L42.5824946,72.8153942 L32.3439707,62.5939721 L38.7544118,56.1079235 L49.7013065,67.0503177 L60.1234487,56.7100837 L66.6365,63.2240351 L55.6896053,74.1673294 L66.0091373,84.4778605 L59.4033767,90.873 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>lock-open</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="lock-open" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M79.577,26.479 C79.577,10.833 66.387,-0.164 50.476,-0.164 C34.57,-0.164 20.304,10.782 20.801,29.479 L20.785,45.112 C20.785,45.112 21.025,45.133 19.825,45.133 C18.555,45.133 10.185,46.606 10.185,54.069 L10.185,89.893 C10.185,97.852 19.605,99.836 19.825,99.836 L81.027,99.836 C81.247,99.836 90.181,98.843 90.181,89.893 L90.181,54.564 C90.181,46.107 81.726,45.13 81.5,45.13 L34.259,45.13 L34.275,29.684 C34.275,19.735 40.346,11.781 50.181,11.781 C59.922,11.781 66.664,18.164 66.664,29.164 L79.577,26.479 Z M59.334,86.055 L41.061,86.055 L46.024,71.49 C43.904,70.078 42.496,67.624 42.496,64.825 C42.496,60.44 45.938,56.887 50.183,56.887 C54.428,56.887 57.87,60.445 57.87,64.825 C57.87,67.62 56.466,70.078 54.348,71.485 L59.334,86.055 L59.334,86.055 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>signature-expired-cutout</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="signature-expired-cutout" sketch:type="MSArtboardGroup" transform="translate(0.110156, 0.000000)" fill="#000000">
<path d="M5.21763502,25.9334098 C4.62201801,24.5421709 5.31408066,20.2649627 6.50270803,18.5737297 C7.69394204,16.8824967 14.8139764,11.1118682 18.0827017,9.51888655 C21.3514269,7.92852492 25.1232335,10.7136228 25.1232335,10.7136228 L31.1693326,18.5737297 C21.6564037,21.754453 12.2477403,33.889148 12.2477403,33.889148 C12.2477403,33.889148 5.81325202,27.3259588 5.21763502,25.9334098 Z M50.7969868,98.0040129 C30.5564763,98.0040129 14.1592664,81.3860653 14.1592664,60.910451 C14.1592664,41.4138456 29.0387981,25.4459175 47.9423376,23.9707712 L47.9423376,18.3341735 L41.6333009,18.3341735 L41.6333009,9.02828206 L59.2561767,9.02828206 L59.2561767,18.3341735 L53.6477076,18.3341735 L53.6477076,23.9707712 C72.5460092,25.4445909 87.4333977,41.412519 87.4333977,60.910451 C87.4333977,81.3847387 71.0296405,98.0040129 50.7969868,98.0040129 Z M51.541054,71.6933659 C57.6539179,71.6933659 62.6093732,66.7455263 62.6093732,60.6420567 C62.6093732,54.5385872 57.6539179,49.5907476 51.541054,49.5907476 C45.4281901,49.5907476 40.4727348,54.5385872 40.4727348,60.6420567 C40.4727348,66.7455263 45.4281901,71.6933659 51.541054,71.6933659 Z M96.3766201,25.9341425 C95.7811759,27.3252533 89.3433427,33.889148 89.3433427,33.889148 C89.3433427,33.889148 79.9321974,21.7542607 70.4233315,18.5751403 L76.4676764,10.7157573 C76.4676764,10.7157573 80.2396916,7.92829614 83.5087714,9.5185113 C86.7765483,11.1152759 93.8997286,16.884063 95.0880111,18.5751403 C96.2775965,20.2635977 96.9694584,24.540412 96.3766201,25.9341425 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>signature-invalid-cutout</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="signature-invalid-cutout" sketch:type="MSArtboardGroup" transform="translate(0.110156, 0.000000)" fill="#000000">
<path d="M77.3119658,92 L50,64.6787909 L22.6865385,92 L8.00299145,77.3054987 L35.3149573,49.9977557 L8,22.6870202 L22.6850427,8.00149623 L50,35.3137279 L77.3149573,8 L92,22.6825315 L64.6850427,49.9977557 L91.9970085,77.3054987 L77.3119658,92 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 995 B

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="101px" height="100px" viewBox="0 0 101 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>signature-revoked-cutout</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="signature-revoked-cutout" sketch:type="MSArtboardGroup" transform="translate(0.915625, 0.000000)" fill="#000000">
<path d="M50.1457786,95.2902674 C25.2543974,95.2902674 5,75.0407401 5,50.1451337 C5,25.252107 25.2556872,5 50.1457786,5 C75.03587,5 95.2902674,25.252107 95.2902674,50.1451337 C95.2902674,75.0394503 75.0371599,95.2902674 50.1457786,95.2902674 Z M35.5297191,75.6701923 C39.8404345,78.1467253 44.8296167,79.569442 50.1464236,79.569442 C66.3793238,79.569442 79.5862102,66.3638454 79.5862102,50.1296554 C79.5862102,44.8115586 78.1622037,39.8223764 75.6843808,35.5116611 L35.5297191,75.6701923 Z M50.1464236,20.6911586 C33.9135233,20.6911586 20.7066369,33.8967551 20.7066369,50.1309452 C20.7066369,55.3523024 22.0803389,60.2563538 24.473031,64.512895 L64.5296632,24.4575526 C60.2718321,22.0635707 55.3690706,20.6911586 50.1464236,20.6911586 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="101px" height="100px" viewBox="0 0 101 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>signature-unknown-cutout</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="signature-unknown-cutout" sketch:type="MSArtboardGroup" transform="translate(0.915625, 0.000000)" fill="#000000">
<path d="M11.4743662,97.2253545 C1.98936285,97.2253571 -1.69987039,86.6466353 1.98936288,81.2764443 C2.36018089,80.2888073 37.5445854,9.4248374 37.6406733,9.21698534 C41.524789,0.483122973 56.8650161,0.0416071437 60.7924391,9.21698534 C60.7572519,9.19524917 98.2991929,81.8687547 97.9337883,81.2642177 C101.323931,86.2404407 96.9260512,97.2253571 88.8978453,97.2253545 C88.8978453,97.2253545 11.4756386,97.2879401 11.4743662,97.2253545 Z M50.5378687,73.3388569 C47.2443918,73.3388569 44.2703808,76.046195 44.2703808,79.5061732 C44.2703808,82.9729198 47.1388056,85.6802579 50.5378687,85.6802579 C53.9369317,85.6802579 56.8040029,82.9729198 56.8040029,79.5061732 C56.8053565,76.046195 53.8313455,73.3388569 50.5378687,73.3388569 Z M50.3063913,28.5 C46.5729719,28.5 42.719076,30.2990258 43.0805057,32.9143334 L45.8826007,65.934287 L54.7315355,65.934287 L57.5322768,32.9143334 C57.8937065,30.2990258 54.0398106,28.5 50.3063913,28.5 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="101px" height="100px" viewBox="0 0 101 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>signature-unverified-cutout</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="signature-unverified-cutout" sketch:type="MSArtboardGroup" transform="translate(0.915625, 0.000000)" fill="#000000">
<path d="M49.8900274,96.5521596 C75.8474106,96.5521596 96.8900274,75.5095428 96.8900274,49.5521596 C96.8900274,23.5947764 75.8474106,2.5521596 49.8900274,2.5521596 C23.9326441,2.5521596 2.89002736,23.5947764 2.89002736,49.5521596 C2.89002736,75.5095428 23.9326441,96.5521596 49.8900274,96.5521596 Z M42.9188472,79.4349375 L42.9188472,67.0146143 L55.3391704,67.0146143 L55.3391704,79.4349375 L42.9188472,79.4349375 Z M68.652586,41.8646591 C67.9712562,43.583078 67.1302842,45.0524085 66.1249189,46.2716815 C65.1167028,47.4919237 64.0039592,48.5318919 62.7800362,49.3906167 C61.5570634,50.25128 60.4006082,51.1080664 59.3135213,51.9677605 C58.2254842,52.829393 57.2609796,53.8121774 56.4181072,54.9209598 C55.5733342,56.0307115 55.0449948,57.4147511 54.8273874,59.0779247 L54.8273874,62.237567 L43.8168316,62.237567 L43.8168316,58.4954263 C43.9802747,56.114064 44.4278428,54.1165111 45.1623867,52.5095519 C45.89503,50.9025928 46.7531065,49.5292145 47.7309145,48.3923248 C48.7106231,47.2564044 49.7425954,46.2716815 50.8296823,45.4400947 C51.9177195,44.6104463 52.9230848,43.7769211 53.8476788,42.9463035 C54.7722728,42.1147166 55.5201202,41.2007465 56.0912209,40.2024546 C56.6623216,39.2041628 56.9188893,37.9577517 56.8647251,36.4612832 C56.8647251,33.9112774 56.2537138,32.0261534 55.030741,30.804942 C53.8058678,29.5876075 52.1058691,28.9760325 49.9326456,28.9760325 C48.4645081,28.9760325 47.2006746,29.2677664 46.1392445,29.8492956 C45.0797149,30.4317941 44.2092851,31.2071664 43.5298558,32.177351 C42.848526,33.1475357 42.3477439,34.2844253 42.0208576,35.5860816 C41.6939713,36.8906456 41.5305282,38.2901926 41.5305282,39.7866612 L29.5431146,39.7866612 C29.5953784,36.7917856 30.0999615,34.0479368 31.0521128,31.5541455 C32.0023636,29.0593851 33.3346152,26.8970655 35.0479174,25.0691252 C36.7612195,23.2382773 38.8270647,21.8115922 41.2464032,20.7832547 C43.6666919,19.7568556 46.3730062,19.2441406 49.3624951,19.2441406 C53.2224138,19.2441406 56.4447142,19.785932 59.0274958,20.8666072 C61.6093272,21.9482516 63.6894262,23.2935226 65.2668425,24.9024202 C66.8442588,26.5103485 67.9712562,28.2423365 68.6516357,30.0993532 C69.3310651,31.9573391 69.6703046,33.6883579 69.6703046,35.2962862 C69.6722051,37.9567825 69.3320153,40.1481786 68.652586,41.8646591 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
<title>signature-verified-cutout</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="signature-verified-cutout" sketch:type="MSArtboardGroup" transform="translate(0.110156, 0.000000)" fill="#000000">
<path d="M50,97 C75.9573832,97 97,75.9573832 97,50 C97,24.0426168 75.9573832,3 50,3 C24.0426168,3 3,24.0426168 3,50 C3,75.9573832 24.0426168,97 50,97 Z M46.2732912,77.5085 L20,57.830916 L27.9184401,47.6349702 L43.3096859,59.5152262 L70.31112,23 L80.867825,30.7782191 L46.2732912,77.5085 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

19
images/update-drawables-pgp.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
APP_DIR=../k9mail/src/main
MDPI_DIR=$APP_DIR/res/drawable-mdpi
HDPI_DIR=$APP_DIR/res/drawable-hdpi
XDPI_DIR=$APP_DIR/res/drawable-xhdpi
XXDPI_DIR=$APP_DIR/res/drawable-xxhdpi
XXXDPI_DIR=$APP_DIR/res/drawable-xxxhdpi
SRC_DIR=./drawables-pgp/
for NAME in "status_lock_closed" "status_lock_error" "status_lock_open" "status_signature_expired_cutout" "status_signature_invalid_cutout" "status_signature_revoked_cutout" "status_signature_unknown_cutout" "status_signature_unverified_cutout" "status_signature_verified_cutout"
do
echo $NAME
inkscape -w 24 -h 24 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
inkscape -w 32 -h 32 -e "$HDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
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

View File

@ -1,5 +1,6 @@
package com.fsck.k9.mailstore;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@ -11,6 +12,8 @@ import com.fsck.k9.activity.K9ActivityCommon;
import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Part;
import com.fsck.k9.mail.internet.MessageExtractor;
import com.fsck.k9.mail.internet.MimeBodyPart;
import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mail.internet.MimeMessageHelper;
@ -38,7 +41,8 @@ public class LocalMessageExtractorTest {
MimeMessageHelper.setBody(message, body);
// Extract text
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
MessageExtractor.getViewables(message, attachments), new ArrayList<Part>());
String expectedText = bodyText;
String expectedHtml =
@ -63,7 +67,8 @@ public class LocalMessageExtractorTest {
MimeMessageHelper.setBody(message, body);
// Extract text
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
MessageExtractor.getViewables(message, attachments), new ArrayList<Part>());
String expectedText = "K-9 Mail rocks :>";
String expectedHtml =
@ -94,7 +99,8 @@ public class LocalMessageExtractorTest {
MimeMessageHelper.setBody(message, multipart);
// Extract text
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
MessageExtractor.getViewables(message, attachments), new ArrayList<Part>());
String expectedText =
bodyText1 + "\r\n\r\n" +
@ -151,7 +157,8 @@ public class LocalMessageExtractorTest {
MimeMessageHelper.setBody(message, multipart);
// Extract text
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(),
MessageExtractor.getViewables(message, attachments), new ArrayList<Part>());
String expectedText =
bodyText +

View File

@ -51,7 +51,7 @@ 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.view.MessageHeader;
import com.fsck.k9.ui.messageview.MessageOpenPgpView;
import com.fsck.k9.ui.messageview.MessageOpenPgpViewOld;
import com.fsck.k9.view.MessageTitleView;
import com.fsck.k9.view.ViewSwitcher;
import com.fsck.k9.view.ViewSwitcher.OnSwitchCompleteListener;
@ -1564,7 +1564,7 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
// handle OpenPGP results from PendingIntents in OpenPGP view
// must be handled in this main activity, because startIntentSenderForResult() does not support Fragments
MessageOpenPgpView openPgpView = (MessageOpenPgpView) findViewById(R.id.layout_decrypt_openpgp);
MessageOpenPgpViewOld openPgpView = (MessageOpenPgpViewOld) findViewById(R.id.layout_decrypt_openpgp);
if (openPgpView != null && openPgpView.handleOnActivityResult(requestCode, resultCode, data)) {
return;
}

View File

@ -13,7 +13,9 @@ import com.fsck.k9.mail.internet.MessageExtractor;
import com.fsck.k9.mail.internet.MimeHeader;
import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mail.internet.Viewable;
import com.fsck.k9.mailstore.MessageViewInfo.MessageViewContainer;
import com.fsck.k9.provider.AttachmentProvider;
import org.openintents.openpgp.OpenPgpSignatureResult;
import java.util.ArrayList;
import java.util.Date;
@ -40,18 +42,19 @@ public class LocalMessageExtractor {
* Extract the viewable textual parts of a message and return the rest as attachments.
*
* @param context A {@link android.content.Context} instance that will be used to get localized strings.
* @param viewables
* @param attachments
* @return A {@link ViewableContainer} instance containing the textual parts of the message as
* plain text and HTML, and a list of message parts considered attachments.
*
* @throws com.fsck.k9.mail.MessagingException
* In case of an error.
*/
public static ViewableContainer extractTextAndAttachments(Context context, Message message) throws MessagingException {
public static ViewableContainer extractTextAndAttachments(Context context, List<Viewable> viewables,
List<Part> attachments) throws MessagingException {
try {
List<Part> attachments = new ArrayList<Part>();
// Collect all viewable parts
List<Viewable> viewables = MessageExtractor.getViewables(message, attachments);
/*
* Convert the tree of viewable parts into text and HTML
@ -412,10 +415,33 @@ public class LocalMessageExtractor {
}
public static MessageViewInfo decodeMessageForView(Context context, Message message) throws MessagingException {
//TODO: Modify extractTextAndAttachments() to only extract the text type (plain vs. HTML) we currently need.
ViewableContainer viewable = LocalMessageExtractor.extractTextAndAttachments(context, message);
List<AttachmentViewInfo> attachments = extractAttachmentInfos(viewable.attachments);
return new MessageViewInfo(viewable.html, attachments, message);
// 1. break mime structure on encryption/signature boundaries
ArrayList<Part> parts = new ArrayList<Part>();
// TODO: actually break it down
parts.add(message);
// parts.add(message);
// 2. extract viewables/attachments of parts
ArrayList<MessageViewContainer> containers = new ArrayList<MessageViewContainer>();
for (Part part : parts) {
ArrayList<Part> attachments = new ArrayList<Part>();
List<Viewable> viewables = MessageExtractor.getViewables(part, attachments);
// 3. parse viewables into html string
ViewableContainer viewable = LocalMessageExtractor.extractTextAndAttachments(context, viewables,
attachments);
List<AttachmentViewInfo> attachmentInfos = extractAttachmentInfos(attachments);
// TODO correctly extract OpenPgpSignatureResult and add to MessageViewContainer
OpenPgpSignatureResult result = null;
result = new OpenPgpSignatureResult(OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED, "lul", false, 0x123,
new ArrayList<String>());
containers.add(new MessageViewContainer(viewable.html, attachmentInfos, result, true, null));
}
return new MessageViewInfo(containers, message);
}
private static List<AttachmentViewInfo> extractAttachmentInfos(List<Part> attachmentParts)

View File

@ -1,20 +1,58 @@
package com.fsck.k9.mailstore;
import java.util.Collections;
import android.app.PendingIntent;
import java.util.ArrayList;
import java.util.List;
import com.fsck.k9.mail.Message;
import org.openintents.openpgp.OpenPgpSignatureResult;
public class MessageViewInfo {
public final String text;
public final List<AttachmentViewInfo> attachments;
public final Message message;
public final Message message;
public final List<MessageViewContainer> containers;
@Deprecated
public MessageViewInfo(String text, List<AttachmentViewInfo> attachments, Message message) {
this.text = text;
this.attachments = Collections.unmodifiableList(attachments);
containers = new ArrayList<MessageViewContainer>();
containers.add(new MessageViewContainer(text, attachments));
this.message = message;
}
public MessageViewInfo(List<MessageViewContainer> containers, Message message) {
this.containers = containers;
this.message = message;
}
public static class MessageViewContainer {
final public String text;
final public List<AttachmentViewInfo> attachments;
final public boolean encrypted;
final public OpenPgpSignatureResult signatureResult;
final public PendingIntent pgpPendingIntent;
MessageViewContainer(String text, List<AttachmentViewInfo> attachments) {
this.text = text;
this.attachments = attachments;
this.signatureResult = null;
this.encrypted = false;
this.pgpPendingIntent = null;
}
MessageViewContainer(String text, List<AttachmentViewInfo> attachments,
OpenPgpSignatureResult signatureResult, boolean encrypted,
PendingIntent pgpPendingIntent) {
this.text = text;
this.attachments = attachments;
this.signatureResult = signatureResult;
this.encrypted = encrypted;
this.pgpPendingIntent = pgpPendingIntent;
}
}
}

View File

@ -15,12 +15,12 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@ -32,38 +32,33 @@ import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewStub;
import android.webkit.WebView;
import android.webkit.WebView.HitTestResult;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.crypto.PgpData;
import com.fsck.k9.helper.ClipboardManager;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.helper.FileHelper;
import com.fsck.k9.helper.HtmlConverter;
import com.fsck.k9.helper.UrlEncodingHelper;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.Address;
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.AttachmentViewInfo;
import com.fsck.k9.mailstore.MessageViewInfo;
import com.fsck.k9.mailstore.MessageViewInfo.MessageViewContainer;
import com.fsck.k9.provider.AttachmentProvider.AttachmentProviderColumns;
import com.fsck.k9.view.MessageHeader;
import com.fsck.k9.view.MessageHeader.OnLayoutChangedListener;
import com.fsck.k9.view.MessageWebView;
import org.apache.commons.io.IOUtils;
public class SingleMessageView extends LinearLayout implements OnClickListener,
public class MessageContainerView extends LinearLayout implements OnClickListener,
OnLayoutChangedListener, OnCreateContextMenuListener {
private static final int MENU_ITEM_LINK_VIEW = Menu.FIRST;
private static final int MENU_ITEM_LINK_SHARE = Menu.FIRST + 1;
@ -87,10 +82,9 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
};
private static final int DISPLAY_NAME_INDEX = 1;
private MessageOpenPgpView mOpenPgpView;
private ViewStub mOpenPgpHeaderStub;
private View mSidebar;
private MessageWebView mMessageContentView;
private MessageHeader mHeaderContainer;
private LinearLayout mAttachments;
private Button mShowHiddenAttachments;
private LinearLayout mHiddenAttachments;
@ -99,10 +93,11 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
private View mShowAttachmentsAction;
private boolean mShowPictures;
private boolean mHasAttachments;
private Button mDownloadRemainder;
private boolean mHasOpenPgpInfo;
private LayoutInflater mInflater;
private Contacts mContacts;
private AttachmentViewCallback attachmentCallback;
private OpenPgpHeaderViewCallback openPgpHeaderViewCallback;
private View mAttachmentsContainer;
private SavedState mSavedState;
private ClipboardManager mClipboardManager;
@ -110,25 +105,26 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
private Map<AttachmentViewInfo, AttachmentView> attachments = new HashMap<AttachmentViewInfo, AttachmentView>();
public void initialize(Fragment fragment) {
public void initialize(Fragment fragment, AttachmentViewCallback attachmentCallback,
OpenPgpHeaderViewCallback openPgpHeaderViewCallback) {
this.attachmentCallback = attachmentCallback;
this.openPgpHeaderViewCallback = openPgpHeaderViewCallback;
mOpenPgpHeaderStub = (ViewStub) findViewById(R.id.openpgp_header_stub);
mSidebar = findViewById(R.id.message_sidebar);
Activity activity = fragment.getActivity();
mMessageContentView = (MessageWebView) findViewById(R.id.message_content);
mMessageContentView.configure();
activity.registerForContextMenu(mMessageContentView);
mMessageContentView.setOnCreateContextMenuListener(this);
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
mHeaderContainer.setOnLayoutChangedListener(this);
mAttachmentsContainer = findViewById(R.id.attachments_container);
mAttachments = (LinearLayout) findViewById(R.id.attachments);
mHiddenAttachments = (LinearLayout) findViewById(R.id.hidden_attachments);
mHiddenAttachments.setVisibility(View.GONE);
mShowHiddenAttachments = (Button) findViewById(R.id.show_hidden_attachments);
mShowHiddenAttachments.setVisibility(View.GONE);
mOpenPgpView = (MessageOpenPgpView) findViewById(R.id.layout_decrypt_openpgp);
mOpenPgpView.setFragment(fragment);
mOpenPgpView.setupChildViews();
mShowPicturesAction = findViewById(R.id.show_pictures);
mShowMessageAction = findViewById(R.id.show_message);
@ -139,23 +135,19 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
mContacts = Contacts.getInstance(activity);
mInflater = ((MessageViewFragment) fragment).getFragmentLayoutInflater();
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
mDownloadRemainder.setVisibility(View.GONE);
mAttachmentsContainer.setVisibility(View.GONE);
mMessageContentView.setVisibility(View.VISIBLE);
// the HTC version of WebView tries to force the background of the
// titlebar, which is really unfair.
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.messageViewHeaderBackgroundColor, outValue, true);
mHeaderContainer.setBackgroundColor(outValue.data);
// also set background of the whole view (including the attachments view)
setBackgroundColor(outValue.data);
mShowHiddenAttachments.setOnClickListener(this);
mShowMessageAction.setOnClickListener(this);
mShowAttachmentsAction.setOnClickListener(this);
mShowPicturesAction.setOnClickListener(this);
// mShowMessageAction.setOnClickListener(this);
// mShowAttachmentsAction.setOnClickListener(this);
// mShowPicturesAction.setOnClickListener(this);
mClipboardManager = ClipboardManager.getInstance(activity);
}
@ -382,14 +374,6 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
onShowHiddenAttachments();
break;
}
case R.id.show_message: {
onShowMessage();
break;
}
case R.id.show_attachments: {
onShowAttachments();
break;
}
case R.id.show_pictures: {
// Allow network access first...
setLoadPictures(true);
@ -405,21 +389,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
mHiddenAttachments.setVisibility(View.VISIBLE);
}
public void onShowMessage() {
showShowMessageAction(false);
showAttachments(false);
showShowAttachmentsAction(mHasAttachments);
showMessageWebView(true);
}
public void onShowAttachments() {
showMessageWebView(false);
showShowAttachmentsAction(false);
showShowMessageAction(true);
showAttachments(true);
}
public SingleMessageView(Context context, AttributeSet attrs) {
public MessageContainerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@ -446,58 +416,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
}
public void showShowPicturesAction(boolean show) {
mShowPicturesAction.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showShowMessageAction(boolean show) {
mShowMessageAction.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showShowAttachmentsAction(boolean show) {
mShowAttachmentsAction.setVisibility(show ? View.VISIBLE : View.GONE);
}
/**
* 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) {
try {
mHeaderContainer.populate(message, account);
mHeaderContainer.setVisibility(View.VISIBLE);
} catch (Exception me) {
Log.e(K9.LOG_TAG, "setHeaders - error", me);
}
}
public void setOnToggleFlagClickListener(OnClickListener listener) {
mHeaderContainer.setOnFlagListener(listener);
}
public void setOnDownloadButtonClickListener(OnClickListener listener) {
mDownloadRemainder.setOnClickListener(listener);
}
public void enableDownloadButton() {
mDownloadRemainder.setEnabled(true);
}
public void disableDownloadButton() {
mDownloadRemainder.setEnabled(false);
}
public void setShowDownloadButton(Message message) {
if (message.isSet(Flag.X_DOWNLOADED_FULL)) {
mDownloadRemainder.setVisibility(View.GONE);
} else {
mDownloadRemainder.setEnabled(true);
mDownloadRemainder.setVisibility(View.VISIBLE);
}
// mShowPicturesAction.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void enableAttachmentButtons() {
@ -512,36 +431,24 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
}
}
public void showAllHeaders() {
mHeaderContainer.onShowAdditionalHeaders();
}
public boolean additionalHeadersVisible() {
return mHeaderContainer.additionalHeadersVisible();
}
public void setMessage(Account account, MessageViewInfo messageViewInfo, PgpData pgpData)
public void setMessage(MessageViewContainer messageViewContainer)
throws MessagingException {
resetView();
String text = null;
if (pgpData != null) {
text = pgpData.getDecryptedData();
if (text != null) {
text = HtmlConverter.textToHtml(text);
}
}
// mHasOpenPgpInfo = (messageViewContainer.signatureResult != null
// || messageViewContainer.encrypted);
// if (mHasOpenPgpInfo) {
renderOpenPgpHeader(messageViewContainer);
mSidebar.setVisibility(View.VISIBLE);
if (text == null) {
text = messageViewInfo.text;
}
// }
// Save the text so we can reset the WebView when the user clicks the "Show pictures" button
mText = text;
mText = messageViewContainer.text;
mHasAttachments = !messageViewInfo.attachments.isEmpty();
mHasAttachments = !messageViewContainer.attachments.isEmpty();
if (mHasAttachments) {
renderAttachments(messageViewInfo);
renderAttachments(messageViewContainer);
}
mHiddenAttachments.setVisibility(View.GONE);
@ -553,27 +460,20 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
lookForImages = false;
}
if (mSavedState.attachmentViewVisible) {
onShowAttachments();
} else {
onShowMessage();
}
if (mSavedState.hiddenAttachmentsVisible) {
onShowHiddenAttachments();
}
mSavedState = null;
} else {
onShowMessage();
}
/*
if (text != null && lookForImages) {
// If the message contains external pictures and the "Show pictures"
// button wasn't already pressed, see if the user's preferences has us
// showing them anyway.
if (Utility.hasExternalImages(text) && !showPictures()) {
Address[] from = messageViewInfo.message.getFrom();
Address[] from = messageViewContainer.message.getFrom();
if ((account.getShowPictures() == Account.ShowPictures.ALWAYS) ||
((account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS) &&
// Make sure we have at least one from address
@ -585,11 +485,10 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
}
}
}
*/
if (text != null) {
loadBodyFromText(text);
mOpenPgpView.updateLayout(account, pgpData.getDecryptedData(),
pgpData.getSignatureResult(), messageViewInfo.message);
if (mText != null) {
loadBodyFromText(mText);
} else {
showStatusMessage(getContext().getString(R.string.webview_empty_message));
}
@ -604,18 +503,15 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
mMessageContentView.setText(emailText);
}
public void showAttachments(boolean show) {
mAttachmentsContainer.setVisibility(show ? View.VISIBLE : View.GONE);
boolean showHidden = (show && mHiddenAttachments.getVisibility() == View.GONE &&
mHiddenAttachments.getChildCount() > 0);
mShowHiddenAttachments.setVisibility(showHidden ? View.VISIBLE : View.GONE);
public void renderOpenPgpHeader(MessageViewContainer messageContainer) {
// inflate real header into stub
OpenPgpHeaderView view = (OpenPgpHeaderView) mOpenPgpHeaderStub.inflate();
view.setCallback(openPgpHeaderViewCallback);
view.setOpenPgpData(messageContainer.signatureResult, messageContainer.encrypted,
messageContainer.pgpPendingIntent);
}
public void showMessageWebView(boolean show) {
mMessageContentView.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void renderAttachments(MessageViewInfo messageContainer) throws MessagingException {
public void renderAttachments(MessageViewContainer messageContainer) throws MessagingException {
for (AttachmentViewInfo attachment : messageContainer.attachments) {
AttachmentView view = (AttachmentView) mInflater.inflate(R.layout.message_view_attachment, null);
view.setCallback(attachmentCallback);
@ -652,10 +548,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
}
public void resetView() {
mDownloadRemainder.setVisibility(View.GONE);
setLoadPictures(false);
showShowAttachmentsAction(false);
showShowMessageAction(false);
showShowPicturesAction(false);
mAttachments.removeAllViews();
mHiddenAttachments.removeAllViews();
@ -670,14 +563,6 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
loadBodyFromText("");
}
public void resetHeaderView() {
mHeaderContainer.setVisibility(View.GONE);
}
public void setAttachmentCallback(AttachmentViewCallback attachmentCallback) {
this.attachmentCallback = attachmentCallback;
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();

View File

@ -42,7 +42,7 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
public class MessageOpenPgpView extends LinearLayout {
public class MessageOpenPgpViewOld extends LinearLayout {
private Context mContext;
private MessageViewFragment mFragment;
@ -66,7 +66,7 @@ public class MessageOpenPgpView extends LinearLayout {
String mData;
Account mAccount;
public MessageOpenPgpView(Context context, AttributeSet attrs) {
public MessageOpenPgpViewOld(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
@ -127,7 +127,7 @@ public class MessageOpenPgpView extends LinearLayout {
if (decryptedData != null && signatureResult == null) {
// encrypted-only
MessageOpenPgpView.this.setBackgroundColor(mFragment.getResources().getColor(
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor(
R.color.openpgp_blue));
mText.setText(R.string.openpgp_successful_decryption);
@ -140,7 +140,7 @@ public class MessageOpenPgpView extends LinearLayout {
case OpenPgpSignatureResult.SIGNATURE_ERROR:
// TODO: signature error but decryption works?
mText.setText(R.string.openpgp_signature_invalid);
MessageOpenPgpView.this.setBackgroundColor(mFragment.getResources().getColor(
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor(
R.color.openpgp_red));
mGetKeyButton.setVisibility(View.GONE);
@ -155,7 +155,7 @@ public class MessageOpenPgpView extends LinearLayout {
else {
mText.setText(R.string.openpgp_successful_decryption_valid_signature_certified);
}
MessageOpenPgpView.this.setBackgroundColor(mFragment.getResources().getColor(
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor(
R.color.openpgp_green));
mGetKeyButton.setVisibility(View.GONE);
@ -172,7 +172,7 @@ public class MessageOpenPgpView extends LinearLayout {
else {
mText.setText(R.string.openpgp_successful_decryption_unknown_signature);
}
MessageOpenPgpView.this.setBackgroundColor(mFragment.getResources().getColor(
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor(
R.color.openpgp_orange));
mGetKeyButton.setVisibility(View.VISIBLE);
@ -189,7 +189,7 @@ public class MessageOpenPgpView extends LinearLayout {
else {
mText.setText(R.string.openpgp_successful_decryption_valid_signature_uncertified);
}
MessageOpenPgpView.this.setBackgroundColor(mFragment.getResources().getColor(
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor(
R.color.openpgp_orange));
mGetKeyButton.setVisibility(View.GONE);
@ -229,7 +229,7 @@ public class MessageOpenPgpView extends LinearLayout {
private void decryptAndVerify(final Message message) {
this.setVisibility(View.VISIBLE);
mProgress.setVisibility(View.VISIBLE);
MessageOpenPgpView.this.setBackgroundColor(mFragment.getResources().getColor(
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor(
R.color.openpgp_orange));
mText.setText(R.string.openpgp_decrypting_verifying);
@ -393,7 +393,7 @@ public class MessageOpenPgpView extends LinearLayout {
mText.setText(mFragment.getString(R.string.openpgp_error) + " "
+ error.getMessage());
MessageOpenPgpView.this.setBackgroundColor(mFragment.getResources().getColor(
MessageOpenPgpViewOld.this.setBackgroundColor(mFragment.getResources().getColor(
R.color.openpgp_red));
}
});

View File

@ -0,0 +1,136 @@
package com.fsck.k9.ui.messageview;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.crypto.PgpData;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mailstore.MessageViewInfo;
import com.fsck.k9.mailstore.MessageViewInfo.MessageViewContainer;
import com.fsck.k9.view.MessageHeader;
public class MessageTopView extends LinearLayout {
private MessageHeader mHeaderContainer;
private LayoutInflater mInflater;
private LinearLayout containerViews;
private Fragment fragment;
private Button mDownloadRemainder;
private AttachmentViewCallback attachmentCallback;
private OpenPgpHeaderViewCallback openPgpHeaderViewCallback;
public MessageTopView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void initialize (Fragment fragment, AttachmentViewCallback attachmentCallback,
OpenPgpHeaderViewCallback openPgpHeaderViewCallback) {
this.fragment = fragment;
this.attachmentCallback = attachmentCallback;
this.openPgpHeaderViewCallback = openPgpHeaderViewCallback;
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
// mHeaderContainer.setOnLayoutChangedListener(this);
mInflater = ((MessageViewFragment) fragment).getFragmentLayoutInflater();
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.messageViewHeaderBackgroundColor, outValue, true);
mHeaderContainer.setBackgroundColor(outValue.data);
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
mDownloadRemainder.setVisibility(View.GONE);
containerViews = (LinearLayout) findViewById(R.id.message_containers);
}
public void resetView() {
mDownloadRemainder.setVisibility(View.GONE);
containerViews.removeAllViews();
}
public void setMessage(Account account, MessageViewInfo messageViewInfo)
throws MessagingException {
resetView();
for (MessageViewContainer container : messageViewInfo.containers) {
MessageContainerView view = (MessageContainerView) mInflater.inflate(R.layout.message_container, null);
view.initialize(fragment, attachmentCallback, openPgpHeaderViewCallback);
view.setMessage(container);
containerViews.addView(view);
}
}
/**
* 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) {
try {
mHeaderContainer.populate(message, account);
mHeaderContainer.setVisibility(View.VISIBLE);
} catch (Exception me) {
Log.e(K9.LOG_TAG, "setHeaders - error", me);
}
}
public void setOnToggleFlagClickListener(OnClickListener listener) {
mHeaderContainer.setOnFlagListener(listener);
}
public void showAllHeaders() {
mHeaderContainer.onShowAdditionalHeaders();
}
public boolean additionalHeadersVisible() {
return mHeaderContainer.additionalHeadersVisible();
}
public void resetHeaderView() {
mHeaderContainer.setVisibility(View.GONE);
}
public void setOnDownloadButtonClickListener(OnClickListener listener) {
mDownloadRemainder.setOnClickListener(listener);
}
public void enableDownloadButton() {
mDownloadRemainder.setEnabled(true);
}
public void disableDownloadButton() {
mDownloadRemainder.setEnabled(false);
}
public void setShowDownloadButton(Message message) {
if (message.isSet(Flag.X_DOWNLOADED_FULL)) {
mDownloadRemainder.setVisibility(View.GONE);
} else {
mDownloadRemainder.setEnabled(true);
mDownloadRemainder.setVisibility(View.VISIBLE);
}
}
}

View File

@ -16,8 +16,10 @@ import android.app.Fragment;
import android.app.FragmentManager;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.Loader;
import android.net.Uri;
import android.os.AsyncTask;
@ -74,7 +76,7 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection.OnBound;
public class MessageViewFragment extends Fragment implements ConfirmationDialogFragmentListener,
AttachmentViewCallback {
AttachmentViewCallback, OpenPgpHeaderViewCallback {
private static final String ARG_REFERENCE = "reference";
@ -100,7 +102,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
}
private SingleMessageView mMessageView;
private MessageTopView mMessageView;
private PgpData mPgpData;
private Account mAccount;
private MessageReference mMessageReference;
@ -170,17 +172,16 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
View view = mLayoutInflater.inflate(R.layout.message, container, false);
mMessageView = (SingleMessageView) view.findViewById(R.id.message_view);
mMessageView = (MessageTopView) view.findViewById(R.id.message_view);
mMessageView.setAttachmentCallback(this);
mMessageView.initialize(this);
mMessageView.initialize(this, this, this);
mMessageView.setOnToggleFlagClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onToggleFlagged();
}
});
mMessageView.setOnDownloadButtonClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@ -420,7 +421,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
}
private void onLoadMessageFromDatabaseFailed() {
mMessageView.showStatusMessage(mContext.getString(R.string.status_invalid_id_error));
// mMessageView.showStatusMessage(mContext.getString(R.string.status_invalid_id_error));
}
private void startDownloadingMessageBody(LocalMessage message) {
@ -460,7 +461,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
private void showMessage(MessageViewInfo messageContainer) {
try {
mMessageView.setMessage(mAccount, messageContainer, mPgpData);
mMessageView.setMessage(mAccount, messageContainer);
mMessageView.setShowDownloadButton(mMessage);
} catch (MessagingException e) {
Log.e(K9.LOG_TAG, "Error while trying to display message", e);
@ -597,7 +598,8 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
}
public void onSelectText() {
mMessageView.beginSelectingText();
// FIXME
// mMessageView.beginSelectingText();
}
private void startRefileActivity(int activity) {
@ -609,7 +611,6 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
startActivityForResult(intent, activity);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
@ -724,7 +725,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
PgpData data = new PgpData();
data.setDecryptedData(decryptedData);
data.setSignatureResult(signatureResult);
mMessageView.setMessage(mAccount, messageViewInfo, data);
mMessageView.setMessage(mAccount, messageViewInfo);
} catch (MessagingException e) {
Log.e(K9.LOG_TAG, "displayMessageBody failed", e);
}
@ -791,7 +792,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
}
public void zoom(KeyEvent event) {
mMessageView.zoom(event);
// mMessageView.zoom(event);
}
@Override
@ -859,11 +860,11 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
}
public void disableAttachmentButtons(AttachmentViewInfo attachment) {
mMessageView.disableAttachmentButtons(attachment);
// mMessageView.disableAttachmentButtons(attachment);
}
public void enableAttachmentButtons(AttachmentViewInfo attachment) {
mMessageView.enableAttachmentButtons(attachment);
// mMessageView.enableAttachmentButtons(attachment);
}
public void runOnMainThread(Runnable runnable) {
@ -871,7 +872,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
}
public void showAttachmentLoadingDialog() {
mMessageView.disableAttachmentButtons();
// mMessageView.disableAttachmentButtons();
showDialog(R.id.dialog_attachment_progress);
}
@ -880,13 +881,24 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
@Override
public void run() {
removeDialog(R.id.dialog_attachment_progress);
mMessageView.enableAttachmentButtons();
// mMessageView.enableAttachmentButtons();
}
});
}
public void refreshAttachmentThumbnail(AttachmentViewInfo attachment) {
mMessageView.refreshAttachmentThumbnail(attachment);
// mMessageView.refreshAttachmentThumbnail(attachment);
}
@Override
public void onPgpSignatureButtonClick(PendingIntent pendingIntent) {
try {
getActivity().startIntentSenderForResult(
pendingIntent.getIntentSender(),
42, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.e(K9.LOG_TAG, "SendIntentException", e);
}
}
public interface MessageViewFragmentListener {

View File

@ -0,0 +1,296 @@
package com.fsck.k9.ui.messageview;
import android.app.PendingIntent;
import android.content.Context;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.fsck.k9.R;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpUtils;
public class OpenPgpHeaderView extends LinearLayout {
private Context mContext;
private OpenPgpHeaderViewCallback callback;
private OpenPgpSignatureResult signatureResult;
private boolean encrypted;
private PendingIntent pendingIntent;
private ImageView mResultEncryptionIcon;
private TextView mResultEncryptionText;
private ImageView mResultSignatureIcon;
private TextView mResultSignatureText;
private LinearLayout mResultSignatureLayout;
private TextView mResultSignatureName;
private TextView mResultSignatureEmail;
private Button mResultSignatureButton;
public OpenPgpHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public void setOpenPgpData(OpenPgpSignatureResult signatureResult,
boolean encrypted, PendingIntent pendingIntent) {
this.signatureResult = signatureResult;
this.encrypted = encrypted;
this.pendingIntent = pendingIntent;
displayOpenPgpView();
}
public void setCallback(OpenPgpHeaderViewCallback callback) {
this.callback = callback;
}
public void displayOpenPgpView() {
mResultEncryptionIcon = (ImageView) findViewById(R.id.result_encryption_icon);
mResultEncryptionText = (TextView) findViewById(R.id.result_encryption_text);
mResultSignatureIcon = (ImageView) findViewById(R.id.result_signature_icon);
mResultSignatureText = (TextView) findViewById(R.id.result_signature_text);
mResultSignatureLayout = (LinearLayout) findViewById(R.id.result_signature_layout);
mResultSignatureName = (TextView) findViewById(R.id.result_signature_name);
mResultSignatureEmail = (TextView) findViewById(R.id.result_signature_email);
mResultSignatureButton = (Button) findViewById(R.id.result_signature_button);
mResultSignatureButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
callback.onPgpSignatureButtonClick(pendingIntent);
}
});
if (encrypted) {
setStatusImage(mContext, mResultEncryptionIcon, mResultEncryptionText, STATE_ENCRYPTED);
mResultEncryptionText.setText(R.string.openpgp_result_encrypted);
} else {
setStatusImage(mContext, mResultEncryptionIcon, mResultEncryptionText, STATE_NOT_ENCRYPTED);
mResultEncryptionText.setText(R.string.openpgp_result_not_encrypted);
}
if (signatureResult == null) {
setStatusImage(mContext, mResultSignatureIcon, mResultSignatureText, STATE_NOT_SIGNED);
mResultSignatureText.setText(R.string.openpgp_result_no_signature);
mResultSignatureLayout.setVisibility(View.GONE);
} else {
switch (signatureResult.getStatus()) {
case OpenPgpSignatureResult.SIGNATURE_ERROR: {
setStatusImage(mContext, mResultSignatureIcon, mResultSignatureText, STATE_INVALID);
mResultSignatureText.setText(R.string.openpgp_result_invalid_signature);
mResultSignatureButton.setVisibility(View.GONE);
mResultSignatureLayout.setVisibility(View.GONE);
break;
}
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: {
setStatusImage(mContext, mResultSignatureIcon, mResultSignatureText, STATE_VERIFIED);
mResultSignatureText.setText(R.string.openpgp_result_signature_certified);
setUserId(signatureResult);
mResultSignatureButton.setText(R.string.openpgp_result_action_show);
mResultSignatureButton.setVisibility(View.VISIBLE);
mResultSignatureLayout.setVisibility(View.VISIBLE);
break;
}
case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: {
setStatusImage(mContext, mResultSignatureIcon, mResultSignatureText, STATE_UNKNOWN_KEY);
mResultSignatureText.setText(R.string.openpgp_result_signature_missing_key);
setUserId(signatureResult);
mResultSignatureButton.setText(R.string.openpgp_result_action_lookup);
mResultSignatureButton.setVisibility(View.VISIBLE);
mResultSignatureLayout.setVisibility(View.VISIBLE);
break;
}
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: {
setStatusImage(mContext, mResultSignatureIcon, mResultSignatureText, STATE_UNVERIFIED);
mResultSignatureText.setText(R.string.openpgp_result_signature_uncertified);
setUserId(signatureResult);
mResultSignatureButton.setText(R.string.openpgp_result_action_show);
mResultSignatureButton.setVisibility(View.VISIBLE);
mResultSignatureLayout.setVisibility(View.VISIBLE);
break;
}
case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: {
setStatusImage(mContext, mResultSignatureIcon, mResultSignatureText, STATE_EXPIRED);
mResultSignatureText.setText(R.string.openpgp_result_signature_expired_key);
setUserId(signatureResult);
mResultSignatureButton.setText(R.string.openpgp_result_action_show);
mResultSignatureButton.setVisibility(View.VISIBLE);
mResultSignatureLayout.setVisibility(View.VISIBLE);
break;
}
case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: {
setStatusImage(mContext, mResultSignatureIcon, mResultSignatureText, STATE_REVOKED);
mResultSignatureText.setText(R.string.openpgp_result_signature_revoked_key);
setUserId(signatureResult);
mResultSignatureButton.setText(R.string.openpgp_result_action_show);
mResultSignatureButton.setVisibility(View.VISIBLE);
mResultSignatureLayout.setVisibility(View.VISIBLE);
break;
}
default:
break;
}
}
}
private void setUserId(OpenPgpSignatureResult signatureResult) {
String[] splitUserId = OpenPgpUtils.splitUserId(signatureResult.getPrimaryUserId());
if (splitUserId[0] != null) {
mResultSignatureName.setText(splitUserId[0]);
} else {
mResultSignatureName.setText(R.string.openpgp_result_no_name);
}
if (splitUserId[1] != null) {
mResultSignatureEmail.setText(splitUserId[1]);
} else {
mResultSignatureEmail.setText(R.string.openpgp_result_no_email);
}
}
public static final int STATE_REVOKED = 1;
public static final int STATE_EXPIRED = 2;
public static final int STATE_VERIFIED = 3;
public static final int STATE_UNAVAILABLE = 4;
public static final int STATE_ENCRYPTED = 5;
public static final int STATE_NOT_ENCRYPTED = 6;
public static final int STATE_UNVERIFIED = 7;
public static final int STATE_UNKNOWN_KEY = 8;
public static final int STATE_INVALID = 9;
public static final int STATE_NOT_SIGNED = 10;
public static void setStatusImage(Context context, ImageView statusIcon, int state) {
setStatusImage(context, statusIcon, null, state);
}
/**
* Sets status image based on constant
*/
public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText,
int state) {
switch (state) {
/** GREEN: everything is good **/
case STATE_VERIFIED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_verified_cutout));
int color = R.color.openpgp_green;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
case STATE_ENCRYPTED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_lock_closed));
int color = R.color.openpgp_green;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
/** ORANGE: mostly bad... **/
case STATE_UNVERIFIED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout));
int color = R.color.openpgp_orange;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
case STATE_UNKNOWN_KEY: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout));
int color = R.color.openpgp_orange;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
/** RED: really bad... **/
case STATE_REVOKED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout));
int color = R.color.openpgp_red;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
case STATE_EXPIRED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_expired_cutout));
int color = R.color.openpgp_red;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
case STATE_NOT_ENCRYPTED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_lock_open));
int color = R.color.openpgp_red;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
case STATE_NOT_SIGNED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout));
int color = R.color.openpgp_red;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
case STATE_INVALID: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout));
int color = R.color.openpgp_red;
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(color));
}
break;
}
}
}
}

View File

@ -0,0 +1,9 @@
package com.fsck.k9.ui.messageview;
import android.app.PendingIntent;
interface OpenPgpHeaderViewCallback {
void onPgpSignatureButtonClick(PendingIntent pendingIntent);
}

View File

@ -16,7 +16,6 @@ import com.fsck.k9.helper.HtmlSanitizer;
public class MessageWebView extends RigidWebView {
public MessageWebView(Context context) {
super(context);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1008 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fsck.k9.ui.messageview.SingleMessageView
<com.fsck.k9.ui.messageview.MessageTopView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/message_view"
android:orientation="vertical"
@ -20,41 +20,11 @@
<!-- Header area -->
<include layout="@layout/message_view_header"/>
<!-- Content area -->
<com.fsck.k9.view.MessageWebView
android:id="@+id/message_content"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<!-- Attachments area -->
<LinearLayout
android:id="@+id/attachments_container"
android:orientation="vertical"
android:id="@+id/message_containers"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/attachments"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" />
<Button
android:id="@+id/show_hidden_attachments"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/message_view_show_more_attachments_action"/>
<LinearLayout
android:id="@+id/hidden_attachments"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip"/>
</LinearLayout>
android:layout_height="wrap_content" />
</LinearLayout>
@ -66,4 +36,4 @@
android:visibility="gone"
android:layout_width="fill_parent"/>
</com.fsck.k9.ui.messageview.SingleMessageView>
</com.fsck.k9.ui.messageview.MessageTopView>

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fsck.k9.ui.messageview.MessageContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- OpenPGP header -->
<ViewStub
android:id="@+id/openpgp_header_stub"
android:inflatedId="@+id/openpgp_header"
android:layout="@layout/message_view_openpgp_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- sidebar -->
<View
android:id="@+id/message_sidebar"
android:layout_width="4dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="4dp"
android:layout_height="match_parent"
android:background="@color/openpgp_sidebar"
android:visibility="gone"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Content area -->
<com.fsck.k9.view.MessageWebView
android:id="@+id/message_content"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<!-- Attachments area -->
<LinearLayout
android:id="@+id/attachments_container"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/attachments"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" />
<Button
android:id="@+id/show_hidden_attachments"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/message_view_show_more_attachments_action" />
<LinearLayout
android:id="@+id/hidden_attachments"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.fsck.k9.ui.messageview.MessageContainerView>

View File

@ -250,6 +250,6 @@
</LinearLayout>
<include layout="@layout/message_view_openpgp_layout"/>
<include layout="@layout/message_view_openpgp_layout_old"/>
</com.fsck.k9.view.MessageHeader>

View File

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fsck.k9.ui.messageview.OpenPgpHeaderView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_decrypt_openpgp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="4dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/result_encryption_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/status_lock_open"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/result_encryption_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Not Encrypted (set in-code)"
android:layout_marginLeft="4dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/result_signature_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/status_signature_unverified_cutout"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/result_signature_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Signed by (set in-code)"
android:layout_marginLeft="4dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="4dp"
android:layout_marginLeft="8dp"
android:layout_height="match_parent"
android:background="@color/openpgp_sidebar" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/result_signature_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:layout_marginLeft="14dp"
android:paddingRight="4dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingRight="4dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/result_signature_name"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Alice (set in-code)" />
<TextView
android:id="@+id/result_signature_email"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="alice@example.com (set in-code)"
android:gravity="center_vertical" />
</LinearLayout>
<Button
android:id="@+id/result_signature_button"
android:paddingLeft="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show"
android:drawablePadding="8dp"
android:gravity="center_vertical" />
</LinearLayout>
<View
android:id="@+id/result_signature_divider2"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@color/openpgp_sidebar" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.fsck.k9.ui.messageview.OpenPgpHeaderView>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fsck.k9.ui.messageview.MessageOpenPgpView xmlns:android="http://schemas.android.com/apk/res/android"
<com.fsck.k9.ui.messageview.MessageOpenPgpViewOld xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_decrypt_openpgp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -88,4 +88,4 @@
android:padding="4dp"
android:visibility="gone" />
</com.fsck.k9.ui.messageview.MessageOpenPgpView>
</com.fsck.k9.ui.messageview.MessageOpenPgpViewOld>

View File

@ -6,4 +6,6 @@
<color name="openpgp_orange">#FF8800</color>
<color name="openpgp_green">#669900</color>
<color name="openpgp_blue">#336699</color>
<color name="openpgp_sidebar">#D8D8D8</color>
</resources>

View File

@ -1117,6 +1117,20 @@ Please submit bug reports, contribute new features and ask questions at
<string name="openpgp_error">OpenPGP Error:</string>
<string name="openpgp_user_id">User Id</string>
<string name="openpgp_result_no_signature">"Not Signed"</string>
<string name="openpgp_result_invalid_signature">"Invalid signature!"</string>
<string name="openpgp_result_signature_uncertified">"Signed by (not certified!)"</string>
<string name="openpgp_result_signature_certified">"Signed by"</string>
<string name="openpgp_result_signature_expired_key">"Key is expired!"</string>
<string name="openpgp_result_signature_revoked_key">"Key has been revoked!"</string>
<string name="openpgp_result_signature_missing_key">"Unknown public key"</string>
<string name="openpgp_result_encrypted">"Encrypted"</string>
<string name="openpgp_result_not_encrypted">"Not Encrypted"</string>
<string name="openpgp_result_action_show">"Show"</string>
<string name="openpgp_result_action_lookup">"Lookup"</string>
<string name="openpgp_result_no_name">"No name"</string>
<string name="openpgp_result_no_email">"No email"</string>
<!-- === Client certificates specific ================================================================== -->
<string name="account_setup_basics_client_certificate">Use client certificate</string>
<string name="client_certificate_spinner_empty">No client certificate</string>

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,7 +41,7 @@ public class OpenPgpApi {
* ---------------
* <p/>
* 3:
* - first public stable version
* - First public stable version
* <p/>
* 4:
* - No changes to existing methods -> backward compatible
@ -50,8 +50,14 @@ public class OpenPgpApi {
* 5:
* - OpenPgpSignatureResult: new consts SIGNATURE_KEY_REVOKED and SIGNATURE_KEY_EXPIRED
* - OpenPgpSignatureResult: ArrayList<String> userIds
* 6:
* - Deprecate ACTION_SIGN
* - Introduce ACTION_CLEARTEXT_SIGN and ACTION_DETACHED_SIGN
* - New extra for ACTION_DETACHED_SIGN: EXTRA_DETACHED_SIGNATURE
* - New result for ACTION_DECRYPT_VERIFY: RESULT_DETACHED_SIGNATURE
* - New result for ACTION_DECRYPT_VERIFY: RESULT_CHARSET
*/
public static final int API_VERSION = 5;
public static final int API_VERSION = 6;
/**
* General extras
@ -90,7 +96,7 @@ public class OpenPgpApi {
/**
* Sign text or binary data resulting in a detached signature.
* No OutputStream for ACTION_DETACHED_SIGN (No magic pre-processing like in ACTION_CLEARTEXT_SIGN)!
* No OutputStream necessary for ACTION_DETACHED_SIGN (No magic pre-processing like in ACTION_CLEARTEXT_SIGN)!
* The detached signature is returned separately in RESULT_DETACHED_SIGNATURE.
* <p/>
* optional extras:
@ -135,17 +141,18 @@ public class OpenPgpApi {
/**
* Decrypts and verifies given input stream. This methods handles encrypted-only, signed-and-encrypted,
* and also signed-only input.
* OutputStream is optional, e.g., for verifying detached signatures!
* <p/>
* If OpenPgpSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING
* in addition a PendingIntent is returned via RESULT_INTENT to download missing keys.
* <p/>
* optional extras:
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
* byte[] EXTRA_DETACHED_SIGNATURE (detached signature)
* <p/>
* returned extras:
* OpenPgpSignatureResult RESULT_SIGNATURE
* OpenPgpDecryptMetadata RESULT_METADATA
* String RESULT_CHARSET (charset which was specified in the headers of ascii armored input, if any)
*/
public static final String ACTION_DECRYPT_VERIFY = "org.openintents.openpgp.action.DECRYPT_VERIFY";
@ -156,6 +163,7 @@ public class OpenPgpApi {
* <p/>
* returned extras:
* OpenPgpDecryptMetadata RESULT_METADATA
* String RESULT_CHARSET (charset which was specified in the headers of ascii armored input, if any)
*/
public static final String ACTION_DECRYPT_METADATA = "org.openintents.openpgp.action.DECRYPT_METADATA";

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -73,4 +73,39 @@ public class OpenPgpUtils {
}
return hexString;
}
private static final Pattern USER_ID_PATTERN = Pattern.compile("^(.*?)(?: \\((.*)\\))?(?: <(.*)>)?$");
/**
* Splits userId string into naming part, email part, and comment part
*
* @param userId
* @return array with naming (0), email (1), comment (2)
*/
public static String[] splitUserId(String userId) {
String[] result = new String[]{null, null, null};
if (userId == null || userId.equals("")) {
return result;
}
/*
* User ID matching:
* http://fiddle.re/t4p6f
*
* test cases:
* "Max Mustermann (this is a comment) <max@example.com>"
* "Max Mustermann <max@example.com>"
* "Max Mustermann (this is a comment)"
* "Max Mustermann [this is nothing]"
*/
Matcher matcher = USER_ID_PATTERN.matcher(userId);
if (matcher.matches()) {
result[0] = matcher.group(1);
result[1] = matcher.group(3);
result[2] = matcher.group(2);
}
return result;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
* 2013 Florian Schmaus <flo@geekplace.eu>
*
* Licensed under the Apache License, Version 2.0 (the "License");