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:
parent
f184350aec
commit
3dfabbbd0c
BIN
res/drawable/ic_menu_thread.png
Normal file
BIN
res/drawable/ic_menu_thread.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
res/drawable/ic_menu_unthread.png
Normal file
BIN
res/drawable/ic_menu_unthread.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user