Save/restore instance state for SingleMessageView

This commit is contained in:
cketti 2012-02-24 03:43:42 +01:00
parent 2c09d75afa
commit 4e12dc154e
2 changed files with 157 additions and 69 deletions

View File

@ -7,7 +7,6 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Config;
import android.util.Log; import android.util.Log;
import android.view.*; import android.view.*;
import android.view.View.OnClickListener; 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;
import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback; import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback;
import com.fsck.k9.mail.*; 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.mail.store.StorageManager;
import com.fsck.k9.view.AttachmentView; import com.fsck.k9.view.AttachmentView;
import com.fsck.k9.view.SingleMessageView; 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_MESSAGE_REFERENCES = "com.fsck.k9.MessageView_messageReferences";
private static final String EXTRA_NEXT = "com.fsck.k9.MessageView_next"; 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 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 String STATE_PGP_DATA = "pgpData";
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1; private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2; private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2;
@ -417,10 +415,10 @@ public class MessageView extends K9Activity implements OnClickListener {
@Override @Override
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(EXTRA_MESSAGE_REFERENCE, mMessageReference); outState.putParcelable(EXTRA_MESSAGE_REFERENCE, mMessageReference);
outState.putParcelableArrayList(EXTRA_MESSAGE_REFERENCES, mMessageReferences); outState.putParcelableArrayList(EXTRA_MESSAGE_REFERENCES, mMessageReferences);
outState.putSerializable(STATE_PGP_DATA, mPgpData); outState.putSerializable(STATE_PGP_DATA, mPgpData);
outState.putBoolean(SHOW_PICTURES, mMessageView.showPictures());
} }
@Override @Override
@ -428,7 +426,6 @@ public class MessageView extends K9Activity implements OnClickListener {
super.onRestoreInstanceState(savedInstanceState); super.onRestoreInstanceState(savedInstanceState);
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA); mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
mMessageView.updateCryptoLayout(mAccount.getCryptoProvider(), mPgpData, mMessage); mMessageView.updateCryptoLayout(mAccount.getCryptoProvider(), mPgpData, mMessage);
mMessageView.setLoadPictures(savedInstanceState.getBoolean(SHOW_PICTURES));
} }
private void displayMessage(MessageReference ref) { private void displayMessage(MessageReference ref) {
@ -439,7 +436,11 @@ public class MessageView extends K9Activity implements OnClickListener {
findSurroundingMessagesUid(); findSurroundingMessagesUid();
// start with fresh, empty PGP data // start with fresh, empty PGP data
mPgpData = new PgpData(); mPgpData = new PgpData();
mMessageView.showMessageWebView(true);
// Clear previous message
mMessageView.resetView();
mMessageView.resetHeaderView();
mController.loadMessageForView(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener); mController.loadMessageForView(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener);
setupDisplayMessageButtons(); setupDisplayMessageButtons();
} }
@ -949,46 +950,6 @@ public class MessageView extends K9Activity implements OnClickListener {
return super.onPrepareOptionsMenu(menu); 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 { class Listener extends MessagingListener {
@Override @Override
public void loadMessageForViewHeadersAvailable(final Account account, String folder, String uid, public void loadMessageForViewHeadersAvailable(final Account account, String folder, String uid,
@ -1030,17 +991,28 @@ public class MessageView extends K9Activity implements OnClickListener {
} }
@Override @Override
public void loadMessageForViewBodyAvailable(Account account, String folder, String uid, public void loadMessageForViewBodyAvailable(final Account account, String folder,
Message message) { String uid, final Message message) {
if (!mMessageReference.uid.equals(uid) || !mMessageReference.folderName.equals(folder) if (!mMessageReference.uid.equals(uid) ||
|| !mMessageReference.accountUuid.equals(account.getUuid())) { !mMessageReference.folderName.equals(folder) ||
!mMessageReference.accountUuid.equals(account.getUuid())) {
return; return;
} }
displayMessageBody(account, folder, uid, message); runOnUiThread(new Runnable() {
}//loadMessageForViewBodyAvailable @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 @Override
public void loadMessageForViewFailed(Account account, String folder, String uid, final Throwable t) { 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 // This REALLY should be in MessageCryptoView
public void onDecryptDone(PgpData pgpData) { public void onDecryptDone(PgpData pgpData) {
Account account = mAccount; Account account = mAccount;
Message message = mMessage; LocalMessage message = (LocalMessage) mMessage;
MessagingController controller = mController;
Listener listener = mListener;
try { try {
mMessageView.displayMessageBody(account, message, pgpData); mMessageView.setMessage(account, message, pgpData, controller, listener);
} catch (MessagingException e) { } catch (MessagingException e) {
Log.e(K9.LOG_TAG, "displayMessageBody failed", e); Log.e(K9.LOG_TAG, "displayMessageBody failed", e);
} }

View File

@ -7,6 +7,8 @@ import android.content.Intent;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
@ -27,6 +29,7 @@ import com.fsck.k9.helper.Contacts;
import com.fsck.k9.helper.Utility; import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.*; import com.fsck.k9.mail.*;
import com.fsck.k9.mail.store.LocalStore; import com.fsck.k9.mail.store.LocalStore;
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
import java.util.List; import java.util.List;
@ -51,6 +54,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener {
private LinearLayout mHeaderPlaceHolder; private LinearLayout mHeaderPlaceHolder;
private LinearLayout mTitleBarHeaderContainer; private LinearLayout mTitleBarHeaderContainer;
private View mAttachmentsContainer; private View mAttachmentsContainer;
private SavedState mSavedState;
public void initialize(Activity activity) { public void initialize(Activity activity) {
mMessageContentView = (MessageWebView) findViewById(R.id.message_content); mMessageContentView = (MessageWebView) findViewById(R.id.message_content);
@ -258,8 +262,8 @@ public class SingleMessageView extends LinearLayout implements OnClickListener {
return mHeaderContainer.additionalHeadersVisible(); return mHeaderContainer.additionalHeadersVisible();
} }
public void displayMessageBody(Account account, Message message, PgpData pgpData) public void setMessage(Account account, LocalMessage message, PgpData pgpData,
throws MessagingException { MessagingController controller, MessagingListener listener) throws MessagingException {
resetView(); resetView();
String type; String type;
@ -268,14 +272,49 @@ public class SingleMessageView extends LinearLayout implements OnClickListener {
type = "text/plain"; type = "text/plain";
} else { } else {
// getTextForDisplay() always returns HTML-ified content. // getTextForDisplay() always returns HTML-ified content.
text = ((LocalStore.LocalMessage) message).getTextForDisplay(); text = message.getTextForDisplay();
type = "text/html"; type = "text/html";
} }
if (text != null) { if (text != null) {
final String emailText = text; final String emailText = text;
final String contentType = type; final String contentType = type;
loadBodyFromText(message, emailText, contentType); loadBodyFromText(emailText, contentType);
updateCryptoLayout(account.getCryptoProvider(), pgpData, message); 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" // If the message contains external pictures and the "Show pictures"
// button wasn't already pressed, see if the user's preferences has us // button wasn't already pressed, see if the user's preferences has us
// showing them anyway. // showing them anyway.
@ -291,12 +330,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener {
showShowPicturesAction(true); showShowPicturesAction(true);
} }
} }
mHasAttachments = ((LocalStore.LocalMessage) message).hasAttachments();
} else {
loadBodyFromUrl("file:///android_asset/empty.html");
} }
onShowMessage();
} }
public void loadBodyFromUrl(String url) { 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) { if (mScreenReaderEnabled) {
mAccessibleMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null); mAccessibleMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null);
} else { } else {
@ -321,14 +355,14 @@ public class SingleMessageView extends LinearLayout implements OnClickListener {
public void showAttachments(boolean show) { public void showAttachments(boolean show) {
mAttachmentsContainer.setVisibility(show ? View.VISIBLE : View.GONE); 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); mShowHiddenAttachments.setVisibility(showHidden ? View.VISIBLE : View.GONE);
if (show) { if (show) {
moveHeaderToLayout(); moveHeaderToLayout();
} else { } else {
moveHeaderToWebViewTitleBar(); moveHeaderToWebViewTitleBar();
mHiddenAttachments.setVisibility(View.GONE);
} }
} }
@ -395,10 +429,22 @@ public class SingleMessageView extends LinearLayout implements OnClickListener {
} }
public void resetView() { public void resetView() {
mMessageContentView.scrollTo(0, 0); mDownloadRemainder.setVisibility(View.GONE);
mMessageContentView.clearView(); setLoadPictures(false);
showShowAttachmentsAction(false);
showShowMessageAction(false);
showShowPicturesAction(false);
mAttachments.removeAllViews(); mAttachments.removeAllViews();
mHiddenAttachments.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() { public void resetHeaderView() {
@ -427,4 +473,72 @@ public class SingleMessageView extends LinearLayout implements OnClickListener {
mTitleBarHeaderContainer.addView(mHeaderContainer); 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<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
@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);
}
}
} }