From 474780cbf41a3eb9371b178c1dc8b03764800209 Mon Sep 17 00:00:00 2001 From: Kris Wong Date: Mon, 2 Jan 2012 13:47:44 -0500 Subject: [PATCH] Prevent the display of the message list before the folder list has initially been retrieved from the server after account setup. --- res/layout/account_setup_check_settings.xml | 32 +--- res/layout/folder_list.xml | 11 +- res/layout/progress_bar.xml | 32 ++++ res/values/strings.xml | 1 + src/com/fsck/k9/activity/Accounts.java | 15 +- src/com/fsck/k9/activity/FolderList.java | 11 +- .../k9/controller/MessagingController.java | 161 +++++++++--------- 7 files changed, 143 insertions(+), 120 deletions(-) create mode 100644 res/layout/progress_bar.xml diff --git a/res/layout/account_setup_check_settings.xml b/res/layout/account_setup_check_settings.xml index f6f977843..f8d2dadce 100644 --- a/res/layout/account_setup_check_settings.xml +++ b/res/layout/account_setup_check_settings.xml @@ -4,34 +4,6 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> - - - - - - - + + diff --git a/res/layout/folder_list.xml b/res/layout/folder_list.xml index edeeaf112..dfa67dac0 100644 --- a/res/layout/folder_list.xml +++ b/res/layout/folder_list.xml @@ -6,7 +6,12 @@ - + android:layout_height="fill_parent"/> + + + diff --git a/res/layout/progress_bar.xml b/res/layout/progress_bar.xml new file mode 100644 index 000000000..a23188d0a --- /dev/null +++ b/res/layout/progress_bar.xml @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 858dd3a6d..2f610e4df 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -842,6 +842,7 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin Display only 1st Class folders Display 1st and 2nd Class folders Display all except 2nd Class folders + Loading folder list\u2026 Signature position Before quoted text diff --git a/src/com/fsck/k9/activity/Accounts.java b/src/com/fsck/k9/activity/Accounts.java index d6c29a098..3b6104fce 100644 --- a/src/com/fsck/k9/activity/Accounts.java +++ b/src/com/fsck/k9/activity/Accounts.java @@ -78,6 +78,7 @@ import com.fsck.k9.controller.MessagingController; import com.fsck.k9.controller.MessagingListener; import com.fsck.k9.helper.SizeFormatter; import com.fsck.k9.mail.Flag; +import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.ServerSettings; import com.fsck.k9.mail.Store; import com.fsck.k9.mail.Transport; @@ -566,10 +567,16 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC Log.i(K9.LOG_TAG, "refusing to open account that is not available"); return false; } - if (K9.FOLDER_NONE.equals(realAccount.getAutoExpandFolderName())) { - FolderList.actionHandleAccount(this, realAccount); - } else { - MessageList.actionHandleFolder(this, realAccount, realAccount.getAutoExpandFolderName()); + try { + if (K9.FOLDER_NONE.equals(realAccount.getAutoExpandFolderName()) || + realAccount.getLocalStore().getFolderCount() == 0) { + FolderList.actionHandleAccount(this, realAccount); + } else { + MessageList.actionHandleFolder(this, realAccount, realAccount.getAutoExpandFolderName()); + } + } + catch (MessagingException e) { + Log.e(K9.LOG_TAG, "Exception while getting local folder count", e); } } return true; diff --git a/src/com/fsck/k9/activity/FolderList.java b/src/com/fsck/k9/activity/FolderList.java index 6d91ab0a2..9eeb5729b 100644 --- a/src/com/fsck/k9/activity/FolderList.java +++ b/src/com/fsck/k9/activity/FolderList.java @@ -83,8 +83,6 @@ public class FolderList extends K9ListActivity { public void run() { String dispString = mAdapter.mListener.formatHeader(FolderList.this, getString(R.string.folder_list_title, mAccount.getDescription()), mUnreadMessageCount, getTimeFormat()); - - setTitle(dispString); } }); @@ -116,7 +114,6 @@ public class FolderList extends K9ListActivity { runOnUiThread(new Runnable() { public void run() { String toastText = getString(R.string.account_size_changed, mAccount.getDescription(), SizeFormatter.formatSize(getApplication(), oldSize), SizeFormatter.formatSize(getApplication(), newSize)); - Toast toast = Toast.makeText(getApplication(), toastText, Toast.LENGTH_LONG); toast.show(); } @@ -127,12 +124,9 @@ public class FolderList extends K9ListActivity { runOnUiThread(new Runnable() { public void run() { FolderInfoHolder folderHolder = mAdapter.getFolder(folder); - - if (folderHolder != null) { folderHolder.loading = loading; } - } }); } @@ -253,7 +247,10 @@ public class FolderList extends K9ListActivity { } }); registerForContextMenu(mListView); - + + TextView progressMsg = (TextView)findViewById(R.id.message); + progressMsg.setText(getString(R.string.folder_list_loading_folders)); + mListView.setSaveEnabled(true); mInflater = getLayoutInflater(); diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 974f0bf9e..910f6db73 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -139,7 +139,9 @@ public class MessagingController implements Runnable { private final ConcurrentHashMap sendCount = new ConcurrentHashMap(); - ConcurrentHashMap pushers = new ConcurrentHashMap(); + private ConcurrentHashMap pushers = new ConcurrentHashMap(); + + private Set mCurrentlyRefreshing = Collections.synchronizedSet(new HashSet()); private final ExecutorService threadPool = Executors.newCachedThreadPool(); @@ -448,81 +450,93 @@ public class MessagingController implements Runnable { } private void doRefreshRemote(final Account account, MessagingListener listener) { - put("doRefreshRemote", listener, new Runnable() { - @Override - public void run() { - List localFolders = null; - try { - Store store = account.getRemoteStore(); + // It is possible that multiple threads may try to refresh the same account at the same time. + // Currently, this can happen immediately after the account is setup initially, and is + // generally a bad thing. Let's use a hack to prevent this from happening. + if (!mCurrentlyRefreshing.contains(account)) { + mCurrentlyRefreshing.add(account); + put("doRefreshRemote", listener, new Runnable() { + @Override + public void run() { + doRefreshRemoteSynchronous(account); + mCurrentlyRefreshing.remove(account); + } + }); + } + } + + private void doRefreshRemoteSynchronous(final Account account) { + List localFolders = null; + try { + Store remoteStore = account.getRemoteStore(); + List remoteFolders = remoteStore.getPersonalNamespaces(true); - List remoteFolders = store.getPersonalNamespaces(true); + LocalStore localStore = account.getLocalStore(); + localFolders = localStore.getPersonalNamespaces(false); + + syncLocalFoldersWithRemoteFolders(localFolders, remoteFolders, account); - LocalStore localStore = account.getLocalStore(); - HashSet remoteFolderNames = new HashSet(); - List foldersToCreate = new LinkedList(); + // Get the updated local folder list. + localFolders = localStore.getPersonalNamespaces(false); + Folder[] folderArray = localFolders.toArray(EMPTY_FOLDER_ARRAY); - localFolders = localStore.getPersonalNamespaces(false); - HashSet localFolderNames = new HashSet(); - for (Folder localFolder : localFolders) { - localFolderNames.add(localFolder.getRemoteName()); - } - for (Folder remoteFolder : remoteFolders) { - LocalFolder localFolder = null; - if (localFolderNames.contains(remoteFolder.getRemoteName()) == false) { - localFolder = localStore.getFolder(remoteFolder.getRemoteName(), - remoteFolder.getName()); - foldersToCreate.add(localFolder); - } else { - for (Folder folder : localFolders) { - if (folder.getRemoteName().equals(remoteFolder.getRemoteName())) { - localFolder = (LocalFolder)folder; - break; - } - } - } - remoteFolderNames.add(remoteFolder.getRemoteName()); - - if (remoteFolder instanceof EasFolder) { - ((EasFolder)remoteFolder).setLocalFolder(localFolder, false); - } - } - localStore.createFolders(foldersToCreate, account.getDisplayCount()); - - localFolders = localStore.getPersonalNamespaces(false); - - /* - * Clear out any folders that are no longer on the remote store. - */ - for (Folder localFolder : localFolders) { - if (!account.isSpecialFolder(localFolder.getRemoteName()) && - !remoteFolderNames.contains(localFolder.getRemoteName())) { - localFolder.delete(false); - } - } - - localFolders = localStore.getPersonalNamespaces(false); - Folder[] folderArray = localFolders.toArray(EMPTY_FOLDER_ARRAY); - - for (MessagingListener l : getListeners()) { - l.listFolders(account, folderArray); - } - for (MessagingListener l : getListeners()) { - l.listFoldersFinished(account); - } - } catch (Exception e) { - for (MessagingListener l : getListeners()) { - l.listFoldersFailed(account, ""); - } - addErrorMessage(account, null, e); - } finally { - if (localFolders != null) { - for (Folder localFolder : localFolders) { - closeFolder(localFolder); - } - } + for (MessagingListener l : getListeners()) { + l.listFolders(account, folderArray); + } + for (MessagingListener l : getListeners()) { + l.listFoldersFinished(account); + } + } catch (Exception e) { + for (MessagingListener l : getListeners()) { + l.listFoldersFailed(account, ""); + } + addErrorMessage(account, null, e); + } finally { + if (localFolders != null) { + for (Folder localFolder : localFolders) { + closeFolder(localFolder); } } - }); + } + } + + private void syncLocalFoldersWithRemoteFolders(List localFolders, + List remoteFolders, final Account account) throws MessagingException { + HashSet remoteFolderNames = new HashSet(); + HashMap localFolderNames = new HashMap(); + + List foldersToCreate = new LinkedList(); + LocalStore localStore = account.getLocalStore(); + + for (Folder localFolder : localFolders) { + localFolderNames.put(localFolder.getRemoteName(), localFolder); + } + + // Add any new folders in the remote store to the local store. + for (Folder remoteFolder : remoteFolders) { + LocalFolder localFolder = (LocalFolder)localFolderNames.get(remoteFolder.getRemoteName()); + if (localFolder == null) { + localFolder = localStore.getFolder(remoteFolder.getRemoteName(), + remoteFolder.getName()); + foldersToCreate.add(localFolder); + } + remoteFolderNames.add(remoteFolder.getRemoteName()); + + if (remoteFolder instanceof EasFolder) { + ((EasFolder)remoteFolder).setLocalFolder(localFolder, false); + } + } + + localStore.createFolders(foldersToCreate, account.getDisplayCount()); + localFolders = localStore.getPersonalNamespaces(false); + + // Delete any folders in the local store that are no longer in the remote store. + for (Folder localFolder : localFolders) { + if (!account.isSpecialFolder(localFolder.getRemoteName()) && + !remoteFolderNames.contains(localFolder.getRemoteName())) { + localFolder.delete(false); + } + } } /** @@ -562,10 +576,6 @@ public class MessagingController implements Runnable { new MessageRetrievalListener() { List pendingMessages = new ArrayList(); - - int totalDone = 0; - - @Override public void messageStarted(String message, int number, int ofTotal) {} @Override @@ -573,7 +583,6 @@ public class MessagingController implements Runnable { if (!isMessageSuppressed(account, folder, message)) { pendingMessages.add(message); - totalDone++; if (pendingMessages.size() > 10) { addPendingMessages(); }