1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-10-31 15:45:08 -04:00

Provide folder threading support. When threading is on, messages in

folders are sorted first by subject, then by date.  Subject sorting is
case insensitive and disregards leading re:, fw: and fwd: prefixes.

Threading can be toggled via the T hotkey or the option menu.

The icons could use improvement.

Threading state is maintained during a run of K-9, among all
accounts.
This commit is contained in:
Daniel Applebaum 2009-02-01 00:08:14 +00:00
parent f184350aec
commit 3dfabbbd0c
6 changed files with 114 additions and 8 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -28,10 +28,10 @@
android:title="@string/account_settings_action"
android:icon="@android:drawable/ic_menu_preferences"
/>
<!--
<item android:id="@+id/search"
android:title="@string/search_action" />
<item android:id="@+id/preferences"
android:title="@string/preferences_action" />
-->
<item
android:id="@+id/thread"
android:title="@string/thread_action"
android:icon="@drawable/ic_menu_thread"
/>
</menu>

View File

@ -60,6 +60,8 @@
<string name="add_attachment_action">Add attachment</string>
<string name="dump_settings_action">Dump settings</string>
<string name="empty_trash_action">Empty Trash</string>
<string name="thread_action">Thread</string>
<string name="unthread_action">Unthread</string>
<string name="about_action">About</string>
<string name="accounts_context_menu_title">Account options</string>
@ -111,6 +113,8 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based
* Keyboard shortcuts
* Better IMAP support
* Saving attachments to SD
* Empty Trash
* Threading
* ...and more
\nPlease note that K-9 does not support most free hotmail accounts and, like many email clients, has some quirks when talking to Microsoft Exchange.
\nSubmit bug reports, contribute new features and ask questions at http://code.google.com/p/k9mail
@ -371,6 +375,6 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based
Message\u000AK, N - Next Message\u000AZ - Zoom Out\u000AShift-Z -
Zoom In\u000aG - Flag</string>
<string name="message_list_help_key">Del (or D) - Delete\u000AR -
Reply\u000AA - Reply All\u000AC - Compose\u000AF - Forward\u000aG - Flag\u000AQ
Reply\u000AA - Reply All\u000AC - Compose\u000AF - Forward\u000aG - Flag\u000AT - Thread\u000AQ
- Return to Accounts</string>
</resources>

View File

@ -108,6 +108,8 @@ public class MessagingController implements Runnable {
//private Set<MessagingListener> mListeners = Collections.synchronizedSet(new HashSet<MessagingListener>());
private Set<MessagingListener> mListeners = new CopyOnWriteArraySet<MessagingListener>();
private boolean threading = false;
private MessagingListener checkMailListener = null;
private boolean mBusy;
@ -2477,4 +2479,14 @@ s * critical data as fast as possible, and then we'll fill in the de
addListener(this.checkMailListener);
}
}
public boolean isThreading()
{
return threading;
}
public void setThreading(boolean threading)
{
this.threading = threading;
}
}

View File

@ -7,6 +7,8 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.ExpandableListActivity;
import android.app.NotificationManager;
@ -126,6 +128,9 @@ public class FolderMessageList extends ExpandableListActivity
private Account mAccount;
private Menu optionsMenu = null;
/**
* Stores the name of the folder that we want to open as soon as possible
* after load. It is set to null once the folder has been opened once.
@ -144,6 +149,8 @@ public class FolderMessageList extends ExpandableListActivity
private DateFormat timeFormat = null;
private boolean thread = false;
private DateFormat getDateFormat()
{
if (dateFormat == null)
@ -527,6 +534,7 @@ public class FolderMessageList extends ExpandableListActivity
{
final int expandedGroup = savedInstanceState.getInt(
STATE_KEY_EXPANDED_GROUP, -1);
if (expandedGroup >= 0 && mAdapter.getGroupCount() > expandedGroup)
{
mListView.expandGroup(expandedGroup);
@ -573,6 +581,8 @@ public class FolderMessageList extends ExpandableListActivity
NotificationManager notifMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notifMgr.cancel(mAccount.getAccountNumber());
thread = MessagingController.getInstance(getApplication()).isThreading();
}
@ -630,6 +640,7 @@ public class FolderMessageList extends ExpandableListActivity
case KeyEvent.KEYCODE_C: { onCompose(); return true;}
case KeyEvent.KEYCODE_Q: { onAccounts(); return true; }
case KeyEvent.KEYCODE_S: { onEditAccount(); return true; }
case KeyEvent.KEYCODE_T: { onToggleThread(); return true; }
case KeyEvent.KEYCODE_H: {
Toast toast = Toast.makeText(this, R.string.message_list_help_key, Toast.LENGTH_LONG);
toast.show();
@ -770,6 +781,20 @@ public class FolderMessageList extends ExpandableListActivity
MessageCompose.actionCompose(this, mAccount);
}
private void onToggleThread()
{
thread = !thread;
for (FolderInfoHolder folder : mAdapter.mFolders)
{
Collections.sort(folder.messages);
}
mAdapter.notifyDataSetChanged();
setMenuThread();
MessagingController.getInstance(getApplication()).setThreading(thread);
}
private void onDelete(MessageInfoHolder holder)
{
if (holder.read == false && holder.folder.unreadMessageCount > 0)
@ -878,6 +903,9 @@ public class FolderMessageList extends ExpandableListActivity
return true;
case R.id.account_settings:
onEditAccount();
return true;
case R.id.thread:
onToggleThread();
return true;
case R.id.empty_trash:
onEmptyTrash(mAccount);
@ -893,9 +921,25 @@ public class FolderMessageList extends ExpandableListActivity
{
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.folder_message_list_option, menu);
optionsMenu = menu;
setMenuThread();
return true;
}
private void setMenuThread()
{
Menu menu = optionsMenu;
if (menu != null)
{
MenuItem threadItem = menu.findItem(R.id.thread);
if (threadItem != null)
{
threadItem.setTitle(thread ? R.string.unthread_action : R.string.thread_action);
threadItem.setIcon(thread ? R.drawable.ic_menu_unthread : R.drawable.ic_menu_thread);
}
}
}
@Override
public boolean onContextItemSelected(MenuItem item)
{
@ -1865,6 +1909,8 @@ public class FolderMessageList extends ExpandableListActivity
public Date compareDate;
public String compareSubject;
public String sender;
public String[] recipients;
@ -1929,8 +1975,52 @@ public class FolderMessageList extends ExpandableListActivity
public int compareTo(MessageInfoHolder o)
{
if (thread)
{
if (compareSubject == null)
{
compareSubject = stripPrefixes(subject).toLowerCase();
}
if (o.compareSubject == null)
{
o.compareSubject = stripPrefixes(o.subject).toLowerCase();
}
int subjCompare = this.compareSubject.compareTo(o.compareSubject);
if (subjCompare != 0)
{
return subjCompare;
}
}
return this.compareDate.compareTo(o.compareDate) * -1;
}
Pattern pattern = null;
String patternString = "^ *(re|fw|fwd): *";
private String stripPrefixes(String in)
{
synchronized(patternString)
{
if (pattern == null)
{
pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE );
}
}
Matcher matcher = pattern.matcher(in);
int lastPrefix = -1;
while (matcher.find())
{
lastPrefix = matcher.end();
}
if (lastPrefix > -1 && lastPrefix < in.length() - 1)
{
return in.substring(lastPrefix);
}
else
{
return in;
}
}
}
class FolderViewHolder