Merge branch 'master' of https://github.com/k9mail/k-9
This commit is contained in:
commit
42edb24c4b
14 changed files with 617 additions and 453 deletions
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="13001"
|
||||
android:versionName="3.701" package="com.fsck.k9"
|
||||
android:versionCode="13002"
|
||||
android:versionName="3.702" package="com.fsck.k9"
|
||||
>
|
||||
<uses-sdk
|
||||
android:minSdkVersion="3"
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<com.fsck.k9.view.SingleMessageView
|
||||
android:id="@+id/message_view"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Header area -->
|
||||
<com.fsck.k9.view.MessageHeader
|
||||
android:id="@+id/header_container"
|
||||
|
@ -216,4 +223,4 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_width="fill_parent" />
|
||||
</merge>
|
||||
</com.fsck.k9.view.SingleMessageView>
|
|
@ -18,13 +18,9 @@
|
|||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
<include layout="@layout/message_view_header" />
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1" />
|
||||
<include layout="@layout/message" />
|
||||
<include layout="@layout/message_view_scrolling_buttons"/>
|
||||
</LinearLayout>
|
||||
</com.fsck.k9.view.ToggleScrollView>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<com.fsck.k9.view.MessageCryptoView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/layout_decrypt"
|
||||
android:orientation="horizontal"
|
||||
|
@ -55,4 +55,4 @@
|
|||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
</com.fsck.k9.view.MessageCryptoView>
|
||||
|
|
|
@ -1,88 +1,88 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<LinearLayout
|
||||
android:id="@+id/extra_buttons"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
<LinearLayout
|
||||
android:id="@+id/extra_buttons"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="2dip"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/reply"
|
||||
android:text="@string/reply_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="2dip"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/reply"
|
||||
android:text="@string/reply_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
<Button
|
||||
android:id="@+id/reply_all"
|
||||
android:text="@string/reply_all_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
<Button
|
||||
android:id="@+id/forward"
|
||||
android:text="@string/forward_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/scrolling_move_buttons"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
<Button
|
||||
android:id="@+id/reply_all"
|
||||
android:text="@string/reply_all_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="2dip"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/archive_scrolling"
|
||||
android:text="@string/message_view_archive_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/move_scrolling"
|
||||
android:text="@string/message_view_move_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/spam_scrolling"
|
||||
android:text="@string/message_view_spam_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/scrolling_buttons"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
<Button
|
||||
android:id="@+id/forward"
|
||||
android:text="@string/forward_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/previous_scrolling"
|
||||
android:text="@string/message_view_prev_action"
|
||||
android:contentDescription="@string/previous_action"
|
||||
android:textSize="35dip"
|
||||
android:padding="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/scrolling_move_buttons"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="2dip"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/archive_scrolling"
|
||||
android:text="@string/message_view_archive_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/delete_scrolling"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_button_delete"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
<Button
|
||||
android:id="@+id/next_scrolling"
|
||||
android:padding="0dip"
|
||||
android:text="@string/message_view_next_action"
|
||||
android:textSize="35dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
<Button
|
||||
android:id="@+id/move_scrolling"
|
||||
android:text="@string/message_view_move_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/spam_scrolling"
|
||||
android:text="@string/message_view_spam_action"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/scrolling_buttons"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/previous_scrolling"
|
||||
android:text="@string/message_view_prev_action"
|
||||
android:contentDescription="@string/previous_action"
|
||||
android:textSize="35dip"
|
||||
android:padding="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/delete_scrolling"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_button_delete"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
<Button
|
||||
android:id="@+id/next_scrolling"
|
||||
android:padding="0dip"
|
||||
android:text="@string/message_view_next_action"
|
||||
android:textSize="35dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
</merge>
|
||||
|
|
|
@ -683,6 +683,8 @@ public class Account implements BaseAccount {
|
|||
switchLocalStorage(id);
|
||||
successful = true;
|
||||
} catch (MessagingException e) {
|
||||
Log.e(K9.LOG_TAG, "Switching local storage provider from " +
|
||||
mLocalStorageProviderId + " to " + id + " failed.", e);
|
||||
} finally {
|
||||
// if migration to/from SD-card failed once, it will fail again.
|
||||
if (!successful) {
|
||||
|
|
|
@ -299,6 +299,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
finish();
|
||||
} else if (startup && accounts.length == 1 && onOpenAccount(accounts[0])) {
|
||||
// fall through to "else" if !onOpenAccount()
|
||||
finish();
|
||||
} else {
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
|
|
|
@ -20,20 +20,15 @@ import android.widget.*;
|
|||
import com.fsck.k9.*;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.*;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mail.store.LocalStore.LocalAttachmentBodyPart;
|
||||
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
|
||||
import com.fsck.k9.mail.store.StorageManager;
|
||||
import com.fsck.k9.view.AccessibleWebView;
|
||||
import com.fsck.k9.view.AttachmentView;
|
||||
import com.fsck.k9.view.MessageWebView;
|
||||
import com.fsck.k9.view.ToggleScrollView;
|
||||
import com.fsck.k9.view.MessageHeader;
|
||||
import com.fsck.k9.view.SingleMessageView;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
@ -46,22 +41,15 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
private static final String STATE_PGP_DATA = "pgpData";
|
||||
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
|
||||
private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2;
|
||||
private View mDecryptLayout;
|
||||
private Button mDecryptButton;
|
||||
private LinearLayout mCryptoSignatureLayout = null;
|
||||
private ImageView mCryptoSignatureStatusImage = null;
|
||||
private TextView mCryptoSignatureUserId = null;
|
||||
private TextView mCryptoSignatureUserIdRest = null;
|
||||
private MessageWebView mMessageContentView;
|
||||
private boolean mScreenReaderEnabled;
|
||||
private AccessibleWebView mAccessibleMessageContentView;
|
||||
private MessageHeader mHeaderContainer;
|
||||
private LinearLayout mAttachments;
|
||||
private View mShowPicturesSection;
|
||||
private boolean mShowPictures;
|
||||
private Button mDownloadRemainder;
|
||||
View next;
|
||||
View previous;
|
||||
|
||||
|
||||
private SingleMessageView mMessageView;
|
||||
|
||||
private PgpData mPgpData;
|
||||
|
||||
|
||||
private View mNext;
|
||||
private View mPrevious;
|
||||
private View mDelete;
|
||||
private View mArchive;
|
||||
private View mMove;
|
||||
|
@ -71,14 +59,12 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
private MessageReference mMessageReference;
|
||||
private ArrayList<MessageReference> mMessageReferences;
|
||||
private Message mMessage;
|
||||
private PgpData mPgpData = null;
|
||||
private static final int PREVIOUS = 1;
|
||||
private static final int NEXT = 2;
|
||||
private int mLastDirection = PREVIOUS;
|
||||
private MessagingController mController = MessagingController.getInstance(getApplication());
|
||||
private MessageReference mNextMessage = null;
|
||||
private MessageReference mPreviousMessage = null;
|
||||
private Menu optionsMenu = null;
|
||||
private Listener mListener = new Listener();
|
||||
private MessageViewHandler mHandler = new MessageViewHandler();
|
||||
private Contacts mContacts;
|
||||
|
@ -209,15 +195,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
case KeyEvent.KEYCODE_Z: {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (mScreenReaderEnabled) {
|
||||
mAccessibleMessageContentView.zoomIn();
|
||||
} else {
|
||||
if (event.isShiftPressed()) {
|
||||
mMessageContentView.zoomIn();
|
||||
} else {
|
||||
mMessageContentView.zoomOut();
|
||||
}
|
||||
}
|
||||
mMessageView.zoom(event);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
@ -245,31 +223,6 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
}
|
||||
|
||||
class MessageViewHandler extends Handler {
|
||||
public void setHeaders(final Message message) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
mHeaderContainer.populate(message, mAccount);
|
||||
mHeaderContainer.setOnFlagListener(new OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if (mMessage != null) {
|
||||
onFlag();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception me) {
|
||||
Log.e(K9.LOG_TAG, "setHeaders - error", me);
|
||||
}
|
||||
if (mMessage.isSet(Flag.X_DOWNLOADED_FULL)) {
|
||||
mDownloadRemainder.setVisibility(View.GONE);
|
||||
} else {
|
||||
mDownloadRemainder.setEnabled(true);
|
||||
mDownloadRemainder.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void progress(final boolean progress) {
|
||||
runOnUiThread(new Runnable() {
|
||||
|
@ -282,8 +235,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
public void addAttachment(final View attachmentView) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
mAttachments.addView(attachmentView);
|
||||
mAttachments.setVisibility(View.VISIBLE);
|
||||
mMessageView.addAttachment(attachmentView);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -291,32 +243,16 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
public void removeAllAttachments() {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
mAttachments.removeView(mAttachments.getChildAt(i));
|
||||
}
|
||||
mMessageView.removeAllAttachments();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void setAttachmentsEnabled(final boolean enabled) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
AttachmentView attachment = (AttachmentView) mAttachments.getChildAt(i);
|
||||
attachment.viewButton.setEnabled(enabled);
|
||||
attachment.downloadButton.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void networkError() {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Toast.makeText(MessageView.this,
|
||||
R.string.status_network_error, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(MessageView.this, R.string.status_network_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -324,8 +260,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
public void invalidIdError() {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Toast.makeText(MessageView.this,
|
||||
R.string.status_invalid_id_error, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(MessageView.this, R.string.status_invalid_id_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -344,13 +279,22 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
public void showShowPictures(final boolean show) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
mShowPicturesSection.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
mMessageView.showShowPicturesSection(show);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setHeaders(final Message message, final Account account) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
mMessageView.setHeaders(message, account);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void actionView(Context context, MessageReference messRef, List<MessageReference> messReferences) {
|
||||
actionView(context, messRef, messReferences, null);
|
||||
}
|
||||
|
@ -372,22 +316,11 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.message_view);
|
||||
mMessageContentView = (MessageWebView) findViewById(R.id.message_content);
|
||||
mAccessibleMessageContentView = (AccessibleWebView) findViewById(R.id.accessible_message_content);
|
||||
mAttachments = (LinearLayout) findViewById(R.id.attachments);
|
||||
|
||||
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
|
||||
mTopView = mToggleScrollView = (ToggleScrollView) findViewById(R.id.top_view);
|
||||
mMessageView = (SingleMessageView) findViewById(R.id.message_view);
|
||||
|
||||
mScreenReaderEnabled = isScreenReaderActive();
|
||||
if (mScreenReaderEnabled) {
|
||||
mAccessibleMessageContentView.setVisibility(View.VISIBLE);
|
||||
mMessageContentView.setVisibility(View.GONE);
|
||||
} else {
|
||||
mAccessibleMessageContentView.setVisibility(View.GONE);
|
||||
mMessageContentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
setupDecryptLayout();
|
||||
mMessageView.initialize(this, isScreenReaderActive());
|
||||
|
||||
setTitle("");
|
||||
Intent intent = getIntent();
|
||||
|
@ -395,7 +328,6 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (icicle != null) {
|
||||
restoreMessageReferences(icicle);
|
||||
mPgpData = (PgpData) icicle.getSerializable(STATE_PGP_DATA);
|
||||
updateDecryptLayout();
|
||||
} else {
|
||||
if (uri == null) {
|
||||
restoreMessageReferencesExtra(intent);
|
||||
|
@ -437,12 +369,10 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (K9.DEBUG)
|
||||
Log.d(K9.LOG_TAG, "MessageView got message " + mMessageReference);
|
||||
if (intent.getBooleanExtra(EXTRA_NEXT, false)) {
|
||||
next.requestFocus();
|
||||
mNext.requestFocus();
|
||||
}
|
||||
|
||||
setupHeaderLayout();
|
||||
setupButtonViews();
|
||||
|
||||
displayMessage(mMessageReference);
|
||||
}
|
||||
|
||||
|
@ -513,51 +443,6 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
buttons.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void setupHeaderLayout() {
|
||||
mShowPicturesSection = findViewById(R.id.show_pictures_section);
|
||||
mShowPictures = false;
|
||||
|
||||
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
|
||||
mMessageContentView.configure();
|
||||
|
||||
mTopView = mToggleScrollView = (ToggleScrollView) findViewById(R.id.top_view);
|
||||
|
||||
mAttachments.setVisibility(View.GONE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void setupDecryptLayout() {
|
||||
mDecryptLayout = findViewById(R.id.layout_decrypt);
|
||||
mDecryptButton = (Button) findViewById(R.id.btn_decrypt);
|
||||
mDecryptButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
String data = null;
|
||||
Part part = MimeUtility.findFirstPartByMimeType(mMessage, "text/plain");
|
||||
if (part == null) {
|
||||
part = MimeUtility.findFirstPartByMimeType(mMessage, "text/html");
|
||||
}
|
||||
if (part != null) {
|
||||
data = MimeUtility.getTextFromPart(part);
|
||||
}
|
||||
mAccount.getCryptoProvider().decrypt(MessageView.this, data, mPgpData);
|
||||
} catch (MessagingException me) {
|
||||
Log.e(K9.LOG_TAG, "Unable to decrypt email.", me);
|
||||
}
|
||||
}
|
||||
});
|
||||
mCryptoSignatureLayout = (LinearLayout) findViewById(R.id.crypto_signature);
|
||||
mCryptoSignatureStatusImage = (ImageView) findViewById(R.id.ic_crypto_signature_status);
|
||||
mCryptoSignatureUserId = (TextView) findViewById(R.id.userId);
|
||||
mCryptoSignatureUserIdRest = (TextView) findViewById(R.id.userIdRest);
|
||||
mCryptoSignatureLayout.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
private boolean isScreenReaderActive() {
|
||||
|
@ -598,15 +483,15 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
outState.putSerializable(EXTRA_MESSAGE_REFERENCE, mMessageReference);
|
||||
outState.putSerializable(EXTRA_MESSAGE_REFERENCES, mMessageReferences);
|
||||
outState.putSerializable(STATE_PGP_DATA, mPgpData);
|
||||
outState.putBoolean(SHOW_PICTURES, mShowPictures);
|
||||
outState.putBoolean(SHOW_PICTURES, mMessageView.showPictures());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
setLoadPictures(savedInstanceState.getBoolean(SHOW_PICTURES));
|
||||
initializeCrypto((PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA));
|
||||
updateDecryptLayout();
|
||||
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
|
||||
mMessageView.updateCryptoLayout(mAccount.getCryptoProvider(), mPgpData, mMessage);
|
||||
}
|
||||
|
||||
private void displayMessage(MessageReference ref) {
|
||||
|
@ -614,30 +499,28 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (K9.DEBUG)
|
||||
Log.d(K9.LOG_TAG, "MessageView displaying message " + mMessageReference);
|
||||
mAccount = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
||||
mTopView.setVisibility(View.GONE);
|
||||
mTopView.scrollTo(0, 0);
|
||||
mMessageContentView.scrollTo(0, 0);
|
||||
mHeaderContainer.setVisibility(View.GONE);
|
||||
|
||||
mMessageContentView.clearView();
|
||||
setLoadPictures(false);
|
||||
mAttachments.removeAllViews();
|
||||
clearMessageDisplay();
|
||||
findSurroundingMessagesUid();
|
||||
// start with fresh, empty PGP data
|
||||
initializeCrypto(null);
|
||||
mPgpData = new PgpData();
|
||||
mTopView.setVisibility(View.VISIBLE);
|
||||
mController.loadMessageForView(
|
||||
mAccount,
|
||||
mMessageReference.folderName,
|
||||
mMessageReference.uid,
|
||||
mListener);
|
||||
mController.loadMessageForView(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener);
|
||||
setupDisplayMessageButtons();
|
||||
}
|
||||
|
||||
private void clearMessageDisplay() {
|
||||
mTopView.setVisibility(View.GONE);
|
||||
mTopView.scrollTo(0, 0);
|
||||
setLoadPictures(false);
|
||||
|
||||
mMessageView.resetView();
|
||||
|
||||
}
|
||||
|
||||
private void setupDisplayMessageButtons() {
|
||||
mDelete.setEnabled(true);
|
||||
next.setEnabled(mNextMessage != null);
|
||||
previous.setEnabled(mPreviousMessage != null);
|
||||
mNext.setEnabled(mNextMessage != null);
|
||||
mPrevious.setEnabled(mPreviousMessage != null);
|
||||
// If moving isn't support at all, then all of them must be disabled anyway.
|
||||
if (mController.isMoveCapable(mAccount)) {
|
||||
// Only enable the button if the Archive folder is not the current folder and not NONE.
|
||||
|
@ -657,8 +540,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (buttons != null) {
|
||||
buttons.setVisibility(View.GONE);
|
||||
}
|
||||
next = findViewById(R.id.next);
|
||||
previous = findViewById(R.id.previous);
|
||||
mNext = findViewById(R.id.next);
|
||||
mPrevious = findViewById(R.id.previous);
|
||||
mDelete = findViewById(R.id.delete);
|
||||
}
|
||||
|
||||
|
@ -667,8 +550,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (buttons != null) {
|
||||
buttons.setVisibility(View.GONE);
|
||||
}
|
||||
next = findViewById(R.id.next_scrolling);
|
||||
previous = findViewById(R.id.previous_scrolling);
|
||||
mNext = findViewById(R.id.next_scrolling);
|
||||
mPrevious = findViewById(R.id.previous_scrolling);
|
||||
mDelete = findViewById(R.id.delete_scrolling);
|
||||
}
|
||||
|
||||
|
@ -695,8 +578,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
private void disableButtons() {
|
||||
setLoadPictures(false);
|
||||
disableMoveButtons();
|
||||
next.setEnabled(false);
|
||||
previous.setEnabled(false);
|
||||
mNext.setEnabled(false);
|
||||
mPrevious.setEnabled(false);
|
||||
mDelete.setEnabled(false);
|
||||
}
|
||||
|
||||
|
@ -869,8 +752,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
mMessage.getFolder().getName(), new String[] {mMessage.getUid()}, Flag.FLAGGED, !mMessage.isSet(Flag.FLAGGED));
|
||||
try {
|
||||
mMessage.setFlag(Flag.FLAGGED, !mMessage.isSet(Flag.FLAGGED));
|
||||
mHandler.setHeaders(mMessage);
|
||||
prepareMenuItems();
|
||||
mMessageView.setHeaders(mMessage, mAccount);
|
||||
} catch (MessagingException me) {
|
||||
Log.e(K9.LOG_TAG, "Could not set flag on local message", me);
|
||||
}
|
||||
|
@ -967,7 +849,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
mTopView.startAnimation(outToLeftAnimation());
|
||||
}
|
||||
displayMessage(mNextMessage);
|
||||
next.requestFocus();
|
||||
mNext.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -982,7 +864,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
mTopView.startAnimation(inFromRightAnimation());
|
||||
}
|
||||
displayMessage(mPreviousMessage);
|
||||
previous.requestFocus();
|
||||
mPrevious.requestFocus();
|
||||
}
|
||||
|
||||
private void onMarkAsUnread() {
|
||||
|
@ -995,7 +877,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
false);
|
||||
try {
|
||||
mMessage.setFlag(Flag.SEEN, false);
|
||||
mHandler.setHeaders(mMessage);
|
||||
mMessageView.setHeaders(mMessage, mAccount);
|
||||
String subject = mMessage.getSubject();
|
||||
setTitle(subject);
|
||||
} catch (Exception e) {
|
||||
|
@ -1009,17 +891,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (mMessage.isSet(Flag.X_DOWNLOADED_FULL)) {
|
||||
return;
|
||||
}
|
||||
mDownloadRemainder.setEnabled(false);
|
||||
mController.loadMessageForViewRemote(
|
||||
mAccount,
|
||||
mMessageReference.folderName,
|
||||
mMessageReference.uid,
|
||||
mListener);
|
||||
}
|
||||
|
||||
private void onShowPictures() {
|
||||
// TODO: Download attachments that are used as inline image
|
||||
setLoadPictures(true);
|
||||
mMessageView.downloadRemainderButton().setEnabled(false);
|
||||
mController.loadMessageForViewRemote(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1030,11 +903,12 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
* false, otherwise.
|
||||
*/
|
||||
private void setLoadPictures(boolean enable) {
|
||||
mMessageContentView.blockNetworkData(!enable);
|
||||
mShowPictures = enable;
|
||||
mMessageView.blockNetworkData(!enable);
|
||||
mMessageView.setShowPictures(enable);
|
||||
mHandler.showShowPictures(false);
|
||||
}
|
||||
|
||||
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.reply:
|
||||
|
@ -1076,7 +950,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
((AttachmentView)view).saveFile();
|
||||
break;
|
||||
case R.id.show_pictures:
|
||||
onShowPictures();
|
||||
setLoadPictures(true);
|
||||
break;
|
||||
case R.id.download_remainder:
|
||||
onDownloadRemainder();
|
||||
|
@ -1122,14 +996,15 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
break;
|
||||
case R.id.show_full_header:
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override public void run() {
|
||||
mHeaderContainer.onShowAdditionalHeaders();
|
||||
@Override
|
||||
public void run() {
|
||||
mMessageView.showAllHeaders();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case R.id.select_text:
|
||||
mToggleScrollView.setScrolling(false);
|
||||
mMessageContentView.emulateShiftHeld();
|
||||
mMessageView.beginSelectingText();
|
||||
break;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
|
@ -1141,8 +1016,6 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.message_view_option, menu);
|
||||
optionsMenu = menu;
|
||||
prepareMenuItems();
|
||||
if (!mController.isCopyCapable(mAccount)) {
|
||||
menu.findItem(R.id.copy).setVisible(false);
|
||||
}
|
||||
|
@ -1160,11 +1033,6 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
prepareMenuItems();
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
// TODO: when switching to API version 8, override onCreateDialog(int, Bundle)
|
||||
|
||||
/**
|
||||
|
@ -1182,8 +1050,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
return super.onCreateDialog(id);
|
||||
}
|
||||
|
||||
private void prepareMenuItems() {
|
||||
Menu menu = optionsMenu;
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
if (menu != null) {
|
||||
MenuItem flagItem = menu.findItem(R.id.flag);
|
||||
if (flagItem != null && mMessage != null) {
|
||||
|
@ -1191,10 +1059,11 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
}
|
||||
MenuItem additionalHeadersItem = menu.findItem(R.id.show_full_header);
|
||||
if (additionalHeadersItem != null) {
|
||||
additionalHeadersItem.setTitle(mHeaderContainer.additionalHeadersVisible() ?
|
||||
additionalHeadersItem.setTitle(mMessageView.additionalHeadersVisible() ?
|
||||
R.string.hide_full_header_action : R.string.show_full_header_action);
|
||||
}
|
||||
}
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
public void displayMessage(Account account, String folder, String uid, Message message) {
|
||||
|
@ -1202,13 +1071,13 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (MessageView.this.mMessage != null
|
||||
&& MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)
|
||||
&& message.isSet(Flag.X_DOWNLOADED_FULL)) {
|
||||
mHandler.setHeaders(message);
|
||||
mMessageView.setHeaders(message, account);
|
||||
}
|
||||
MessageView.this.mMessage = message;
|
||||
mHandler.removeAllAttachments();
|
||||
String text, type;
|
||||
if (mPgpData.getDecryptedData() != null) {
|
||||
text = mPgpData.getDecryptedData();
|
||||
String type;
|
||||
String text = mPgpData.getDecryptedData();
|
||||
if (text != null) {
|
||||
type = "text/plain";
|
||||
} else {
|
||||
// getTextForDisplay() always returns HTML-ified content.
|
||||
|
@ -1221,38 +1090,29 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mTopView.scrollTo(0, 0);
|
||||
if (mScreenReaderEnabled) {
|
||||
mAccessibleMessageContentView.loadDataWithBaseURL("http://",
|
||||
emailText, contentType, "utf-8", null);
|
||||
} else {
|
||||
mMessageContentView.loadDataWithBaseURL("http://", emailText,
|
||||
contentType, "utf-8", null);
|
||||
mMessageContentView.scrollTo(0, 0);
|
||||
}
|
||||
updateDecryptLayout();
|
||||
mMessageView.loadBodyFromText(mAccount.getCryptoProvider(), mPgpData, mMessage, emailText, contentType);
|
||||
}
|
||||
});
|
||||
// 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) && !mShowPictures) {
|
||||
if (Utility.hasExternalImages(text) && !mMessageView.showPictures()) {
|
||||
if ((account.getShowPictures() == Account.ShowPictures.ALWAYS) ||
|
||||
((account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS) &&
|
||||
mContacts.isInContacts(message.getFrom()[0].getAddress()))) {
|
||||
onShowPictures();
|
||||
setLoadPictures(true);
|
||||
} else {
|
||||
mHandler.showShowPictures(true);
|
||||
mMessageView.showShowPicturesSection(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mMessageContentView.loadUrl("file:///android_asset/empty.html");
|
||||
updateDecryptLayout();
|
||||
mMessageView.loadBodyFromUrl("file:///android_asset/empty.html");
|
||||
}
|
||||
});
|
||||
}
|
||||
renderAttachments(mMessage, 0);
|
||||
mMessageView.renderAttachments(mMessage, 0, mMessage, mAccount, mController, mListener);
|
||||
} catch (Exception e) {
|
||||
if (Config.LOGV) {
|
||||
Log.v(K9.LOG_TAG, "loadMessageForViewBodyAvailable", e);
|
||||
|
@ -1260,53 +1120,31 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
}
|
||||
}
|
||||
|
||||
private void renderAttachments(Part part, int depth) throws MessagingException {
|
||||
if (part.getBody() instanceof Multipart) {
|
||||
Multipart mp = (Multipart) part.getBody();
|
||||
for (int i = 0; i < mp.getCount(); i++) {
|
||||
renderAttachments(mp.getBodyPart(i), depth + 1);
|
||||
}
|
||||
} else if (part instanceof LocalAttachmentBodyPart) {
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
// Inline parts with a content-id are almost certainly components of an HTML message
|
||||
// not attachments. Don't show attachment download buttons for them.
|
||||
if (contentDisposition != null &&
|
||||
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)")
|
||||
&& part.getHeader("Content-ID") != null) {
|
||||
return;
|
||||
}
|
||||
renderPartAsAttachment(part);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPartAsAttachment(Part part) throws MessagingException {
|
||||
LayoutInflater inflater = getLayoutInflater();
|
||||
AttachmentView view = (AttachmentView)inflater.inflate(R.layout.message_view_attachment, null);
|
||||
if (view.populateFromPart(part, mMessage, mAccount, mController, mListener)) {
|
||||
mHandler.addAttachment(view);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
class Listener extends MessagingListener {
|
||||
@Override
|
||||
public void loadMessageForViewHeadersAvailable(Account account, String folder, String uid,
|
||||
public void loadMessageForViewHeadersAvailable(final Account account, String folder, String uid,
|
||||
final Message message) {
|
||||
if (!mMessageReference.uid.equals(uid) || !mMessageReference.folderName.equals(folder)
|
||||
|| !mMessageReference.accountUuid.equals(account.getUuid())) {
|
||||
return;
|
||||
}
|
||||
MessageView.this.mMessage = message;
|
||||
if (!message.isSet(Flag.X_DOWNLOADED_FULL)
|
||||
&& !message.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mMessageContentView.loadUrl("file:///android_asset/downloading.html");
|
||||
updateDecryptLayout();
|
||||
runOnUiThread(
|
||||
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
if (!message.isSet(Flag.X_DOWNLOADED_FULL) && !message.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
|
||||
mMessageView.loadBodyFromUrl("file:///android_asset/downloading.html");
|
||||
}
|
||||
});
|
||||
}
|
||||
mHandler.setHeaders(message);
|
||||
mMessageView.setHeaders(message, account);
|
||||
mMessageView.setOnFlagListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onFlag();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1339,8 +1177,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
}
|
||||
if ((MessageView.this.mMessage == null) ||
|
||||
!MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
|
||||
mMessageContentView.loadUrl("file:///android_asset/empty.html");
|
||||
updateDecryptLayout();
|
||||
mMessageView.loadBodyFromUrl("file:///android_asset/empty.html");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1348,7 +1185,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
|
||||
@Override
|
||||
public void loadMessageForViewFinished(Account account, String folder, String uid,
|
||||
Message message) {
|
||||
final Message message) {
|
||||
if (!mMessageReference.uid.equals(uid) || !mMessageReference.folderName.equals(folder)
|
||||
|| !mMessageReference.accountUuid.equals(account.getUuid())) {
|
||||
return;
|
||||
|
@ -1356,6 +1193,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
mMessageView.setShowDownloadButton(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1368,7 +1206,6 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
}
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
updateDecryptLayout();
|
||||
setProgressBarIndeterminateVisibility(true);
|
||||
}
|
||||
});
|
||||
|
@ -1380,7 +1217,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (mMessage != message) {
|
||||
return;
|
||||
}
|
||||
mHandler.setAttachmentsEnabled(false);
|
||||
mMessageView.setAttachmentsEnabled(false);
|
||||
mHandler.progress(true);
|
||||
if (requiresDownload) {
|
||||
mHandler.fetchingAttachment();
|
||||
|
@ -1388,12 +1225,11 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void loadAttachmentFinished(Account account, Message message,
|
||||
Part part, Object tag) {
|
||||
public void loadAttachmentFinished(Account account, Message message, Part part, Object tag) {
|
||||
if (mMessage != message) {
|
||||
return;
|
||||
}
|
||||
mHandler.setAttachmentsEnabled(true);
|
||||
mMessageView.setAttachmentsEnabled(true);
|
||||
mHandler.progress(false);
|
||||
Object[] params = (Object[]) tag;
|
||||
boolean download = (Boolean) params[0];
|
||||
|
@ -1412,93 +1248,22 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||
if (mMessage != message) {
|
||||
return;
|
||||
}
|
||||
mHandler.setAttachmentsEnabled(true);
|
||||
mMessageView.setAttachmentsEnabled(true);
|
||||
mHandler.progress(false);
|
||||
mHandler.networkError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeCrypto(PgpData data) {
|
||||
if (data == null) {
|
||||
if (mAccount == null) {
|
||||
mAccount = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
||||
}
|
||||
mPgpData = new PgpData();
|
||||
} else {
|
||||
mPgpData = data;
|
||||
}
|
||||
public PgpData getPgpData() {
|
||||
return mPgpData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the decrypt layout with signature data, if known, make controls visible, if
|
||||
* they should be visible.
|
||||
*/
|
||||
public void updateDecryptLayout() {
|
||||
if (mPgpData.getSignatureKeyId() != 0) {
|
||||
mCryptoSignatureUserIdRest.setText(
|
||||
getString(R.string.key_id, Long.toHexString(mPgpData.getSignatureKeyId() & 0xffffffffL)));
|
||||
String userId = mPgpData.getSignatureUserId();
|
||||
if (userId == null) {
|
||||
userId = getString(R.string.unknown_crypto_signature_user_id);
|
||||
}
|
||||
String chunks[] = userId.split(" <", 2);
|
||||
String name = chunks[0];
|
||||
if (chunks.length > 1) {
|
||||
mCryptoSignatureUserIdRest.setText("<" + chunks[1]);
|
||||
}
|
||||
mCryptoSignatureUserId.setText(name);
|
||||
if (mPgpData.getSignatureSuccess()) {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
|
||||
} else if (mPgpData.getSignatureUnknown()) {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||
} else {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||
}
|
||||
mCryptoSignatureLayout.setVisibility(View.VISIBLE);
|
||||
mDecryptLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mCryptoSignatureLayout.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (false || ((mMessage == null) && (mPgpData.getDecryptedData() == null))) {
|
||||
mDecryptLayout.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
if (mPgpData.getDecryptedData() != null) {
|
||||
if (mPgpData.getSignatureKeyId() == 0) {
|
||||
mDecryptLayout.setVisibility(View.GONE);
|
||||
} else {
|
||||
// no need to show this after decryption/verification
|
||||
mDecryptButton.setVisibility(View.GONE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
mDecryptButton.setVisibility(View.VISIBLE);
|
||||
CryptoProvider crypto = mAccount.getCryptoProvider();
|
||||
if (crypto.isEncrypted(mMessage)) {
|
||||
mDecryptButton.setText(R.string.btn_decrypt);
|
||||
mDecryptLayout.setVisibility(View.VISIBLE);
|
||||
} else if (crypto.isSigned(mMessage)) {
|
||||
mDecryptButton.setText(R.string.btn_verify);
|
||||
mDecryptLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mDecryptLayout.setVisibility(View.GONE);
|
||||
try {
|
||||
// check for PGP/MIME encryption
|
||||
Part pgp = MimeUtility.findFirstPartByMimeType(mMessage, "application/pgp-encrypted");
|
||||
if (pgp != null) {
|
||||
Toast.makeText(this, R.string.pgp_mime_unsupported, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
// nothing to do...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onDecryptDone() {
|
||||
// This REALLY should be in MessageCryptoView
|
||||
public void onDecryptDone(PgpData pgpData) {
|
||||
// TODO: this might not be enough if the orientation was changed while in APG,
|
||||
// sometimes shows the original encrypted content
|
||||
mMessageContentView.loadDataWithBaseURL("email://", mPgpData.getDecryptedData(), "text/plain", "utf-8", null);
|
||||
updateDecryptLayout();
|
||||
mMessageView.loadBodyFromText(mAccount.getCryptoProvider(), mPgpData, mMessage, mPgpData.getDecryptedData(), "text/plain");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import com.fsck.k9.mail.Flag;
|
|||
import com.fsck.k9.mail.Folder;
|
||||
import com.fsck.k9.mail.Folder.FolderType;
|
||||
import com.fsck.k9.mail.Folder.OpenMode;
|
||||
import com.fsck.k9.mail.Message.RecipientType;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
|
@ -1004,13 +1005,19 @@ public class MessagingController implements Runnable {
|
|||
* Remove any messages that are in the local store but no longer on the remote store or are too old
|
||||
*/
|
||||
if (account.syncRemoteDeletions()) {
|
||||
ArrayList<Message> destroyMessages = new ArrayList<Message>();
|
||||
for (Message localMessage : localMessages) {
|
||||
if (remoteUidMap.get(localMessage.getUid()) == null) {
|
||||
localMessage.destroy();
|
||||
destroyMessages.add(localMessage);
|
||||
}
|
||||
}
|
||||
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.synchronizeMailboxRemovedMessage(account, folder, localMessage);
|
||||
}
|
||||
|
||||
localFolder.destroyMessages(destroyMessages.toArray(EMPTY_MESSAGE_ARRAY));
|
||||
|
||||
for (Message destroyMessage : destroyMessages) {
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.synchronizeMailboxRemovedMessage(account, folder, destroyMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3469,7 +3476,22 @@ public class MessagingController implements Runnable {
|
|||
if (quotedText != null) {
|
||||
msg.putExtra(Intent.EXTRA_TEXT, quotedText);
|
||||
}
|
||||
msg.putExtra(Intent.EXTRA_SUBJECT, "Fwd: " + message.getSubject());
|
||||
msg.putExtra(Intent.EXTRA_SUBJECT, message.getSubject());
|
||||
|
||||
Address[] to = message.getRecipients(RecipientType.TO);
|
||||
String[] recipientsTo = new String[to.length];
|
||||
for (int i = 0; i < to.length; i++) {
|
||||
recipientsTo[i] = to[i].toString();
|
||||
}
|
||||
msg.putExtra(Intent.EXTRA_EMAIL, recipientsTo);
|
||||
|
||||
Address[] cc = message.getRecipients(RecipientType.CC);
|
||||
String[] recipientsCc = new String[cc.length];
|
||||
for (int i = 0; i < cc.length; i++) {
|
||||
recipientsCc[i] = cc[i].toString();
|
||||
}
|
||||
msg.putExtra(Intent.EXTRA_CC, recipientsCc);
|
||||
|
||||
msg.setType("text/plain");
|
||||
context.startActivity(Intent.createChooser(msg, context.getString(R.string.send_alternate_chooser_title)));
|
||||
} catch (MessagingException me) {
|
||||
|
|
|
@ -327,7 +327,7 @@ public class Apg extends CryptoProvider {
|
|||
pgpData.setSignatureUnknown(data.getBooleanExtra(Apg.EXTRA_SIGNATURE_UNKNOWN, false));
|
||||
|
||||
pgpData.setDecryptedData(data.getStringExtra(Apg.EXTRA_DECRYPTED_MESSAGE));
|
||||
((MessageView) activity).onDecryptDone();
|
||||
((MessageView) activity).onDecryptDone(pgpData);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -386,9 +386,7 @@ public class Apg extends CryptoProvider {
|
|||
activity.startActivityForResult(intent, Apg.DECRYPT_MESSAGE);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(activity,
|
||||
R.string.error_activity_not_found,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(activity, R.string.error_activity_not_found, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2020,6 +2020,27 @@ public class LocalStore extends Store implements Serializable {
|
|||
appendMessages(messages, false);
|
||||
}
|
||||
|
||||
public void destroyMessages(final Message[] messages) throws MessagingException {
|
||||
try {
|
||||
database.execute(true, new DbCallback<Void>() {
|
||||
@Override
|
||||
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
|
||||
for (Message message : messages) {
|
||||
try {
|
||||
message.destroy();
|
||||
} catch (MessagingException e) {
|
||||
throw new WrappedException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (MessagingException e) {
|
||||
throw new WrappedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The method differs slightly from the contract; If an incoming message already has a uid
|
||||
* assigned and it matches the uid of an existing message then this message will replace the
|
||||
|
|
|
@ -27,10 +27,8 @@ import java.security.MessageDigest;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SmtpTransport extends Transport {
|
||||
public static final int CONNECTION_SECURITY_NONE = 0;
|
||||
|
@ -284,7 +282,7 @@ public class SmtpTransport extends Transport {
|
|||
addressesOfCharset.add(addressString);
|
||||
}
|
||||
|
||||
for (HashMap.Entry<String, ArrayList<String>> charsetAddressesMapEntry :
|
||||
for (Map.Entry<String, ArrayList<String>> charsetAddressesMapEntry :
|
||||
charsetAddressesMap.entrySet()) {
|
||||
String charset = charsetAddressesMapEntry.getKey();
|
||||
ArrayList<String> addressesOfCharset = charsetAddressesMapEntry.getValue();
|
||||
|
|
143
src/com/fsck/k9/view/MessageCryptoView.java
Normal file
143
src/com/fsck/k9/view/MessageCryptoView.java
Normal file
|
@ -0,0 +1,143 @@
|
|||
package com.fsck.k9.view;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.*;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
|
||||
|
||||
|
||||
|
||||
public class MessageCryptoView extends LinearLayout {
|
||||
|
||||
private Context mContext;
|
||||
private Activity mActivity;
|
||||
private Button mDecryptButton;
|
||||
private LinearLayout mCryptoSignatureLayout = null;
|
||||
private ImageView mCryptoSignatureStatusImage = null;
|
||||
private TextView mCryptoSignatureUserId = null;
|
||||
private TextView mCryptoSignatureUserIdRest = null;
|
||||
|
||||
|
||||
public MessageCryptoView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void setupChildViews() {
|
||||
mCryptoSignatureLayout = (LinearLayout) findViewById(R.id.crypto_signature);
|
||||
mCryptoSignatureStatusImage = (ImageView) findViewById(R.id.ic_crypto_signature_status);
|
||||
mCryptoSignatureUserId = (TextView) findViewById(R.id.userId);
|
||||
mCryptoSignatureUserIdRest = (TextView) findViewById(R.id.userIdRest);
|
||||
mCryptoSignatureLayout.setVisibility(View.INVISIBLE);
|
||||
mDecryptButton = (Button) findViewById(R.id.btn_decrypt);
|
||||
}
|
||||
|
||||
public void setActivity(Activity activity) {
|
||||
mActivity = activity;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void hide () {
|
||||
this.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the decrypt layout with signature data, if known, make controls visible, if
|
||||
* they should be visible.
|
||||
*/
|
||||
public void updateLayout(final CryptoProvider cryptoProvider, final PgpData pgpData, final Message message) {
|
||||
if (pgpData.getSignatureKeyId() != 0) {
|
||||
mCryptoSignatureUserIdRest.setText(
|
||||
mContext.getString(R.string.key_id, Long.toHexString(pgpData.getSignatureKeyId() & 0xffffffffL)));
|
||||
String userId = pgpData.getSignatureUserId();
|
||||
if (userId == null) {
|
||||
userId = mContext.getString(R.string.unknown_crypto_signature_user_id);
|
||||
}
|
||||
String chunks[] = userId.split(" <", 2);
|
||||
String name = chunks[0];
|
||||
if (chunks.length > 1) {
|
||||
mCryptoSignatureUserIdRest.setText("<" + chunks[1]);
|
||||
}
|
||||
mCryptoSignatureUserId.setText(name);
|
||||
if (pgpData.getSignatureSuccess()) {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
|
||||
} else if (pgpData.getSignatureUnknown()) {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||
} else {
|
||||
mCryptoSignatureStatusImage.setImageResource(R.drawable.overlay_error);
|
||||
}
|
||||
mCryptoSignatureLayout.setVisibility(View.VISIBLE);
|
||||
this.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mCryptoSignatureLayout.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if ((message == null) && (pgpData.getDecryptedData() == null)) {
|
||||
this.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
if (pgpData.getDecryptedData() != null) {
|
||||
if (pgpData.getSignatureKeyId() == 0) {
|
||||
this.setVisibility(View.GONE);
|
||||
} else {
|
||||
// no need to show this after decryption/verification
|
||||
mDecryptButton.setVisibility(View.GONE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mDecryptButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
String data = null;
|
||||
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||
if (part == null) {
|
||||
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
|
||||
}
|
||||
if (part != null) {
|
||||
data = MimeUtility.getTextFromPart(part);
|
||||
}
|
||||
cryptoProvider.decrypt(mActivity, data, pgpData);
|
||||
} catch (MessagingException me) {
|
||||
Log.e(K9.LOG_TAG, "Unable to decrypt email.", me);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
mDecryptButton.setVisibility(View.VISIBLE);
|
||||
if (cryptoProvider.isEncrypted(message)) {
|
||||
mDecryptButton.setText(R.string.btn_decrypt);
|
||||
this.setVisibility(View.VISIBLE);
|
||||
} else if (cryptoProvider.isSigned(message)) {
|
||||
mDecryptButton.setText(R.string.btn_verify);
|
||||
this.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
this.setVisibility(View.GONE);
|
||||
try {
|
||||
// check for PGP/MIME encryption
|
||||
Part pgp = MimeUtility.findFirstPartByMimeType(message, "application/pgp-encrypted");
|
||||
if (pgp != null) {
|
||||
Toast.makeText(mContext, R.string.pgp_mime_unsupported, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
// nothing to do...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
211
src/com/fsck/k9/view/SingleMessageView.java
Normal file
211
src/com/fsck/k9/view/SingleMessageView.java
Normal file
|
@ -0,0 +1,211 @@
|
|||
package com.fsck.k9.view;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
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.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.mail.*;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mail.store.LocalStore;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
public class SingleMessageView extends LinearLayout {
|
||||
private boolean mScreenReaderEnabled;
|
||||
private MessageCryptoView mCryptoView;
|
||||
private MessageWebView mMessageContentView;
|
||||
private AccessibleWebView mAccessibleMessageContentView;
|
||||
private MessageHeader mHeaderContainer;
|
||||
private LinearLayout mAttachments;
|
||||
private View mShowPicturesSection;
|
||||
private boolean mShowPictures;
|
||||
private Button mDownloadRemainder;
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
|
||||
public void initialize(Activity activity, Boolean isScreenReaderActive) {
|
||||
mMessageContentView = (MessageWebView) findViewById(R.id.message_content);
|
||||
mAccessibleMessageContentView = (AccessibleWebView) findViewById(R.id.accessible_message_content);
|
||||
mAttachments = (LinearLayout) findViewById(R.id.attachments);
|
||||
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
|
||||
mCryptoView = (MessageCryptoView) findViewById(R.id.layout_decrypt);
|
||||
mCryptoView.setActivity(activity);
|
||||
mCryptoView.setupChildViews();
|
||||
mShowPicturesSection = findViewById(R.id.show_pictures_section);
|
||||
mShowPictures = false;
|
||||
|
||||
mInflater = activity.getLayoutInflater();
|
||||
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
|
||||
mMessageContentView.configure();
|
||||
|
||||
|
||||
mAttachments.setVisibility(View.GONE);
|
||||
if (isScreenReaderActive) {
|
||||
mAccessibleMessageContentView.setVisibility(View.VISIBLE);
|
||||
mMessageContentView.setVisibility(View.GONE);
|
||||
} else {
|
||||
mAccessibleMessageContentView.setVisibility(View.GONE);
|
||||
mMessageContentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
mScreenReaderEnabled = isScreenReaderActive;
|
||||
|
||||
}
|
||||
|
||||
public SingleMessageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public boolean showPictures() {
|
||||
return mShowPictures;
|
||||
}
|
||||
public void setShowPictures(Boolean show) {
|
||||
mShowPictures = show;
|
||||
}
|
||||
|
||||
public void blockNetworkData(Boolean block) {
|
||||
mMessageContentView.blockNetworkData(block);
|
||||
}
|
||||
|
||||
public Button downloadRemainderButton() {
|
||||
return mDownloadRemainder;
|
||||
}
|
||||
|
||||
public void showShowPicturesSection(boolean show) {
|
||||
mShowPicturesSection.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
public void setHeaders(final Message message, Account account) {
|
||||
try {
|
||||
mHeaderContainer.populate(message, account);
|
||||
|
||||
|
||||
} catch (Exception me) {
|
||||
Log.e(K9.LOG_TAG, "setHeaders - error", me);
|
||||
}
|
||||
}
|
||||
|
||||
public void setShowDownloadButton(Message message) {
|
||||
if (message.isSet(Flag.X_DOWNLOADED_FULL)) {
|
||||
mDownloadRemainder.setVisibility(View.GONE);
|
||||
} else {
|
||||
mDownloadRemainder.setEnabled(true);
|
||||
mDownloadRemainder.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnFlagListener(OnClickListener listener) {
|
||||
mHeaderContainer.setOnFlagListener(listener);
|
||||
}
|
||||
|
||||
public void showAllHeaders() {
|
||||
mHeaderContainer.onShowAdditionalHeaders();
|
||||
}
|
||||
|
||||
public boolean additionalHeadersVisible() {
|
||||
return mHeaderContainer.additionalHeadersVisible();
|
||||
}
|
||||
|
||||
|
||||
public void loadBodyFromUrl(String url) {
|
||||
mMessageContentView.loadUrl(url);
|
||||
mCryptoView.hide();
|
||||
|
||||
}
|
||||
|
||||
public void loadBodyFromText(CryptoProvider cryptoProvider, PgpData pgpData, Message message, String emailText, String contentType) {
|
||||
if (mScreenReaderEnabled) {
|
||||
mAccessibleMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null);
|
||||
} else {
|
||||
mMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null);
|
||||
mMessageContentView.scrollTo(0, 0);
|
||||
}
|
||||
updateCryptoLayout(cryptoProvider, pgpData, message);
|
||||
|
||||
}
|
||||
|
||||
public void updateCryptoLayout(CryptoProvider cp, PgpData pgpData, Message message) {
|
||||
mCryptoView.updateLayout(cp, pgpData, message);
|
||||
}
|
||||
|
||||
public void setAttachmentsEnabled(boolean enabled) {
|
||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
AttachmentView attachment = (AttachmentView) mAttachments.getChildAt(i);
|
||||
attachment.viewButton.setEnabled(enabled);
|
||||
attachment.downloadButton.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeAllAttachments() {
|
||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
mAttachments.removeView(mAttachments.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void renderAttachments(Part part, int depth,
|
||||
|
||||
Message message, Account account, MessagingController controller, MessagingListener listener) throws MessagingException {
|
||||
|
||||
if (part.getBody() instanceof Multipart) {
|
||||
Multipart mp = (Multipart) part.getBody();
|
||||
for (int i = 0; i < mp.getCount(); i++) {
|
||||
renderAttachments(mp.getBodyPart(i), depth + 1, message, account, controller, listener);
|
||||
}
|
||||
} else if (part instanceof LocalStore.LocalAttachmentBodyPart) {
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
// Inline parts with a content-id are almost certainly components of an HTML message
|
||||
// not attachments. Don't show attachment download buttons for them.
|
||||
if (contentDisposition != null &&
|
||||
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)")
|
||||
&& part.getHeader("Content-ID") != null) {
|
||||
return;
|
||||
}
|
||||
AttachmentView view = (AttachmentView)mInflater.inflate(R.layout.message_view_attachment, null);
|
||||
if (view.populateFromPart(part, message, account, controller, listener)) {
|
||||
addAttachment(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addAttachment(View attachmentView) {
|
||||
mAttachments.addView(attachmentView);
|
||||
mAttachments.setVisibility(View.VISIBLE);
|
||||
}
|
||||
public void zoom(KeyEvent event) {
|
||||
if (mScreenReaderEnabled) {
|
||||
mAccessibleMessageContentView.zoomIn();
|
||||
} else {
|
||||
if (event.isShiftPressed()) {
|
||||
mMessageContentView.zoomIn();
|
||||
} else {
|
||||
mMessageContentView.zoomOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void beginSelectingText() {
|
||||
mMessageContentView.emulateShiftHeld();
|
||||
}
|
||||
|
||||
|
||||
public void resetView() {
|
||||
|
||||
mMessageContentView.scrollTo(0, 0);
|
||||
mHeaderContainer.setVisibility(View.GONE);
|
||||
mMessageContentView.clearView();
|
||||
mAttachments.removeAllViews();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue