1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-12-25 00:58:50 -05:00

Fixes Issue 1448

Fixes ClassCastException.

Also:
Envelope and star in Accounts Activity are now both "hot".  Tapping
the main part of the search opens the full search; tapping the
envelope opens the search only for unread messages; tapping the star
opens the search but only for starred messages.

The envelope and star are a bit small to reliably tap.  Both options
should be available via long-press, also.

Methodology will be extended to real accounts, as well.
This commit is contained in:
Daniel Applebaum 2010-04-22 02:20:35 +00:00
parent 8ebbc611e9
commit 41c5dc5986
14 changed files with 360 additions and 126 deletions

View File

@ -37,6 +37,7 @@
android:layout_width="0dip" android:layout_width="0dip"
android:layout_weight="1" /> android:layout_weight="1" />
<RelativeLayout <RelativeLayout
android:id="@+id/active_icons"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" android:orientation="vertical"
@ -45,6 +46,7 @@
android:paddingLeft="6dip" android:paddingLeft="6dip"
android:paddingRight="6dip" android:paddingRight="6dip"
android:gravity="right" android:gravity="right"
android:clickable="true"
> >
<TextView <TextView
android:id="@+id/new_message_count" android:id="@+id/new_message_count"
@ -63,6 +65,7 @@
android:gravity="right" android:gravity="right"
android:layout_gravity="top" android:layout_gravity="top"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:clickable="true"
/> />
<TextView <TextView
android:id="@+id/flagged_message_count" android:id="@+id/flagged_message_count"
@ -80,6 +83,7 @@
android:gravity="right" android:gravity="right"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:clickable="true"
/> />
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>

View File

@ -690,17 +690,13 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
<string name="count_search_title">Count search results</string> <string name="count_search_title">Count search results</string>
<string name="count_search_summary">Turn off for faster display</string> <string name="count_search_summary">Turn off for faster display</string>
<string name="search_unread_messages_title">All unread messages</string> <string name="search_all_messages_title">All messages</string>
<string name="search_unread_messages_detail">Unread messages in searchable accounts</string> <string name="search_all_messages_detail">All messages in searchable folders</string>
<string name="search_starred_messages_title">All starred messages</string> <string name="integrated_inbox_title">Integrated Inbox</string>
<string name="search_starred_messages_detail">Starred messages in searchable accounts</string> <string name="integrated_inbox_detail">All messages in integrated folders</string>
<string name="integrated_inbox_title">Integrated Inbox (unread)</string>
<string name="integrated_inbox_detail">All unread messages in integrated folders</string>
<string name="integrated_inbox_starred_title">Integrated Inbox (starred)</string> <string name="tap_hint">Tap envelope or star for unread or starred messages</string>
<string name="integrated_inbox_starred_detail">All starred messages in integrated folders</string>
<string name="folder_settings_include_in_integrated_inbox_label">Integrate</string> <string name="folder_settings_include_in_integrated_inbox_label">Integrate</string>
<string name="folder_settings_include_in_integrated_inbox_summary">Unread messages are shown in Integrated Inbox</string> <string name="folder_settings_include_in_integrated_inbox_summary">Unread messages are shown in Integrated Inbox</string>

View File

@ -426,6 +426,7 @@ public class Account implements BaseAccount
// Why should everything be in MessagingController? This is an Account-specific operation. --danapple0 // Why should everything be in MessagingController? This is an Account-specific operation. --danapple0
public AccountStats getStats(Context context) throws MessagingException public AccountStats getStats(Context context) throws MessagingException
{ {
long startTime = System.currentTimeMillis();
AccountStats stats = new AccountStats(); AccountStats stats = new AccountStats();
int unreadMessageCount = 0; int unreadMessageCount = 0;
int flaggedMessageCount = 0; int flaggedMessageCount = 0;
@ -436,10 +437,15 @@ public class Account implements BaseAccount
} }
Account.FolderMode aMode = getFolderDisplayMode(); Account.FolderMode aMode = getFolderDisplayMode();
Preferences prefs = Preferences.getPreferences(context); Preferences prefs = Preferences.getPreferences(context);
for (LocalFolder folder : localStore.getPersonalNamespaces()) long folderLoadStart = System.currentTimeMillis();
List<? extends Folder> folders = localStore.getPersonalNamespaces();
long folderLoadEnd = System.currentTimeMillis();
long folderEvalStart = folderLoadEnd;
for (Folder folder : folders)
{ {
folder.refresh(prefs); LocalFolder localFolder = (LocalFolder)folder;
Folder.FolderClass fMode = folder.getDisplayClass(); //folder.refresh(prefs);
Folder.FolderClass fMode = localFolder.getDisplayClass(prefs);
if (folder.getName().equals(getTrashFolderName()) == false && if (folder.getName().equals(getTrashFolderName()) == false &&
folder.getName().equals(getDraftsFolderName()) == false && folder.getName().equals(getDraftsFolderName()) == false &&
@ -472,9 +478,14 @@ public class Account implements BaseAccount
} }
} }
long folderEvalEnd = System.currentTimeMillis();
stats.unreadMessageCount = unreadMessageCount; stats.unreadMessageCount = unreadMessageCount;
stats.flaggedMessageCount = flaggedMessageCount; stats.flaggedMessageCount = flaggedMessageCount;
Log.i(K9.LOG_TAG, "flaggedMessageCount for " + getDescription() + " = " + flaggedMessageCount); long endTime = System.currentTimeMillis();
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "Account.getStats() on " + getDescription() + " took " + (endTime - startTime) + " ms;"
+ " loading " + folders.size() + " took " + (folderLoadEnd - folderLoadStart) + " ms;"
+ " evaluating took " + (folderEvalEnd - folderEvalStart) + " ms");
return stats; return stats;
} }

View File

@ -410,24 +410,26 @@ public class MessagingController implements Runnable
{ {
listener.listFoldersStarted(account); listener.listFoldersStarted(account);
} }
Folder[] localFolders = null; List<? extends Folder> localFolders = null;
try try
{ {
Store localStore = account.getLocalStore(); Store localStore = account.getLocalStore();
localFolders = localStore.getPersonalNamespaces(); localFolders = localStore.getPersonalNamespaces();
if (refreshRemote || localFolders == null || localFolders.length == 0) Folder[] folderArray = localFolders.toArray(new Folder[0]);
if (refreshRemote || localFolders == null || localFolders.size() == 0)
{ {
doRefreshRemote(account, listener); doRefreshRemote(account, listener);
return; return;
} }
for (MessagingListener l : getListeners()) for (MessagingListener l : getListeners())
{ {
l.listFolders(account, localFolders); l.listFolders(account, folderArray);
} }
if (listener != null) if (listener != null)
{ {
listener.listFolders(account, localFolders); listener.listFolders(account, folderArray);
} }
} }
catch (Exception e) catch (Exception e)
@ -475,23 +477,23 @@ public class MessagingController implements Runnable
{ {
public void run() public void run()
{ {
Folder[] localFolders = null; List<? extends Folder> localFolders = null;
try try
{ {
Store store = account.getRemoteStore(); Store store = account.getRemoteStore();
Folder[] remoteFolders = store.getPersonalNamespaces(); List<? extends Folder> remoteFolders = store.getPersonalNamespaces();
LocalStore localStore = account.getLocalStore(); LocalStore localStore = account.getLocalStore();
HashSet<String> remoteFolderNames = new HashSet<String>(); HashSet<String> remoteFolderNames = new HashSet<String>();
for (int i = 0, count = remoteFolders.length; i < count; i++) for (int i = 0, count = remoteFolders.size(); i < count; i++)
{ {
LocalFolder localFolder = localStore.getFolder(remoteFolders[i].getName()); LocalFolder localFolder = localStore.getFolder(remoteFolders.get(i).getName());
if (!localFolder.exists()) if (!localFolder.exists())
{ {
localFolder.create(FolderType.HOLDS_MESSAGES, account.getDisplayCount()); localFolder.create(FolderType.HOLDS_MESSAGES, account.getDisplayCount());
} }
remoteFolderNames.add(remoteFolders[i].getName()); remoteFolderNames.add(remoteFolders.get(i).getName());
} }
localFolders = localStore.getPersonalNamespaces(); localFolders = localStore.getPersonalNamespaces();
@ -518,10 +520,11 @@ public class MessagingController implements Runnable
} }
localFolders = localStore.getPersonalNamespaces(); localFolders = localStore.getPersonalNamespaces();
Folder[] folderArray = localFolders.toArray(new Folder[0]);
for (MessagingListener l : getListeners()) for (MessagingListener l : getListeners())
{ {
l.listFolders(account, localFolders); l.listFolders(account, folderArray);
} }
for (MessagingListener l : getListeners()) for (MessagingListener l : getListeners())
{ {
@ -696,27 +699,34 @@ public class MessagingController implements Runnable
} }
} }
public void searchLocalMessages(SearchAccount searchAccount, final Message[] messages, final MessagingListener listener) public void searchLocalMessages(SearchSpecification searchSpecification, final Message[] messages, final MessagingListener listener)
{ {
searchLocalMessages(searchAccount, searchAccount.getQuery(), messages, searchAccount.isIntegrate(), searchLocalMessages(searchSpecification.getAccountUuids(), searchSpecification.getQuery(), messages,
searchAccount.getRequiredFlags(), searchAccount.getForbiddenFlags(), listener); searchSpecification.isIntegrate(), searchSpecification.getRequiredFlags(), searchSpecification.getForbiddenFlags(), listener);
} }
/** /**
* Find all messages in any local account which match the query 'query' * Find all messages in any local account which match the query 'query'
* @param account TODO * @param searchAccounts TODO
* @param query * @param query
* @param listener * @param listener
* @param account TODO
* @param account * @param account
*
* @throws MessagingException * @throws MessagingException
*/ */
public void searchLocalMessages(final BaseAccount baseAccount, final String query, final Message[] messages, final boolean integrate, final Flag[] requiredFlags, public void searchLocalMessages(final String[] accountUuids, final String query, final Message[] messages, final boolean integrate, final Flag[] requiredFlags,
final Flag[] forbiddenFlags, final MessagingListener listener) final Flag[] forbiddenFlags, final MessagingListener listener)
{ {
final AccountStats stats = new AccountStats(); final AccountStats stats = new AccountStats();
final Set<String> accountUuidsSet = new HashSet<String>();
if (accountUuids != null)
{
for (String accountUuid : accountUuids)
{
accountUuidsSet.add(accountUuid);
}
}
threadPool.execute(new Runnable() threadPool.execute(new Runnable()
{ {
public void run() public void run()
@ -728,6 +738,10 @@ public class MessagingController implements Runnable
boolean displayableOnly = false; boolean displayableOnly = false;
for (final Account account : accounts) for (final Account account : accounts)
{ {
if (accountUuids != null && accountUuidsSet.contains(account.getUuid()) == false)
{
continue;
}
Account.Searchable searchableFolders = account.getSearchableFolders(); Account.Searchable searchableFolders = account.getSearchableFolders();
switch (searchableFolders) switch (searchableFolders)
{ {
@ -749,23 +763,24 @@ public class MessagingController implements Runnable
try try
{ {
LocalStore store = account.getLocalStore(); LocalStore store = account.getLocalStore();
LocalFolder[] folders = store.getPersonalNamespaces(); List<? extends Folder> folders = store.getPersonalNamespaces();
for (LocalFolder folder : folders) for (Folder folder : folders)
{ {
LocalFolder localFolder = (LocalFolder)folder;
boolean include = true; boolean include = true;
folder.refresh(prefs); folder.refresh(prefs);
if (displayableOnly && modeMismatch(account.getFolderDisplayMode(), folder.getDisplayClass())) if (displayableOnly && modeMismatch(account.getFolderDisplayMode(), folder.getDisplayClass()))
{ {
include = false; include = false;
} }
if (integrate && folder.isIntegrate() == false) if (integrate && localFolder.isIntegrate() == false)
{ {
include = false; include = false;
} }
if (include) if (include)
{ {
tmpFoldersToSearch.add(folder); tmpFoldersToSearch.add(localFolder);
} }
} }
foldersToSearch = tmpFoldersToSearch; foldersToSearch = tmpFoldersToSearch;
@ -801,10 +816,7 @@ public class MessagingController implements Runnable
} }
public void messagesFinished(int number) public void messagesFinished(int number)
{ {
if (baseAccount != null) listener.searchStats(stats);
{
listener.accountStatusChanged(baseAccount, stats);
}
} }
}; };
@ -4337,15 +4349,15 @@ public class MessagingController implements Runnable
} }
int unreadMessageCount = 0; int unreadMessageCount = 0;
try // try
{ // {
AccountStats stats = account.getStats(context); // AccountStats stats = account.getStats(context);
unreadMessageCount = stats.unreadMessageCount; // unreadMessageCount = stats.unreadMessageCount;
} // }
catch (MessagingException e) // catch (MessagingException e)
{ // {
Log.e(K9.LOG_TAG, "Unable to getUnreadMessageCount for account: " + account, e); // Log.e(K9.LOG_TAG, "Unable to getUnreadMessageCount for account: " + account, e);
} // }
NotificationManager notifMgr = NotificationManager notifMgr =
(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
@ -4355,7 +4367,6 @@ public class MessagingController implements Runnable
Intent i = FolderList.actionHandleAccountIntent(context, account, account.getAutoExpandFolderName()); Intent i = FolderList.actionHandleAccountIntent(context, account, account.getAutoExpandFolderName());
PendingIntent pi = PendingIntent.getActivity(context, 0, i, 0); PendingIntent pi = PendingIntent.getActivity(context, 0, i, 0);
// 279 Unread (someone@gmail.com)
String accountNotice = context.getString(R.string.notification_new_one_account_fmt, unreadMessageCount, account.getDescription()); String accountNotice = context.getString(R.string.notification_new_one_account_fmt, unreadMessageCount, account.getDescription());
notif.setLatestEventInfo(context, accountNotice, messageNotice, pi); notif.setLatestEventInfo(context, accountNotice, messageNotice, pi);

View File

@ -17,7 +17,8 @@ import java.util.List;
*/ */
public class MessagingListener public class MessagingListener
{ {
public void searchStats(AccountStats stats) {}
public void accountStatusChanged(BaseAccount account, AccountStats stats) public void accountStatusChanged(BaseAccount account, AccountStats stats)
{ {
} }

View File

@ -3,6 +3,7 @@
*/ */
package com.fsck.k9; package com.fsck.k9;
import java.io.Serializable;
import java.util.UUID; import java.util.UUID;
import android.content.Context; import android.content.Context;
@ -10,7 +11,7 @@ import android.content.Context;
import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message; import com.fsck.k9.mail.Message;
public class SearchAccount implements BaseAccount public class SearchAccount implements BaseAccount, SearchSpecification, Serializable
{ {
private Flag[] mRequiredFlags = null; private Flag[] mRequiredFlags = null;
private Flag[] mForbiddenFlags = null; private Flag[] mForbiddenFlags = null;
@ -19,6 +20,23 @@ public class SearchAccount implements BaseAccount
private String query = ""; private String query = "";
private boolean integrate = false; private boolean integrate = false;
private String mUuid = UUID.randomUUID().toString(); private String mUuid = UUID.randomUUID().toString();
private boolean builtin = false;
private String[] accountUuids = null;
public SearchAccount(Preferences preferences)
{
}
protected synchronized void delete(Preferences preferences)
{
}
public synchronized void save(Preferences preferences)
{
}
public SearchAccount(Context context, boolean nintegrate, Flag[] requiredFlags, Flag[] forbiddenFlags) public SearchAccount(Context context, boolean nintegrate, Flag[] requiredFlags, Flag[] forbiddenFlags)
{ {
@ -86,4 +104,22 @@ public class SearchAccount implements BaseAccount
{ {
this.integrate = integrate; this.integrate = integrate;
} }
public boolean isBuiltin()
{
return builtin;
}
public void setBuiltin(boolean builtin)
{
this.builtin = builtin;
}
public String[] getAccountUuids()
{
return accountUuids;
}
public void setAccountUuids(String[] accountUuids)
{
this.accountUuids = accountUuids;
}
} }

View File

@ -0,0 +1,18 @@
package com.fsck.k9;
import com.fsck.k9.mail.Flag;
public interface SearchSpecification
{
public Flag[] getRequiredFlags();
public Flag[] getForbiddenFlags();
public boolean isIntegrate();
public String getQuery();
public String[] getAccountUuids();
}

View File

@ -37,15 +37,13 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
private ConcurrentHashMap<BaseAccount, String> pendingWork = new ConcurrentHashMap<BaseAccount, String>(); private ConcurrentHashMap<BaseAccount, String> pendingWork = new ConcurrentHashMap<BaseAccount, String>();
private Account mSelectedContextAccount; private BaseAccount mSelectedContextAccount;
private int mUnreadMessageCount = 0; private int mUnreadMessageCount = 0;
private AccountsHandler mHandler = new AccountsHandler(); private AccountsHandler mHandler = new AccountsHandler();
private AccountsAdapter mAdapter; private AccountsAdapter mAdapter;
private SearchAccount unreadAccount = null; private SearchAccount unreadAccount = null;
private SearchAccount flaggedAccount = null;
private SearchAccount integratedInboxAccount = null; private SearchAccount integratedInboxAccount = null;
private SearchAccount integratedInboxStarredAccount = null;
private FontSizes mFontSizes = K9.getFontSizes(); private FontSizes mFontSizes = K9.getFontSizes();
class AccountsHandler extends Handler class AccountsHandler extends Handler
@ -308,22 +306,14 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
@Override @Override
public void onCreate(Bundle icicle) public void onCreate(Bundle icicle)
{ {
unreadAccount = new SearchAccount(this, false, null, new Flag[] { Flag.SEEN } ); unreadAccount = new SearchAccount(this, false, null, null );
unreadAccount.setDescription(getString(R.string.search_unread_messages_title)); unreadAccount.setDescription(getString(R.string.search_all_messages_title));
unreadAccount.setEmail(getString(R.string.search_unread_messages_detail)); unreadAccount.setEmail(getString(R.string.search_all_messages_detail));
flaggedAccount = new SearchAccount(this, false, new Flag[] { Flag.FLAGGED }, null); integratedInboxAccount = new SearchAccount(this, true, null, null);
flaggedAccount.setDescription(getString(R.string.search_starred_messages_title));
flaggedAccount.setEmail(getString(R.string.search_starred_messages_detail));
integratedInboxAccount = new SearchAccount(this, true, null, new Flag[] { Flag.SEEN });
integratedInboxAccount.setDescription(getString(R.string.integrated_inbox_title)); integratedInboxAccount.setDescription(getString(R.string.integrated_inbox_title));
integratedInboxAccount.setEmail(getString(R.string.integrated_inbox_detail)); integratedInboxAccount.setEmail(getString(R.string.integrated_inbox_detail));
integratedInboxStarredAccount = new SearchAccount(this, true, new Flag[] { Flag.FLAGGED }, null);
integratedInboxStarredAccount.setDescription(getString(R.string.integrated_inbox_starred_title));
integratedInboxStarredAccount.setEmail(getString(R.string.integrated_inbox_starred_detail));
super.onCreate(icicle); super.onCreate(icicle);
Account[] accounts = Preferences.getPreferences(this).getAccounts(); Account[] accounts = Preferences.getPreferences(this).getAccounts();
@ -397,15 +387,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
List<BaseAccount> newAccounts = new ArrayList<BaseAccount>(accounts.length + 4); List<BaseAccount> newAccounts = new ArrayList<BaseAccount>(accounts.length + 4);
newAccounts.add(integratedInboxAccount); newAccounts.add(integratedInboxAccount);
if (K9.messageListStars())
{
newAccounts.add(integratedInboxStarredAccount);
}
newAccounts.add(unreadAccount); newAccounts.add(unreadAccount);
if (K9.messageListStars())
{
newAccounts.add(flaggedAccount);
}
for (BaseAccount account : accounts) for (BaseAccount account : accounts)
{ {
newAccounts.add(account); newAccounts.add(account);
@ -431,9 +414,16 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
else if (K9.countSearchMessages() && account instanceof SearchAccount) else if (K9.countSearchMessages() && account instanceof SearchAccount)
{ {
pendingWork.put(account, "true"); pendingWork.put(account, "true");
SearchAccount searchAccount = (SearchAccount)account; final SearchAccount searchAccount = (SearchAccount)account;
MessagingController.getInstance(getApplication()).searchLocalMessages(searchAccount, null, mListener); MessagingController.getInstance(getApplication()).searchLocalMessages(searchAccount, null, new MessagingListener()
{
@Override
public void searchStats(AccountStats stats)
{
mListener.accountStatusChanged(searchAccount, stats);
}
});
} }
} }
@ -561,18 +551,23 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
public void onClick(DialogInterface dialog, int whichButton) public void onClick(DialogInterface dialog, int whichButton)
{ {
dismissDialog(DIALOG_REMOVE_ACCOUNT); dismissDialog(DIALOG_REMOVE_ACCOUNT);
try
if (mSelectedContextAccount instanceof Account)
{ {
mSelectedContextAccount.getLocalStore().delete(); Account realAccount = (Account)mSelectedContextAccount;
try
{
realAccount.getLocalStore().delete();
}
catch (Exception e)
{
// Ignore
}
MessagingController.getInstance(getApplication()).notifyAccountCancel(Accounts.this, realAccount);
Preferences.getPreferences(Accounts.this).deleteAccount(realAccount);
K9.setServicesEnabled(Accounts.this);
refresh();
} }
catch (Exception e)
{
// Ignore
}
MessagingController.getInstance(getApplication()).notifyAccountCancel(Accounts.this, mSelectedContextAccount);
Preferences.getPreferences(Accounts.this).deleteAccount(mSelectedContextAccount);
K9.setServicesEnabled(Accounts.this);
refresh();
} }
}) })
.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() .setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener()
@ -593,33 +588,38 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
// submenu wouldn't work. // submenu wouldn't work.
if (menuInfo != null) if (menuInfo != null)
{ {
mSelectedContextAccount = (Account)getListView().getItemAtPosition(menuInfo.position); mSelectedContextAccount = (BaseAccount)getListView().getItemAtPosition(menuInfo.position);
}
Account realAccount = null;
if (mSelectedContextAccount instanceof Account)
{
realAccount = (Account)mSelectedContextAccount;
} }
switch (item.getItemId()) switch (item.getItemId())
{ {
case R.id.delete_account: case R.id.delete_account:
onDeleteAccount(mSelectedContextAccount); onDeleteAccount(realAccount);
break; break;
case R.id.edit_account: case R.id.edit_account:
onEditAccount(mSelectedContextAccount); onEditAccount(realAccount);
break; break;
case R.id.open: case R.id.open:
onOpenAccount(mSelectedContextAccount); onOpenAccount(mSelectedContextAccount);
break; break;
case R.id.check_mail: case R.id.check_mail:
onCheckMail(mSelectedContextAccount); onCheckMail(realAccount);
break; break;
case R.id.clear_pending: case R.id.clear_pending:
onClearCommands(mSelectedContextAccount); onClearCommands(realAccount);
break; break;
case R.id.empty_trash: case R.id.empty_trash:
onEmptyTrash(mSelectedContextAccount); onEmptyTrash(realAccount);
break; break;
case R.id.compact: case R.id.compact:
onCompact(mSelectedContextAccount); onCompact(realAccount);
break; break;
case R.id.clear: case R.id.clear:
onClear(mSelectedContextAccount); onClear(realAccount);
break; break;
} }
return true; return true;
@ -769,7 +769,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) public View getView(int position, View convertView, ViewGroup parent)
{ {
BaseAccount account = getItem(position); final BaseAccount account = getItem(position);
View view; View view;
if (convertView != null) if (convertView != null)
{ {
@ -787,6 +787,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
holder.email = (TextView) view.findViewById(R.id.email); holder.email = (TextView) view.findViewById(R.id.email);
holder.newMessageCount = (TextView) view.findViewById(R.id.new_message_count); holder.newMessageCount = (TextView) view.findViewById(R.id.new_message_count);
holder.flaggedMessageCount = (TextView) view.findViewById(R.id.flagged_message_count); holder.flaggedMessageCount = (TextView) view.findViewById(R.id.flagged_message_count);
holder.activeIcons = (RelativeLayout) view.findViewById(R.id.active_icons);
holder.chip = view.findViewById(R.id.chip); holder.chip = view.findViewById(R.id.chip);
@ -825,6 +826,127 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
holder.flaggedMessageCount.setText(Integer.toString(stats.flaggedMessageCount)); holder.flaggedMessageCount.setText(Integer.toString(stats.flaggedMessageCount));
holder.flaggedMessageCount.setVisibility(K9.messageListStars() && stats.flaggedMessageCount > 0 ? View.VISIBLE : View.GONE); holder.flaggedMessageCount.setVisibility(K9.messageListStars() && stats.flaggedMessageCount > 0 ? View.VISIBLE : View.GONE);
holder.flaggedMessageCount.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Log.i(K9.LOG_TAG, "Star on " + account.getDescription());
// TODO: Better String formatting using resources
String description = account.getDescription() + " (Stars)";
if (account instanceof SearchAccount)
{
SearchAccount searchAccount = (SearchAccount)account;
MessageList.actionHandle(Accounts.this,
description, "", searchAccount.isIntegrate(), new Flag[] { Flag.FLAGGED }, null);
}
else
{
SearchSpecification searchSpec = new SearchSpecification()
{
@Override
public String[] getAccountUuids()
{
return new String[] { account.getUuid() };
}
@Override
public Flag[] getForbiddenFlags()
{
return null;
}
@Override
public String getQuery()
{
return null;
}
@Override
public Flag[] getRequiredFlags()
{
return new Flag[] { Flag.FLAGGED };
}
@Override
public boolean isIntegrate()
{
return false;
}
};
// TODO: Need a way to pass a SearchSpecification to the MessageList
// MessageList.actionHandle(Accounts.this,
// description, searchSpec);
}
}
});
holder.newMessageCount.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
// TODO: Better String formatting using resources
String description = account.getDescription() + " (Unread)";
Log.i(K9.LOG_TAG, "Envelope on " + account.getDescription());
if (account instanceof SearchAccount)
{
SearchAccount searchAccount = (SearchAccount)account;
MessageList.actionHandle(Accounts.this,
description, "", searchAccount.isIntegrate(), null, new Flag[] { Flag.SEEN });
}
else
{
SearchSpecification searchSpec = new SearchSpecification()
{
@Override
public String[] getAccountUuids()
{
return new String[] { account.getUuid() };
}
@Override
public Flag[] getForbiddenFlags()
{
return new Flag[] { Flag.SEEN };
}
@Override
public String getQuery()
{
return null;
}
@Override
public Flag[] getRequiredFlags()
{
return null;
}
@Override
public boolean isIntegrate()
{
return false;
}
};
// TODO: Need a way to pass a SearchSpecification to the MessageList
// MessageList.actionHandle(Accounts.this,
// description, searchSpec);
}
}
});
holder.activeIcons.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Toast toast = Toast.makeText(getApplication(), getString(R.string.tap_hint), Toast.LENGTH_SHORT);
toast.show();
}
}
);
} }
else else
{ {
@ -866,6 +988,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
public TextView email; public TextView email;
public TextView newMessageCount; public TextView newMessageCount;
public TextView flaggedMessageCount; public TextView flaggedMessageCount;
public RelativeLayout activeIcons;
public View chip; public View chip;
} }
} }

View File

@ -68,7 +68,7 @@ public class MessageList
private static final String EXTRA_FORBIDDEN_FLAGS = "forbiddenFlags"; private static final String EXTRA_FORBIDDEN_FLAGS = "forbiddenFlags";
private static final String EXTRA_INTEGRATE = "integrate"; private static final String EXTRA_INTEGRATE = "integrate";
private static final String EXTRA_TITLE = "title"; private static final String EXTRA_TITLE = "title";
private static final String EXTRA_SEARCH_SPECIFICATION = "searchSpecification";
private ListView mListView; private ListView mListView;
@ -264,7 +264,8 @@ public class MessageList
{ {
if (mTitle != null) if (mTitle != null)
{ {
setTitle(mTitle); String dispString = mAdapter.mListener.formatHeader(MessageList.this, mTitle, mUnreadMessageCount, getTimeFormat());
setTitle(dispString);
} }
else else
{ {
@ -1621,6 +1622,14 @@ public class MessageList
{ {
addOrUpdateMessage(account, folder, message); addOrUpdateMessage(account, folder, message);
} }
@Override
public void searchStats(AccountStats stats)
{
mUnreadMessageCount = stats.unreadMessageCount;
mHandler.refreshTitle();
}
@Override @Override
public void folderStatusChanged(Account account, String folder, int unreadMessageCount) public void folderStatusChanged(Account account, String folder, int unreadMessageCount)
{ {

View File

@ -10,6 +10,7 @@ import com.fsck.k9.mail.store.Pop3Store;
import com.fsck.k9.mail.store.WebDavStore; import com.fsck.k9.mail.store.WebDavStore;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** /**
* Store is the access point for an email message store. It's location can be * Store is the access point for an email message store. It's location can be
@ -115,7 +116,7 @@ public abstract class Store
public abstract Folder getFolder(String name) throws MessagingException; public abstract Folder getFolder(String name) throws MessagingException;
public abstract Folder[] getPersonalNamespaces() throws MessagingException; public abstract List<? extends Folder> getPersonalNamespaces() throws MessagingException;
public abstract void checkSettings() throws MessagingException; public abstract void checkSettings() throws MessagingException;

View File

@ -248,12 +248,12 @@ public class ImapStore extends Store
} }
@Override @Override
public Folder[] getPersonalNamespaces() throws MessagingException public List<? extends Folder> getPersonalNamespaces() throws MessagingException
{ {
ImapConnection connection = getConnection(); ImapConnection connection = getConnection();
try try
{ {
ArrayList<Folder> folders = new ArrayList<Folder>(); LinkedList<Folder> folders = new LinkedList<Folder>();
List<ImapResponse> responses = List<ImapResponse> responses =
connection.executeSimpleCommand(String.format("LIST \"\" \"%s*\"", connection.executeSimpleCommand(String.format("LIST \"\" \"%s*\"",
@ -308,7 +308,7 @@ public class ImapStore extends Store
} }
} }
folders.add(getFolder("INBOX")); folders.add(getFolder("INBOX"));
return folders.toArray(new Folder[] {}); return folders;
} }
catch (IOException ioe) catch (IOException ioe)
{ {

View File

@ -266,37 +266,46 @@ public class LocalStore extends Store implements Serializable
public void compact() throws MessagingException public void compact() throws MessagingException
{ {
Log.i(K9.LOG_TAG, "Before prune size = " + getSize()); if (K9.DEBUG)
Log.i(K9.LOG_TAG, "Before prune size = " + getSize());
pruneCachedAttachments(); pruneCachedAttachments();
Log.i(K9.LOG_TAG, "After prune / before compaction size = " + getSize()); if (K9.DEBUG)
Log.i(K9.LOG_TAG, "After prune / before compaction size = " + getSize());
mDb.execSQL("VACUUM"); mDb.execSQL("VACUUM");
Log.i(K9.LOG_TAG, "After compaction size = " + getSize()); if (K9.DEBUG)
Log.i(K9.LOG_TAG, "After compaction size = " + getSize());
} }
public void clear() throws MessagingException public void clear() throws MessagingException
{ {
Log.i(K9.LOG_TAG, "Before prune size = " + getSize()); if (K9.DEBUG)
Log.i(K9.LOG_TAG, "Before prune size = " + getSize());
pruneCachedAttachments(true); pruneCachedAttachments(true);
if (K9.DEBUG)
{
Log.i(K9.LOG_TAG, "After prune / before compaction size = " + getSize());
Log.i(K9.LOG_TAG, "After prune / before compaction size = " + getSize()); Log.i(K9.LOG_TAG, "Before clear folder count = " + getFolderCount());
Log.i(K9.LOG_TAG, "Before clear message count = " + getMessageCount());
Log.i(K9.LOG_TAG, "Before clear folder count = " + getFolderCount()); Log.i(K9.LOG_TAG, "After prune / before clear size = " + getSize());
Log.i(K9.LOG_TAG, "Before clear message count = " + getMessageCount()); }
Log.i(K9.LOG_TAG, "After prune / before clear size = " + getSize());
// don't delete messages that are Local, since there is no copy on the server. // don't delete messages that are Local, since there is no copy on the server.
// Don't delete deleted messages. They are essentially placeholders for UIDs of messages that have // Don't delete deleted messages. They are essentially placeholders for UIDs of messages that have
// been deleted locally. They take up insignificant space // been deleted locally. They take up insignificant space
mDb.execSQL("DELETE FROM messages WHERE deleted = 0 and uid not like 'Local%'"); mDb.execSQL("DELETE FROM messages WHERE deleted = 0 and uid not like 'Local%'");
compact(); compact();
Log.i(K9.LOG_TAG, "After clear message count = " + getMessageCount()); if (K9.DEBUG)
{
Log.i(K9.LOG_TAG, "After clear message count = " + getMessageCount());
Log.i(K9.LOG_TAG, "After clear size = " + getSize()); Log.i(K9.LOG_TAG, "After clear size = " + getSize());
}
} }
public int getMessageCount() throws MessagingException public int getMessageCount() throws MessagingException
@ -345,12 +354,11 @@ public class LocalStore extends Store implements Serializable
// TODO this takes about 260-300ms, seems slow. // TODO this takes about 260-300ms, seems slow.
@Override @Override
public LocalFolder[] getPersonalNamespaces() throws MessagingException public List<? extends Folder> getPersonalNamespaces() throws MessagingException
{ {
ArrayList<LocalFolder> folders = new ArrayList<LocalFolder>(); LinkedList<LocalFolder> folders = new LinkedList<LocalFolder>();
Cursor cursor = null; Cursor cursor = null;
try try
{ {
cursor = mDb.rawQuery("SELECT id, name, unread_count, visible_limit, last_updated, status, push_state, last_pushed, flagged_count FROM folders", null); cursor = mDb.rawQuery("SELECT id, name, unread_count, visible_limit, last_updated, status, push_state, last_pushed, flagged_count FROM folders", null);
@ -369,7 +377,7 @@ public class LocalStore extends Store implements Serializable
cursor.close(); cursor.close();
} }
} }
return folders.toArray(new LocalFolder[] {}); return folders;
} }
@Override @Override
@ -457,7 +465,8 @@ public class LocalStore extends Store implements Serializable
{ {
if (cursor.getString(0) == null) if (cursor.getString(0) == null)
{ {
Log.d(K9.LOG_TAG, "Attachment " + file.getAbsolutePath() + " has no store data, not deleting"); if (K9.DEBUG)
Log.d(K9.LOG_TAG, "Attachment " + file.getAbsolutePath() + " has no store data, not deleting");
/* /*
* If the attachment has no store data it is not recoverable, so * If the attachment has no store data it is not recoverable, so
* we won't delete it. * we won't delete it.
@ -692,8 +701,11 @@ public class LocalStore extends Store implements Serializable
whereClause.append(" )"); whereClause.append(" )");
} }
Log.i(K9.LOG_TAG, "whereClause = " + whereClause.toString()); if (K9.DEBUG)
Log.i(K9.LOG_TAG, "args = " + args); {
Log.v(K9.LOG_TAG, "whereClause = " + whereClause.toString());
Log.v(K9.LOG_TAG, "args = " + args);
}
return getMessages( return getMessages(
listener, listener,
null, null,
@ -1193,6 +1205,15 @@ public class LocalStore extends Store implements Serializable
editor.commit(); editor.commit();
} }
public FolderClass getDisplayClass(Preferences preferences) throws MessagingException
{
String id = getPrefId();
return FolderClass.valueOf(preferences.getPreferences().getString(id + ".displayMode",
FolderClass.NO_CLASS.name()));
}
@Override @Override
public void refresh(Preferences preferences) throws MessagingException public void refresh(Preferences preferences) throws MessagingException
{ {

View File

@ -19,8 +19,10 @@ import java.net.*;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
public class Pop3Store extends Store public class Pop3Store extends Store
{ {
@ -156,12 +158,11 @@ public class Pop3Store extends Store
} }
@Override @Override
public Folder[] getPersonalNamespaces() throws MessagingException public List<? extends Folder> getPersonalNamespaces() throws MessagingException
{ {
return new Folder[] List<Folder> folders = new LinkedList<Folder>();
{ folders.add(getFolder("INBOX"));
getFolder("INBOX"), return folders;
};
} }
@Override @Override

View File

@ -49,6 +49,8 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack; import java.util.Stack;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -260,9 +262,9 @@ public class WebDavStore extends Store
} }
@Override @Override
public Folder[] getPersonalNamespaces() throws MessagingException public List<? extends Folder> getPersonalNamespaces() throws MessagingException
{ {
ArrayList<Folder> folderList = new ArrayList<Folder>(); LinkedList<Folder> folderList = new LinkedList<Folder>();
HashMap<String, String> headers = new HashMap<String, String>(); HashMap<String, String> headers = new HashMap<String, String>();
DataSet dataset = new DataSet(); DataSet dataset = new DataSet();
String messageBody; String messageBody;
@ -323,7 +325,7 @@ public class WebDavStore extends Store
this.mFolderList.put(folderName, wdFolder); this.mFolderList.put(folderName, wdFolder);
} }
return folderList.toArray(new WebDavFolder[] {}); return folderList;
} }
@Override @Override