mirror of
https://github.com/moparisthebest/k-9
synced 2025-01-31 07:10:14 -05:00
Merge branch 'threading_schema_change'
This commit is contained in:
commit
543fefebaa
@ -371,16 +371,7 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
|
|||||||
int itemId = item.getItemId();
|
int itemId = item.getItemId();
|
||||||
switch (itemId) {
|
switch (itemId) {
|
||||||
case android.R.id.home: {
|
case android.R.id.home: {
|
||||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
goBack();
|
||||||
if (fragmentManager.getBackStackEntryCount() > 0) {
|
|
||||||
fragmentManager.popBackStack();
|
|
||||||
} else if (mMessageListFragment.isManualSearch()) {
|
|
||||||
onBackPressed();
|
|
||||||
} else if (!mSingleFolderMode) {
|
|
||||||
onAccounts();
|
|
||||||
} else {
|
|
||||||
onShowFolderList();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.compose: {
|
case R.id.compose: {
|
||||||
@ -719,8 +710,7 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
|
|||||||
public void showThread(Account account, String folderName, long threadRootId) {
|
public void showThread(Account account, String folderName, long threadRootId) {
|
||||||
LocalSearch tmpSearch = new LocalSearch();
|
LocalSearch tmpSearch = new LocalSearch();
|
||||||
tmpSearch.addAccountUuid(account.getUuid());
|
tmpSearch.addAccountUuid(account.getUuid());
|
||||||
tmpSearch.and(Searchfield.THREAD_ROOT, String.valueOf(threadRootId), Attribute.EQUALS);
|
tmpSearch.and(Searchfield.THREAD_ID, String.valueOf(threadRootId), Attribute.EQUALS);
|
||||||
tmpSearch.or(new SearchCondition(Searchfield.ID, Attribute.EQUALS, String.valueOf(threadRootId)));
|
|
||||||
|
|
||||||
MessageListFragment fragment = MessageListFragment.newInstance(tmpSearch, true, false);
|
MessageListFragment fragment = MessageListFragment.newInstance(tmpSearch, true, false);
|
||||||
addMessageListFragment(fragment, true);
|
addMessageListFragment(fragment, true);
|
||||||
@ -731,4 +721,18 @@ public class MessageList extends K9FragmentActivity implements MessageListFragme
|
|||||||
// Remove action button for remote search
|
// Remove action button for remote search
|
||||||
configureMenu(mMenu);
|
configureMenu(mMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void goBack() {
|
||||||
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
|
if (fragmentManager.getBackStackEntryCount() > 0) {
|
||||||
|
fragmentManager.popBackStack();
|
||||||
|
} else if (mMessageListFragment.isManualSearch()) {
|
||||||
|
onBackPressed();
|
||||||
|
} else if (!mSingleFolderMode) {
|
||||||
|
onAccounts();
|
||||||
|
} else {
|
||||||
|
onShowFolderList();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2680,17 +2680,28 @@ public class MessagingController implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setFlag(final Account account, final List<Long> messageIds, final Flag flag,
|
public void setFlag(final Account account, final List<Long> messageIds, final Flag flag,
|
||||||
final boolean newState, final boolean threadedList) {
|
final boolean newState) {
|
||||||
|
|
||||||
threadPool.execute(new Runnable() {
|
threadPool.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
setFlagSynchronous(account, messageIds, flag, newState, threadedList);
|
setFlagSynchronous(account, messageIds, flag, newState, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFlagSynchronous(final Account account, final List<Long> messageIds,
|
public void setFlagForThreads(final Account account, final List<Long> threadRootIds,
|
||||||
|
final Flag flag, final boolean newState) {
|
||||||
|
|
||||||
|
threadPool.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setFlagSynchronous(account, threadRootIds, flag, newState, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFlagSynchronous(final Account account, final List<Long> ids,
|
||||||
final Flag flag, final boolean newState, final boolean threadedList) {
|
final Flag flag, final boolean newState, final boolean threadedList) {
|
||||||
|
|
||||||
LocalStore localStore;
|
LocalStore localStore;
|
||||||
@ -2704,7 +2715,11 @@ public class MessagingController implements Runnable {
|
|||||||
// Update affected messages in the database. This should be as fast as possible so the UI
|
// Update affected messages in the database. This should be as fast as possible so the UI
|
||||||
// can be updated with the new state.
|
// can be updated with the new state.
|
||||||
try {
|
try {
|
||||||
localStore.setFlag(messageIds, flag, newState, threadedList);
|
if (threadedList) {
|
||||||
|
localStore.setFlagForThreads(ids, flag, newState);
|
||||||
|
} else {
|
||||||
|
localStore.setFlag(ids, flag, newState);
|
||||||
|
}
|
||||||
} catch (MessagingException e) {
|
} catch (MessagingException e) {
|
||||||
Log.e(K9.LOG_TAG, "Couldn't set flags in local database", e);
|
Log.e(K9.LOG_TAG, "Couldn't set flags in local database", e);
|
||||||
}
|
}
|
||||||
@ -2712,7 +2727,7 @@ public class MessagingController implements Runnable {
|
|||||||
// Read folder name and UID of messages from the database
|
// Read folder name and UID of messages from the database
|
||||||
Map<String, List<String>> folderMap;
|
Map<String, List<String>> folderMap;
|
||||||
try {
|
try {
|
||||||
folderMap = localStore.getFoldersAndUids(messageIds, threadedList);
|
folderMap = localStore.getFoldersAndUids(ids, threadedList);
|
||||||
} catch (MessagingException e) {
|
} catch (MessagingException e) {
|
||||||
Log.e(K9.LOG_TAG, "Couldn't get folder name and UID of messages", e);
|
Log.e(K9.LOG_TAG, "Couldn't get folder name and UID of messages", e);
|
||||||
return;
|
return;
|
||||||
@ -3905,8 +3920,9 @@ public class MessagingController implements Runnable {
|
|||||||
|
|
||||||
List<Message> messagesInThreads = new ArrayList<Message>();
|
List<Message> messagesInThreads = new ArrayList<Message>();
|
||||||
for (Message message : messages) {
|
for (Message message : messages) {
|
||||||
long rootId = ((LocalMessage) message).getRootId();
|
LocalMessage localMessage = (LocalMessage) message;
|
||||||
long threadId = (rootId == -1) ? message.getId() : rootId;
|
long rootId = localMessage.getRootId();
|
||||||
|
long threadId = (rootId == -1) ? localMessage.getThreadId() : rootId;
|
||||||
|
|
||||||
Message[] messagesInThread = localStore.getMessagesInThread(threadId);
|
Message[] messagesInThread = localStore.getMessagesInThread(threadId);
|
||||||
Collections.addAll(messagesInThreads, messagesInThread);
|
Collections.addAll(messagesInThreads, messagesInThread);
|
||||||
|
@ -91,8 +91,12 @@ import com.fsck.k9.mail.store.LocalStore.LocalFolder;
|
|||||||
import com.fsck.k9.provider.EmailProvider;
|
import com.fsck.k9.provider.EmailProvider;
|
||||||
import com.fsck.k9.provider.EmailProvider.MessageColumns;
|
import com.fsck.k9.provider.EmailProvider.MessageColumns;
|
||||||
import com.fsck.k9.provider.EmailProvider.SpecialColumns;
|
import com.fsck.k9.provider.EmailProvider.SpecialColumns;
|
||||||
|
import com.fsck.k9.provider.EmailProvider.ThreadColumns;
|
||||||
|
import com.fsck.k9.search.ConditionsTreeNode;
|
||||||
import com.fsck.k9.search.LocalSearch;
|
import com.fsck.k9.search.LocalSearch;
|
||||||
import com.fsck.k9.search.SearchSpecification;
|
import com.fsck.k9.search.SearchSpecification;
|
||||||
|
import com.fsck.k9.search.SearchSpecification.SearchCondition;
|
||||||
|
import com.fsck.k9.search.SearchSpecification.Searchfield;
|
||||||
import com.fsck.k9.search.SqlQueryBuilder;
|
import com.fsck.k9.search.SqlQueryBuilder;
|
||||||
import com.handmark.pulltorefresh.library.PullToRefreshBase;
|
import com.handmark.pulltorefresh.library.PullToRefreshBase;
|
||||||
import com.handmark.pulltorefresh.library.PullToRefreshListView;
|
import com.handmark.pulltorefresh.library.PullToRefreshListView;
|
||||||
@ -117,11 +121,11 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
MessageColumns.ATTACHMENT_COUNT,
|
MessageColumns.ATTACHMENT_COUNT,
|
||||||
MessageColumns.FOLDER_ID,
|
MessageColumns.FOLDER_ID,
|
||||||
MessageColumns.PREVIEW,
|
MessageColumns.PREVIEW,
|
||||||
MessageColumns.THREAD_ROOT,
|
ThreadColumns.ROOT,
|
||||||
SpecialColumns.ACCOUNT_UUID,
|
SpecialColumns.ACCOUNT_UUID,
|
||||||
SpecialColumns.FOLDER_NAME,
|
SpecialColumns.FOLDER_NAME,
|
||||||
|
|
||||||
MessageColumns.THREAD_COUNT,
|
SpecialColumns.THREAD_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int ID_COLUMN = 0;
|
private static final int ID_COLUMN = 0;
|
||||||
@ -425,6 +429,7 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
private static final int ACTION_REFRESH_TITLE = 2;
|
private static final int ACTION_REFRESH_TITLE = 2;
|
||||||
private static final int ACTION_PROGRESS = 3;
|
private static final int ACTION_PROGRESS = 3;
|
||||||
private static final int ACTION_REMOTE_SEARCH_FINISHED = 4;
|
private static final int ACTION_REMOTE_SEARCH_FINISHED = 4;
|
||||||
|
private static final int ACTION_GO_BACK = 5;
|
||||||
|
|
||||||
|
|
||||||
public void folderLoading(String folder, boolean loading) {
|
public void folderLoading(String folder, boolean loading) {
|
||||||
@ -458,6 +463,11 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void goBack() {
|
||||||
|
android.os.Message msg = android.os.Message.obtain(this, ACTION_GO_BACK);
|
||||||
|
sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(android.os.Message msg) {
|
public void handleMessage(android.os.Message msg) {
|
||||||
// The following messages don't need an attached activity.
|
// The following messages don't need an attached activity.
|
||||||
@ -490,6 +500,10 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
MessageListFragment.this.progress(progress);
|
MessageListFragment.this.progress(progress);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ACTION_GO_BACK: {
|
||||||
|
mFragmentListener.goBack();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1195,8 +1209,9 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
|
|
||||||
mActiveMessages = null; // don't need it any more
|
mActiveMessages = null; // don't need it any more
|
||||||
|
|
||||||
final Account account = messages.get(0).getFolder().getAccount();
|
// We currently only support copy/move in 'single account mode', so it's okay to
|
||||||
account.setLastSelectedFolderName(destFolderName);
|
// use mAccount.
|
||||||
|
mAccount.setLastSelectedFolderName(destFolderName);
|
||||||
|
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case ACTIVITY_CHOOSE_FOLDER_MOVE:
|
case ACTIVITY_CHOOSE_FOLDER_MOVE:
|
||||||
@ -2052,10 +2067,16 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
|
|
||||||
Cursor cursor = (Cursor) mAdapter.getItem(adapterPosition);
|
Cursor cursor = (Cursor) mAdapter.getItem(adapterPosition);
|
||||||
Account account = mPreferences.getAccount(cursor.getString(ACCOUNT_UUID_COLUMN));
|
Account account = mPreferences.getAccount(cursor.getString(ACCOUNT_UUID_COLUMN));
|
||||||
long id = cursor.getLong(ID_COLUMN);
|
|
||||||
|
|
||||||
mController.setFlag(account, Collections.singletonList(Long.valueOf(id)), flag, newState,
|
if (mThreadedList && cursor.getInt(THREAD_COUNT_COLUMN) > 1) {
|
||||||
mThreadedList);
|
long threadRootId = cursor.getLong(THREAD_ROOT_COLUMN);
|
||||||
|
mController.setFlagForThreads(account,
|
||||||
|
Collections.singletonList(Long.valueOf(threadRootId)), flag, newState);
|
||||||
|
} else {
|
||||||
|
long id = cursor.getLong(ID_COLUMN);
|
||||||
|
mController.setFlag(account, Collections.singletonList(Long.valueOf(id)), flag,
|
||||||
|
newState);
|
||||||
|
}
|
||||||
|
|
||||||
computeBatchDirection();
|
computeBatchDirection();
|
||||||
}
|
}
|
||||||
@ -2065,7 +2086,8 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Account, List<Long>> accountMapping = new HashMap<Account, List<Long>>();
|
Map<Account, List<Long>> messageMap = new HashMap<Account, List<Long>>();
|
||||||
|
Map<Account, List<Long>> threadMap = new HashMap<Account, List<Long>>();
|
||||||
Set<Account> accounts = new HashSet<Account>();
|
Set<Account> accounts = new HashSet<Account>();
|
||||||
|
|
||||||
for (int position = 0, end = mAdapter.getCount(); position < end; position++) {
|
for (int position = 0, end = mAdapter.getCount(); position < end; position++) {
|
||||||
@ -2075,29 +2097,39 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
if (mSelected.contains(uniqueId)) {
|
if (mSelected.contains(uniqueId)) {
|
||||||
String uuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
String uuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
||||||
Account account = mPreferences.getAccount(uuid);
|
Account account = mPreferences.getAccount(uuid);
|
||||||
|
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
List<Long> messageIdList = accountMapping.get(account);
|
|
||||||
|
if (mThreadedList && cursor.getInt(THREAD_COUNT_COLUMN) > 1) {
|
||||||
|
List<Long> threadRootIdList = threadMap.get(account);
|
||||||
|
if (threadRootIdList == null) {
|
||||||
|
threadRootIdList = new ArrayList<Long>();
|
||||||
|
threadMap.put(account, threadRootIdList);
|
||||||
|
}
|
||||||
|
|
||||||
|
threadRootIdList.add(cursor.getLong(THREAD_ROOT_COLUMN));
|
||||||
|
} else {
|
||||||
|
List<Long> messageIdList = messageMap.get(account);
|
||||||
if (messageIdList == null) {
|
if (messageIdList == null) {
|
||||||
messageIdList = new ArrayList<Long>();
|
messageIdList = new ArrayList<Long>();
|
||||||
accountMapping.put(account, messageIdList);
|
messageMap.put(account, messageIdList);
|
||||||
}
|
}
|
||||||
|
|
||||||
long selectionId;
|
messageIdList.add(cursor.getLong(ID_COLUMN));
|
||||||
if (mThreadedList) {
|
|
||||||
selectionId = (cursor.isNull(THREAD_ROOT_COLUMN)) ?
|
|
||||||
cursor.getLong(ID_COLUMN) : cursor.getLong(THREAD_ROOT_COLUMN);
|
|
||||||
} else {
|
|
||||||
selectionId = cursor.getLong(ID_COLUMN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messageIdList.add(selectionId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
List<Long> messageIds = accountMapping.get(account);
|
List<Long> messageIds = messageMap.get(account);
|
||||||
mController.setFlag(account, messageIds, flag, newState, mThreadedList);
|
List<Long> threadRootIds = threadMap.get(account);
|
||||||
|
|
||||||
|
if (messageIds != null) {
|
||||||
|
mController.setFlag(account, messageIds, flag, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threadRootIds != null) {
|
||||||
|
mController.setFlagForThreads(account, threadRootIds, flag, newState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
computeBatchDirection();
|
computeBatchDirection();
|
||||||
@ -2118,10 +2150,16 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Folder folder = (messages.size() == 1) ?
|
final Folder folder;
|
||||||
messages.get(0).getFolder() : mCurrentFolder.folder;
|
if (mIsThreadDisplay) {
|
||||||
|
folder = messages.get(0).getFolder();
|
||||||
|
} else if (mSingleFolderMode) {
|
||||||
|
folder = mCurrentFolder.folder;
|
||||||
|
} else {
|
||||||
|
folder = null;
|
||||||
|
}
|
||||||
|
|
||||||
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_MOVE, folder, messages);
|
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_MOVE, mAccount, folder, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onCopy(Message message) {
|
private void onCopy(Message message) {
|
||||||
@ -2139,10 +2177,16 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Folder folder = (messages.size() == 1) ?
|
final Folder folder;
|
||||||
messages.get(0).getFolder() : mCurrentFolder.folder;
|
if (mIsThreadDisplay) {
|
||||||
|
folder = messages.get(0).getFolder();
|
||||||
|
} else if (mSingleFolderMode) {
|
||||||
|
folder = mCurrentFolder.folder;
|
||||||
|
} else {
|
||||||
|
folder = null;
|
||||||
|
}
|
||||||
|
|
||||||
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_COPY, folder, messages);
|
displayFolderChoice(ACTIVITY_CHOOSE_FOLDER_COPY, mAccount, folder, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2159,11 +2203,19 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
*
|
*
|
||||||
* @see #startActivityForResult(Intent, int)
|
* @see #startActivityForResult(Intent, int)
|
||||||
*/
|
*/
|
||||||
private void displayFolderChoice(final int requestCode, final Folder folder, final List<Message> messages) {
|
private void displayFolderChoice(int requestCode, Account account, Folder folder,
|
||||||
final Intent intent = new Intent(getActivity(), ChooseFolder.class);
|
List<Message> messages) {
|
||||||
intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, folder.getAccount().getUuid());
|
|
||||||
|
Intent intent = new Intent(getActivity(), ChooseFolder.class);
|
||||||
|
intent.putExtra(ChooseFolder.EXTRA_ACCOUNT, account.getUuid());
|
||||||
|
intent.putExtra(ChooseFolder.EXTRA_SEL_FOLDER, account.getLastSelectedFolderName());
|
||||||
|
|
||||||
|
if (folder == null) {
|
||||||
|
intent.putExtra(ChooseFolder.EXTRA_SHOW_CURRENT, "yes");
|
||||||
|
} else {
|
||||||
intent.putExtra(ChooseFolder.EXTRA_CUR_FOLDER, folder.getName());
|
intent.putExtra(ChooseFolder.EXTRA_CUR_FOLDER, folder.getName());
|
||||||
intent.putExtra(ChooseFolder.EXTRA_SEL_FOLDER, folder.getAccount().getLastSelectedFolderName());
|
}
|
||||||
|
|
||||||
// remember the selected messages for #onActivityResult
|
// remember the selected messages for #onActivityResult
|
||||||
mActiveMessages = messages;
|
mActiveMessages = messages;
|
||||||
startActivityForResult(intent, requestCode);
|
startActivityForResult(intent, requestCode);
|
||||||
@ -2318,37 +2370,14 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
private void copyOrMove(List<Message> messages, final String destination,
|
private void copyOrMove(List<Message> messages, final String destination,
|
||||||
final FolderOperation operation) {
|
final FolderOperation operation) {
|
||||||
|
|
||||||
if (K9.FOLDER_NONE.equalsIgnoreCase(destination)) {
|
if (K9.FOLDER_NONE.equalsIgnoreCase(destination) || !mSingleAccountMode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean first = true;
|
Account account = mAccount;
|
||||||
Account account = null;
|
Map<String, List<Message>> folderMap = new HashMap<String, List<Message>>();
|
||||||
String folderName = null;
|
|
||||||
|
|
||||||
List<Message> outMessages = new ArrayList<Message>();
|
|
||||||
|
|
||||||
for (Message message : messages) {
|
for (Message message : messages) {
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
|
|
||||||
folderName = message.getFolder().getName();
|
|
||||||
account = message.getFolder().getAccount();
|
|
||||||
|
|
||||||
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(account)) ||
|
|
||||||
(operation == FolderOperation.COPY &&
|
|
||||||
!mController.isCopyCapable(account))) {
|
|
||||||
|
|
||||||
// Account is not copy/move capable
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (!message.getFolder().getAccount().equals(account) ||
|
|
||||||
!message.getFolder().getName().equals(folderName)) {
|
|
||||||
|
|
||||||
// Make sure all messages come from the same account/folder
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(message)) ||
|
if ((operation == FolderOperation.MOVE && !mController.isMoveCapable(message)) ||
|
||||||
(operation == FolderOperation.COPY && !mController.isCopyCapable(message))) {
|
(operation == FolderOperation.COPY && !mController.isCopyCapable(message))) {
|
||||||
|
|
||||||
@ -2361,9 +2390,24 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String folderName = message.getFolder().getName();
|
||||||
|
if (folderName.equals(destination)) {
|
||||||
|
// Skip messages already in the destination folder
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Message> outMessages = folderMap.get(folderName);
|
||||||
|
if (outMessages == null) {
|
||||||
|
outMessages = new ArrayList<Message>();
|
||||||
|
folderMap.put(folderName, outMessages);
|
||||||
|
}
|
||||||
|
|
||||||
outMessages.add(message);
|
outMessages.add(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String folderName : folderMap.keySet()) {
|
||||||
|
List<Message> outMessages = folderMap.get(folderName);
|
||||||
|
|
||||||
if (operation == FolderOperation.MOVE) {
|
if (operation == FolderOperation.MOVE) {
|
||||||
if (mThreadedList) {
|
if (mThreadedList) {
|
||||||
mController.moveMessagesInThread(account, folderName, outMessages, destination);
|
mController.moveMessagesInThread(account, folderName, outMessages, destination);
|
||||||
@ -2378,6 +2422,7 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ActionModeCallback implements ActionMode.Callback {
|
class ActionModeCallback implements ActionMode.Callback {
|
||||||
@ -2713,6 +2758,7 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
void onCompose(Account account);
|
void onCompose(Account account);
|
||||||
boolean startSearch(Account account, String folderName);
|
boolean startSearch(Account account, String folderName);
|
||||||
void remoteSearchStarted();
|
void remoteSearchStarted();
|
||||||
|
void goBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onReverseSort() {
|
public void onReverseSort() {
|
||||||
@ -2888,19 +2934,30 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
String accountUuid = mAccountUuids[id];
|
String accountUuid = mAccountUuids[id];
|
||||||
Account account = mPreferences.getAccount(accountUuid);
|
Account account = mPreferences.getAccount(accountUuid);
|
||||||
|
|
||||||
|
String threadId = getThreadId(mSearch);
|
||||||
|
|
||||||
Uri uri;
|
Uri uri;
|
||||||
String[] projection;
|
String[] projection;
|
||||||
if (mThreadedList) {
|
boolean needConditions;
|
||||||
|
if (threadId != null) {
|
||||||
|
uri = Uri.withAppendedPath(EmailProvider.CONTENT_URI, "account/" + accountUuid + "/thread/" + threadId);
|
||||||
|
projection = PROJECTION;
|
||||||
|
needConditions = false;
|
||||||
|
} else if (mThreadedList) {
|
||||||
uri = Uri.withAppendedPath(EmailProvider.CONTENT_URI, "account/" + accountUuid + "/messages/threaded");
|
uri = Uri.withAppendedPath(EmailProvider.CONTENT_URI, "account/" + accountUuid + "/messages/threaded");
|
||||||
projection = THREADED_PROJECTION;
|
projection = THREADED_PROJECTION;
|
||||||
|
needConditions = true;
|
||||||
} else {
|
} else {
|
||||||
uri = Uri.withAppendedPath(EmailProvider.CONTENT_URI, "account/" + accountUuid + "/messages");
|
uri = Uri.withAppendedPath(EmailProvider.CONTENT_URI, "account/" + accountUuid + "/messages");
|
||||||
projection = PROJECTION;
|
projection = PROJECTION;
|
||||||
|
needConditions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder query = new StringBuilder();
|
StringBuilder query = new StringBuilder();
|
||||||
List<String> queryArgs = new ArrayList<String>();
|
List<String> queryArgs = new ArrayList<String>();
|
||||||
|
if (needConditions) {
|
||||||
SqlQueryBuilder.buildWhereClause(account, mSearch.getConditions(), query, queryArgs);
|
SqlQueryBuilder.buildWhereClause(account, mSearch.getConditions(), query, queryArgs);
|
||||||
|
}
|
||||||
|
|
||||||
String selection = query.toString();
|
String selection = query.toString();
|
||||||
String[] selectionArgs = queryArgs.toArray(new String[0]);
|
String[] selectionArgs = queryArgs.toArray(new String[0]);
|
||||||
@ -2911,6 +2968,17 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
sortOrder);
|
sortOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getThreadId(LocalSearch search) {
|
||||||
|
for (ConditionsTreeNode node : search.getLeafSet()) {
|
||||||
|
SearchCondition condition = node.mCondition;
|
||||||
|
if (condition.field == Searchfield.THREAD_ID) {
|
||||||
|
return condition.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private String buildSortOrder() {
|
private String buildSortOrder() {
|
||||||
String sortColumn = MessageColumns.ID;
|
String sortColumn = MessageColumns.ID;
|
||||||
switch (mSortType) {
|
switch (mSortType) {
|
||||||
@ -2960,6 +3028,11 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
||||||
|
if (mIsThreadDisplay && data.getCount() == 0) {
|
||||||
|
mHandler.goBack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the "Loading..." view
|
// Remove the "Loading..." view
|
||||||
mPullToRefreshView.setEmptyView(null);
|
mPullToRefreshView.setEmptyView(null);
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -54,7 +54,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
private static final int MESSAGE_BASE = 0;
|
private static final int MESSAGE_BASE = 0;
|
||||||
private static final int MESSAGES = MESSAGE_BASE;
|
private static final int MESSAGES = MESSAGE_BASE;
|
||||||
private static final int MESSAGES_THREADED = MESSAGE_BASE + 1;
|
private static final int MESSAGES_THREADED = MESSAGE_BASE + 1;
|
||||||
//private static final int MESSAGES_THREAD = MESSAGE_BASE + 2;
|
private static final int MESSAGES_THREAD = MESSAGE_BASE + 2;
|
||||||
|
|
||||||
private static final int STATS_BASE = 100;
|
private static final int STATS_BASE = 100;
|
||||||
private static final int STATS = STATS_BASE;
|
private static final int STATS = STATS_BASE;
|
||||||
@ -78,8 +78,6 @@ public class EmailProvider extends ContentProvider {
|
|||||||
MessageColumns.ATTACHMENT_COUNT,
|
MessageColumns.ATTACHMENT_COUNT,
|
||||||
MessageColumns.FOLDER_ID,
|
MessageColumns.FOLDER_ID,
|
||||||
MessageColumns.PREVIEW,
|
MessageColumns.PREVIEW,
|
||||||
MessageColumns.THREAD_ROOT,
|
|
||||||
MessageColumns.THREAD_PARENT,
|
|
||||||
MessageColumns.READ,
|
MessageColumns.READ,
|
||||||
MessageColumns.FLAGGED,
|
MessageColumns.FLAGGED,
|
||||||
MessageColumns.ANSWERED,
|
MessageColumns.ANSWERED,
|
||||||
@ -95,6 +93,8 @@ public class EmailProvider extends ContentProvider {
|
|||||||
MessageColumns.ID
|
MessageColumns.ID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final String FOLDERS_TABLE = "folders";
|
||||||
|
|
||||||
private static final String[] FOLDERS_COLUMNS = {
|
private static final String[] FOLDERS_COLUMNS = {
|
||||||
FolderColumns.ID,
|
FolderColumns.ID,
|
||||||
FolderColumns.NAME,
|
FolderColumns.NAME,
|
||||||
@ -112,12 +112,21 @@ public class EmailProvider extends ContentProvider {
|
|||||||
FolderColumns.DISPLAY_CLASS
|
FolderColumns.DISPLAY_CLASS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final String THREADS_TABLE = "threads";
|
||||||
|
|
||||||
|
private static final String[] THREADS_COLUMNS = {
|
||||||
|
ThreadColumns.ID,
|
||||||
|
ThreadColumns.MESSAGE_ID,
|
||||||
|
ThreadColumns.ROOT,
|
||||||
|
ThreadColumns.PARENT
|
||||||
|
};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
UriMatcher matcher = sUriMatcher;
|
UriMatcher matcher = sUriMatcher;
|
||||||
|
|
||||||
matcher.addURI(AUTHORITY, "account/*/messages", MESSAGES);
|
matcher.addURI(AUTHORITY, "account/*/messages", MESSAGES);
|
||||||
matcher.addURI(AUTHORITY, "account/*/messages/threaded", MESSAGES_THREADED);
|
matcher.addURI(AUTHORITY, "account/*/messages/threaded", MESSAGES_THREADED);
|
||||||
//matcher.addURI(AUTHORITY, "account/*/thread/#", MESSAGES_THREAD);
|
matcher.addURI(AUTHORITY, "account/*/thread/#", MESSAGES_THREAD);
|
||||||
|
|
||||||
matcher.addURI(AUTHORITY, "account/*/stats", STATS);
|
matcher.addURI(AUTHORITY, "account/*/stats", STATS);
|
||||||
}
|
}
|
||||||
@ -125,6 +134,8 @@ public class EmailProvider extends ContentProvider {
|
|||||||
public interface SpecialColumns {
|
public interface SpecialColumns {
|
||||||
public static final String ACCOUNT_UUID = "account_uuid";
|
public static final String ACCOUNT_UUID = "account_uuid";
|
||||||
|
|
||||||
|
public static final String THREAD_COUNT = "thread_count";
|
||||||
|
|
||||||
public static final String FOLDER_NAME = "name";
|
public static final String FOLDER_NAME = "name";
|
||||||
public static final String INTEGRATE = "integrate";
|
public static final String INTEGRATE = "integrate";
|
||||||
}
|
}
|
||||||
@ -145,9 +156,6 @@ public class EmailProvider extends ContentProvider {
|
|||||||
public static final String ATTACHMENT_COUNT = "attachment_count";
|
public static final String ATTACHMENT_COUNT = "attachment_count";
|
||||||
public static final String FOLDER_ID = "folder_id";
|
public static final String FOLDER_ID = "folder_id";
|
||||||
public static final String PREVIEW = "preview";
|
public static final String PREVIEW = "preview";
|
||||||
public static final String THREAD_ROOT = "thread_root";
|
|
||||||
public static final String THREAD_PARENT = "thread_parent";
|
|
||||||
public static final String THREAD_COUNT = "thread_count";
|
|
||||||
public static final String READ = "read";
|
public static final String READ = "read";
|
||||||
public static final String FLAGGED = "flagged";
|
public static final String FLAGGED = "flagged";
|
||||||
public static final String ANSWERED = "answered";
|
public static final String ANSWERED = "answered";
|
||||||
@ -179,6 +187,13 @@ public class EmailProvider extends ContentProvider {
|
|||||||
public static final String DISPLAY_CLASS = "display_class";
|
public static final String DISPLAY_CLASS = "display_class";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ThreadColumns {
|
||||||
|
public static final String ID = "id";
|
||||||
|
public static final String MESSAGE_ID = "message_id";
|
||||||
|
public static final String ROOT = "root";
|
||||||
|
public static final String PARENT = "parent";
|
||||||
|
}
|
||||||
|
|
||||||
public interface StatsColumns {
|
public interface StatsColumns {
|
||||||
public static final String UNREAD_COUNT = "unread_count";
|
public static final String UNREAD_COUNT = "unread_count";
|
||||||
public static final String FLAGGED_COUNT = "flagged_count";
|
public static final String FLAGGED_COUNT = "flagged_count";
|
||||||
@ -216,7 +231,8 @@ public class EmailProvider extends ContentProvider {
|
|||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
switch (match) {
|
switch (match) {
|
||||||
case MESSAGES:
|
case MESSAGES:
|
||||||
case MESSAGES_THREADED: {
|
case MESSAGES_THREADED:
|
||||||
|
case MESSAGES_THREAD: {
|
||||||
List<String> segments = uri.getPathSegments();
|
List<String> segments = uri.getPathSegments();
|
||||||
String accountUuid = segments.get(1);
|
String accountUuid = segments.get(1);
|
||||||
|
|
||||||
@ -238,11 +254,16 @@ public class EmailProvider extends ContentProvider {
|
|||||||
} else if (match == MESSAGES_THREADED) {
|
} else if (match == MESSAGES_THREADED) {
|
||||||
cursor = getThreadedMessages(accountUuid, dbProjection, selection,
|
cursor = getThreadedMessages(accountUuid, dbProjection, selection,
|
||||||
selectionArgs, sortOrder);
|
selectionArgs, sortOrder);
|
||||||
|
} else if (match == MESSAGES_THREAD) {
|
||||||
|
String threadId = segments.get(3);
|
||||||
|
cursor = getThread(accountUuid, dbProjection, threadId, sortOrder);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Not implemented");
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.setNotificationUri(contentResolver, uri);
|
Uri notificationUri = Uri.withAppendedPath(CONTENT_URI, "account/" + accountUuid +
|
||||||
|
"/messages");
|
||||||
|
cursor.setNotificationUri(contentResolver, notificationUri);
|
||||||
|
|
||||||
cursor = new SpecialColumnsCursor(new IdTrickeryCursor(cursor), projection,
|
cursor = new SpecialColumnsCursor(new IdTrickeryCursor(cursor), projection,
|
||||||
specialColumns);
|
specialColumns);
|
||||||
@ -328,6 +349,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
query.append(" FROM messages m " +
|
query.append(" FROM messages m " +
|
||||||
|
"JOIN threads t ON (t.message_id = m.id) " +
|
||||||
"LEFT JOIN folders f ON (m.folder_id = f.id) " +
|
"LEFT JOIN folders f ON (m.folder_id = f.id) " +
|
||||||
"WHERE ");
|
"WHERE ");
|
||||||
query.append(SqlQueryBuilder.addPrefixToSelection(FIXUP_MESSAGES_COLUMNS,
|
query.append(SqlQueryBuilder.addPrefixToSelection(FIXUP_MESSAGES_COLUMNS,
|
||||||
@ -363,6 +385,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
UnavailableStorageException {
|
UnavailableStorageException {
|
||||||
|
|
||||||
StringBuilder query = new StringBuilder();
|
StringBuilder query = new StringBuilder();
|
||||||
|
|
||||||
query.append("SELECT ");
|
query.append("SELECT ");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (String columnName : projection) {
|
for (String columnName : projection) {
|
||||||
@ -372,18 +395,62 @@ public class EmailProvider extends ContentProvider {
|
|||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MessageColumns.DATE.equals(columnName)) {
|
if (MessageColumns.ID.equals(columnName)) {
|
||||||
query.append("MAX(m.date) AS " + MessageColumns.DATE);
|
query.append("u." + MessageColumns.ID + " AS " + MessageColumns.ID);
|
||||||
} else if (MessageColumns.THREAD_COUNT.equals(columnName)) {
|
} else if (MessageColumns.DATE.equals(columnName)) {
|
||||||
query.append("COUNT(h.id) AS " + MessageColumns.THREAD_COUNT);
|
query.append("MAX(date) AS " + MessageColumns.DATE);
|
||||||
} else if (SpecialColumns.FOLDER_NAME.equals(columnName)) {
|
} else if (SpecialColumns.THREAD_COUNT.equals(columnName)) {
|
||||||
query.append("f." + SpecialColumns.FOLDER_NAME + " AS " +
|
query.append("COUNT(g) AS " + SpecialColumns.THREAD_COUNT);
|
||||||
SpecialColumns.FOLDER_NAME);
|
|
||||||
} else if (SpecialColumns.INTEGRATE.equals(columnName)) {
|
|
||||||
query.append("f." + SpecialColumns.INTEGRATE + " AS " +
|
|
||||||
SpecialColumns.INTEGRATE);
|
|
||||||
} else {
|
} else {
|
||||||
query.append("m.");
|
query.append(columnName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query.append(" FROM (");
|
||||||
|
|
||||||
|
createThreadedSubQuery(projection, selection, selectionArgs, "t1.id = t2.id", query);
|
||||||
|
query.append(" UNION ALL ");
|
||||||
|
createThreadedSubQuery(projection, selection, selectionArgs, "t1.id = t2.root", query);
|
||||||
|
|
||||||
|
query.append(") u GROUP BY g");
|
||||||
|
|
||||||
|
if (!StringUtils.isNullOrEmpty(sortOrder)) {
|
||||||
|
query.append(" ORDER BY ");
|
||||||
|
query.append(SqlQueryBuilder.addPrefixToSelection(MESSAGES_COLUMNS,
|
||||||
|
"u.", sortOrder));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need the selection arguments twice. Once for each sub query.
|
||||||
|
String[] args = new String[selectionArgs.length * 2];
|
||||||
|
System.arraycopy(selectionArgs, 0, args, 0, selectionArgs.length);
|
||||||
|
System.arraycopy(selectionArgs, 0, args, selectionArgs.length, selectionArgs.length);
|
||||||
|
|
||||||
|
return db.rawQuery(query.toString(), args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (UnavailableStorageException e) {
|
||||||
|
throw new RuntimeException("Storage not available", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createThreadedSubQuery(String[] projection, String selection,
|
||||||
|
String[] selectionArgs, String join, StringBuilder query) {
|
||||||
|
|
||||||
|
query.append("SELECT h." + MessageColumns.ID + " AS g");
|
||||||
|
for (String columnName : projection) {
|
||||||
|
if (SpecialColumns.THREAD_COUNT.equals(columnName)) {
|
||||||
|
// Skip
|
||||||
|
} else if (SpecialColumns.FOLDER_NAME.equals(columnName) ||
|
||||||
|
SpecialColumns.INTEGRATE.equals(columnName)) {
|
||||||
|
query.append("," + columnName);
|
||||||
|
} else if (ThreadColumns.ROOT.equals(columnName)) {
|
||||||
|
// Always return the thread ID of the root message (even for the root
|
||||||
|
// message itself)
|
||||||
|
query.append(",CASE WHEN t2." + ThreadColumns.ROOT + " IS NULL THEN " +
|
||||||
|
"t2." + ThreadColumns.ID + " ELSE t2." + ThreadColumns.ROOT +
|
||||||
|
" END AS " + ThreadColumns.ROOT);
|
||||||
|
} else {
|
||||||
|
query.append(",m.");
|
||||||
query.append(columnName);
|
query.append(columnName);
|
||||||
query.append(" AS ");
|
query.append(" AS ");
|
||||||
query.append(columnName);
|
query.append(columnName);
|
||||||
@ -391,8 +458,12 @@ public class EmailProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
query.append(
|
query.append(
|
||||||
" FROM messages h JOIN messages m " +
|
" FROM messages h " +
|
||||||
"ON (h.id = m.thread_root OR h.id = m.id) ");
|
"LEFT JOIN threads t1 ON (t1.message_id = h.id) " +
|
||||||
|
"JOIN threads t2 ON (");
|
||||||
|
query.append(join);
|
||||||
|
query.append(") " +
|
||||||
|
"LEFT JOIN messages m ON (m.id = t2.message_id) ");
|
||||||
|
|
||||||
if (Utility.arrayContainsAny(projection, (Object[]) FOLDERS_COLUMNS)) {
|
if (Utility.arrayContainsAny(projection, (Object[]) FOLDERS_COLUMNS)) {
|
||||||
query.append("LEFT JOIN folders f ON (m.folder_id = f.id) ");
|
query.append("LEFT JOIN folders f ON (m.folder_id = f.id) ");
|
||||||
@ -400,9 +471,9 @@ public class EmailProvider extends ContentProvider {
|
|||||||
|
|
||||||
query.append(
|
query.append(
|
||||||
"WHERE " +
|
"WHERE " +
|
||||||
"(m.deleted = 0 AND " +
|
"(t1.root IS NULL AND " +
|
||||||
"(m.empty IS NULL OR m.empty != 1) AND " +
|
"m.deleted = 0 AND " +
|
||||||
"h.thread_root IS NULL) ");
|
"(m.empty IS NULL OR m.empty != 1))");
|
||||||
|
|
||||||
if (!StringUtils.isNullOrEmpty(selection)) {
|
if (!StringUtils.isNullOrEmpty(selection)) {
|
||||||
query.append(" AND (");
|
query.append(" AND (");
|
||||||
@ -410,16 +481,58 @@ public class EmailProvider extends ContentProvider {
|
|||||||
"h.", selection));
|
"h.", selection));
|
||||||
query.append(")");
|
query.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
query.append("GROUP BY h.id");
|
|
||||||
|
|
||||||
if (!StringUtils.isNullOrEmpty(sortOrder)) {
|
|
||||||
query.append(" ORDER BY ");
|
|
||||||
query.append(SqlQueryBuilder.addPrefixToSelection(MESSAGES_COLUMNS,
|
|
||||||
"m.", sortOrder));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.rawQuery(query.toString(), selectionArgs);
|
protected Cursor getThread(String accountUuid, final String[] projection, final String threadId,
|
||||||
|
final String sortOrder) {
|
||||||
|
|
||||||
|
Account account = getAccount(accountUuid);
|
||||||
|
LockableDatabase database = getDatabase(account);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return database.execute(false, new DbCallback<Cursor>() {
|
||||||
|
@Override
|
||||||
|
public Cursor doDbWork(SQLiteDatabase db) throws WrappedException,
|
||||||
|
UnavailableStorageException {
|
||||||
|
|
||||||
|
StringBuilder query = new StringBuilder();
|
||||||
|
query.append("SELECT ");
|
||||||
|
boolean first = true;
|
||||||
|
for (String columnName : projection) {
|
||||||
|
if (!first) {
|
||||||
|
query.append(",");
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MessageColumns.ID.equals(columnName)) {
|
||||||
|
query.append("m." + MessageColumns.ID + " AS " + MessageColumns.ID);
|
||||||
|
} else {
|
||||||
|
query.append(columnName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query.append(" FROM " + THREADS_TABLE + " t JOIN " + MESSAGES_TABLE + " m " +
|
||||||
|
"ON (m." + MessageColumns.ID + " = t." + ThreadColumns.MESSAGE_ID +
|
||||||
|
") ");
|
||||||
|
|
||||||
|
if (Utility.arrayContainsAny(projection, (Object[]) FOLDERS_COLUMNS)) {
|
||||||
|
query.append("LEFT JOIN " + FOLDERS_TABLE + " f " +
|
||||||
|
"ON (m." + MessageColumns.FOLDER_ID + " = f." + FolderColumns.ID +
|
||||||
|
") ");
|
||||||
|
}
|
||||||
|
|
||||||
|
query.append("WHERE (t." + ThreadColumns.ID + " = ? OR " +
|
||||||
|
ThreadColumns.ROOT + " = ?) AND " +
|
||||||
|
InternalMessageColumns.DELETED + " = 0 AND (" +
|
||||||
|
InternalMessageColumns.EMPTY + " IS NULL OR " +
|
||||||
|
InternalMessageColumns.EMPTY + " != 1)");
|
||||||
|
|
||||||
|
query.append(" ORDER BY ");
|
||||||
|
query.append(SqlQueryBuilder.addPrefixToSelection(FIXUP_MESSAGES_COLUMNS,
|
||||||
|
"m.", sortOrder));
|
||||||
|
|
||||||
|
return db.rawQuery(query.toString(), new String[] { threadId, threadId });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (UnavailableStorageException e) {
|
} catch (UnavailableStorageException e) {
|
||||||
|
@ -76,7 +76,7 @@ public interface SearchSpecification extends Parcelable {
|
|||||||
MESSAGE_CONTENTS,
|
MESSAGE_CONTENTS,
|
||||||
ATTACHMENT_COUNT,
|
ATTACHMENT_COUNT,
|
||||||
DELETED,
|
DELETED,
|
||||||
THREAD_ROOT,
|
THREAD_ID,
|
||||||
ID,
|
ID,
|
||||||
INTEGRATE,
|
INTEGRATE,
|
||||||
READ,
|
READ,
|
||||||
|
@ -66,6 +66,12 @@ public class SqlQueryBuilder {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case THREAD_ID: {
|
||||||
|
query.append("threads.id = ? OR threads.root = ?");
|
||||||
|
selectionArgs.add(condition.value);
|
||||||
|
selectionArgs.add(condition.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
appendCondition(condition, query, selectionArgs);
|
appendCondition(condition, query, selectionArgs);
|
||||||
}
|
}
|
||||||
@ -149,10 +155,6 @@ public class SqlQueryBuilder {
|
|||||||
columnName = "subject";
|
columnName = "subject";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case THREAD_ROOT: {
|
|
||||||
columnName = "thread_root";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TO: {
|
case TO: {
|
||||||
columnName = "to_list";
|
columnName = "to_list";
|
||||||
break;
|
break;
|
||||||
@ -177,6 +179,7 @@ public class SqlQueryBuilder {
|
|||||||
columnName = "display_class";
|
columnName = "display_class";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case THREAD_ID:
|
||||||
case FOLDER:
|
case FOLDER:
|
||||||
case SEARCHABLE: {
|
case SEARCHABLE: {
|
||||||
// Special cases handled in buildWhereClauseInternal()
|
// Special cases handled in buildWhereClauseInternal()
|
||||||
@ -258,7 +261,7 @@ public class SqlQueryBuilder {
|
|||||||
case FOLDER:
|
case FOLDER:
|
||||||
case ID:
|
case ID:
|
||||||
case INTEGRATE:
|
case INTEGRATE:
|
||||||
case THREAD_ROOT:
|
case THREAD_ID:
|
||||||
case READ:
|
case READ:
|
||||||
case FLAGGED: {
|
case FLAGGED: {
|
||||||
return true;
|
return true;
|
||||||
@ -272,7 +275,7 @@ public class SqlQueryBuilder {
|
|||||||
public static String addPrefixToSelection(String[] columnNames, String prefix, String selection) {
|
public static String addPrefixToSelection(String[] columnNames, String prefix, String selection) {
|
||||||
String result = selection;
|
String result = selection;
|
||||||
for (String columnName : columnNames) {
|
for (String columnName : columnNames) {
|
||||||
result = result.replaceAll("\\b" + columnName + "\\b", prefix + columnName);
|
result = result.replaceAll("(?<=^|[^\\.])\\b" + columnName + "\\b", prefix + columnName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
Loading…
Reference in New Issue
Block a user