From f1baa8f461c92b4d489e7ac52e0c91cef16eed0f Mon Sep 17 00:00:00 2001 From: m0viefreak Date: Fri, 2 Mar 2012 05:16:58 +0100 Subject: [PATCH 01/63] invalidate message content WebView when the message header changes This fixes redraw issues where text appears doubled or is cut off --- src/com/fsck/k9/view/MessageHeader.java | 17 +++++++++++++++++ src/com/fsck/k9/view/SingleMessageView.java | 10 +++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/com/fsck/k9/view/MessageHeader.java b/src/com/fsck/k9/view/MessageHeader.java index a3f10afad..ed51d70d4 100644 --- a/src/com/fsck/k9/view/MessageHeader.java +++ b/src/com/fsck/k9/view/MessageHeader.java @@ -63,6 +63,8 @@ public class MessageHeader extends ScrollView implements OnClickListener { private ImageView mShowAdditionalHeadersIcon; private SavedState mSavedState; + private OnLayoutChangedListener mOnLayoutChangedListener; + /** * Pair class is only available since API Level 5, so we need * this helper class unfortunately @@ -272,6 +274,7 @@ public class MessageHeader extends ScrollView implements OnClickListener { } else { showAdditionalHeaders(); } + layoutChanged(); } private List getAdditionalHeaders(final Message message) @@ -378,4 +381,18 @@ public class MessageHeader extends ScrollView implements OnClickListener { out.writeInt((this.additionalHeadersVisible) ? 1 : 0); } } + + public interface OnLayoutChangedListener { + void onLayoutChanged(); + } + + public void setOnLayoutChangedListener(OnLayoutChangedListener listener) { + mOnLayoutChangedListener = listener; + } + + private void layoutChanged() { + if (mOnLayoutChangedListener != null) { + mOnLayoutChangedListener.onLayoutChanged(); + } + } } diff --git a/src/com/fsck/k9/view/SingleMessageView.java b/src/com/fsck/k9/view/SingleMessageView.java index b1e0980e9..a19796d8c 100644 --- a/src/com/fsck/k9/view/SingleMessageView.java +++ b/src/com/fsck/k9/view/SingleMessageView.java @@ -33,7 +33,8 @@ import com.fsck.k9.mail.store.LocalStore.LocalMessage; import java.util.List; -public class SingleMessageView extends LinearLayout implements OnClickListener { +public class SingleMessageView extends LinearLayout implements OnClickListener, + MessageHeader.OnLayoutChangedListener { private boolean mScreenReaderEnabled; private MessageCryptoView mCryptoView; private MessageWebView mMessageContentView; @@ -65,6 +66,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { mHeaderPlaceHolder = (LinearLayout) findViewById(R.id.message_view_header_container); mHeaderContainer = (MessageHeader) findViewById(R.id.header_container); + mHeaderContainer.setOnLayoutChangedListener(this); mAttachmentsContainer = findViewById(R.id.attachments_container); mInsideAttachmentsContainer = (LinearLayout) findViewById(R.id.inside_attachments_container); @@ -508,6 +510,12 @@ public class SingleMessageView extends LinearLayout implements OnClickListener { mSavedState = savedState; } + public void onLayoutChanged() { + if (mMessageContentView != null) { + mMessageContentView.invalidate(); + } + } + static class SavedState extends BaseSavedState { boolean attachmentViewVisible; boolean hiddenAttachmentsVisible; From 8d12244a9c23da0b5146afa418f75a4b7e49747d Mon Sep 17 00:00:00 2001 From: m0viefreak Date: Fri, 2 Mar 2012 05:41:01 +0100 Subject: [PATCH 02/63] Message header changes * remove expand/collapse arrows, instead use the background area of the header to toggle * allow expanding of To: and Cc: texts when too long and cut off by clicking on them --- ...xml => message_view_header_background.xml} | 0 res/layout/message_view_header.xml | 50 ++----------------- src/com/fsck/k9/view/MessageHeader.java | 37 ++++++++++---- 3 files changed, 31 insertions(+), 56 deletions(-) rename res/drawable/{separator_area_background.xml => message_view_header_background.xml} (100%) diff --git a/res/drawable/separator_area_background.xml b/res/drawable/message_view_header_background.xml similarity index 100% rename from res/drawable/separator_area_background.xml rename to res/drawable/message_view_header_background.xml diff --git a/res/layout/message_view_header.xml b/res/layout/message_view_header.xml index fe5c486a0..5b4d0d591 100644 --- a/res/layout/message_view_header.xml +++ b/res/layout/message_view_header.xml @@ -17,7 +17,7 @@ android:layout_height="wrap_content" android:stretchColumns="1" android:shrinkColumns="1" - android:background="@color/message_view_header_background"> + android:background="@drawable/message_view_header_background"> @@ -194,51 +194,11 @@ - - - - - - - - - - - - - - - - - + android:layout_height="1.5dp" + android:background="#59000000"/> getAdditionalHeaders(final Message message) throws MessagingException { List additionalHeaders = new LinkedList(); From 78615f878d4ea28201e79652bd2c8694a09980a4 Mon Sep 17 00:00:00 2001 From: ashley willis Date: Mon, 5 Mar 2012 15:17:31 -0600 Subject: [PATCH 03/63] added From: addresses on reply all when Reply-To: is set. don't repeat address in To: field if it's already included in replyToAddresses. --- src/com/fsck/k9/activity/MessageCompose.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/com/fsck/k9/activity/MessageCompose.java b/src/com/fsck/k9/activity/MessageCompose.java index 927078cf2..8ecc78a08 100644 --- a/src/com/fsck/k9/activity/MessageCompose.java +++ b/src/com/fsck/k9/activity/MessageCompose.java @@ -2289,8 +2289,15 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } if (ACTION_REPLY_ALL.equals(action)) { + if (message.getReplyTo().length > 0) { + for (Address address : message.getFrom()) { + if (!mAccount.isAnIdentity(address)) { + addAddress(mToView, address); + } + } + } for (Address address : message.getRecipients(RecipientType.TO)) { - if (!mAccount.isAnIdentity(address)) { + if (!mAccount.isAnIdentity(address) && !Utility.arrayContains(replyToAddresses, address)) { addAddress(mToView, address); } From faf9dc6e0263e7cb3df1d09ebdeea6fb85777df8 Mon Sep 17 00:00:00 2001 From: cketti Date: Tue, 6 Mar 2012 04:26:18 +0100 Subject: [PATCH 04/63] Restored show/more less indicator in the message header --- res/layout/message_view_header.xml | 62 ++++++++++++++++++++++++- src/com/fsck/k9/view/MessageHeader.java | 11 ++++- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/res/layout/message_view_header.xml b/res/layout/message_view_header.xml index 5b4d0d591..19bd2a52d 100644 --- a/res/layout/message_view_header.xml +++ b/res/layout/message_view_header.xml @@ -30,6 +30,7 @@ @@ -134,14 +135,56 @@ + + - + + + + + + + + + + + + + + @@ -188,6 +231,21 @@ android:textColor="?android:attr/textColorPrimary" android:textAppearance="?android:attr/textAppearanceSmall"/> + + + + + diff --git a/src/com/fsck/k9/view/MessageHeader.java b/src/com/fsck/k9/view/MessageHeader.java index f3f3b9a32..277885b95 100644 --- a/src/com/fsck/k9/view/MessageHeader.java +++ b/src/com/fsck/k9/view/MessageHeader.java @@ -59,6 +59,7 @@ public class MessageHeader extends ScrollView implements OnClickListener { private Account mAccount; private FontSizes mFontSizes = K9.getFontSizes(); private Contacts mContacts; + private ImageView mShowAdditionalHeadersIcon; private SavedState mSavedState; private OnLayoutChangedListener mOnLayoutChangedListener; @@ -98,6 +99,7 @@ public class MessageHeader extends ScrollView implements OnClickListener { mDateView = (TextView) findViewById(R.id.date); mTimeView = (TextView) findViewById(R.id.time); mFlagged = (CheckBox) findViewById(R.id.flagged); + mShowAdditionalHeadersIcon = (ImageView) findViewById(R.id.show_additional_headers_icon); defaultSubjectColor = mSubjectView.getCurrentTextColor(); mSubjectView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewSubject()); @@ -113,10 +115,13 @@ public class MessageHeader extends ScrollView implements OnClickListener { ((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()); - mToView.setOnClickListener(this); - mCcView.setOnClickListener(this); mFromView.setOnClickListener(this); findViewById(R.id.top_container).setOnClickListener(this); + + TextView dummyDateView = (TextView) findViewById(R.id.dummy_date); + TextView dummyTimeView = (TextView) findViewById(R.id.dummy_time); + dummyTimeView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewTime()); + dummyDateView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewDate()); } @Override @@ -168,6 +173,7 @@ public class MessageHeader extends ScrollView implements OnClickListener { private void hideAdditionalHeaders() { mAdditionalHeadersView.setVisibility(View.GONE); mAdditionalHeadersView.setText(""); + mShowAdditionalHeadersIcon.setImageResource(R.drawable.show_more); } @@ -186,6 +192,7 @@ public class MessageHeader extends ScrollView implements OnClickListener { // Show the additional headers that we have got. populateAdditionalHeadersView(additionalHeaders); mAdditionalHeadersView.setVisibility(View.VISIBLE); + mShowAdditionalHeadersIcon.setImageResource(R.drawable.show_less); } if (!allHeadersDownloaded) { /* From 4721d92e7909fd00619a02571916c438ec5b395b Mon Sep 17 00:00:00 2001 From: cketti Date: Wed, 7 Mar 2012 21:40:41 +0100 Subject: [PATCH 05/63] Avoid some instances of autoboxing This will hopefully allow us to compile with "Android Java IDE". --- src/com/fsck/k9/activity/MessageCompose.java | 10 +++++----- src/com/fsck/k9/controller/MessagingController.java | 10 ++++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/com/fsck/k9/activity/MessageCompose.java b/src/com/fsck/k9/activity/MessageCompose.java index 8ecc78a08..e14c34c8e 100644 --- a/src/com/fsck/k9/activity/MessageCompose.java +++ b/src/com/fsck/k9/activity/MessageCompose.java @@ -2427,19 +2427,19 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc updateFrom(); Integer bodyLength = k9identity.get(IdentityField.LENGTH) != null - ? Integer.parseInt(k9identity.get(IdentityField.LENGTH)) + ? Integer.valueOf(k9identity.get(IdentityField.LENGTH)) : 0; Integer bodyOffset = k9identity.get(IdentityField.OFFSET) != null - ? Integer.parseInt(k9identity.get(IdentityField.OFFSET)) + ? Integer.valueOf(k9identity.get(IdentityField.OFFSET)) : 0; Integer bodyFooterOffset = k9identity.get(IdentityField.FOOTER_OFFSET) != null - ? Integer.parseInt(k9identity.get(IdentityField.FOOTER_OFFSET)) + ? Integer.valueOf(k9identity.get(IdentityField.FOOTER_OFFSET)) : null; Integer bodyPlainLength = k9identity.get(IdentityField.PLAIN_LENGTH) != null - ? Integer.parseInt(k9identity.get(IdentityField.PLAIN_LENGTH)) + ? Integer.valueOf(k9identity.get(IdentityField.PLAIN_LENGTH)) : null; Integer bodyPlainOffset = k9identity.get(IdentityField.PLAIN_OFFSET) != null - ? Integer.parseInt(k9identity.get(IdentityField.PLAIN_OFFSET)) + ? Integer.valueOf(k9identity.get(IdentityField.PLAIN_OFFSET)) : null; mQuoteStyle = k9identity.get(IdentityField.QUOTE_STYLE) != null ? QuoteStyle.valueOf(k9identity.get(IdentityField.QUOTE_STYLE)) diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 023d19f60..250e3fb3d 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -629,7 +629,7 @@ public class MessagingController implements Runnable { Log.i(K9.LOG_TAG, "searchLocalMessages (" + "accountUuids=" + Utility.combine(accountUuids, ',') + ", folderNames = " + Utility.combine(folderNames, ',') - + ", messages.size() = " + (messages != null ? messages.length : null) + + ", messages.size() = " + (messages != null ? messages.length : -1) + ", query = " + query + ", integrate = " + integrate + ", requiredFlags = " + Utility.combine(requiredFlags, ',') @@ -4182,7 +4182,13 @@ public class MessagingController implements Runnable { NotificationSetting n = account.getNotificationSetting(); - configureNotification(notif, (n.shouldRing() ? n.getRingtone() : null), (n.shouldVibrate() ? n.getVibration() : null), (n.isLed() ? n.getLedColor() : null), K9.NOTIFICATION_LED_BLINK_SLOW, ringAndVibrate); + configureNotification( + notif, + (n.shouldRing()) ? n.getRingtone() : null, + (n.shouldVibrate()) ? n.getVibration() : null, + (n.isLed()) ? Integer.valueOf(n.getLedColor()) : null, + K9.NOTIFICATION_LED_BLINK_SLOW, + ringAndVibrate); notifMgr.notify(account.getAccountNumber(), notif); } From ee34344d30fded0c3cba2b489a3462b271ff97a8 Mon Sep 17 00:00:00 2001 From: cketti Date: Wed, 7 Mar 2012 21:52:47 +0100 Subject: [PATCH 06/63] Upgrade to SDK 15 --- project.properties | 2 +- src/com/fsck/k9/preferences/Editor.java | 6 ++++ src/com/fsck/k9/preferences/Storage.java | 7 ++++ src/com/fsck/k9/provider/MessageProvider.java | 32 +++++++++++-------- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/project.properties b/project.properties index 213821e1f..46fb34716 100644 --- a/project.properties +++ b/project.properties @@ -11,5 +11,5 @@ split.density=false java.encoding=utf8 # Project target. -target=android-9 +target=android-15 extensible.libs.classpath=compile-only-libs diff --git a/src/com/fsck/k9/preferences/Editor.java b/src/com/fsck/k9/preferences/Editor.java index 412d14ff8..88479d0e2 100644 --- a/src/com/fsck/k9/preferences/Editor.java +++ b/src/com/fsck/k9/preferences/Editor.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; public class Editor implements android.content.SharedPreferences.Editor { private Storage storage; @@ -138,4 +139,9 @@ public class Editor implements android.content.SharedPreferences.Editor { return this; } + @Override + public android.content.SharedPreferences.Editor putStringSet(String arg0, Set arg1) { + throw new RuntimeException("Not implemented"); + } + } diff --git a/src/com/fsck/k9/preferences/Storage.java b/src/com/fsck/k9/preferences/Storage.java index 34c978754..b9041c8f6 100644 --- a/src/com/fsck/k9/preferences/Storage.java +++ b/src/com/fsck/k9/preferences/Storage.java @@ -15,6 +15,7 @@ import java.net.URI; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -399,4 +400,10 @@ public class Storage implements SharedPreferences { Log.e(K9.LOG_TAG, "Error writing key '" + key + "', value = '" + value + "'"); } } + + + @Override + public Set getStringSet(String arg0, Set arg1) { + throw new RuntimeException("Not implemented"); + } } diff --git a/src/com/fsck/k9/provider/MessageProvider.java b/src/com/fsck/k9/provider/MessageProvider.java index 50220c31c..0557575af 100644 --- a/src/com/fsck/k9/provider/MessageProvider.java +++ b/src/com/fsck/k9/provider/MessageProvider.java @@ -1,18 +1,5 @@ package com.fsck.k9.provider; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.Semaphore; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentValues; @@ -46,6 +33,19 @@ import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.store.LocalStore; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.Semaphore; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + public class MessageProvider extends ContentProvider { public static interface MessageColumns extends BaseColumns { @@ -714,6 +714,12 @@ public class MessageProvider extends ContentProvider { checkClosed(); mCursor.unregisterDataSetObserver(observer); } + + @Override + public int getType(int columnIndex) { + checkClosed(); + return mCursor.getType(columnIndex); + } } protected class ThrottlingQueryHandler implements QueryHandler { From 7163d39091b2a32724d9767b5ebf92dcb786a90b Mon Sep 17 00:00:00 2001 From: cketti Date: Fri, 9 Mar 2012 21:50:26 +0100 Subject: [PATCH 07/63] Change ImapException to always be a permanent error This way IMAP commands that get anything but an "OK" response are never tried again (pending actions). --- src/com/fsck/k9/mail/store/ImapStore.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/com/fsck/k9/mail/store/ImapStore.java b/src/com/fsck/k9/mail/store/ImapStore.java index 6a77db634..008d8d45a 100644 --- a/src/com/fsck/k9/mail/store/ImapStore.java +++ b/src/com/fsck/k9/mail/store/ImapStore.java @@ -2735,13 +2735,8 @@ public class ImapStore extends Store { private static final long serialVersionUID = 3725007182205882394L; String mAlertText; - public ImapException(String message, String alertText, Throwable throwable) { - super(message, throwable); - this.mAlertText = alertText; - } - public ImapException(String message, String alertText) { - super(message); + super(message, true); this.mAlertText = alertText; } From 0cb4207ef73027e86feee4400647ad8f10f777d9 Mon Sep 17 00:00:00 2001 From: cketti Date: Fri, 9 Mar 2012 21:51:48 +0100 Subject: [PATCH 08/63] IMAP: don't create the destination folder when copying messages --- src/com/fsck/k9/mail/store/ImapStore.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/com/fsck/k9/mail/store/ImapStore.java b/src/com/fsck/k9/mail/store/ImapStore.java index 008d8d45a..043920aa6 100644 --- a/src/com/fsck/k9/mail/store/ImapStore.java +++ b/src/com/fsck/k9/mail/store/ImapStore.java @@ -1101,15 +1101,6 @@ public class ImapStore extends Store { try { String remoteDestName = encodeString(encodeFolderName(iFolder.getPrefixedName())); - if (!exists(remoteDestName)) { - // If the remote trash folder doesn't exist we try to create it. - if (K9.DEBUG) { - Log.i(K9.LOG_TAG, "Attempting to create remote folder '" + remoteDestName + - "' for " + getLogId()); - } - iFolder.create(FolderType.HOLDS_MESSAGES); - } - //TODO: Split this into multiple commands if the command exceeds a certain length. mConnection.sendCommand(String.format("UID COPY %s %s", Utility.combine(uids, ','), From dda072eff65c135a59da78b8b04482471e9ad199 Mon Sep 17 00:00:00 2001 From: ashley willis Date: Sun, 11 Mar 2012 14:31:35 -0500 Subject: [PATCH 09/63] Upgrade to SDK 15 --- ant.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ant.properties b/ant.properties index cfc6e1ad4..6be7f3220 100644 --- a/ant.properties +++ b/ant.properties @@ -19,5 +19,5 @@ split.density=false java.encoding=utf8 # Project target. -target=android-9 +target=android-15 extensible.libs.classpath=compile-only-libs From f9a30d1822b0de034bab4d08b1e9392b7d7e69e4 Mon Sep 17 00:00:00 2001 From: ashley willis Date: Sun, 11 Mar 2012 17:48:56 -0500 Subject: [PATCH 10/63] added sort by arrival option. --- res/menu/message_list_option.xml | 4 ++++ res/values/strings.xml | 1 + src/com/fsck/k9/activity/MessageInfoHolder.java | 1 + src/com/fsck/k9/activity/MessageList.java | 16 +++++++++++++++- .../fsck/k9/controller/MessagingController.java | 1 + src/com/fsck/k9/helper/MessageHelper.java | 1 + 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/res/menu/message_list_option.xml b/res/menu/message_list_option.xml index 2aa550a0f..b8bbf03a7 100644 --- a/res/menu/message_list_option.xml +++ b/res/menu/message_list_option.xml @@ -15,6 +15,10 @@ android:id="@+id/set_sort_date" android:title="@string/sort_by_date" /> + Sort by... Date + Arrival Sender Subject Star diff --git a/src/com/fsck/k9/activity/MessageInfoHolder.java b/src/com/fsck/k9/activity/MessageInfoHolder.java index e19fb953a..baee99b9a 100644 --- a/src/com/fsck/k9/activity/MessageInfoHolder.java +++ b/src/com/fsck/k9/activity/MessageInfoHolder.java @@ -7,6 +7,7 @@ import com.fsck.k9.mail.store.LocalStore.LocalMessage; public class MessageInfoHolder { public String date; public Date compareDate; + public Date compareArrival; public String compareSubject; public CharSequence sender; public String senderAddress; diff --git a/src/com/fsck/k9/activity/MessageList.java b/src/com/fsck/k9/activity/MessageList.java index f874267f9..aec709cfe 100644 --- a/src/com/fsck/k9/activity/MessageList.java +++ b/src/com/fsck/k9/activity/MessageList.java @@ -185,6 +185,15 @@ public class MessageList } + public static class ArrivalComparator implements Comparator { + + @Override + public int compare(MessageInfoHolder object1, MessageInfoHolder object2) { + return object1.compareArrival.compareTo(object2.compareArrival); + } + + } + public static class SubjectComparator implements Comparator { @Override @@ -234,6 +243,7 @@ public class MessageList final Map> map = new EnumMap>(SORT_TYPE.class); map.put(SORT_TYPE.SORT_ATTACHMENT, new AttachmentComparator()); map.put(SORT_TYPE.SORT_DATE, new DateComparator()); + map.put(SORT_TYPE.SORT_ARRIVAL, new ArrivalComparator()); map.put(SORT_TYPE.SORT_FLAGGED, new FlaggedComparator()); map.put(SORT_TYPE.SORT_SENDER, new SenderComparator()); map.put(SORT_TYPE.SORT_SUBJECT, new SubjectComparator()); @@ -460,7 +470,7 @@ public class MessageList { // add the date comparator if not already specified - if (sortType != SORT_TYPE.SORT_DATE) { + if (sortType != SORT_TYPE.SORT_DATE && sortType != SORT_TYPE.SORT_ARRIVAL) { final Comparator comparator = SORT_COMPARATORS.get(SORT_TYPE.SORT_DATE); if (sortDateAscending) { chain.add(comparator); @@ -1439,6 +1449,10 @@ public class MessageList changeSort(SORT_TYPE.SORT_DATE); return true; } + case R.id.set_sort_arrival: { + changeSort(SORT_TYPE.SORT_ARRIVAL); + return true; + } case R.id.set_sort_subject: { changeSort(SORT_TYPE.SORT_SUBJECT); return true; diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 250e3fb3d..33acd96f1 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -146,6 +146,7 @@ public class MessagingController implements Runnable { public enum SORT_TYPE { SORT_DATE(R.string.sort_earliest_first, R.string.sort_latest_first, false), + SORT_ARRIVAL(R.string.sort_earliest_first, R.string.sort_latest_first, false), SORT_SUBJECT(R.string.sort_subject_alpha, R.string.sort_subject_re_alpha, true), SORT_SENDER(R.string.sort_sender_alpha, R.string.sort_sender_re_alpha, true), SORT_UNREAD(R.string.sort_unread_first, R.string.sort_unread_last, true), diff --git a/src/com/fsck/k9/helper/MessageHelper.java b/src/com/fsck/k9/helper/MessageHelper.java index 43b208a77..018b481e2 100644 --- a/src/com/fsck/k9/helper/MessageHelper.java +++ b/src/com/fsck/k9/helper/MessageHelper.java @@ -49,6 +49,7 @@ public class MessageHelper { try { LocalMessage message = (LocalMessage) m; target.message = message; + target.compareArrival = message.getInternalDate(); target.compareDate = message.getSentDate(); if (target.compareDate == null) { target.compareDate = message.getInternalDate(); From 561d2a1a44ae6e9615b9a9c04d8a040b4a724690 Mon Sep 17 00:00:00 2001 From: cketti Date: Mon, 12 Mar 2012 17:44:53 +0100 Subject: [PATCH 11/63] Added unit test for MimeUtility.getHeaderParameter() --- .../k9/mail/internet/MimeUtilityTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/src/com/fsck/k9/mail/internet/MimeUtilityTest.java diff --git a/tests/src/com/fsck/k9/mail/internet/MimeUtilityTest.java b/tests/src/com/fsck/k9/mail/internet/MimeUtilityTest.java new file mode 100644 index 000000000..8bf122395 --- /dev/null +++ b/tests/src/com/fsck/k9/mail/internet/MimeUtilityTest.java @@ -0,0 +1,39 @@ +package com.fsck.k9.mail.internet; + +import android.test.AndroidTestCase; + +public class MimeUtilityTest extends AndroidTestCase { + + public void testGetHeaderParameter() { + String result; + + /* Test edge cases */ + result = MimeUtility.getHeaderParameter(";", null); + assertEquals(null, result); + + result = MimeUtility.getHeaderParameter("name", "name"); + assertEquals(null, result); + + result = MimeUtility.getHeaderParameter("name=", "name"); + assertEquals("", result); + + result = MimeUtility.getHeaderParameter("name=\"", "name"); + assertEquals("\"", result); + + /* Test expected cases */ + result = MimeUtility.getHeaderParameter("name=value", "name"); + assertEquals("value", result); + + result = MimeUtility.getHeaderParameter("name = value", "name"); + assertEquals("value", result); + + result = MimeUtility.getHeaderParameter("name=\"value\"", "name"); + assertEquals("value", result); + + result = MimeUtility.getHeaderParameter("name = \"value\"" , "name"); + assertEquals("value", result); + + result = MimeUtility.getHeaderParameter("name=\"\"", "name"); + assertEquals("", result); + } +} From aeb0220e56b4717e4af262097f391d42fd3a3a4b Mon Sep 17 00:00:00 2001 From: cketti Date: Mon, 12 Mar 2012 17:45:34 +0100 Subject: [PATCH 12/63] Fixed MimeUtility.getHeaderParameter() to not crash on unexpected input --- src/com/fsck/k9/mail/internet/MimeUtility.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index 405243d4b..0b8caf71f 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -953,16 +953,20 @@ public class MimeUtility { } header = header.replaceAll("\r|\n", ""); String[] parts = header.split(";"); - if (name == null) { + if (name == null && parts.length > 0) { return parts[0]; } for (String part : parts) { if (part.trim().toLowerCase(Locale.US).startsWith(name.toLowerCase(Locale.US))) { - String parameter = part.split("=", 2)[1].trim(); - if (parameter.startsWith("\"") && parameter.endsWith("\"")) { - return parameter.substring(1, parameter.length() - 1); - } else { - return parameter; + String[] partParts = part.split("=", 2); + if (partParts.length == 2) { + String parameter = partParts[1].trim(); + int len = parameter.length(); + if (len >= 2 && parameter.startsWith("\"") && parameter.endsWith("\"")) { + return parameter.substring(1, len - 1); + } else { + return parameter; + } } } } From f181e923ca8bb4f75f250f6f56f8b4409e0a4ae3 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 15 Mar 2012 21:21:00 +0100 Subject: [PATCH 13/63] Don't modify draft messages when storing them in the database --- .../fsck/k9/mail/internet/MimeUtility.java | 57 +++++++++++++++++++ src/com/fsck/k9/mail/store/LocalStore.java | 27 +++++++-- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index 0b8caf71f..0405fd567 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -3260,4 +3260,61 @@ public class MimeUtility { return charset; } + + public static ViewableContainer extractPartsFromDraft(Message message) + throws MessagingException { + + Body body = message.getBody(); + if (message.isMimeType("multipart/mixed") && body instanceof MimeMultipart) { + MimeMultipart multipart = (MimeMultipart) body; + + ViewableContainer container; + int count = multipart.getCount(); + if (count >= 1) { + // The first part is either a text/plain or a multipart/alternative + BodyPart firstPart = multipart.getBodyPart(0); + container = extractTextual(firstPart); + + // The rest should be attachments + for (int i = 1; i < count; i++) { + BodyPart bodyPart = multipart.getBodyPart(i); + container.attachments.add(bodyPart); + } + } else { + container = new ViewableContainer(null, null, new ArrayList()); + } + + return container; + } + + return extractTextual(message); + } + + private static ViewableContainer extractTextual(Part part) throws MessagingException { + String text = null; + String html = null; + List attachments = new ArrayList(); + + Body firstBody = part.getBody(); + if (part.isMimeType("text/plain") && + firstBody instanceof TextBody) { + text = ((TextBody) firstBody).getText(); + } else if (part.isMimeType("multipart/alternative") && + firstBody instanceof MimeMultipart) { + MimeMultipart multipart = (MimeMultipart) firstBody; + for (int i = 0, count = multipart.getCount(); i < count; i++) { + BodyPart bodyPart = multipart.getBodyPart(i); + if (bodyPart.getBody() instanceof TextBody) { + TextBody textBody = (TextBody) bodyPart.getBody(); + if (text == null && bodyPart.isMimeType("text/plain")) { + text = textBody.getText(); + } else if (html == null && bodyPart.isMimeType("text/html")) { + html = textBody.getText(); + } + } + } + } + + return new ViewableContainer(text, html, attachments); + } } diff --git a/src/com/fsck/k9/mail/store/LocalStore.java b/src/com/fsck/k9/mail/store/LocalStore.java index f9d769511..64d89610c 100644 --- a/src/com/fsck/k9/mail/store/LocalStore.java +++ b/src/com/fsck/k9/mail/store/LocalStore.java @@ -2134,12 +2134,29 @@ public class LocalStore extends Store implements Serializable { deleteAttachments(message.getUid()); } - ViewableContainer container = - MimeUtility.extractTextAndAttachments(mApplication, message); + boolean isDraft = (message.getHeader(K9.IDENTITY_HEADER) != null); - List attachments = container.attachments; - String text = container.text; - String html = HtmlConverter.convertEmoji2Img(container.html); + List attachments; + String text; + String html; + if (isDraft) { + // Don't modify the text/plain or text/html part of our own + // draft messages because this will cause the values stored in + // the identity header to be wrong. + ViewableContainer container = + MimeUtility.extractPartsFromDraft(message); + + text = container.text; + html = container.html; + attachments = container.attachments; + } else { + ViewableContainer container = + MimeUtility.extractTextAndAttachments(mApplication, message); + + attachments = container.attachments; + text = container.text; + html = HtmlConverter.convertEmoji2Img(container.html); + } String preview = calculateContentPreview(text); From a48adafbbc99ce2b0ad275060f2045d1f8199328 Mon Sep 17 00:00:00 2001 From: cketti Date: Fri, 16 Mar 2012 22:56:09 +0100 Subject: [PATCH 14/63] Don't use null for 'text' and 'html' in ViewableContainer --- src/com/fsck/k9/mail/internet/MimeUtility.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index 0405fd567..1c43d3b58 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -3281,7 +3281,7 @@ public class MimeUtility { container.attachments.add(bodyPart); } } else { - container = new ViewableContainer(null, null, new ArrayList()); + container = new ViewableContainer("", "", new ArrayList()); } return container; @@ -3291,8 +3291,8 @@ public class MimeUtility { } private static ViewableContainer extractTextual(Part part) throws MessagingException { - String text = null; - String html = null; + String text = ""; + String html = ""; List attachments = new ArrayList(); Body firstBody = part.getBody(); From dbf38dae653aa2fdfe2372cec2ab2e19bea5f5c7 Mon Sep 17 00:00:00 2001 From: cketti Date: Sat, 17 Mar 2012 00:30:40 +0100 Subject: [PATCH 15/63] Fixed the change of the previous commit --- src/com/fsck/k9/mail/internet/MimeUtility.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index 1c43d3b58..20486232c 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -3306,9 +3306,9 @@ public class MimeUtility { BodyPart bodyPart = multipart.getBodyPart(i); if (bodyPart.getBody() instanceof TextBody) { TextBody textBody = (TextBody) bodyPart.getBody(); - if (text == null && bodyPart.isMimeType("text/plain")) { + if ("".equals(text) && bodyPart.isMimeType("text/plain")) { text = textBody.getText(); - } else if (html == null && bodyPart.isMimeType("text/html")) { + } else if ("".equals(html) && bodyPart.isMimeType("text/html")) { html = textBody.getText(); } } From 3fa8081e88e0b035377c721fd21676a735d82baf Mon Sep 17 00:00:00 2001 From: cketti Date: Sat, 17 Mar 2012 03:19:09 +0100 Subject: [PATCH 16/63] Fixed MimeUtility.extractTextual() when loading messages from the server --- src/com/fsck/k9/mail/internet/MimeUtility.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index 20486232c..eb6948c11 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -3304,12 +3304,12 @@ public class MimeUtility { MimeMultipart multipart = (MimeMultipart) firstBody; for (int i = 0, count = multipart.getCount(); i < count; i++) { BodyPart bodyPart = multipart.getBodyPart(i); - if (bodyPart.getBody() instanceof TextBody) { - TextBody textBody = (TextBody) bodyPart.getBody(); - if ("".equals(text) && bodyPart.isMimeType("text/plain")) { - text = textBody.getText(); - } else if ("".equals(html) && bodyPart.isMimeType("text/html")) { - html = textBody.getText(); + String bodyText = getTextFromPart(bodyPart); + if (bodyText != null) { + if (text.length() == 0 && bodyPart.isMimeType("text/plain")) { + text = bodyText; + } else if (html.length() == 0 && bodyPart.isMimeType("text/html")) { + html = bodyText; } } } From f9a35aeaeeae67bd88c3b253c25d06832ca7da73 Mon Sep 17 00:00:00 2001 From: cketti Date: Sat, 17 Mar 2012 04:15:30 +0100 Subject: [PATCH 17/63] Replace CRLF with LF when loading drafts This is necessary because we save the offset and length of the user- supplied text in the identity header. These values are then later used to split the draft in user text and quoted message. When calculating these values we operate on a string with LF line endings. Ideally we want to do the reverse operation on the same string, but when saving the message to the server LF is converted to CRLF to create RFC-conforming messages. This is only a hack and will probably be the cause of more trouble in the future. A better solution would be to make the identity header more robust or get rid of it entirely. --- .../fsck/k9/mail/internet/MimeUtility.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index eb6948c11..842a7cc8d 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -3296,9 +3296,11 @@ public class MimeUtility { List attachments = new ArrayList(); Body firstBody = part.getBody(); - if (part.isMimeType("text/plain") && - firstBody instanceof TextBody) { - text = ((TextBody) firstBody).getText(); + if (part.isMimeType("text/plain")) { + String bodyText = getTextFromPart(part); + if (bodyText != null) { + text = fixDraftTextBody(bodyText); + } } else if (part.isMimeType("multipart/alternative") && firstBody instanceof MimeMultipart) { MimeMultipart multipart = (MimeMultipart) firstBody; @@ -3307,9 +3309,9 @@ public class MimeUtility { String bodyText = getTextFromPart(bodyPart); if (bodyText != null) { if (text.length() == 0 && bodyPart.isMimeType("text/plain")) { - text = bodyText; + text = fixDraftTextBody(bodyText); } else if (html.length() == 0 && bodyPart.isMimeType("text/html")) { - html = bodyText; + html = fixDraftTextBody(bodyText); } } } @@ -3317,4 +3319,21 @@ public class MimeUtility { return new ViewableContainer(text, html, attachments); } + + /** + * Fix line endings of text bodies in draft messages. + * + *

+ * We create drafts with LF line endings. The values in the identity header are based on that. + * So we replace CRLF with LF when loading messages (from the server). + *

+ * + * @param text + * The body text with CRLF line endings + * + * @return The text with LF line endings + */ + private static String fixDraftTextBody(String text) { + return text.replace("\r\n", "\n"); + } } From 8192d54cce6d5f0796ad9a806627dd9b11249238 Mon Sep 17 00:00:00 2001 From: Koji Arai Date: Sat, 17 Mar 2012 23:08:14 +0900 Subject: [PATCH 18/63] Updated Japanese translation. catch up with f9a30d1. --- res/values-ja/strings.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 55815636e..794a17cf2 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -287,8 +287,11 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール SDカードに添付ファイルを保存できません \"画像表示\"ボタンを押下すると描画します 画像表示 - 添付取込中 - 添付ファイルのビューワー見つけられません .%s + メッセージ表示 + 添付ファイル表示 + 他… + 添付ファイル取得中 + %sのビューワーが見つかりません すべてダウンロード @@ -777,6 +780,7 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール 並べ替え... 日付 + 受信順 送信者 件名 フラグ From 39f2138292225c1b904c5bfbeec41e58c20d100b Mon Sep 17 00:00:00 2001 From: Koji Arai Date: Sun, 4 Mar 2012 09:47:29 +0900 Subject: [PATCH 19/63] added a Japanese provider "auone.jp" --- res/values-ja/strings.xml | 4 +++- res/values/strings.xml | 1 + res/xml/providers.xml | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 794a17cf2..4c678800b 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -799,7 +799,9 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール このプログラムでPOPアクセスが許可されているのは一部の「Plus」アカウントだけです。有料の「Plus」アカウントがなければ、正しいメールアドレスとパスワードを入力してもログインできません。これらのアカウントにはブラウザからアクセスしてください。 - Yahoo! JapanでPOP3アクセスを使う場合は、Yahoo!メールサイトの「メールの設定」にてPOPアクセスが許可されていることを確認してください。 + Yahoo! JapanでPOP3アクセスを行う場合は、Yahoo!メールサイトの「メールの設定」にてPOPアクセスが許可されていることを確認してください。 + + au oneでIMAPアクセスを行う場合は、au oneポータルサイトの「メール」→「設定」ページにて「IMAPを有効にする」をチェックしてください。 証明書が無効です 許可 diff --git a/res/values/strings.xml b/res/values/strings.xml index d7ad77b8d..820960b66 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -805,6 +805,7 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin \"Plus\" account. Please launch the Web browser to gain access to these mail accounts.
If you would like to use POP3 for this provider, You should permit to use POP3 on Yahoo mail settings page. + If you would like to use IMAP or POP3 for this provider, You should permit to use IMAP or POP3 on au one mail settings page. If you would like to use IMAP or POP3 for this provider, You should permit to use IMAP or POP3 on Naver mail settings page. If you would like to use IMAP or POP3 for this provider, You should permit to use IMAP or POP3 on Hanmail(Daum) mail settings page. If you would like to use IMAP or POP3 for this provider, You should permit to use IMAP or POP3 on Paran mail settings page. diff --git a/res/xml/providers.xml b/res/xml/providers.xml index a00108996..d94d929a7 100644 --- a/res/xml/providers.xml +++ b/res/xml/providers.xml @@ -283,6 +283,11 @@ + + + + Date: Wed, 29 Feb 2012 00:51:02 +0900 Subject: [PATCH 20/63] avoid NPE. address may be null when the parser is failed. --- src/com/fsck/k9/mail/internet/MimeUtility.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index 842a7cc8d..13ebc9304 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -2182,6 +2182,8 @@ public class MimeUtility { } private static String getJisVariantFromAddress(String address) { + if (address == null) + return null; if (isInDomain(address, "docomo.ne.jp") || isInDomain(address, "dwmail.jp") || isInDomain(address, "pdx.ne.jp") || isInDomain(address, "willcom.com")) return "docomo"; From 10c37942a632dc1a05cbf7624e0739a7e624ae02 Mon Sep 17 00:00:00 2001 From: Koji Arai Date: Wed, 7 Mar 2012 00:56:33 +0900 Subject: [PATCH 21/63] Added two domains handle docomo emoji --- src/com/fsck/k9/mail/internet/MimeUtility.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/fsck/k9/mail/internet/MimeUtility.java b/src/com/fsck/k9/mail/internet/MimeUtility.java index 13ebc9304..e1908670d 100644 --- a/src/com/fsck/k9/mail/internet/MimeUtility.java +++ b/src/com/fsck/k9/mail/internet/MimeUtility.java @@ -2185,7 +2185,8 @@ public class MimeUtility { if (address == null) return null; if (isInDomain(address, "docomo.ne.jp") || isInDomain(address, "dwmail.jp") || - isInDomain(address, "pdx.ne.jp") || isInDomain(address, "willcom.com")) + isInDomain(address, "pdx.ne.jp") || isInDomain(address, "willcom.com") || + isInDomain(address, "emnet.ne.jp") || isInDomain(address, "emobile.ne.jp")) return "docomo"; else if (isInDomain(address, "softbank.ne.jp") || isInDomain(address, "vodafone.ne.jp") || isInDomain(address, "disney.ne.jp") || isInDomain(address, "vertuclub.ne.jp")) From ef01dc906b1b006a0bab045ebd426281407c2558 Mon Sep 17 00:00:00 2001 From: cketti Date: Sat, 17 Mar 2012 18:27:17 +0100 Subject: [PATCH 22/63] Use AlertDialog's ListView on import instead of creating our own This fixes a display problem when using the dark theme. --- src/com/fsck/k9/activity/Accounts.java | 52 +++++++++++--------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/com/fsck/k9/activity/Accounts.java b/src/com/fsck/k9/activity/Accounts.java index 339494044..d31bced32 100644 --- a/src/com/fsck/k9/activity/Accounts.java +++ b/src/com/fsck/k9/activity/Accounts.java @@ -21,6 +21,7 @@ import android.app.ProgressDialog; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; +import android.content.DialogInterface.OnMultiChoiceClickListener; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -45,12 +46,10 @@ import android.webkit.WebView; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; -import android.widget.CheckedTextView; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageButton; import android.widget.LinearLayout; -import android.widget.ListAdapter; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.ScrollView; @@ -58,7 +57,6 @@ import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemSelectedListener; import android.widget.CompoundButton.OnCheckedChangeListener; import com.fsck.k9.Account; @@ -1464,8 +1462,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC private static class ImportSelectionDialog implements NonConfigurationInstance { private ImportContents mImportContents; private Uri mUri; - private Dialog mDialog; - private ListView mImportSelectionView; + private AlertDialog mDialog; private SparseBooleanArray mSelection; @@ -1483,8 +1480,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC public boolean retain() { if (mDialog != null) { // Save the selection state of each list item - mSelection = mImportSelectionView.getCheckedItemPositions(); - mImportSelectionView = null; + mSelection = mDialog.getListView().getCheckedItemPositions(); mDialog.dismiss(); mDialog = null; @@ -1498,8 +1494,6 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC } public void show(final Accounts activity, SparseBooleanArray selection) { - final ListView importSelectionView = new ListView(activity); - mImportSelectionView = importSelectionView; List contents = new ArrayList(); if (mImportContents.globalSettings) { @@ -1510,23 +1504,15 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC contents.add(account.name); } - importSelectionView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - importSelectionView.setAdapter(new ArrayAdapter(activity, - android.R.layout.simple_list_item_checked, contents)); - importSelectionView.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int pos, long id) { - CheckedTextView ctv = (CheckedTextView)view; - ctv.setChecked(!ctv.isChecked()); - } - - @Override - public void onNothingSelected(AdapterView arg0) { /* Do nothing */ } - }); - + int count = contents.size(); + boolean[] checkedItems = new boolean[count]; if (selection != null) { - for (int i = 0, end = contents.size(); i < end; i++) { - importSelectionView.setItemChecked(i, selection.get(i)); + for (int i = 0; i < count; i++) { + checkedItems[i] = selection.get(i); + } + } else { + for (int i = 0; i < count; i++) { + checkedItems[i] = true; } } @@ -1534,23 +1520,29 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC //TODO: listview footer: "Select all" / "Select none" buttons? //TODO: listview footer: "Overwrite existing accounts?" checkbox + OnMultiChoiceClickListener listener = new OnMultiChoiceClickListener() { + @Override + public void onClick(DialogInterface dialog, int which, boolean isChecked) { + ((AlertDialog) dialog).getListView().setItemChecked(which, isChecked); + } + }; + final AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setMultiChoiceItems(contents.toArray(new String[0]), checkedItems, listener); builder.setTitle(activity.getString(R.string.settings_import_selection)); - builder.setView(importSelectionView); builder.setInverseBackgroundForced(true); builder.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - ListAdapter adapter = importSelectionView.getAdapter(); - int count = adapter.getCount(); - SparseBooleanArray pos = importSelectionView.getCheckedItemPositions(); + ListView listView = ((AlertDialog) dialog).getListView(); + SparseBooleanArray pos = listView.getCheckedItemPositions(); boolean includeGlobals = mImportContents.globalSettings ? pos.get(0) : false; List accountUuids = new ArrayList(); int start = mImportContents.globalSettings ? 1 : 0; - for (int i = start; i < count; i++) { + for (int i = start, end = listView.getCount(); i < end; i++) { if (pos.get(i)) { accountUuids.add(mImportContents.accounts.get(i-start).uuid); } From 69ee6a48187d7c1cde3bc3cdb292f4858d7c5c56 Mon Sep 17 00:00:00 2001 From: cketti Date: Sat, 17 Mar 2012 20:12:33 +0100 Subject: [PATCH 23/63] Avoid NullPointerException in Accounts.onCreateDialog() Also cleaned up code formatting of onCreateDialog() and onPrepareDialog(). --- src/com/fsck/k9/activity/Accounts.java | 195 ++++++++++++++----------- 1 file changed, 108 insertions(+), 87 deletions(-) diff --git a/src/com/fsck/k9/activity/Accounts.java b/src/com/fsck/k9/activity/Accounts.java index d31bced32..bb8d9a96a 100644 --- a/src/com/fsck/k9/activity/Accounts.java +++ b/src/com/fsck/k9/activity/Accounts.java @@ -918,107 +918,128 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC @Override public Dialog onCreateDialog(int id) { + // Android recreates our dialogs on configuration changes even when they have been + // dismissed. Make sure we have all information necessary before creating a new dialog. switch (id) { - case DIALOG_REMOVE_ACCOUNT: - return ConfirmationDialog.create(this, id, - R.string.account_delete_dlg_title, - getString(R.string.account_delete_dlg_instructions_fmt, - mSelectedContextAccount.getDescription()), - R.string.okay_action, - R.string.cancel_action, - new Runnable() { - @Override - public void run() { - if (mSelectedContextAccount instanceof Account) { - Account realAccount = (Account)mSelectedContextAccount; - try { - realAccount.getLocalStore().delete(); - } catch (Exception e) { - // Ignore, this may lead to localStores on sd-cards that are - // currently not inserted to be left - } - MessagingController.getInstance(getApplication()) - .notifyAccountCancel(Accounts.this, realAccount); - Preferences.getPreferences(Accounts.this).deleteAccount(realAccount); - K9.setServicesEnabled(Accounts.this); - refresh(); - } + case DIALOG_REMOVE_ACCOUNT: { + if (mSelectedContextAccount == null) { + return null; } - }); - case DIALOG_CLEAR_ACCOUNT: - return ConfirmationDialog.create(this, id, - R.string.account_clear_dlg_title, - getString(R.string.account_clear_dlg_instructions_fmt, - mSelectedContextAccount.getDescription()), - R.string.okay_action, - R.string.cancel_action, - new Runnable() { - @Override - public void run() { - if (mSelectedContextAccount instanceof Account) { - Account realAccount = (Account)mSelectedContextAccount; - mHandler.workingAccount(realAccount, R.string.clearing_account); - MessagingController.getInstance(getApplication()).clear(realAccount, null); - } + return ConfirmationDialog.create(this, id, + R.string.account_delete_dlg_title, + getString(R.string.account_delete_dlg_instructions_fmt, + mSelectedContextAccount.getDescription()), + R.string.okay_action, + R.string.cancel_action, + new Runnable() { + @Override + public void run() { + if (mSelectedContextAccount instanceof Account) { + Account realAccount = (Account) mSelectedContextAccount; + try { + realAccount.getLocalStore().delete(); + } catch (Exception e) { + // Ignore, this may lead to localStores on sd-cards that + // are currently not inserted to be left + } + MessagingController.getInstance(getApplication()) + .notifyAccountCancel(Accounts.this, realAccount); + Preferences.getPreferences(Accounts.this) + .deleteAccount(realAccount); + K9.setServicesEnabled(Accounts.this); + refresh(); + } + } + }); + } + case DIALOG_CLEAR_ACCOUNT: { + if (mSelectedContextAccount == null) { + return null; } - }); - case DIALOG_RECREATE_ACCOUNT: - return ConfirmationDialog.create(this, id, - R.string.account_recreate_dlg_title, - getString(R.string.account_recreate_dlg_instructions_fmt, - mSelectedContextAccount.getDescription()), - R.string.okay_action, - R.string.cancel_action, - new Runnable() { - @Override - public void run() { - if (mSelectedContextAccount instanceof Account) { - Account realAccount = (Account)mSelectedContextAccount; - mHandler.workingAccount(realAccount, R.string.recreating_account); - MessagingController.getInstance(getApplication()).recreate(realAccount, null); - } + return ConfirmationDialog.create(this, id, + R.string.account_clear_dlg_title, + getString(R.string.account_clear_dlg_instructions_fmt, + mSelectedContextAccount.getDescription()), + R.string.okay_action, + R.string.cancel_action, + new Runnable() { + @Override + public void run() { + if (mSelectedContextAccount instanceof Account) { + Account realAccount = (Account) mSelectedContextAccount; + mHandler.workingAccount(realAccount, + R.string.clearing_account); + MessagingController.getInstance(getApplication()) + .clear(realAccount, null); + } + } + }); + } + case DIALOG_RECREATE_ACCOUNT: { + if (mSelectedContextAccount == null) { + return null; } - }); - case DIALOG_NO_FILE_MANAGER: - return ConfirmationDialog.create(this, id, - R.string.import_dialog_error_title, - getString(R.string.import_dialog_error_message), - R.string.open_market, - R.string.close, - new Runnable() { - @Override - public void run() { - Uri uri = Uri.parse(ANDROID_MARKET_URL); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - } - }); + + return ConfirmationDialog.create(this, id, + R.string.account_recreate_dlg_title, + getString(R.string.account_recreate_dlg_instructions_fmt, + mSelectedContextAccount.getDescription()), + R.string.okay_action, + R.string.cancel_action, + new Runnable() { + @Override + public void run() { + if (mSelectedContextAccount instanceof Account) { + Account realAccount = (Account) mSelectedContextAccount; + mHandler.workingAccount(realAccount, + R.string.recreating_account); + MessagingController.getInstance(getApplication()) + .recreate(realAccount, null); + } + } + }); + } + case DIALOG_NO_FILE_MANAGER: { + return ConfirmationDialog.create(this, id, + R.string.import_dialog_error_title, + getString(R.string.import_dialog_error_message), + R.string.open_market, + R.string.close, + new Runnable() { + @Override + public void run() { + Uri uri = Uri.parse(ANDROID_MARKET_URL); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + startActivity(intent); + } + }); + } } + return super.onCreateDialog(id); } @Override public void onPrepareDialog(int id, Dialog d) { - AlertDialog alert = (AlertDialog) d; switch (id) { - case DIALOG_REMOVE_ACCOUNT: - alert.setMessage(getString(R.string.account_delete_dlg_instructions_fmt, - mSelectedContextAccount.getDescription())); - break; - case DIALOG_CLEAR_ACCOUNT: - alert.setMessage(getString(R.string.account_clear_dlg_instructions_fmt, - mSelectedContextAccount.getDescription())); - break; - case DIALOG_RECREATE_ACCOUNT: - alert.setMessage(getString(R.string.account_recreate_dlg_instructions_fmt, - mSelectedContextAccount.getDescription())); - break; - case DIALOG_NO_FILE_MANAGER: - alert.setMessage(getString(R.string.import_dialog_error_message)); - break; + case DIALOG_REMOVE_ACCOUNT: { + alert.setMessage(getString(R.string.account_delete_dlg_instructions_fmt, + mSelectedContextAccount.getDescription())); + break; + } + case DIALOG_CLEAR_ACCOUNT: { + alert.setMessage(getString(R.string.account_clear_dlg_instructions_fmt, + mSelectedContextAccount.getDescription())); + break; + } + case DIALOG_RECREATE_ACCOUNT: { + alert.setMessage(getString(R.string.account_recreate_dlg_instructions_fmt, + mSelectedContextAccount.getDescription())); + break; + } } super.onPrepareDialog(id, d); From 482ae352c158d75eb3db820305d020b809715a32 Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 04:51:29 +0100 Subject: [PATCH 24/63] Reverted most of the recent message header changes Clicking the additional headers area still allows to hide that view again. --- res/layout/message_view_header.xml | 147 ++++++++++++------------ src/com/fsck/k9/view/MessageHeader.java | 21 ++-- 2 files changed, 86 insertions(+), 82 deletions(-) diff --git a/res/layout/message_view_header.xml b/res/layout/message_view_header.xml index 19bd2a52d..67f8fe010 100644 --- a/res/layout/message_view_header.xml +++ b/res/layout/message_view_header.xml @@ -17,7 +17,7 @@ android:layout_height="wrap_content" android:stretchColumns="1" android:shrinkColumns="1" - android:background="@drawable/message_view_header_background"> + android:background="@color/message_view_header_background"> @@ -30,7 +30,6 @@ @@ -123,68 +122,16 @@ - - - - - - - - - - - - - - - - - - + @@ -231,32 +178,82 @@ android:textColor="?android:attr/textColorPrimary" android:textAppearance="?android:attr/textAppearanceSmall"/> - - - - - + + + + + + + + + + - + + + android:layout_height="21.5dp" + android:focusable="true" + android:clickable="true" + android:background="@drawable/message_view_header_background"> + + + + + + + + + + + + + + Date: Sun, 18 Mar 2012 18:28:03 +0100 Subject: [PATCH 25/63] Fix for Issue 4164: Force close when moving an email to another folder --- src/com/fsck/k9/activity/ChooseFolder.java | 34 +++++++++++++++------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/com/fsck/k9/activity/ChooseFolder.java b/src/com/fsck/k9/activity/ChooseFolder.java index dc4a88115..2525c5763 100644 --- a/src/com/fsck/k9/activity/ChooseFolder.java +++ b/src/com/fsck/k9/activity/ChooseFolder.java @@ -1,6 +1,11 @@ package com.fsck.k9.activity; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; @@ -19,15 +24,16 @@ import android.widget.EditText; import android.widget.Filter; import android.widget.ListView; import android.widget.TextView; -import com.fsck.k9.*; + +import com.fsck.k9.Account; import com.fsck.k9.Account.FolderMode; +import com.fsck.k9.K9; +import com.fsck.k9.Preferences; +import com.fsck.k9.R; import com.fsck.k9.controller.MessagingController; import com.fsck.k9.controller.MessagingListener; import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.MessagingException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; public class ChooseFolder extends K9ListActivity { String mFolder; @@ -40,6 +46,8 @@ public class ChooseFolder extends K9ListActivity { boolean hideCurrentFolder = true; boolean showOptionNone = false; boolean showDisplayableOnly = false; + + private List folderList; /** * What folders to display.
@@ -361,17 +369,19 @@ public class ChooseFolder extends K9ListActivity { return aName.compareToIgnoreCase(bName); } }); - mAdapter.setNotifyOnChange(false); int selectedFolder = -1; + // We're not allowed to change the adapter from a background thread, so we use + // a java.util.List to build a list of the folder names. + // We'll add the folder names to the adapter from the UI-thread (see the 'finally' block). + folderList = new ArrayList(); try { - mAdapter.clear(); int position = 0; for (String name : localFolders) { if (mAccount.getInboxFolderName().equalsIgnoreCase(name)) { - mAdapter.add(getString(R.string.special_mailbox_name_inbox)); + folderList.add(getString(R.string.special_mailbox_name_inbox)); heldInbox = name; } else if (!K9.ERROR_FOLDER_NAME.equals(name) && !account.getOutboxFolderName().equals(name)) { - mAdapter.add(name); + folderList.add(name); } if (mSelectFolder != null) { @@ -390,11 +400,13 @@ public class ChooseFolder extends K9ListActivity { position++; } } finally { - mAdapter.setNotifyOnChange(true); runOnUiThread(new Runnable() { public void run() { - // runOnUiThread( - mAdapter.notifyDataSetChanged(); + // Now we're in the UI-thread, we can safely change the contents of the adapter. + mAdapter.clear(); + for (String folderName: folderList) { + mAdapter.add(folderName); + } } }); } From 6bdaac4353cfcb7bc61674cefd6b2fff5741016b Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 21:46:32 +0100 Subject: [PATCH 26/63] Fixed whitespace (tabs vs. spaces) --- src/com/fsck/k9/activity/ChooseFolder.java | 88 +++++++++++----------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/com/fsck/k9/activity/ChooseFolder.java b/src/com/fsck/k9/activity/ChooseFolder.java index 2525c5763..98210bc7c 100644 --- a/src/com/fsck/k9/activity/ChooseFolder.java +++ b/src/com/fsck/k9/activity/ChooseFolder.java @@ -46,7 +46,7 @@ public class ChooseFolder extends K9ListActivity { boolean hideCurrentFolder = true; boolean showOptionNone = false; boolean showDisplayableOnly = false; - + private List folderList; /** @@ -216,7 +216,7 @@ public class ChooseFolder extends K9ListActivity { return true; } case R.id.filter_folders: { - onEnterFilter(); + onEnterFilter(); } return true; default: @@ -236,43 +236,43 @@ public class ChooseFolder extends K9ListActivity { * Filter {@link #mAdapter} with the user-input. */ private void onEnterFilter() { - final AlertDialog.Builder filterAlert = new AlertDialog.Builder(this); + final AlertDialog.Builder filterAlert = new AlertDialog.Builder(this); - final EditText input = new EditText(this); - input.addTextChangedListener(new TextWatcher() { - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - mAdapter.getFilter().filter(input.getText().toString()); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } - - @Override - public void afterTextChanged(Editable s) { - } - }); - input.setHint(R.string.folder_list_filter_hint); - filterAlert.setView(input); + final EditText input = new EditText(this); + input.addTextChangedListener(new TextWatcher() { - filterAlert.setPositiveButton("Ok", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - String value = input.getText().toString().trim(); - mAdapter.getFilter().filter(value); - } - }); + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mAdapter.getFilter().filter(input.getText().toString()); + } - filterAlert.setNegativeButton("Cancel", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - mAdapter.getFilter().filter(""); - } - }); + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + } - filterAlert.show(); + @Override + public void afterTextChanged(Editable s) { + } + }); + input.setHint(R.string.folder_list_filter_hint); + filterAlert.setView(input); + + filterAlert.setPositiveButton("Ok", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + String value = input.getText().toString().trim(); + mAdapter.getFilter().filter(value); + } + }); + + filterAlert.setNegativeButton("Cancel", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + mAdapter.getFilter().filter(""); + } + }); + + filterAlert.show(); } @@ -370,18 +370,18 @@ public class ChooseFolder extends K9ListActivity { } }); int selectedFolder = -1; - // We're not allowed to change the adapter from a background thread, so we use + // We're not allowed to change the adapter from a background thread, so we use // a java.util.List to build a list of the folder names. - // We'll add the folder names to the adapter from the UI-thread (see the 'finally' block). + // We'll add the folder names to the adapter from the UI-thread (see the 'finally' block). folderList = new ArrayList(); try { int position = 0; for (String name : localFolders) { if (mAccount.getInboxFolderName().equalsIgnoreCase(name)) { - folderList.add(getString(R.string.special_mailbox_name_inbox)); + folderList.add(getString(R.string.special_mailbox_name_inbox)); heldInbox = name; } else if (!K9.ERROR_FOLDER_NAME.equals(name) && !account.getOutboxFolderName().equals(name)) { - folderList.add(name); + folderList.add(name); } if (mSelectFolder != null) { @@ -402,11 +402,11 @@ public class ChooseFolder extends K9ListActivity { } finally { runOnUiThread(new Runnable() { public void run() { - // Now we're in the UI-thread, we can safely change the contents of the adapter. - mAdapter.clear(); - for (String folderName: folderList) { - mAdapter.add(folderName); - } + // Now we're in the UI-thread, we can safely change the contents of the adapter. + mAdapter.clear(); + for (String folderName: folderList) { + mAdapter.add(folderName); + } } }); } From 09bc07596ec7bff27ae9a912a86fc5804277fc7d Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 21:48:22 +0100 Subject: [PATCH 27/63] Got rid of unnecessary instance variable --- src/com/fsck/k9/activity/ChooseFolder.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/com/fsck/k9/activity/ChooseFolder.java b/src/com/fsck/k9/activity/ChooseFolder.java index 98210bc7c..7e7a9e2a4 100644 --- a/src/com/fsck/k9/activity/ChooseFolder.java +++ b/src/com/fsck/k9/activity/ChooseFolder.java @@ -47,8 +47,6 @@ public class ChooseFolder extends K9ListActivity { boolean showOptionNone = false; boolean showDisplayableOnly = false; - private List folderList; - /** * What folders to display.
* Initialized to whatever is configured @@ -370,10 +368,12 @@ public class ChooseFolder extends K9ListActivity { } }); int selectedFolder = -1; - // We're not allowed to change the adapter from a background thread, so we use - // a java.util.List to build a list of the folder names. - // We'll add the folder names to the adapter from the UI-thread (see the 'finally' block). - folderList = new ArrayList(); + + /* + * We're not allowed to change the adapter from a background thread, so we collect the + * folder names and update the adapter in the UI thread (see finally block). + */ + final List folderList = new ArrayList(); try { int position = 0; for (String name : localFolders) { From b7c1f8ab2fb1a2be01ffa783e7491417a7bfd9c5 Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 21:51:01 +0100 Subject: [PATCH 28/63] Prefixed instance variables with "m" to comply with K-9 code style --- src/com/fsck/k9/activity/ChooseFolder.java | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/com/fsck/k9/activity/ChooseFolder.java b/src/com/fsck/k9/activity/ChooseFolder.java index 7e7a9e2a4..746d2a17f 100644 --- a/src/com/fsck/k9/activity/ChooseFolder.java +++ b/src/com/fsck/k9/activity/ChooseFolder.java @@ -42,10 +42,10 @@ public class ChooseFolder extends K9ListActivity { MessageReference mMessageReference; ArrayAdapter mAdapter; private ChooseFolderHandler mHandler = new ChooseFolderHandler(); - String heldInbox = null; - boolean hideCurrentFolder = true; - boolean showOptionNone = false; - boolean showDisplayableOnly = false; + String mHeldInbox = null; + boolean mHideCurrentFolder = true; + boolean mShowOptionNone = false; + boolean mShowDisplayableOnly = false; /** * What folders to display.
@@ -59,7 +59,7 @@ public class ChooseFolder extends K9ListActivity { * Created on the fly and invalidated if a new * set of folders is chosen via {@link #onOptionsItemSelected(MenuItem)} */ - private FolderListFilter myFilter = null; + private FolderListFilter mMyFilter = null; public static final String EXTRA_ACCOUNT = "com.fsck.k9.ChooseFolder_account"; public static final String EXTRA_CUR_FOLDER = "com.fsck.k9.ChooseFolder_curfolder"; @@ -85,13 +85,13 @@ public class ChooseFolder extends K9ListActivity { mFolder = intent.getStringExtra(EXTRA_CUR_FOLDER); mSelectFolder = intent.getStringExtra(EXTRA_SEL_FOLDER); if (intent.getStringExtra(EXTRA_SHOW_CURRENT) != null) { - hideCurrentFolder = false; + mHideCurrentFolder = false; } if (intent.getStringExtra(EXTRA_SHOW_FOLDER_NONE) != null) { - showOptionNone = true; + mShowOptionNone = true; } if (intent.getStringExtra(EXTRA_SHOW_DISPLAYABLE_ONLY) != null) { - showDisplayableOnly = true; + mShowDisplayableOnly = true; } if (mFolder == null) mFolder = ""; @@ -121,8 +121,8 @@ public class ChooseFolder extends K9ListActivity { intent.putExtra(EXTRA_ACCOUNT, mAccount.getUuid()); intent.putExtra(EXTRA_CUR_FOLDER, mFolder); String destFolderName = (String)((TextView)view).getText(); - if (heldInbox != null && getString(R.string.special_mailbox_name_inbox).equals(destFolderName)) { - destFolderName = heldInbox; + if (mHeldInbox != null && getString(R.string.special_mailbox_name_inbox).equals(destFolderName)) { + destFolderName = mHeldInbox; } intent.putExtra(EXTRA_NEW_FOLDER, destFolderName); intent.putExtra(EXTRA_MESSAGE, mMessageReference); @@ -277,8 +277,8 @@ public class ChooseFolder extends K9ListActivity { private void setDisplayMode(FolderMode aMode) { mMode = aMode; // invalidate the current filter as it is working on an inval - if (myFilter != null) { - myFilter.invalidate(); + if (mMyFilter != null) { + mMyFilter.invalidate(); } //re-populate the list MessagingController.getInstance(getApplication()).listFolders(mAccount, @@ -322,7 +322,7 @@ public class ChooseFolder extends K9ListActivity { String name = folder.getName(); // Inbox needs to be compared case-insensitively - if (hideCurrentFolder && (name.equals(mFolder) || + if (mHideCurrentFolder && (name.equals(mFolder) || (mAccount.getInboxFolderName().equalsIgnoreCase(mFolder) && mAccount.getInboxFolderName().equalsIgnoreCase(name)))) { continue; } @@ -345,7 +345,7 @@ public class ChooseFolder extends K9ListActivity { } - if (showOptionNone) { + if (mShowOptionNone) { localFolders.add(K9.FOLDER_NONE); } @@ -379,7 +379,7 @@ public class ChooseFolder extends K9ListActivity { for (String name : localFolders) { if (mAccount.getInboxFolderName().equalsIgnoreCase(name)) { folderList.add(getString(R.string.special_mailbox_name_inbox)); - heldInbox = name; + mHeldInbox = name; } else if (!K9.ERROR_FOLDER_NAME.equals(name) && !account.getOutboxFolderName().equals(name)) { folderList.add(name); } From 4f2412eacda3daae3181bbaaede6eaaaf4e200b2 Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 22:06:44 +0100 Subject: [PATCH 29/63] Changed code formatting. No functional changes --- src/com/fsck/k9/activity/ChooseFolder.java | 182 +++++++++++---------- 1 file changed, 92 insertions(+), 90 deletions(-) diff --git a/src/com/fsck/k9/activity/ChooseFolder.java b/src/com/fsck/k9/activity/ChooseFolder.java index 746d2a17f..170f64358 100644 --- a/src/com/fsck/k9/activity/ChooseFolder.java +++ b/src/com/fsck/k9/activity/ChooseFolder.java @@ -36,6 +36,16 @@ import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.MessagingException; public class ChooseFolder extends K9ListActivity { + public static final String EXTRA_ACCOUNT = "com.fsck.k9.ChooseFolder_account"; + public static final String EXTRA_CUR_FOLDER = "com.fsck.k9.ChooseFolder_curfolder"; + public static final String EXTRA_SEL_FOLDER = "com.fsck.k9.ChooseFolder_selfolder"; + public static final String EXTRA_NEW_FOLDER = "com.fsck.k9.ChooseFolder_newfolder"; + public static final String EXTRA_MESSAGE = "com.fsck.k9.ChooseFolder_message"; + public static final String EXTRA_SHOW_CURRENT = "com.fsck.k9.ChooseFolder_showcurrent"; + public static final String EXTRA_SHOW_FOLDER_NONE = "com.fsck.k9.ChooseFolder_showOptionNone"; + public static final String EXTRA_SHOW_DISPLAYABLE_ONLY = "com.fsck.k9.ChooseFolder_showDisplayableOnly"; + + String mFolder; String mSelectFolder; Account mAccount; @@ -54,6 +64,7 @@ public class ChooseFolder extends K9ListActivity { * while this activity is showing. */ private Account.FolderMode mMode; + /** * Current filter used by our ArrayAdapter.
* Created on the fly and invalidated if a new @@ -61,14 +72,6 @@ public class ChooseFolder extends K9ListActivity { */ private FolderListFilter mMyFilter = null; - public static final String EXTRA_ACCOUNT = "com.fsck.k9.ChooseFolder_account"; - public static final String EXTRA_CUR_FOLDER = "com.fsck.k9.ChooseFolder_curfolder"; - public static final String EXTRA_SEL_FOLDER = "com.fsck.k9.ChooseFolder_selfolder"; - public static final String EXTRA_NEW_FOLDER = "com.fsck.k9.ChooseFolder_newfolder"; - public static final String EXTRA_MESSAGE = "com.fsck.k9.ChooseFolder_message"; - public static final String EXTRA_SHOW_CURRENT = "com.fsck.k9.ChooseFolder_showcurrent"; - public static final String EXTRA_SHOW_FOLDER_NONE = "com.fsck.k9.ChooseFolder_showOptionNone"; - public static final String EXTRA_SHOW_DISPLAYABLE_ONLY = "com.fsck.k9.ChooseFolder_showDisplayableOnly"; @Override public void onCreate(Bundle savedInstanceState) { @@ -110,55 +113,54 @@ public class ChooseFolder extends K9ListActivity { setListAdapter(mAdapter); - mMode = mAccount.getFolderTargetMode(); MessagingController.getInstance(getApplication()).listFolders(mAccount, false, mListener); - this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - Intent intent = new Intent(); - intent.putExtra(EXTRA_ACCOUNT, mAccount.getUuid()); - intent.putExtra(EXTRA_CUR_FOLDER, mFolder); + Intent result = new Intent(); + result.putExtra(EXTRA_ACCOUNT, mAccount.getUuid()); + result.putExtra(EXTRA_CUR_FOLDER, mFolder); String destFolderName = (String)((TextView)view).getText(); if (mHeldInbox != null && getString(R.string.special_mailbox_name_inbox).equals(destFolderName)) { destFolderName = mHeldInbox; } - intent.putExtra(EXTRA_NEW_FOLDER, destFolderName); - intent.putExtra(EXTRA_MESSAGE, mMessageReference); - setResult(RESULT_OK, intent); + result.putExtra(EXTRA_NEW_FOLDER, destFolderName); + result.putExtra(EXTRA_MESSAGE, mMessageReference); + setResult(RESULT_OK, result); finish(); } }); - } class ChooseFolderHandler extends Handler { - private static final int MSG_PROGRESS = 2; - private static final int MSG_DATA_CHANGED = 3; private static final int MSG_SET_SELECTED_FOLDER = 4; @Override public void handleMessage(android.os.Message msg) { switch (msg.what) { - case MSG_PROGRESS: - setProgressBarIndeterminateVisibility(msg.arg1 != 0); - break; - case MSG_DATA_CHANGED: - mAdapter.notifyDataSetChanged(); + case MSG_PROGRESS: { + setProgressBarIndeterminateVisibility(msg.arg1 != 0); + break; + } + case MSG_DATA_CHANGED: { + mAdapter.notifyDataSetChanged(); - /* - * Only enable the text filter after the list has been - * populated to avoid possible race conditions because our - * FolderListFilter isn't really thread-safe. - */ - getListView().setTextFilterEnabled(true); - break; - case MSG_SET_SELECTED_FOLDER: - getListView().setSelection(msg.arg1); - break; + /* + * Only enable the text filter after the list has been + * populated to avoid possible race conditions because our + * FolderListFilter isn't really thread-safe. + */ + getListView().setTextFilterEnabled(true); + break; + } + case MSG_SET_SELECTED_FOLDER: { + getListView().setSelection(msg.arg1); + break; + } } } @@ -181,52 +183,48 @@ public class ChooseFolder extends K9ListActivity { } } - @Override public boolean onCreateOptionsMenu(Menu menu) { + @Override + public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.folder_select_option, menu); return true; } - @Override public boolean onOptionsItemSelected(MenuItem item) { + @Override + public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - - - case R.id.display_1st_class: { - setDisplayMode(FolderMode.FIRST_CLASS); - return true; - } - case R.id.display_1st_and_2nd_class: { - setDisplayMode(FolderMode.FIRST_AND_SECOND_CLASS); - return true; - } - case R.id.display_not_second_class: { - setDisplayMode(FolderMode.NOT_SECOND_CLASS); - return true; - } - case R.id.display_all: { - setDisplayMode(FolderMode.ALL); - return true; - } - - case R.id.list_folders: { - onRefresh(); - - return true; - } - case R.id.filter_folders: { - onEnterFilter(); - } - return true; - default: - return super.onOptionsItemSelected(item); + case R.id.display_1st_class: { + setDisplayMode(FolderMode.FIRST_CLASS); + return true; + } + case R.id.display_1st_and_2nd_class: { + setDisplayMode(FolderMode.FIRST_AND_SECOND_CLASS); + return true; + } + case R.id.display_not_second_class: { + setDisplayMode(FolderMode.NOT_SECOND_CLASS); + return true; + } + case R.id.display_all: { + setDisplayMode(FolderMode.ALL); + return true; + } + case R.id.list_folders: { + onRefresh(); + return true; + } + case R.id.filter_folders: { + onEnterFilter(); + return true; + } + default: { + return super.onOptionsItemSelected(item); + } } } - private void onRefresh() { - MessagingController.getInstance(getApplication()).listFolders(mAccount, true, mListener); - } /** @@ -238,40 +236,37 @@ public class ChooseFolder extends K9ListActivity { final EditText input = new EditText(this); input.addTextChangedListener(new TextWatcher() { - @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mAdapter.getFilter().filter(input.getText().toString()); } @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + /* not used */ } @Override - public void afterTextChanged(Editable s) { - } + public void afterTextChanged(Editable s) { /* not used */ } }); input.setHint(R.string.folder_list_filter_hint); filterAlert.setView(input); filterAlert.setPositiveButton("Ok", new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int whichButton) { String value = input.getText().toString().trim(); mAdapter.getFilter().filter(value); } }); - filterAlert.setNegativeButton("Cancel", - new DialogInterface.OnClickListener() { + filterAlert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int whichButton) { mAdapter.getFilter().filter(""); } }); filterAlert.show(); - } private void setDisplayMode(FolderMode aMode) { @@ -281,8 +276,7 @@ public class ChooseFolder extends K9ListActivity { mMyFilter.invalidate(); } //re-populate the list - MessagingController.getInstance(getApplication()).listFolders(mAccount, - false, mListener); + MessagingController.getInstance(getApplication()).listFolders(mAccount, false, mListener); } private MessagingListener mListener = new MessagingListener() { @@ -322,23 +316,27 @@ public class ChooseFolder extends K9ListActivity { String name = folder.getName(); // Inbox needs to be compared case-insensitively - if (mHideCurrentFolder && (name.equals(mFolder) || - (mAccount.getInboxFolderName().equalsIgnoreCase(mFolder) && mAccount.getInboxFolderName().equalsIgnoreCase(name)))) { + if (mHideCurrentFolder && (name.equals(mFolder) || ( + mAccount.getInboxFolderName().equalsIgnoreCase(mFolder) && + mAccount.getInboxFolderName().equalsIgnoreCase(name)))) { continue; } try { folder.refresh(prefs); Folder.FolderClass fMode = folder.getDisplayClass(); - if ((aMode == Account.FolderMode.FIRST_CLASS && fMode != Folder.FolderClass.FIRST_CLASS) - || (aMode == Account.FolderMode.FIRST_AND_SECOND_CLASS && + if ((aMode == Account.FolderMode.FIRST_CLASS && + fMode != Folder.FolderClass.FIRST_CLASS) || ( + aMode == Account.FolderMode.FIRST_AND_SECOND_CLASS && fMode != Folder.FolderClass.FIRST_CLASS && - fMode != Folder.FolderClass.SECOND_CLASS) - || (aMode == Account.FolderMode.NOT_SECOND_CLASS && fMode == Folder.FolderClass.SECOND_CLASS)) { + fMode != Folder.FolderClass.SECOND_CLASS) || ( + aMode == Account.FolderMode.NOT_SECOND_CLASS && + fMode == Folder.FolderClass.SECOND_CLASS)) { continue; } } catch (MessagingException me) { - Log.e(K9.LOG_TAG, "Couldn't get prefs to check for displayability of folder " + folder.getName(), me); + Log.e(K9.LOG_TAG, "Couldn't get prefs to check for displayability of folder " + + folder.getName(), me); } localFolders.add(folder.getName()); @@ -350,6 +348,7 @@ public class ChooseFolder extends K9ListActivity { } Collections.sort(localFolders, new Comparator() { + @Override public int compare(String aName, String bName) { if (K9.FOLDER_NONE.equalsIgnoreCase(aName)) { return -1; @@ -380,7 +379,8 @@ public class ChooseFolder extends K9ListActivity { if (mAccount.getInboxFolderName().equalsIgnoreCase(name)) { folderList.add(getString(R.string.special_mailbox_name_inbox)); mHeldInbox = name; - } else if (!K9.ERROR_FOLDER_NAME.equals(name) && !account.getOutboxFolderName().equals(name)) { + } else if (!K9.ERROR_FOLDER_NAME.equals(name) && + !account.getOutboxFolderName().equals(name)) { folderList.add(name); } @@ -393,14 +393,16 @@ public class ChooseFolder extends K9ListActivity { if (name.equals(mSelectFolder)) { selectedFolder = position; } - } else if (name.equals(mFolder) || - (mAccount.getInboxFolderName().equalsIgnoreCase(mFolder) && mAccount.getInboxFolderName().equalsIgnoreCase(name))) { + } else if (name.equals(mFolder) || ( + mAccount.getInboxFolderName().equalsIgnoreCase(mFolder) && + mAccount.getInboxFolderName().equalsIgnoreCase(name))) { selectedFolder = position; } position++; } } finally { runOnUiThread(new Runnable() { + @Override public void run() { // Now we're in the UI-thread, we can safely change the contents of the adapter. mAdapter.clear(); From 16afff4dfcb6adcedb021d6753feb660a1540e5c Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 22:09:52 +0100 Subject: [PATCH 30/63] Notify the adapter from runOnUiThread() instead of using Handler --- src/com/fsck/k9/activity/ChooseFolder.java | 31 ++++++++-------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/com/fsck/k9/activity/ChooseFolder.java b/src/com/fsck/k9/activity/ChooseFolder.java index 170f64358..1cfdfa976 100644 --- a/src/com/fsck/k9/activity/ChooseFolder.java +++ b/src/com/fsck/k9/activity/ChooseFolder.java @@ -135,9 +135,8 @@ public class ChooseFolder extends K9ListActivity { } class ChooseFolderHandler extends Handler { - private static final int MSG_PROGRESS = 2; - private static final int MSG_DATA_CHANGED = 3; - private static final int MSG_SET_SELECTED_FOLDER = 4; + private static final int MSG_PROGRESS = 1; + private static final int MSG_SET_SELECTED_FOLDER = 2; @Override public void handleMessage(android.os.Message msg) { @@ -146,17 +145,6 @@ public class ChooseFolder extends K9ListActivity { setProgressBarIndeterminateVisibility(msg.arg1 != 0); break; } - case MSG_DATA_CHANGED: { - mAdapter.notifyDataSetChanged(); - - /* - * Only enable the text filter after the list has been - * populated to avoid possible race conditions because our - * FolderListFilter isn't really thread-safe. - */ - getListView().setTextFilterEnabled(true); - break; - } case MSG_SET_SELECTED_FOLDER: { getListView().setSelection(msg.arg1); break; @@ -177,10 +165,6 @@ public class ChooseFolder extends K9ListActivity { msg.arg1 = position; sendMessage(msg); } - - public void dataChanged() { - sendEmptyMessage(MSG_DATA_CHANGED); - } } @Override @@ -409,12 +393,19 @@ public class ChooseFolder extends K9ListActivity { for (String folderName: folderList) { mAdapter.add(folderName); } + + mAdapter.notifyDataSetChanged(); + + /* + * Only enable the text filter after the list has been + * populated to avoid possible race conditions because our + * FolderListFilter isn't really thread-safe. + */ + getListView().setTextFilterEnabled(true); } }); } - mHandler.dataChanged(); - if (selectedFolder != -1) { mHandler.setSelectedFolder(selectedFolder); } From 8c66a2f835b76f323682862a6f4bc4619a86907c Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 22:13:27 +0100 Subject: [PATCH 31/63] Replaced hardcoded strings with references to string resources --- src/com/fsck/k9/activity/ChooseFolder.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/fsck/k9/activity/ChooseFolder.java b/src/com/fsck/k9/activity/ChooseFolder.java index 1cfdfa976..a5b8568fe 100644 --- a/src/com/fsck/k9/activity/ChooseFolder.java +++ b/src/com/fsck/k9/activity/ChooseFolder.java @@ -235,7 +235,8 @@ public class ChooseFolder extends K9ListActivity { input.setHint(R.string.folder_list_filter_hint); filterAlert.setView(input); - filterAlert.setPositiveButton("Ok", new DialogInterface.OnClickListener() { + String okay = getString(R.string.okay_action); + filterAlert.setPositiveButton(okay, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int whichButton) { String value = input.getText().toString().trim(); @@ -243,7 +244,8 @@ public class ChooseFolder extends K9ListActivity { } }); - filterAlert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + String cancel = getString(R.string.cancel_action); + filterAlert.setNegativeButton(cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int whichButton) { mAdapter.getFilter().filter(""); From 5245191900f4568a068a1f35160d3d122c325886 Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 18 Mar 2012 22:43:47 +0100 Subject: [PATCH 32/63] Notify the listener provided as argument to doRefreshRemote() With this change pressing "Refresh folders" in ChooseFolder actually refreshes the folder list. --- src/com/fsck/k9/controller/MessagingController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 33acd96f1..290679e86 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -449,7 +449,7 @@ public class MessagingController implements Runnable { } } - private void doRefreshRemote(final Account account, MessagingListener listener) { + private void doRefreshRemote(final Account account, final MessagingListener listener) { put("doRefreshRemote", listener, new Runnable() { @Override public void run() { @@ -492,14 +492,14 @@ public class MessagingController implements Runnable { localFolders = localStore.getPersonalNamespaces(false); Folder[] folderArray = localFolders.toArray(EMPTY_FOLDER_ARRAY); - for (MessagingListener l : getListeners()) { + for (MessagingListener l : getListeners(listener)) { l.listFolders(account, folderArray); } - for (MessagingListener l : getListeners()) { + for (MessagingListener l : getListeners(listener)) { l.listFoldersFinished(account); } } catch (Exception e) { - for (MessagingListener l : getListeners()) { + for (MessagingListener l : getListeners(listener)) { l.listFoldersFailed(account, ""); } addErrorMessage(account, null, e); From 1d28eb003df376a9ba186fece011d499ef1da96a Mon Sep 17 00:00:00 2001 From: cketti Date: Mon, 19 Mar 2012 04:44:41 +0100 Subject: [PATCH 33/63] Added a setting to disable marking messages as read on viewing --- res/values/strings.xml | 2 ++ res/xml/account_settings_preferences.xml | 11 +++++++++++ src/com/fsck/k9/Account.java | 13 +++++++++++++ src/com/fsck/k9/activity/MessageView.java | 13 +++++++++---- src/com/fsck/k9/activity/setup/AccountSettings.java | 11 ++++++----- src/com/fsck/k9/controller/MessagingController.java | 2 +- src/com/fsck/k9/preferences/AccountSettings.java | 3 +++ src/com/fsck/k9/preferences/Settings.java | 2 +- 8 files changed, 46 insertions(+), 11 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 820960b66..8d66d64ea 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -549,6 +549,8 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin Searches for unread messages when Notification is opened Show unread count Show the number of unread messages in the notification bar. + Mark message as read when opening + Mark a message as read when it is opened for viewing Enable refile buttons Show the Archive, Move, and Spam buttons. diff --git a/res/xml/account_settings_preferences.xml b/res/xml/account_settings_preferences.xml index 9fa5a11a6..683827258 100644 --- a/res/xml/account_settings_preferences.xml +++ b/res/xml/account_settings_preferences.xml @@ -81,6 +81,17 @@ + + + + + + diff --git a/src/com/fsck/k9/Account.java b/src/com/fsck/k9/Account.java index c04e89c06..98c3ddafb 100644 --- a/src/com/fsck/k9/Account.java +++ b/src/com/fsck/k9/Account.java @@ -149,6 +149,7 @@ public class Account implements BaseAccount { private String mCryptoApp; private boolean mCryptoAutoSignature; private boolean mCryptoAutoEncrypt; + private boolean mMarkMessageAsReadOnView; private CryptoProvider mCryptoProvider = null; @@ -236,6 +237,7 @@ public class Account implements BaseAccount { mCryptoAutoSignature = false; mCryptoAutoEncrypt = false; mEnabled = true; + mMarkMessageAsReadOnView = true; searchableFolders = Searchable.ALL; @@ -391,6 +393,7 @@ public class Account implements BaseAccount { mCryptoAutoSignature = prefs.getBoolean(mUuid + ".cryptoAutoSignature", false); mCryptoAutoEncrypt = prefs.getBoolean(mUuid + ".cryptoAutoEncrypt", false); mEnabled = prefs.getBoolean(mUuid + ".enabled", true); + mMarkMessageAsReadOnView = prefs.getBoolean(mUuid + ".markMessageAsReadOnView", true); } protected synchronized void delete(Preferences preferences) { @@ -472,6 +475,7 @@ public class Account implements BaseAccount { editor.remove(mUuid + ".enabled"); editor.remove(mUuid + ".enableMoveButtons"); editor.remove(mUuid + ".hideMoveButtonsEnum"); + editor.remove(mUuid + ".markMessageAsReadOnView"); for (String type : networkTypes) { editor.remove(mUuid + ".useCompression." + type); } @@ -632,6 +636,7 @@ public class Account implements BaseAccount { editor.putBoolean(mUuid + ".cryptoAutoSignature", mCryptoAutoSignature); editor.putBoolean(mUuid + ".cryptoAutoEncrypt", mCryptoAutoEncrypt); editor.putBoolean(mUuid + ".enabled", mEnabled); + editor.putBoolean(mUuid + ".markMessageAsReadOnView", mMarkMessageAsReadOnView); editor.putBoolean(mUuid + ".vibrate", mNotificationSetting.shouldVibrate()); editor.putInt(mUuid + ".vibratePattern", mNotificationSetting.getVibratePattern()); @@ -1500,4 +1505,12 @@ public class Account implements BaseAccount { public synchronized void setEnabled(boolean enabled) { mEnabled = enabled; } + + public synchronized boolean isMarkMessageAsReadOnView() { + return mMarkMessageAsReadOnView; + } + + public synchronized void setMarkMessageAsReadOnView(boolean value) { + mMarkMessageAsReadOnView = value; + } } diff --git a/src/com/fsck/k9/activity/MessageView.java b/src/com/fsck/k9/activity/MessageView.java index 1ffb9586e..87d968681 100644 --- a/src/com/fsck/k9/activity/MessageView.java +++ b/src/com/fsck/k9/activity/MessageView.java @@ -756,17 +756,16 @@ public class MessageView extends K9Activity implements OnClickListener { mPrevious.requestFocus(); } - private void onMarkAsUnread() { + private void onToggleRead() { if (mMessage != null) { mController.setFlag(mAccount, mMessage.getFolder().getName(), - new Message[] { mMessage }, Flag.SEEN, false); + new Message[] { mMessage }, Flag.SEEN, !mMessage.isSet(Flag.SEEN)); mMessageView.setHeaders(mMessage, mAccount); String subject = mMessage.getSubject(); setTitle(subject); } } - private void onDownloadRemainder() { if (mMessage.isSet(Flag.X_DOWNLOADED_FULL)) { return; @@ -833,7 +832,7 @@ public class MessageView extends K9Activity implements OnClickListener { onSendAlternate(); break; case R.id.mark_as_unread: - onMarkAsUnread(); + onToggleRead(); break; case R.id.flag: onFlag(); @@ -944,6 +943,12 @@ public class MessageView extends K9Activity implements OnClickListener { additionalHeadersItem.setTitle(mMessageView.additionalHeadersVisible() ? R.string.hide_full_header_action : R.string.show_full_header_action); } + + if (mMessage != null) { + int actionTitle = mMessage.isSet(Flag.SEEN) ? + R.string.mark_as_unread_action : R.string.mark_as_read_action; + menu.findItem(R.id.mark_as_unread).setTitle(actionTitle); + } } return super.onPrepareOptionsMenu(menu); } diff --git a/src/com/fsck/k9/activity/setup/AccountSettings.java b/src/com/fsck/k9/activity/setup/AccountSettings.java index 9ac8f7058..f38cfa20f 100644 --- a/src/com/fsck/k9/activity/setup/AccountSettings.java +++ b/src/com/fsck/k9/activity/setup/AccountSettings.java @@ -48,6 +48,7 @@ public class AccountSettings extends K9PreferenceActivity { private static final String PREFERENCE_SCREEN_PUSH_ADVANCED = "push_advanced"; private static final String PREFERENCE_DESCRIPTION = "account_description"; + private static final String PREFERENCE_MARK_MESSAGE_AS_READ_ON_VIEW = "mark_message_as_read_on_view"; private static final String PREFERENCE_COMPOSITION = "composition"; private static final String PREFERENCE_MANAGE_IDENTITIES = "manage_identities"; private static final String PREFERENCE_FREQUENCY = "account_check_frequency"; @@ -94,9 +95,7 @@ public class AccountSettings extends K9PreferenceActivity { private static final String PREFERENCE_CRYPTO_APP = "crypto_app"; private static final String PREFERENCE_CRYPTO_AUTO_SIGNATURE = "crypto_auto_signature"; private static final String PREFERENCE_CRYPTO_AUTO_ENCRYPT = "crypto_auto_encrypt"; - private static final String PREFERENCE_LOCAL_STORAGE_PROVIDER = "local_storage_provider"; - private static final String PREFERENCE_CATEGORY_FOLDERS = "folders"; private static final String PREFERENCE_ARCHIVE_FOLDER = "archive_folder"; private static final String PREFERENCE_DRAFTS_FOLDER = "drafts_folder"; @@ -114,6 +113,7 @@ public class AccountSettings extends K9PreferenceActivity { private PreferenceScreen mComposingScreen; private EditTextPreference mAccountDescription; + private CheckBoxPreference mMarkMessageAsReadOnView; private ListPreference mCheckFrequency; private ListPreference mDisplayCount; private ListPreference mMessageAge; @@ -157,10 +157,7 @@ public class AccountSettings extends K9PreferenceActivity { private ListPreference mCryptoApp; private CheckBoxPreference mCryptoAutoSignature; private CheckBoxPreference mCryptoAutoEncrypt; - private ListPreference mLocalStorageProvider; - - private ListPreference mArchiveFolder; private ListPreference mDraftsFolder; private ListPreference mSentFolder; @@ -204,6 +201,9 @@ public class AccountSettings extends K9PreferenceActivity { } }); + mMarkMessageAsReadOnView = (CheckBoxPreference) findPreference(PREFERENCE_MARK_MESSAGE_AS_READ_ON_VIEW); + mMarkMessageAsReadOnView.setChecked(mAccount.isMarkMessageAsReadOnView()); + mMessageFormat = (ListPreference) findPreference(PREFERENCE_MESSAGE_FORMAT); mMessageFormat.setValue(mAccount.getMessageFormat().name()); mMessageFormat.setSummary(mMessageFormat.getEntry()); @@ -672,6 +672,7 @@ public class AccountSettings extends K9PreferenceActivity { } mAccount.setDescription(mAccountDescription.getText()); + mAccount.setMarkMessageAsReadOnView(mMarkMessageAsReadOnView.isChecked()); mAccount.setNotifyNewMail(mAccountNotify.isChecked()); mAccount.setNotifySelfNewMail(mAccountNotifySelf.isChecked()); mAccount.setShowOngoing(mAccountNotifySync.isChecked()); diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 290679e86..9a7065cbd 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -2846,7 +2846,7 @@ public class MessagingController implements Runnable { || message.getId() == 0) { throw new IllegalArgumentException("Message not found: folder=" + folder + ", uid=" + uid); } - if (!message.isSet(Flag.SEEN)) { + if (account.isMarkMessageAsReadOnView() && !message.isSet(Flag.SEEN)) { message.setFlag(Flag.SEEN, true); setFlag(new Message[] { message }, Flag.SEEN, true); } diff --git a/src/com/fsck/k9/preferences/AccountSettings.java b/src/com/fsck/k9/preferences/AccountSettings.java index fdc311820..f2dcf3669 100644 --- a/src/com/fsck/k9/preferences/AccountSettings.java +++ b/src/com/fsck/k9/preferences/AccountSettings.java @@ -96,6 +96,9 @@ public class AccountSettings { s.put("localStorageProvider", Settings.versions( new V(1, new StorageProviderSetting()) )); + s.put("markMessageAsReadOnView", Settings.versions( + new V(7, new BooleanSetting(true)) + )); s.put("maxPushFolders", Settings.versions( new V(1, new IntegerRangeSetting(0, 100, 10)) )); diff --git a/src/com/fsck/k9/preferences/Settings.java b/src/com/fsck/k9/preferences/Settings.java index 3b2bbb979..637d6d74d 100644 --- a/src/com/fsck/k9/preferences/Settings.java +++ b/src/com/fsck/k9/preferences/Settings.java @@ -35,7 +35,7 @@ public class Settings { * * @see SettingsExporter */ - public static final int VERSION = 6; + public static final int VERSION = 7; public static Map validate(int version, Map> settings, From 8180fd9ad2113c5c92a9ea7de2d19b396ffa10f8 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 22 Mar 2012 22:17:10 +0100 Subject: [PATCH 34/63] Added a button to switch the identity in MessageCompose Originally I wanted to use a Spinner, but it doesn't support multiple view types (see [1]). Those are necessary because we use different layouts for accounts (section headers) and identities (selectable list items). Removed the ChooseAccount activity because it's now unused. --- res/layout/choose_account.xml | 9 - res/layout/choose_account_item.xml | 42 +-- res/layout/choose_identity_item.xml | 17 +- res/layout/message_compose.xml | 33 ++- res/menu/message_compose_option.xml | 6 - src/com/fsck/k9/activity/ChooseAccount.java | 243 ------------------ .../k9/activity/K9ExpandableListActivity.java | 18 -- src/com/fsck/k9/activity/MessageCompose.java | 227 ++++++++++++---- 8 files changed, 215 insertions(+), 380 deletions(-) delete mode 100644 res/layout/choose_account.xml delete mode 100644 src/com/fsck/k9/activity/ChooseAccount.java delete mode 100644 src/com/fsck/k9/activity/K9ExpandableListActivity.java diff --git a/res/layout/choose_account.xml b/res/layout/choose_account.xml deleted file mode 100644 index 09c8fe2d8..000000000 --- a/res/layout/choose_account.xml +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/res/layout/choose_account_item.xml b/res/layout/choose_account_item.xml index d212594f0..361db3d61 100644 --- a/res/layout/choose_account_item.xml +++ b/res/layout/choose_account_item.xml @@ -3,37 +3,21 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeight" android:orientation="horizontal" - android:paddingRight="6dip" - android:paddingBottom="2dip" - android:descendantFocusability="blocksDescendants" - android:gravity="center_vertical" > + android:background="#cccccc" + android:gravity="left|center_vertical"> - - - - - - - + android:singleLine="true" + android:ellipsize="end" + android:paddingTop="2dp" + android:paddingLeft="18dp" + android:paddingRight="4dp" + android:paddingBottom="2dp" + android:textColor="?android:attr/textColorPrimary" + android:textAppearance="?android:attr/textAppearanceSmall"/>
diff --git a/res/layout/choose_identity_item.xml b/res/layout/choose_identity_item.xml index 0f1999003..600bb8b75 100644 --- a/res/layout/choose_identity_item.xml +++ b/res/layout/choose_identity_item.xml @@ -5,25 +5,20 @@ android:layout_height="wrap_content" android:minHeight="?android:attr/listPreferredItemHeight" android:orientation="horizontal" - android:paddingRight="6dip" - android:paddingBottom="2dip" - android:descendantFocusability="blocksDescendants" - android:gravity="center_vertical" > + android:gravity="center_vertical"> + android:layout_width="6dp"/> + android:paddingLeft="12dp" + android:paddingRight="4dp"> + android:textAppearance="?android:attr/textAppearanceMedium"/> + android:textAppearance="?android:attr/textAppearanceSmall"/> diff --git a/res/layout/message_compose.xml b/res/layout/message_compose.xml index 2cafb2428..70d3be985 100644 --- a/res/layout/message_compose.xml +++ b/res/layout/message_compose.xml @@ -20,17 +20,34 @@ - + android:orientation="horizontal"> + + + +