From dedfd026bef1bf225d80a68bee5d2c3e8731e467 Mon Sep 17 00:00:00 2001 From: Daniel Applebaum Date: Sun, 30 May 2010 16:56:50 +0000 Subject: [PATCH] Fixes Issue 254 Provide for only showing folders that are subscribed on the server (IMAP only) Also: Change default for Notification behavior to the old way. Make going to the search for unread messages off by default. Fix up some hiding of labels, etc. on the incoming server settings. Check for message suppression in search results. --- res/layout/account_setup_incoming.xml | 9 +++ res/values/strings.xml | 1 + src/com/fsck/k9/Account.java | 20 +++++- .../activity/setup/AccountSetupIncoming.java | 10 +++ .../k9/controller/MessagingController.java | 31 +++++----- src/com/fsck/k9/mail/Store.java | 2 +- src/com/fsck/k9/mail/store/ImapStore.java | 62 +++++++++++++++---- src/com/fsck/k9/mail/store/LocalStore.java | 2 +- src/com/fsck/k9/mail/store/Pop3Store.java | 2 +- src/com/fsck/k9/mail/store/WebDavStore.java | 2 +- 10 files changed, 108 insertions(+), 33 deletions(-) diff --git a/res/layout/account_setup_incoming.xml b/res/layout/account_setup_incoming.xml index a362694e3..41604d165 100644 --- a/res/layout/account_setup_incoming.xml +++ b/res/layout/account_setup_incoming.xml @@ -66,6 +66,8 @@ android:layout_height="wrap_content" android:layout_width="fill_parent" /> + Trash folder name Outbox folder name + Show only subscribed folders Auto-expand folder WebDAV (Exchange) path diff --git a/src/com/fsck/k9/Account.java b/src/com/fsck/k9/Account.java index 1db3ed3f3..30ce49d48 100644 --- a/src/com/fsck/k9/Account.java +++ b/src/com/fsck/k9/Account.java @@ -90,6 +90,7 @@ public class Account implements BaseAccount private boolean goToUnreadMessageSearch; private Map compressionMap = new ConcurrentHashMap(); private Searchable searchableFolders; + private boolean subscribedFoldersOnly; // Tracks if we have sent a notification for this account for // current set of fetched messages private boolean mRingNotified; @@ -140,6 +141,7 @@ public class Account implements BaseAccount mChipColor = (new Random()).nextInt(0xffffff) + 0xff000000; mLedColor = mChipColor; goToUnreadMessageSearch = false; + subscribedFoldersOnly = false; searchableFolders = Searchable.ALL; @@ -200,7 +202,9 @@ public class Account implements BaseAccount mMaxPushFolders = preferences.getPreferences().getInt(mUuid + ".maxPushFolders", 10); goToUnreadMessageSearch = preferences.getPreferences().getBoolean(mUuid + ".goToUnreadMessageSearch", - true); + false); + subscribedFoldersOnly = preferences.getPreferences().getBoolean(mUuid + ".subscribedFoldersOnly", + false); for (String type : networkTypes) { Boolean useCompression = preferences.getPreferences().getBoolean(mUuid + ".useCompression." + type, @@ -370,6 +374,7 @@ public class Account implements BaseAccount editor.remove(mUuid + ".chipColor"); editor.remove(mUuid + ".ledColor"); editor.remove(mUuid + ".goToUnreadMessageSearch"); + editor.remove(mUuid + ".subscribedFoldersOnly"); for (String type : networkTypes) { editor.remove(mUuid + ".useCompression." + type); @@ -453,6 +458,7 @@ public class Account implements BaseAccount editor.putInt(mUuid + ".chipColor", mChipColor); editor.putInt(mUuid + ".ledColor", mLedColor); editor.putBoolean(mUuid + ".goToUnreadMessageSearch", goToUnreadMessageSearch); + editor.putBoolean(mUuid + ".subscribedFoldersOnly", subscribedFoldersOnly); for (String type : networkTypes) { @@ -484,7 +490,7 @@ public class Account implements BaseAccount Account.FolderMode aMode = getFolderDisplayMode(); Preferences prefs = Preferences.getPreferences(context); long folderLoadStart = System.currentTimeMillis(); - List folders = localStore.getPersonalNamespaces(); + List folders = localStore.getPersonalNamespaces(false); long folderLoadEnd = System.currentTimeMillis(); long folderEvalStart = folderLoadEnd; for (Folder folder : folders) @@ -1202,4 +1208,14 @@ public class Account implements BaseAccount { this.goToUnreadMessageSearch = goToUnreadMessageSearch; } + + public boolean subscribedFoldersOnly() + { + return subscribedFoldersOnly; + } + + public void setSubscribedFoldersOnly(boolean subscribedFoldersOnly) + { + this.subscribedFoldersOnly = subscribedFoldersOnly; + } } diff --git a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java index 072cc36ac..605df862d 100644 --- a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java +++ b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java @@ -89,6 +89,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener private CheckBox pushPollOnConnect; private Spinner idleRefreshPeriod; private Spinner folderPushLimit; + private CheckBox subscribedFoldersOnly; public static void actionIncomingSettings(Activity context, Account account, boolean makeDefault) { @@ -133,6 +134,8 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener compressionOther = (CheckBox)findViewById(R.id.compression_other); saveAllHeaders = (CheckBox)findViewById(R.id.save_all_headers); pushPollOnConnect = (CheckBox)findViewById(R.id.push_poll_on_connect); + + subscribedFoldersOnly = (CheckBox)findViewById(R.id.subscribed_folders_only); idleRefreshPeriod = (Spinner)findViewById(R.id.idle_refresh_period); folderPushLimit = (Spinner)findViewById(R.id.folder_push_limit); @@ -296,8 +299,10 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener findViewById(R.id.imap_folder_setup_section).setVisibility(View.GONE); findViewById(R.id.webdav_path_prefix_section).setVisibility(View.GONE); findViewById(R.id.webdav_path_debug_section).setVisibility(View.GONE); + findViewById(R.id.account_auth_type_label).setVisibility(View.GONE); findViewById(R.id.account_auth_type).setVisibility(View.GONE); findViewById(R.id.compression_section).setVisibility(View.GONE); + findViewById(R.id.compression_label).setVisibility(View.GONE); findViewById(R.id.push_poll_on_connect_section).setVisibility(View.GONE); findViewById(R.id.idle_refresh_period_label).setVisibility(View.GONE); findViewById(R.id.idle_refresh_period).setVisibility(View.GONE); @@ -335,13 +340,16 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener /** Hide the unnecessary fields */ findViewById(R.id.imap_path_prefix_section).setVisibility(View.GONE); + findViewById(R.id.account_auth_type_label).setVisibility(View.GONE); findViewById(R.id.account_auth_type).setVisibility(View.GONE); findViewById(R.id.compression_section).setVisibility(View.GONE); + findViewById(R.id.compression_label).setVisibility(View.GONE); findViewById(R.id.push_poll_on_connect_section).setVisibility(View.GONE); findViewById(R.id.idle_refresh_period_label).setVisibility(View.GONE); findViewById(R.id.idle_refresh_period).setVisibility(View.GONE); findViewById(R.id.account_setup_push_limit_label).setVisibility(View.GONE); findViewById(R.id.folder_push_limit).setVisibility(View.GONE); + subscribedFoldersOnly.setVisibility(View.GONE); if (uri.getPath() != null && uri.getPath().length() > 0) { String[] pathParts = uri.getPath().split("\\|"); @@ -408,6 +416,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener saveAllHeaders.setChecked(mAccount.isSaveAllHeaders()); pushPollOnConnect.setChecked(mAccount.isPushPollOnConnect()); + subscribedFoldersOnly.setChecked(mAccount.subscribedFoldersOnly()); SpinnerHelper.initSpinner(this, idleRefreshPeriod, R.array.idle_refresh_period_entries, R.array.idle_refresh_period_values, String.valueOf(mAccount.getIdleRefreshMinutes())); @@ -564,6 +573,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener mAccount.setCompression(Account.TYPE_OTHER, compressionOther.isChecked()); mAccount.setSaveAllHeaders(saveAllHeaders.isChecked()); mAccount.setPushPollOnConnect(pushPollOnConnect.isChecked()); + mAccount.setSubscribedFoldersOnly(subscribedFoldersOnly.isChecked()); String idleRefreshPeriodValue = SpinnerHelper.getSpinnerValue(idleRefreshPeriod); try { diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 616f9c9f9..6e2e2178f 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -421,7 +421,7 @@ public class MessagingController implements Runnable try { Store localStore = account.getLocalStore(); - localFolders = localStore.getPersonalNamespaces(); + localFolders = localStore.getPersonalNamespaces(false); Folder[] folderArray = localFolders.toArray(new Folder[0]); @@ -489,7 +489,7 @@ public class MessagingController implements Runnable { Store store = account.getRemoteStore(); - List remoteFolders = store.getPersonalNamespaces(); + List remoteFolders = store.getPersonalNamespaces(false); LocalStore localStore = account.getLocalStore(); HashSet remoteFolderNames = new HashSet(); @@ -503,7 +503,7 @@ public class MessagingController implements Runnable remoteFolderNames.add(remoteFolders.get(i).getName()); } - localFolders = localStore.getPersonalNamespaces(); + localFolders = localStore.getPersonalNamespaces(false); /* * Clear out any folders that are no longer on the remote store. @@ -526,7 +526,7 @@ public class MessagingController implements Runnable } } - localFolders = localStore.getPersonalNamespaces(); + localFolders = localStore.getPersonalNamespaces(false); Folder[] folderArray = localFolders.toArray(new Folder[0]); for (MessagingListener l : getListeners()) @@ -810,7 +810,7 @@ public class MessagingController implements Runnable try { LocalStore store = account.getLocalStore(); - List folders = store.getPersonalNamespaces(); + List folders = store.getPersonalNamespaces(false); Set folderNameSet = null; if (folderNames != null) { @@ -879,14 +879,17 @@ public class MessagingController implements Runnable public void messageStarted(String message, int number, int ofTotal) {} public void messageFinished(Message message, int number, int ofTotal) { - List messages = new ArrayList(); - - messages.add(message); - stats.unreadMessageCount += (message.isSet(Flag.SEEN) == false) ? 1 : 0; - stats.flaggedMessageCount += (message.isSet(Flag.FLAGGED)) ? 1 : 0; - if (listener != null) + if (isMessageSuppressed(message.getFolder().getAccount(), message.getFolder().getName(), message) == false) { - listener.listLocalMessagesAddMessages(account, null, messages); + List messages = new ArrayList(); + + messages.add(message); + stats.unreadMessageCount += (message.isSet(Flag.SEEN) == false) ? 1 : 0; + stats.flaggedMessageCount += (message.isSet(Flag.FLAGGED)) ? 1 : 0; + if (listener != null) + { + listener.listLocalMessagesAddMessages(account, null, messages); + } } } @@ -4195,7 +4198,7 @@ public class MessagingController implements Runnable Account.FolderMode aSyncMode = account.getFolderSyncMode(); Store localStore = account.getLocalStore(); - for (final Folder folder : localStore.getPersonalNamespaces()) + for (final Folder folder : localStore.getPersonalNamespaces(false)) { folder.open(Folder.OpenMode.READ_WRITE); @@ -4764,7 +4767,7 @@ public class MessagingController implements Runnable List names = new ArrayList(); Store localStore = account.getLocalStore(); - for (final Folder folder : localStore.getPersonalNamespaces()) + for (final Folder folder : localStore.getPersonalNamespaces(false)) { if (folder.getName().equals(account.getErrorFolderName()) || folder.getName().equals(account.getOutboxFolderName())) diff --git a/src/com/fsck/k9/mail/Store.java b/src/com/fsck/k9/mail/Store.java index f00b12d3f..e89fb4f79 100644 --- a/src/com/fsck/k9/mail/Store.java +++ b/src/com/fsck/k9/mail/Store.java @@ -116,7 +116,7 @@ public abstract class Store public abstract Folder getFolder(String name) throws MessagingException; - public abstract List getPersonalNamespaces() throws MessagingException; + public abstract List getPersonalNamespaces(boolean forceListAll) throws MessagingException; public abstract void checkSettings() throws MessagingException; diff --git a/src/com/fsck/k9/mail/store/ImapStore.java b/src/com/fsck/k9/mail/store/ImapStore.java index 687ef53d6..c48f6c048 100644 --- a/src/com/fsck/k9/mail/store/ImapStore.java +++ b/src/com/fsck/k9/mail/store/ImapStore.java @@ -251,20 +251,65 @@ public class ImapStore extends Store } @Override - public List getPersonalNamespaces() throws MessagingException + public List getPersonalNamespaces(boolean forceListAll) throws MessagingException { ImapConnection connection = getConnection(); try { + List allFolders = listFolders(connection, false); + if (forceListAll || mAccount.subscribedFoldersOnly() == false) + { + return allFolders; + } + else + { + List resultFolders = new LinkedList(); + HashSet subscribedFolderNames = new HashSet(); + List subscribedFolders = listFolders(connection, true); + for (Folder subscribedFolder : subscribedFolders) + { + subscribedFolderNames.add(subscribedFolder.getName()); + } + for (Folder folder : allFolders) + { + if (subscribedFolderNames.contains(folder.getName())) + { + resultFolders.add(folder); + } + } + return resultFolders; + } + } + catch (IOException ioe) + { + connection.close(); + throw new MessagingException("Unable to get folder list.", ioe); + } + catch (MessagingException me) + { + connection.close(); + throw new MessagingException("Unable to get folder list.", me); + } + finally + { + releaseConnection(connection); + } + } + + + private List listFolders(ImapConnection connection, boolean LSUB) throws IOException, MessagingException + { + String commandResponse = LSUB ? "LSUB" : "LIST"; + LinkedList folders = new LinkedList(); List responses = - connection.executeSimpleCommand(String.format("LIST \"\" \"%s*\"", + connection.executeSimpleCommand(String.format(commandResponse + " \"\" \"%s*\"", getCombinedPrefix())); for (ImapResponse response : responses) { - if (ImapResponseParser.equalsIgnoreCase(response.get(0), "LIST")) + if (ImapResponseParser.equalsIgnoreCase(response.get(0), commandResponse)) { boolean includeFolder = true; String folder = decodeFolderName(response.getString(3)); @@ -312,16 +357,7 @@ public class ImapStore extends Store } folders.add(getFolder("INBOX")); return folders; - } - catch (IOException ioe) - { - connection.close(); - throw new MessagingException("Unable to get folder list.", ioe); - } - finally - { - releaseConnection(connection); - } + } @Override diff --git a/src/com/fsck/k9/mail/store/LocalStore.java b/src/com/fsck/k9/mail/store/LocalStore.java index a5ef70527..887514527 100644 --- a/src/com/fsck/k9/mail/store/LocalStore.java +++ b/src/com/fsck/k9/mail/store/LocalStore.java @@ -373,7 +373,7 @@ public class LocalStore extends Store implements Serializable // TODO this takes about 260-300ms, seems slow. @Override - public List getPersonalNamespaces() throws MessagingException + public List getPersonalNamespaces(boolean forceListAll) throws MessagingException { LinkedList folders = new LinkedList(); Cursor cursor = null; diff --git a/src/com/fsck/k9/mail/store/Pop3Store.java b/src/com/fsck/k9/mail/store/Pop3Store.java index c7cc3c0db..fea1c389b 100644 --- a/src/com/fsck/k9/mail/store/Pop3Store.java +++ b/src/com/fsck/k9/mail/store/Pop3Store.java @@ -159,7 +159,7 @@ public class Pop3Store extends Store } @Override - public List getPersonalNamespaces() throws MessagingException + public List getPersonalNamespaces(boolean forceListAll) throws MessagingException { List folders = new LinkedList(); folders.add(getFolder("INBOX")); diff --git a/src/com/fsck/k9/mail/store/WebDavStore.java b/src/com/fsck/k9/mail/store/WebDavStore.java index fe7b47bae..54db8526b 100644 --- a/src/com/fsck/k9/mail/store/WebDavStore.java +++ b/src/com/fsck/k9/mail/store/WebDavStore.java @@ -263,7 +263,7 @@ public class WebDavStore extends Store } @Override - public List getPersonalNamespaces() throws MessagingException + public List getPersonalNamespaces(boolean forceListAll) throws MessagingException { LinkedList folderList = new LinkedList(); HashMap headers = new HashMap();