diff --git a/src/com/fsck/k9/activity/MessageView.java b/src/com/fsck/k9/activity/MessageView.java index 3daf7bb72..1ccbb8500 100644 --- a/src/com/fsck/k9/activity/MessageView.java +++ b/src/com/fsck/k9/activity/MessageView.java @@ -7,7 +7,6 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Handler; -import android.util.Config; import android.util.Log; import android.view.*; import android.view.View.OnClickListener; @@ -19,7 +18,7 @@ import com.fsck.k9.crypto.PgpData; import com.fsck.k9.helper.FileBrowserHelper; import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback; import com.fsck.k9.mail.*; -import com.fsck.k9.mail.store.LocalStore; +import com.fsck.k9.mail.store.LocalStore.LocalMessage; import com.fsck.k9.mail.store.StorageManager; import com.fsck.k9.view.AttachmentView; import com.fsck.k9.view.SingleMessageView; @@ -33,7 +32,6 @@ public class MessageView extends K9Activity implements OnClickListener { private static final String EXTRA_MESSAGE_REFERENCES = "com.fsck.k9.MessageView_messageReferences"; private static final String EXTRA_NEXT = "com.fsck.k9.MessageView_next"; private static final String EXTRA_MESSAGE_LIST_EXTRAS = "com.fsck.k9.MessageView_messageListExtras"; - private static final String SHOW_PICTURES = "showPictures"; 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; @@ -417,10 +415,10 @@ public class MessageView extends K9Activity implements OnClickListener { @Override protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); outState.putParcelable(EXTRA_MESSAGE_REFERENCE, mMessageReference); outState.putParcelableArrayList(EXTRA_MESSAGE_REFERENCES, mMessageReferences); outState.putSerializable(STATE_PGP_DATA, mPgpData); - outState.putBoolean(SHOW_PICTURES, mMessageView.showPictures()); } @Override @@ -428,7 +426,6 @@ public class MessageView extends K9Activity implements OnClickListener { super.onRestoreInstanceState(savedInstanceState); mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA); mMessageView.updateCryptoLayout(mAccount.getCryptoProvider(), mPgpData, mMessage); - mMessageView.setLoadPictures(savedInstanceState.getBoolean(SHOW_PICTURES)); } private void displayMessage(MessageReference ref) { @@ -439,7 +436,11 @@ public class MessageView extends K9Activity implements OnClickListener { findSurroundingMessagesUid(); // start with fresh, empty PGP data mPgpData = new PgpData(); - mMessageView.showMessageWebView(true); + + // Clear previous message + mMessageView.resetView(); + mMessageView.resetHeaderView(); + mController.loadMessageForView(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener); setupDisplayMessageButtons(); } @@ -949,46 +950,6 @@ public class MessageView extends K9Activity implements OnClickListener { return super.onPrepareOptionsMenu(menu); } - public void displayMessageBody(final Account account, final String folder, final String uid, final Message message) { - runOnUiThread(new Runnable() { - public void run() { - try { - boolean resetMessageViewState = true; - - // Did we just completely download a previously incomplete message? - if (mMessage != null && mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL) && - message.isSet(Flag.X_DOWNLOADED_FULL)) { - // Update the headers - mMessageView.setHeaders(message, account); - - // Keep the current view state (i.e. if the attachment view was visible, - // keep it that way) - resetMessageViewState = false; - } - - mMessage = message; - - mMessageView.displayMessageBody(account, message, mPgpData); - - boolean hasAttachments = ((LocalStore.LocalMessage) message).hasAttachments(); - - if (hasAttachments) { - mMessageView.renderAttachments(mMessage, 0, mMessage, mAccount, mController, mListener); - } - - if (resetMessageViewState) { - mMessageView.onShowMessage(); - } - - } catch (MessagingException e) { - if (Config.LOGV) { - Log.v(K9.LOG_TAG, "loadMessageForViewBodyAvailable", e); - } - } - } - }); - } - class Listener extends MessagingListener { @Override public void loadMessageForViewHeadersAvailable(final Account account, String folder, String uid, @@ -1030,17 +991,28 @@ public class MessageView extends K9Activity implements OnClickListener { } @Override - public void loadMessageForViewBodyAvailable(Account account, String folder, String uid, - Message message) { - if (!mMessageReference.uid.equals(uid) || !mMessageReference.folderName.equals(folder) - || !mMessageReference.accountUuid.equals(account.getUuid())) { + public void loadMessageForViewBodyAvailable(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; } - displayMessageBody(account, folder, uid, message); - }//loadMessageForViewBodyAvailable - + runOnUiThread(new Runnable() { + @Override + public void run() { + try { + mMessage = message; + mMessageView.setMessage(account, (LocalMessage) message, mPgpData, + mController, mListener); + } catch (MessagingException e) { + Log.v(K9.LOG_TAG, "loadMessageForViewBodyAvailable", e); + } + } + }); + } @Override public void loadMessageForViewFailed(Account account, String folder, String uid, final Throwable t) { @@ -1146,9 +1118,11 @@ public class MessageView extends K9Activity implements OnClickListener { // This REALLY should be in MessageCryptoView public void onDecryptDone(PgpData pgpData) { Account account = mAccount; - Message message = mMessage; + LocalMessage message = (LocalMessage) mMessage; + MessagingController controller = mController; + Listener listener = mListener; try { - mMessageView.displayMessageBody(account, message, pgpData); + mMessageView.setMessage(account, message, pgpData, controller, listener); } catch (MessagingException e) { Log.e(K9.LOG_TAG, "displayMessageBody failed", e); } diff --git a/src/com/fsck/k9/view/SingleMessageView.java b/src/com/fsck/k9/view/SingleMessageView.java index 91ba3d1e4..86809718c 100644 --- a/src/com/fsck/k9/view/SingleMessageView.java +++ b/src/com/fsck/k9/view/SingleMessageView.java @@ -7,6 +7,8 @@ import android.content.Intent; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; @@ -27,6 +29,7 @@ import com.fsck.k9.helper.Contacts; import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.*; import com.fsck.k9.mail.store.LocalStore; +import com.fsck.k9.mail.store.LocalStore.LocalMessage; import java.util.List; @@ -51,6 +54,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { private LinearLayout mHeaderPlaceHolder; private LinearLayout mTitleBarHeaderContainer; private View mAttachmentsContainer; + private SavedState mSavedState; public void initialize(Activity activity) { mMessageContentView = (MessageWebView) findViewById(R.id.message_content); @@ -258,8 +262,8 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { return mHeaderContainer.additionalHeadersVisible(); } - public void displayMessageBody(Account account, Message message, PgpData pgpData) - throws MessagingException { + public void setMessage(Account account, LocalMessage message, PgpData pgpData, + MessagingController controller, MessagingListener listener) throws MessagingException { resetView(); String type; @@ -268,14 +272,49 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { type = "text/plain"; } else { // getTextForDisplay() always returns HTML-ified content. - text = ((LocalStore.LocalMessage) message).getTextForDisplay(); + text = message.getTextForDisplay(); type = "text/html"; } if (text != null) { final String emailText = text; final String contentType = type; - loadBodyFromText(message, emailText, contentType); + loadBodyFromText(emailText, contentType); updateCryptoLayout(account.getCryptoProvider(), pgpData, message); + } else { + loadBodyFromUrl("file:///android_asset/empty.html"); + } + + mHasAttachments = message.hasAttachments(); + + if (mHasAttachments) { + renderAttachments(message, 0, message, account, controller, listener); + } + + mHiddenAttachments.setVisibility(View.GONE); + + boolean lookForImages = true; + if (mSavedState != null) { + if (mSavedState.showPictures) { + setLoadPictures(true); + 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. @@ -291,12 +330,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { showShowPicturesAction(true); } } - mHasAttachments = ((LocalStore.LocalMessage) message).hasAttachments(); - } else { - loadBodyFromUrl("file:///android_asset/empty.html"); } - - onShowMessage(); } public void loadBodyFromUrl(String url) { @@ -305,7 +339,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { } - public void loadBodyFromText(Message message, String emailText, String contentType) { + private void loadBodyFromText(String emailText, String contentType) { if (mScreenReaderEnabled) { mAccessibleMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null); } else { @@ -321,14 +355,14 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { public void showAttachments(boolean show) { mAttachmentsContainer.setVisibility(show ? View.VISIBLE : View.GONE); - boolean showHidden = (show && mHiddenAttachments.getChildCount() > 0); + boolean showHidden = (show && mHiddenAttachments.getVisibility() == View.GONE && + mHiddenAttachments.getChildCount() > 0); mShowHiddenAttachments.setVisibility(showHidden ? View.VISIBLE : View.GONE); if (show) { moveHeaderToLayout(); } else { moveHeaderToWebViewTitleBar(); - mHiddenAttachments.setVisibility(View.GONE); } } @@ -395,10 +429,22 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { } public void resetView() { - mMessageContentView.scrollTo(0, 0); - mMessageContentView.clearView(); + mDownloadRemainder.setVisibility(View.GONE); + setLoadPictures(false); + showShowAttachmentsAction(false); + showShowMessageAction(false); + showShowPicturesAction(false); mAttachments.removeAllViews(); mHiddenAttachments.removeAllViews(); + + /* + * Clear the WebView content + * + * For some reason WebView.clearView() doesn't clear the contents when the WebView changes + * its size because the button to download the complete message was previously shown and + * is now hidden. + */ + loadBodyFromText("", "text/plain"); } public void resetHeaderView() { @@ -427,4 +473,72 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { mTitleBarHeaderContainer.addView(mHeaderContainer); } } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + + SavedState savedState = new SavedState(superState); + + savedState.attachmentViewVisible = (mAttachmentsContainer != null && + mAttachmentsContainer.getVisibility() == View.VISIBLE); + savedState.hiddenAttachmentsVisible = (mHiddenAttachments != null && + mHiddenAttachments.getVisibility() == View.VISIBLE); + savedState.showPictures = mShowPictures; + + return savedState; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + if(!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState savedState = (SavedState)state; + super.onRestoreInstanceState(savedState.getSuperState()); + + mSavedState = savedState; + } + + static class SavedState extends BaseSavedState { + boolean attachmentViewVisible; + boolean hiddenAttachmentsVisible; + boolean showPictures; + + @SuppressWarnings("hiding") + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + + + SavedState(Parcelable superState) { + super(superState); + } + + private SavedState(Parcel in) { + super(in); + this.attachmentViewVisible = (in.readInt() != 0); + this.hiddenAttachmentsVisible = (in.readInt() != 0); + this.showPictures = (in.readInt() != 0); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt((this.attachmentViewVisible) ? 1 : 0); + out.writeInt((this.hiddenAttachmentsVisible) ? 1 : 0); + out.writeInt((this.showPictures) ? 1 : 0); + } + } }