Enable Empty Trash in Email

Add markContentsSeen() and emptyFolder() to EmailConversationCursor.
Add 'purge folder' URI for delete() call in EmailProvider.

Change-Id: I2f65f877f8f4e8376eb5c2149b5051931c2ac083
This commit is contained in:
Tony Mantler 2014-04-10 11:52:45 -07:00
parent cd940b68d3
commit e8c4c22268
2 changed files with 79 additions and 13 deletions

View File

@ -32,11 +32,13 @@ import com.android.emailcommon.Logging;
import com.android.emailcommon.mail.Address;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.Mailbox;
import com.android.mail.browse.ConversationCursorOperationListener;
import com.android.mail.providers.ConversationInfo;
import com.android.mail.providers.Folder;
import com.android.mail.providers.FolderList;
import com.android.mail.providers.ParticipantInfo;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.ConversationColumns;
import com.android.mail.utils.LogUtils;
import com.google.common.collect.Lists;
@ -45,7 +47,8 @@ import com.google.common.collect.Lists;
* any pending notifications for the corresponding mailbox should be canceled). We also handle
* getExtras() to provide a snapshot of the mailbox's status
*/
public class EmailConversationCursor extends CursorWrapper {
public class EmailConversationCursor extends CursorWrapper implements
ConversationCursorOperationListener {
private final long mMailboxId;
private final int mMailboxTypeId;
private final Context mContext;
@ -124,12 +127,7 @@ public class EmailConversationCursor extends CursorWrapper {
final boolean visible = params.getBoolean(setVisibilityKey);
if (visible) {
// Mark all messages as seen
final ContentResolver resolver = mContext.getContentResolver();
final ContentValues contentValues = new ContentValues(1);
contentValues.put(EmailContent.MessageColumns.FLAG_SEEN, true);
final Uri uri = EmailContent.Message.CONTENT_URI;
resolver.update(uri, contentValues, EmailContent.MessageColumns.MAILBOX_KEY +
" = ?", new String[] {String.valueOf(mMailboxId)});
markContentsSeen();
if (params.containsKey(
UIProvider.ConversationCursorCommand.COMMAND_KEY_ENTERED_FOLDER)) {
Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mMailboxId);
@ -142,6 +140,7 @@ public class EmailConversationCursor extends CursorWrapper {
final long timeSinceLastSync =
System.currentTimeMillis() - mailbox.mSyncTime;
if (timeSinceLastSync > AUTO_REFRESH_INTERVAL_MS) {
final ContentResolver resolver = mContext.getContentResolver();
final Uri refreshUri = Uri.parse(EmailContent.CONTENT_URI +
"/" + EmailProvider.QUERY_UIREFRESH + "/" + mailbox.mId);
resolver.query(refreshUri, null, null, null, null);
@ -173,12 +172,12 @@ public class EmailConversationCursor extends CursorWrapper {
}
private ConversationInfo generateConversationInfo() {
final int numMessages = getInt(getColumnIndex(UIProvider.ConversationColumns.NUM_MESSAGES));
final int numMessages = getInt(getColumnIndex(ConversationColumns.NUM_MESSAGES));
final ConversationInfo conversationInfo = new ConversationInfo(numMessages);
conversationInfo.firstSnippet = getString(getColumnIndex(UIProvider.ConversationColumns.SNIPPET));
conversationInfo.firstSnippet = getString(getColumnIndex(ConversationColumns.SNIPPET));
final boolean isRead = getInt(getColumnIndex(UIProvider.ConversationColumns.READ)) != 0;
final boolean isRead = getInt(getColumnIndex(ConversationColumns.READ)) != 0;
final String senderString = getString(getColumnIndex(EmailContent.MessageColumns.DISPLAY_NAME));
final String fromString = getString(getColumnIndex(EmailContent.MessageColumns.FROM_LIST));
@ -222,4 +221,21 @@ public class EmailConversationCursor extends CursorWrapper {
return conversationInfo;
}
@Override
public void markContentsSeen() {
final ContentResolver resolver = mContext.getContentResolver();
final ContentValues contentValues = new ContentValues(1);
contentValues.put(EmailContent.MessageColumns.FLAG_SEEN, true);
final Uri uri = EmailContent.Message.CONTENT_URI;
resolver.update(uri, contentValues, EmailContent.MessageColumns.MAILBOX_KEY + " = ?",
new String[] {String.valueOf(mMailboxId)});
}
@Override
public void emptyFolder() {
final ContentResolver resolver = mContext.getContentResolver();
final Uri purgeUri = EmailProvider.uiUri("uipurgefolder", mMailboxId);
resolver.delete(purgeUri, null, null);
}
}

View File

@ -259,6 +259,7 @@ public class EmailProvider extends ContentProvider {
private static final int UI_DEFAULT_RECENT_FOLDERS = UI_BASE + 16;
private static final int UI_FULL_FOLDERS = UI_BASE + 17;
private static final int UI_ALL_FOLDERS = UI_BASE + 18;
private static final int UI_PURGE_FOLDER = UI_BASE + 19;
private static final int BODY_BASE = 0xA000;
private static final int BODY = BODY_BASE;
@ -618,6 +619,8 @@ public class EmailProvider extends ContentProvider {
return uiDeleteAccountData(uri);
case UI_ACCOUNT:
return uiDeleteAccount(uri);
case UI_PURGE_FOLDER:
return uiPurgeFolder(uri);
case MESSAGE_SELECTION:
Cursor findCursor = db.query(tableName, Message.ID_COLUMN_PROJECTION, selection,
selectionArgs, null, null, null);
@ -1138,6 +1141,7 @@ public class EmailProvider extends ContentProvider {
ACCOUNT_PICK_TRASH_FOLDER);
sURIMatcher.addURI(EmailContent.AUTHORITY, "pickSentFolder/#",
ACCOUNT_PICK_SENT_FOLDER);
sURIMatcher.addURI(EmailContent.AUTHORITY, "uipurgefolder/#", UI_PURGE_FOLDER);
}
}
@ -3111,16 +3115,18 @@ public class EmailProvider extends ContentProvider {
// If the configuration states that feedback is supported, add that capability
final Resources res = context.getResources();
if (res.getBoolean(R.bool.feedback_supported)) {
capabilities |= UIProvider.AccountCapabilities.SEND_FEEDBACK;
capabilities |= AccountCapabilities.SEND_FEEDBACK;
}
// If we can find a help URL then add the Help capability
if (!TextUtils.isEmpty(context.getResources().getString(R.string.help_uri))) {
capabilities |= UIProvider.AccountCapabilities.HELP_CONTENT;
capabilities |= AccountCapabilities.HELP_CONTENT;
}
capabilities |= AccountCapabilities.EMPTY_TRASH;
// TODO: Should this be stored per-account, or some other mechanism?
capabilities |= UIProvider.AccountCapabilities.NESTED_FOLDERS;
capabilities |= AccountCapabilities.NESTED_FOLDERS;
return capabilities;
}
@ -4998,6 +5004,50 @@ public class EmailProvider extends ContentProvider {
return r;
}
/**
* Hard delete all synced messages in a particular mailbox
* @param uri Mailbox to empty (Trash, or maybe Spam/Junk later)
* @return number of rows affected
*/
private int uiPurgeFolder(Uri uri) {
final Context context = getContext();
final long mailboxId = Long.parseLong(uri.getLastPathSegment());
final SQLiteDatabase db = getDatabase(context);
// Find the account ID (needed in a few calls)
final Cursor mailboxCursor = db.query(
Mailbox.TABLE_NAME, new String[] { MailboxColumns.ACCOUNT_KEY },
Mailbox.ID + "=" + mailboxId, null, null, null, null);
if (mailboxCursor == null || !mailboxCursor.moveToFirst()) {
LogUtils.wtf(LogUtils.TAG, "Null or empty cursor when trying to purge mailbox %d",
mailboxId);
return 0;
}
final long accountId = mailboxCursor.getLong(mailboxCursor.getColumnIndex(
MailboxColumns.ACCOUNT_KEY));
// Find all the messages in the mailbox
final String[] messageProjection =
new String[] { MessageColumns.ID };
final String messageWhere = MessageColumns.MAILBOX_KEY + "=" + mailboxId;
final Cursor messageCursor = db.query(Message.TABLE_NAME, messageProjection, messageWhere,
null, null, null, null);
int deletedCount = 0;
// Kill them with fire
while (messageCursor != null && messageCursor.moveToNext()) {
final long messageId = messageCursor.getLong(messageCursor.getColumnIndex(
MessageColumns.ID));
AttachmentUtilities.deleteAllAttachmentFiles(context, accountId, messageId);
deletedCount += context.getContentResolver().delete(
ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, messageId), null, null);
notifyUIMessage(messageId);
}
notifyUIFolder(mailboxId, accountId);
return deletedCount;
}
public static final String PICKER_UI_ACCOUNT = "picker_ui_account";
public static final String PICKER_MAILBOX_TYPE = "picker_mailbox_type";
// Currently unused