diff --git a/res/drawable-hdpi/show_less.png b/res/drawable-hdpi/show_less.png
new file mode 100644
index 000000000..c1a758348
Binary files /dev/null and b/res/drawable-hdpi/show_less.png differ
diff --git a/res/drawable-hdpi/show_more.png b/res/drawable-hdpi/show_more.png
new file mode 100644
index 000000000..8fc07e919
Binary files /dev/null and b/res/drawable-hdpi/show_more.png differ
diff --git a/res/drawable/separator_area_background.xml b/res/drawable/separator_area_background.xml
new file mode 100644
index 000000000..01c289eb7
--- /dev/null
+++ b/res/drawable/separator_area_background.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/res/drawable/show_less.png b/res/drawable/show_less.png
new file mode 100644
index 000000000..bc9e3f948
Binary files /dev/null and b/res/drawable/show_less.png differ
diff --git a/res/drawable/show_more.png b/res/drawable/show_more.png
new file mode 100644
index 000000000..6d0fe5bf1
Binary files /dev/null and b/res/drawable/show_more.png differ
diff --git a/res/layout/message.xml b/res/layout/message.xml
index 8e425eb71..361c90299 100644
--- a/res/layout/message.xml
+++ b/res/layout/message.xml
@@ -1,226 +1,74 @@
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
-
-
-
-
-
-
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:id="@+id/message_view_header_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+
+
-
+
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:layout_width="fill_parent"/>
+
+ android:layout_width="fill_parent"/>
+
-
+ android:layout_weight="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:layout_width="fill_parent"/>
+
diff --git a/res/layout/message_view.xml b/res/layout/message_view.xml
index d653f3dba..5d3181eb4 100644
--- a/res/layout/message_view.xml
+++ b/res/layout/message_view.xml
@@ -1,29 +1,15 @@
-
-
-
-
-
-
+ android:layout_height="fill_parent">
+
+
+
+
+
diff --git a/res/layout/message_view_header.xml b/res/layout/message_view_header.xml
new file mode 100644
index 000000000..9e8708457
--- /dev/null
+++ b/res/layout/message_view_header.xml
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 766227197..17f7ccb30 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -1,5 +1,6 @@
- #ffffff
+ #ffffff
#eeeeee
+ #1a080808
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 79a9efa0e..8e8ad33a5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -289,6 +289,9 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
Unable to save attachment to SD card.
Select \"Show pictures\" to display embedded pictures.
Show pictures
+ Show message
+ Show attachments
+ More…
Fetching attachment.
Unable to find viewer for %s.
diff --git a/src/com/fsck/k9/activity/K9Activity.java b/src/com/fsck/k9/activity/K9Activity.java
index 4cbca5b09..e9a68eccf 100644
--- a/src/com/fsck/k9/activity/K9Activity.java
+++ b/src/com/fsck/k9/activity/K9Activity.java
@@ -6,24 +6,21 @@ import java.util.Locale;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
-import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import com.fsck.k9.K9;
-import com.fsck.k9.view.ToggleScrollView;
public class K9Activity extends Activity {
private GestureDetector gestureDetector;
- protected ToggleScrollView mTopView;
-
@Override
public void onCreate(Bundle icicle) {
onCreate(icicle, true);
@@ -144,22 +141,6 @@ public class K9Activity extends Activity {
private static final float SWIPE_MAX_OFF_PATH_DIP = 250f;
private static final float SWIPE_THRESHOLD_VELOCITY_DIP = 325f;
- @Override
- public boolean onDoubleTap(MotionEvent ev) {
- super.onDoubleTap(ev);
- if (mTopView != null) {
- int height = getResources().getDisplayMetrics().heightPixels;
- if (ev.getRawY() < (height / 4)) {
- mTopView.fullScroll(View.FOCUS_UP);
-
- } else if (ev.getRawY() > (height - height / 4)) {
- mTopView.fullScroll(View.FOCUS_DOWN);
-
- }
- }
- return false;
- }
-
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// Do fling-detection if gestures are force-enabled or we have system-wide gestures enabled.
@@ -169,11 +150,11 @@ public class K9Activity extends Activity {
final float mGestureScale = getResources().getDisplayMetrics().density;
final int minVelocity = (int)(SWIPE_THRESHOLD_VELOCITY_DIP * mGestureScale + 0.5f);
final int maxOffPath = (int)(SWIPE_MAX_OFF_PATH_DIP * mGestureScale + 0.5f);
-
+
// Calculate how much was actually swiped.
final float deltaX = e2.getX() - e1.getX();
final float deltaY = e2.getY() - e1.getY();
-
+
// Calculate the minimum distance required for this to be considered a swipe.
final int minDistance = (int)Math.abs(deltaY * 4);
@@ -216,4 +197,14 @@ public class K9Activity extends Activity {
return false;
}
}
+
+ public int getThemeBackgroundColor() {
+ TypedArray array = getTheme().obtainStyledAttributes(new int[] {
+ android.R.attr.colorBackground,
+ });
+ int backgroundColor = array.getColor(0, 0xFF00FF);
+ array.recycle();
+ return backgroundColor;
+ }
+
}
diff --git a/src/com/fsck/k9/activity/MessageView.java b/src/com/fsck/k9/activity/MessageView.java
index 221d195c9..40da84093 100644
--- a/src/com/fsck/k9/activity/MessageView.java
+++ b/src/com/fsck/k9/activity/MessageView.java
@@ -20,9 +20,9 @@ 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.StorageManager;
import com.fsck.k9.view.AttachmentView;
-import com.fsck.k9.view.ToggleScrollView;
import com.fsck.k9.view.SingleMessageView;
import com.fsck.k9.view.AttachmentView.AttachmentFileDownloadCallback;
@@ -34,7 +34,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 EXTRA_SCROLL_PERCENTAGE = "com.fsck.k9.MessageView_scrollPercentage";
private static final String SHOW_PICTURES = "showPictures";
private static final String STATE_PGP_DATA = "pgpData";
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
@@ -104,24 +103,6 @@ public class MessageView extends K9Activity implements OnClickListener {
public void onMount(String providerId) { /* no-op */ }
}
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_UP) {
- // Text selection is finished. Allow scrolling again.
- mTopView.setScrolling(true);
- } else if (K9.zoomControlsEnabled()) {
- // If we have system zoom controls enabled, disable scrolling so the screen isn't wiggling around while
- // trying to zoom.
- if (ev.getAction() == MotionEvent.ACTION_POINTER_2_DOWN) {
- mTopView.setScrolling(false);
- } else if (ev.getAction() == MotionEvent.ACTION_POINTER_2_UP) {
- mTopView.setScrolling(true);
- }
- }
- return super.dispatchTouchEvent(ev);
- }
-
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
boolean ret = false;
@@ -165,15 +146,6 @@ public class MessageView extends K9Activity implements OnClickListener {
}
break;
}
- case KeyEvent.KEYCODE_SHIFT_LEFT:
- case KeyEvent.KEYCODE_SHIFT_RIGHT: {
- /*
- * Selecting text started via shift key. Disable scrolling as
- * this causes problems when selecting text.
- */
- mTopView.setScrolling(false);
- break;
- }
case KeyEvent.KEYCODE_DEL: {
onDelete();
return true;
@@ -324,7 +296,6 @@ public class MessageView extends K9Activity implements OnClickListener {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.message_view);
- mTopView = (ToggleScrollView) findViewById(R.id.top_view);
mMessageView = (SingleMessageView) findViewById(R.id.message_view);
//set a callback for the attachment view. With this callback the attachmentview
@@ -356,10 +327,6 @@ public class MessageView extends K9Activity implements OnClickListener {
mMessageView.initialize(this);
- // Register the ScrollView's listener to handle scrolling to last known location on resume.
- mController.addListener(mTopView.getListener());
- mMessageView.setListeners(mController.getListeners());
-
setTitle("");
final Intent intent = getIntent();
@@ -481,7 +448,6 @@ public class MessageView extends K9Activity implements OnClickListener {
outState.putParcelableArrayList(EXTRA_MESSAGE_REFERENCES, mMessageReferences);
outState.putSerializable(STATE_PGP_DATA, mPgpData);
outState.putBoolean(SHOW_PICTURES, mMessageView.showPictures());
- outState.putDouble(EXTRA_SCROLL_PERCENTAGE, mTopView.getScrollPercentage());
}
@Override
@@ -490,7 +456,6 @@ public class MessageView extends K9Activity implements OnClickListener {
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
mMessageView.updateCryptoLayout(mAccount.getCryptoProvider(), mPgpData, mMessage);
mMessageView.setLoadPictures(savedInstanceState.getBoolean(SHOW_PICTURES));
- mTopView.setScrollPercentage(savedInstanceState.getDouble(EXTRA_SCROLL_PERCENTAGE));
}
private void displayMessage(MessageReference ref) {
@@ -498,22 +463,14 @@ 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);
- clearMessageDisplay();
findSurroundingMessagesUid();
// start with fresh, empty PGP data
mPgpData = new PgpData();
- mTopView.setVisibility(View.VISIBLE);
+ mMessageView.showMessageWebView(true);
mController.loadMessageForView(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener);
setupDisplayMessageButtons();
}
- private void clearMessageDisplay() {
- mTopView.setVisibility(View.GONE);
- mTopView.scrollTo(0, 0);
- mMessageView.resetView();
-
- }
-
private void setupDisplayMessageButtons() {
mDelete.setEnabled(true);
mNext.setEnabled(mNextMessage != null);
@@ -610,13 +567,11 @@ public class MessageView extends K9Activity implements OnClickListener {
onAccountUnavailable();
return;
}
- mController.addListener(mTopView.getListener());
StorageManager.getInstance(getApplication()).addListener(mStorageListener);
}
@Override
protected void onPause() {
- mController.removeListener(mTopView.getListener());
StorageManager.getInstance(getApplication()).removeListener(mStorageListener);
super.onPause();
}
@@ -840,32 +795,34 @@ public class MessageView extends K9Activity implements OnClickListener {
protected void onNext() {
// Reset scroll percentage when we change messages
- mTopView.setScrollPercentage(0);
if (mNextMessage == null) {
Toast.makeText(this, getString(R.string.end_of_folder), Toast.LENGTH_SHORT).show();
return;
}
mLastDirection = NEXT;
disableButtons();
+ /*
if (K9.showAnimations()) {
mTopView.startAnimation(outToLeftAnimation());
}
+ */
displayMessage(mNextMessage);
mNext.requestFocus();
}
protected void onPrevious() {
// Reset scroll percentage when we change messages
- mTopView.setScrollPercentage(0);
if (mPreviousMessage == null) {
Toast.makeText(this, getString(R.string.end_of_folder), Toast.LENGTH_SHORT).show();
return;
}
mLastDirection = PREVIOUS;
disableButtons();
+ /*
if (K9.showAnimations()) {
mTopView.startAnimation(inFromRightAnimation());
}
+ */
displayMessage(mPreviousMessage);
mPrevious.requestFocus();
}
@@ -984,7 +941,6 @@ public class MessageView extends K9Activity implements OnClickListener {
});
break;
case R.id.select_text:
- mTopView.setScrolling(false);
mMessageView.beginSelectingText();
break;
default:
@@ -1077,16 +1033,37 @@ public class MessageView extends K9Activity implements OnClickListener {
public void displayMessageBody(final Account account, final String folder, final String uid, final Message message) {
runOnUiThread(new Runnable() {
public void run() {
- mTopView.scrollTo(0, 0);
try {
- if (MessageView.this.mMessage != null
- && MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)
- && message.isSet(Flag.X_DOWNLOADED_FULL)) {
+ 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;
}
- MessageView.this.mMessage = message;
- mMessageView.displayMessageBody(account, folder, uid, message, mPgpData);
- mMessageView.renderAttachments(mMessage, 0, mMessage, mAccount, mController, mListener);
+
+ 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.showMessageWebView(true);
+ mMessageView.showAttachments(false);
+ mMessageView.showShowAttachmentsAction(hasAttachments);
+ mMessageView.showShowMessageAction(false);
+ }
+
} catch (MessagingException e) {
if (Config.LOGV) {
Log.v(K9.LOG_TAG, "loadMessageForViewBodyAvailable", e);
@@ -1253,8 +1230,12 @@ public class MessageView extends K9Activity implements OnClickListener {
// 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
- mMessageView.loadBodyFromText(mAccount.getCryptoProvider(), mPgpData, mMessage, mPgpData.getDecryptedData(), "text/plain");
+ Account account = mAccount;
+ Message message = mMessage;
+ try {
+ mMessageView.displayMessageBody(account, message, pgpData);
+ } catch (MessagingException e) {
+ Log.e(K9.LOG_TAG, "displayMessageBody failed", e);
+ }
}
}
diff --git a/src/com/fsck/k9/view/MessageHeader.java b/src/com/fsck/k9/view/MessageHeader.java
index 371bc5905..85cda0b37 100644
--- a/src/com/fsck/k9/view/MessageHeader.java
+++ b/src/com/fsck/k9/view/MessageHeader.java
@@ -11,6 +11,8 @@ import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.ScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -25,14 +27,13 @@ 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.mail.store.LocalStore;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.text.DateFormat;
-public class MessageHeader extends LinearLayout {
+public class MessageHeader extends ScrollView {
private Context mContext;
private TextView mFromView;
private TextView mDateView;
@@ -43,18 +44,18 @@ public class MessageHeader extends LinearLayout {
private DateFormat mDateFormat;
private DateFormat mTimeFormat;
- private View mChip;
private CheckBox mFlagged;
private int defaultSubjectColor;
private LinearLayout mToContainerView;
private LinearLayout mCcContainerView;
private TextView mAdditionalHeadersView;
- private View mAttachmentIcon;
private View mAnsweredIcon;
private Message mMessage;
private Account mAccount;
private FontSizes mFontSizes = K9.getFontSizes();
private Contacts mContacts;
+ private View mAdditionalHeadersArea;
+ private ImageView mShowAdditionalHeadersIcon;
/**
* Pair class is only available since API Level 5, so we need
@@ -79,7 +80,6 @@ public class MessageHeader extends LinearLayout {
}
private void initializeLayout() {
- mAttachmentIcon = findViewById(R.id.attachment);
mAnsweredIcon = findViewById(R.id.answered);
mFromView = (TextView) findViewById(R.id.from);
mToView = (TextView) findViewById(R.id.to);
@@ -88,18 +88,20 @@ public class MessageHeader extends LinearLayout {
mCcContainerView = (LinearLayout) findViewById(R.id.cc_container);
mSubjectView = (TextView) findViewById(R.id.subject);
mAdditionalHeadersView = (TextView) findViewById(R.id.additional_headers_view);
- mChip = findViewById(R.id.chip);
mDateView = (TextView) findViewById(R.id.date);
mTimeView = (TextView) findViewById(R.id.time);
mFlagged = (CheckBox) findViewById(R.id.flagged);
+ mAdditionalHeadersArea = findViewById(R.id.show_additional_headers_area);
+ mShowAdditionalHeadersIcon = (ImageView) findViewById(R.id.show_additional_headers_icon);
+
defaultSubjectColor = mSubjectView.getCurrentTextColor();
mSubjectView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewSubject());
mTimeView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewTime());
mDateView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewDate());
mAdditionalHeadersView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewAdditionalHeaders());
- mAdditionalHeadersView.setVisibility(View.GONE);
- mAttachmentIcon.setVisibility(View.GONE);
+ hideAdditionalHeaders();
+
mAnsweredIcon.setVisibility(View.GONE);
mFromView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewSender());
mToView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewTo());
@@ -107,7 +109,7 @@ public class MessageHeader extends LinearLayout {
((TextView) findViewById(R.id.to_label)).setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewTo());
((TextView) findViewById(R.id.cc_label)).setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewCC());
- setOnClickListener(new OnClickListener() {
+ mAdditionalHeadersArea.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onShowAdditionalHeaders();
@@ -130,6 +132,8 @@ public class MessageHeader extends LinearLayout {
}
public void setOnFlagListener(OnClickListener listener) {
+ if (mFlagged == null)
+ return;
mFlagged.setOnClickListener(listener);
}
@@ -149,7 +153,7 @@ public class MessageHeader extends LinearLayout {
private void hideAdditionalHeaders() {
mAdditionalHeadersView.setVisibility(View.GONE);
mAdditionalHeadersView.setText("");
-
+ mShowAdditionalHeadersIcon.setImageResource(R.drawable.show_more);
}
@@ -168,6 +172,7 @@ public class MessageHeader extends LinearLayout {
// Show the additional headers that we have got.
populateAdditionalHeadersView(additionalHeaders);
mAdditionalHeadersView.setVisibility(View.VISIBLE);
+ mShowAdditionalHeadersIcon.setImageResource(R.drawable.show_less);
}
if (!allHeadersDownloaded) {
/*
@@ -227,11 +232,8 @@ public class MessageHeader extends LinearLayout {
mToView.setText(to);
mCcContainerView.setVisibility((cc != null && cc.length() > 0) ? View.VISIBLE : View.GONE);
mCcView.setText(cc);
- mAttachmentIcon.setVisibility(((LocalStore.LocalMessage) message).hasAttachments() ? View.VISIBLE : View.GONE);
mAnsweredIcon.setVisibility(message.isSet(Flag.ANSWERED) ? View.VISIBLE : View.GONE);
mFlagged.setChecked(message.isSet(Flag.FLAGGED));
- mChip.setBackgroundDrawable(mAccount.generateColorChip().drawable());
- mChip.getBackground().setAlpha(!message.isSet(Flag.SEEN) ? 255 : 127);
setVisibility(View.VISIBLE);
if (mAdditionalHeadersView.getVisibility() == View.VISIBLE) {
showAdditionalHeaders();
diff --git a/src/com/fsck/k9/view/MessageWebView.java b/src/com/fsck/k9/view/MessageWebView.java
index daf53b993..d992b50be 100644
--- a/src/com/fsck/k9/view/MessageWebView.java
+++ b/src/com/fsck/k9/view/MessageWebView.java
@@ -1,25 +1,20 @@
package com.fsck.k9.view;
import android.content.Context;
-import android.graphics.Picture;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
+import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Toast;
import com.fsck.k9.K9;
import com.fsck.k9.R;
-import com.fsck.k9.controller.MessagingListener;
-
import java.lang.reflect.Method;
-import java.util.Set;
public class MessageWebView extends WebView {
- // Store a reference to the listeners in MessagingController. We can't fetch it directly since
- // we don't know the application name.
- private Set mListeners = null;
+
/**
* We use WebSettings.getBlockNetworkLoads() to prevent the WebView that displays email
@@ -75,7 +70,7 @@ public class MessageWebView extends WebView {
this.setVerticalScrollBarEnabled(true);
this.setVerticalScrollbarOverlay(true);
this.setScrollBarStyle(SCROLLBARS_INSIDE_OVERLAY);
-
+ this.setLongClickable(true);
final WebSettings webSettings = this.getSettings();
@@ -97,22 +92,16 @@ public class MessageWebView extends WebView {
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
}
+ if (Integer.parseInt(Build.VERSION.SDK) >= 9 ) {
+ setOverScrollMode(OVER_SCROLL_NEVER);
+ }
+
+
webSettings.setTextSize(K9.getFontSizes().getMessageViewContent());
// Disable network images by default. This is overridden by preferences.
blockNetworkData(true);
- // Listen for when the screen has finished drawing.
- setPictureListener(new PictureListener() {
- @Override
- public void onNewPicture(WebView webView, Picture picture) {
- if (mListeners != null) {
- for (MessagingListener l : mListeners) {
- l.messageViewFinished();
- }
- }
- }
- });
}
/*
@@ -132,7 +121,15 @@ public class MessageWebView extends WebView {
}
}
- public void setListeners(final Set listeners) {
- this.mListeners = listeners;
+ public void wrapSetTitleBar(final View title) {
+ try {
+ Class> webViewClass = Class.forName("android.webkit.WebView");
+ Method setEmbeddedTitleBar = webViewClass.getMethod("setEmbeddedTitleBar", View.class);
+ setEmbeddedTitleBar.invoke(this, title);
+ }
+
+ catch (Exception e) {
+ Log.v(K9.LOG_TAG, "failed to find the setEmbeddedTitleBar method",e);
+ }
}
}
diff --git a/src/com/fsck/k9/view/SingleMessageView.java b/src/com/fsck/k9/view/SingleMessageView.java
index 92699ee2c..53e441ad1 100644
--- a/src/com/fsck/k9/view/SingleMessageView.java
+++ b/src/com/fsck/k9/view/SingleMessageView.java
@@ -17,6 +17,7 @@ import android.widget.LinearLayout;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.R;
+import com.fsck.k9.activity.K9Activity;
import com.fsck.k9.controller.MessagingController;
import com.fsck.k9.controller.MessagingListener;
import com.fsck.k9.crypto.CryptoProvider;
@@ -24,16 +25,10 @@ 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.MimeHeader;
-import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mail.store.LocalStore;
-
import java.util.List;
-import java.util.Set;
-/**
- */
public class SingleMessageView extends LinearLayout {
private boolean mScreenReaderEnabled;
private MessageCryptoView mCryptoView;
@@ -41,32 +36,77 @@ public class SingleMessageView extends LinearLayout {
private AccessibleWebView mAccessibleMessageContentView;
private MessageHeader mHeaderContainer;
private LinearLayout mAttachments;
- private View mShowPicturesSection;
+ private Button mShowHiddenAttachments;
+ private LinearLayout mHiddenAttachments;
+ private View mShowPicturesAction;
+ private View mShowMessageAction;
+ private View mShowAttachmentsAction;
private boolean mShowPictures;
private Button mDownloadRemainder;
private LayoutInflater mInflater;
private Contacts mContacts;
private AttachmentView.AttachmentFileDownloadCallback attachmentCallback;
+ private LinearLayout mHeaderPlaceHolder;
+ private LinearLayout mTitleBarHeaderContainer;
+ private View mAttachmentsContainer;
public void initialize(Activity activity) {
mMessageContentView = (MessageWebView) findViewById(R.id.message_content);
mAccessibleMessageContentView = (AccessibleWebView) findViewById(R.id.accessible_message_content);
- mAttachments = (LinearLayout) findViewById(R.id.attachments);
+ mMessageContentView.configure();
+
+ mHeaderPlaceHolder = (LinearLayout) findViewById(R.id.message_view_header_container);
+
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
+
+ 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);
+ mShowHiddenAttachments.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v)
+ {
+ mShowHiddenAttachments.setVisibility(View.GONE);
+ mHiddenAttachments.setVisibility(View.VISIBLE);
+ }
+ });
mCryptoView = (MessageCryptoView) findViewById(R.id.layout_decrypt);
mCryptoView.setActivity(activity);
mCryptoView.setupChildViews();
- mShowPicturesSection = findViewById(R.id.show_pictures_section);
+ mShowPicturesAction = findViewById(R.id.show_pictures);
+ mShowMessageAction = findViewById(R.id.show_message);
+ mShowMessageAction.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showShowMessageAction(false);
+ showAttachments(false);
+ showMessageWebView(true);
+ showShowAttachmentsAction(true);
+ }
+ });
+
+ mShowAttachmentsAction = findViewById(R.id.show_attachments);
+ mShowAttachmentsAction.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showMessageWebView(false);
+ showShowAttachmentsAction(false);
+ showShowMessageAction(true);
+ showAttachments(true);
+ }
+ });
+
mShowPictures = false;
mContacts = Contacts.getInstance(activity);
mInflater = activity.getLayoutInflater();
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
- mMessageContentView.configure();
-
-
- mAttachments.setVisibility(View.GONE);
+ mDownloadRemainder.setVisibility(View.GONE);
+ mAttachmentsContainer.setVisibility(View.GONE);
if (isScreenReaderActive(activity)) {
mAccessibleMessageContentView.setVisibility(View.VISIBLE);
mMessageContentView.setVisibility(View.GONE);
@@ -75,6 +115,15 @@ public class SingleMessageView extends LinearLayout {
mAccessibleMessageContentView.setVisibility(View.GONE);
mMessageContentView.setVisibility(View.VISIBLE);
mScreenReaderEnabled = false;
+
+ mHeaderPlaceHolder.removeView(mHeaderContainer);
+ // the HTC version of WebView tries to force the background of the
+ // titlebar, which is really unfair.
+ mHeaderContainer.setBackgroundColor(((K9Activity)activity).getThemeBackgroundColor());
+
+ mTitleBarHeaderContainer = new LinearLayout(activity);
+ mTitleBarHeaderContainer.addView(mHeaderContainer);
+ mMessageContentView.wrapSetTitleBar(mTitleBarHeaderContainer);
}
}
@@ -139,20 +188,27 @@ public class SingleMessageView extends LinearLayout {
public void setLoadPictures(boolean enable) {
mMessageContentView.blockNetworkData(!enable);
setShowPictures(enable);
- showShowPicturesSection(false);
+ showShowPicturesAction(false);
}
public Button downloadRemainderButton() {
return mDownloadRemainder;
}
- public void showShowPicturesSection(boolean show) {
- mShowPicturesSection.setVisibility(show ? View.VISIBLE : View.GONE);
+ 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);
}
public void setHeaders(final Message message, Account account) {
try {
mHeaderContainer.populate(message, account);
+ mHeaderContainer.setVisibility(View.VISIBLE);
} catch (Exception me) {
@@ -181,9 +237,9 @@ public class SingleMessageView extends LinearLayout {
return mHeaderContainer.additionalHeadersVisible();
}
- public void displayMessageBody(Account account, String folder, String uid, Message message, PgpData pgpData) throws MessagingException {
- // TODO - really this code path? this is an odd place to put it
- removeAllAttachments();
+ public void displayMessageBody(Account account, Message message, PgpData pgpData)
+ throws MessagingException {
+ resetView();
String type;
String text = pgpData.getDecryptedData();
@@ -197,7 +253,8 @@ public class SingleMessageView extends LinearLayout {
if (text != null) {
final String emailText = text;
final String contentType = type;
- loadBodyFromText(account.getCryptoProvider(), pgpData, message, emailText, contentType);
+ loadBodyFromText(message, emailText, contentType);
+ updateCryptoLayout(account.getCryptoProvider(), pgpData, message);
// 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.
@@ -210,7 +267,7 @@ public class SingleMessageView extends LinearLayout {
mContacts.isInContacts(from[0].getAddress()))) {
setLoadPictures(true);
} else {
- showShowPicturesSection(true);
+ showShowPicturesAction(true);
}
}
} else {
@@ -224,14 +281,13 @@ public class SingleMessageView extends LinearLayout {
}
- public void loadBodyFromText(CryptoProvider cryptoProvider, PgpData pgpData, Message message, String emailText, String contentType) {
+ public void loadBodyFromText(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);
}
@@ -239,6 +295,23 @@ public class SingleMessageView extends LinearLayout {
mCryptoView.updateLayout(cp, pgpData, message);
}
+ public void showAttachments(boolean show) {
+ mAttachmentsContainer.setVisibility(show ? View.VISIBLE : View.GONE);
+ boolean showHidden = (show && mHiddenAttachments.getChildCount() > 0);
+ mShowHiddenAttachments.setVisibility(showHidden ? View.VISIBLE : View.GONE);
+
+ if (show) {
+ moveHeaderToLayout();
+ } else {
+ moveHeaderToWebViewTitleBar();
+ mHiddenAttachments.setVisibility(View.GONE);
+ }
+ }
+
+ public void showMessageWebView(boolean show) {
+ mMessageContentView.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+
public void setAttachmentsEnabled(boolean enabled) {
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
AttachmentView attachment = (AttachmentView) mAttachments.getChildAt(i);
@@ -247,7 +320,6 @@ public class SingleMessageView extends LinearLayout {
}
}
-
public void removeAllAttachments() {
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
mAttachments.removeView(mAttachments.getChildAt(i));
@@ -263,25 +335,23 @@ public class SingleMessageView extends LinearLayout {
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(MimeHeader.HEADER_CONTENT_ID) != null) {
- return;
- }
AttachmentView view = (AttachmentView)mInflater.inflate(R.layout.message_view_attachment, null);
view.setCallback(attachmentCallback);
+
if (view.populateFromPart(part, message, account, controller, listener)) {
addAttachment(view);
+ } else {
+ addHiddenAttachment(view);
}
}
}
public void addAttachment(View attachmentView) {
mAttachments.addView(attachmentView);
- mAttachments.setVisibility(View.VISIBLE);
+ }
+
+ public void addHiddenAttachment(View attachmentView) {
+ mHiddenAttachments.addView(attachmentView);
}
public void zoom(KeyEvent event) {
@@ -303,9 +373,13 @@ public class SingleMessageView extends LinearLayout {
public void resetView() {
setLoadPictures(false);
mMessageContentView.scrollTo(0, 0);
- mHeaderContainer.setVisibility(View.GONE);
mMessageContentView.clearView();
mAttachments.removeAllViews();
+ mHiddenAttachments.removeAllViews();
+ }
+
+ public void resetHeaderView() {
+ mHeaderContainer.setVisibility(View.GONE);
}
public AttachmentView.AttachmentFileDownloadCallback getAttachmentCallback() {
@@ -317,20 +391,17 @@ public class SingleMessageView extends LinearLayout {
this.attachmentCallback = attachmentCallback;
}
- /**
- * Save a copy of the {@link com.fsck.k9.controller.MessagingController#getListeners()}. This method will also
- * pass along these listeners to the underlying views.
- * @param listeners Set of listeners.
- */
- public void setListeners(final Set listeners) {
- if(!mScreenReaderEnabled) {
- if(mMessageContentView != null) {
- mMessageContentView.setListeners(listeners);
- }
- } else {
- if(mAccessibleMessageContentView != null) {
- mAccessibleMessageContentView.setListeners(listeners);
- }
+ private void moveHeaderToLayout() {
+ if (mTitleBarHeaderContainer != null && mTitleBarHeaderContainer.getChildCount() != 0) {
+ mTitleBarHeaderContainer.removeView(mHeaderContainer);
+ mHeaderPlaceHolder.addView(mHeaderContainer);
+ }
+ }
+
+ private void moveHeaderToWebViewTitleBar() {
+ if (mTitleBarHeaderContainer != null && mTitleBarHeaderContainer.getChildCount() == 0) {
+ mHeaderPlaceHolder.removeView(mHeaderContainer);
+ mTitleBarHeaderContainer.addView(mHeaderContainer);
}
}
}