1
0
mirror of https://github.com/moparisthebest/k-9 synced 2025-02-11 20:50:19 -05:00

For EAS accounts, display folder names in the list with parent folder information (i.e., parent/child). Also add support for updating folder names when refreshing the folder list.

This commit is contained in:
Kris Wong 2012-01-22 16:01:31 -05:00
parent 4964fe9e6d
commit 0d368c916a
5 changed files with 78 additions and 210 deletions

View File

@ -503,19 +503,22 @@ public class MessagingController implements Runnable {
private void syncLocalFoldersWithRemoteFolders(List<? extends Folder> localFolders,
List<? extends Folder> remoteFolders, final Account account) throws MessagingException {
HashSet<String> remoteFolderNames = new HashSet<String>();
HashSet<String> localFolderNames = new HashSet<String>();
HashMap<String, Folder> localFolderMap = new HashMap<String, Folder>();
List<LocalFolder> foldersToCreate = new LinkedList<LocalFolder>();
LocalStore localStore = account.getLocalStore();
for (Folder localFolder : localFolders) {
localFolderNames.add(localFolder.getRemoteName());
localFolderMap.put(localFolder.getRemoteName(), localFolder);
}
// Add any new folders in the remote store to the local store.
for (Folder remoteFolder : remoteFolders) {
if (!localFolderNames.contains(remoteFolder.getRemoteName())) {
Folder localFolder = localFolderMap.get(remoteFolder.getRemoteName());
if (localFolder == null) {
foldersToCreate.add(localStore.getFolder(remoteFolder.getRemoteName(), remoteFolder.getName()));
} else {
((LocalFolder)localFolder).setName(remoteFolder.getName());
}
remoteFolderNames.add(remoteFolder.getRemoteName());
}

View File

@ -218,10 +218,6 @@ public abstract class Folder {
public Account getAccount() {
return mAccount;
}
public boolean isSyncMode() {
return false;
}
public String getPushState() {
return null;

View File

@ -91,8 +91,9 @@ public class EasStore extends Store {
private static final Message[] EMPTY_MESSAGE_ARRAY = new Message[0];
// This key is sent the first time we sync the folder hierarchy, and also the first time
// we sync the items any "collection" (emails in a folder).
// we sync the items any "collection" (i.e., emails in a folder).
public static final String INITIAL_SYNC_KEY = "0";
private static final String NO_PARENT_ID = "0";
private static final String PING_COMMAND = "Ping";
private static final String PROVISION_COMMAND = "Provision";
@ -812,13 +813,12 @@ public class EasStore extends Store {
for (Folder folder : folderList) {
EasFolder easFolder = (EasFolder)folder;
// K-9 has its own special Outbox folder that works similar to the one on the
// Exchange server. Adding this one will cause 2 Outbox folders in our list.
if (easFolder.mType != FolderSyncParser.OUTBOX_TYPE) {
mFolderList.put(easFolder.getRemoteName(), easFolder);
easFolder.setSyncKey(syncKeys.get(easFolder.getRemoteName()));
}
mFolderList.put(easFolder.getRemoteName(), easFolder);
easFolder.setSyncKey(syncKeys.get(easFolder.getRemoteName()));
}
// We need to update all folder display names based on parenting.
resolveFolderDisplayNames(mFolderList);
}
for (Folder folder : folderList) {
@ -892,6 +892,32 @@ public class EasStore extends Store {
Log.e(K9.LOG_TAG, "Exception encountered while restoring folders from the local store", e);
}
}
private void resolveFolderDisplayNames(HashMap<String, EasFolder> folderMap) {
for (Entry<String, EasFolder> entry : folderMap.entrySet()) {
String parentId = entry.getValue().getParentId();
if (parentId != null && !parentId.equals(NO_PARENT_ID)) {
resolveOneFolderDisplayName(entry.getValue(), folderMap);
}
}
}
private void resolveOneFolderDisplayName(EasFolder folder, HashMap<String, EasFolder> folderMap) {
EasFolder parentFolder = folderMap.get(folder.getParentId());
if (parentFolder != null) {
String parentId = parentFolder.getParentId();
if (parentId != null && !parentId.equals(NO_PARENT_ID)) {
// Recurse to ensure the folder's name is complete before continuing.
resolveOneFolderDisplayName(parentFolder, folderMap);
}
String name = parentFolder.getName();
folder.mName = name + "/" + folder.mName;
// We only need to update the name once, reset the parent Id so we don't waste
// cycles doing it again.
folder.setParentId(null);
}
}
@Override
public Folder getFolder(String serverId) {
@ -1021,6 +1047,7 @@ public class EasStore extends Store {
private String mName;
private String mServerId;
private int mType;
private String mParentId = null;
private boolean mIsOpen = false;
private String mSyncKey = null;
@ -1034,6 +1061,14 @@ public class EasStore extends Store {
mServerId = serverId;
mType = type;
}
public String getParentId() {
return mParentId;
}
public void setParentId(String parentId) {
mParentId = parentId;
}
public String getSyncKey() throws MessagingException {
if (mSyncKey == null) {
@ -1047,11 +1082,6 @@ public class EasStore extends Store {
mSyncKey = key;
}
@Override
public boolean isSyncMode() {
return true;
}
@Override
public void open(OpenMode mode) throws MessagingException {
mIsOpen = true;

View File

@ -1240,6 +1240,11 @@ public class LocalStore extends Store implements Serializable {
public String getName() {
return mName;
}
public void setName(String name) throws MessagingException {
mName = name;
updateFolderColumn("name", mName);
}
@Override
public boolean exists() throws MessagingException {

View File

@ -19,11 +19,9 @@ package com.fsck.k9.mail.store.exchange.adapter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.content.ContentProviderOperation;
import android.util.Log;
import com.fsck.k9.K9;
@ -56,26 +54,10 @@ public class FolderSyncParser extends Parser {
public static final int USER_MAILBOX_TYPE = 12;
public static final List<Integer> mValidFolderTypes = Arrays.asList(INBOX_TYPE, DRAFTS_TYPE,
DELETED_TYPE, SENT_TYPE, OUTBOX_TYPE, USER_MAILBOX_TYPE);//, CALENDAR_TYPE, CONTACTS_TYPE);
// public static final String ALL_BUT_ACCOUNT_MAILBOX = MailboxColumns.ACCOUNT_KEY + "=? and " +
// MailboxColumns.TYPE + "!=" + Mailbox.TYPE_EAS_ACCOUNT_MAILBOX;
//
// private static final String WHERE_SERVER_ID_AND_ACCOUNT = MailboxColumns.SERVER_ID + "=? and " +
// MailboxColumns.ACCOUNT_KEY + "=?";
//
// private static final String WHERE_DISPLAY_NAME_AND_ACCOUNT = MailboxColumns.DISPLAY_NAME +
// "=? and " + MailboxColumns.ACCOUNT_KEY + "=?";
//
// private static final String WHERE_PARENT_SERVER_ID_AND_ACCOUNT =
// MailboxColumns.PARENT_SERVER_ID +"=? and " + MailboxColumns.ACCOUNT_KEY + "=?";
//
// private static final String[] MAILBOX_ID_COLUMNS_PROJECTION =
// new String[] {MailboxColumns.ID, MailboxColumns.SERVER_ID};
// private long mAccountId;
// private String mAccountIdAsString;
// private String[] mBindArguments = new String[2];
DELETED_TYPE, SENT_TYPE, USER_MAILBOX_TYPE);
// OUTBOX_TYPE is not included because K-9 uses its own special outbox. Adding the remote folder
// causes duplicate folder names.
private List<Folder> folderList;
private EasStore easStore;
@ -85,15 +67,12 @@ public class FolderSyncParser extends Parser {
this.easStore = easStore;
this.folderList = folderList;
// mAccountId = mAccount.mId;
// mAccountIdAsString = Long.toString(mAccountId);
}
@Override
public boolean parse() throws IOException {
int status;
boolean res = false;
boolean resetFolders = false;
if (nextTag(START_DOCUMENT) != Tags.FOLDER_FOLDER_SYNC)
throw new EasParserException();
while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
@ -104,12 +83,8 @@ public class FolderSyncParser extends Parser {
if (status == Eas.FOLDER_STATUS_INVALID_KEY) {
easStore.setStoreSyncKey("0");
Log.e(K9.LOG_TAG, "Bad sync key; RESET and delete all folders");
// mContentResolver.delete(Mailbox.CONTENT_URI, ALL_BUT_ACCOUNT_MAILBOX,
// new String[] {Long.toString(mAccountId)});
// // Stop existing syncs and reconstruct _main
// SyncManager.stopNonAccountMailboxSyncsForAccount(mAccountId);
// EASTODO
res = true;
resetFolders = true;
} else {
// Other errors are at the server, so let's throw an error that will
// cause this sync to be retried at a later time
@ -122,54 +97,27 @@ public class FolderSyncParser extends Parser {
userLog("New Account SyncKey: ", easStore.getStoreSyncKey());
} else if (tag == Tags.FOLDER_CHANGES) {
changesParser();
} else
} else {
skipTag();
}
}
// synchronized (mService.getSynchronizer()) {
// if (!mService.isStopped() || resetFolders) {
// ContentValues cv = new ContentValues();
// cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
// mAccount.update(mContext, cv);
// userLog("Leaving FolderSyncParser with Account syncKey=", mAccount.mSyncKey);
// }
// }
return res;
}
// private Cursor getServerIdCursor(String serverId) {
// mBindArguments[0] = serverId;
// mBindArguments[1] = mAccountIdAsString;
// return mContentResolver.query(Mailbox.CONTENT_URI, EmailContent.ID_PROJECTION,
// WHERE_SERVER_ID_AND_ACCOUNT, mBindArguments, null);
// }
//
public void deleteParser(ArrayList<ContentProviderOperation> ops) throws IOException {
public void deleteParser() throws IOException {
/* Right now we only do full refreshes on the folder list.
while (nextTag(Tags.FOLDER_DELETE) != END) {
switch (tag) {
case Tags.FOLDER_SERVER_ID:
String serverId = getValue();
// // Find the mailbox in this account with the given serverId
// Cursor c = getServerIdCursor(serverId);
// try {
// if (c.moveToFirst()) {
// userLog("Deleting ", serverId);
// ops.add(ContentProviderOperation.newDelete(
// ContentUris.withAppendedId(Mailbox.CONTENT_URI,
// c.getLong(0))).build());
// AttachmentProvider.deleteAllMailboxAttachmentFiles(mContext,
// mAccountId, mMailbox.mId);
// }
// } finally {
// c.close();
// }
break;
default:
skipTag();
}
}
}*/
}
public void addParser(ArrayList<ContentProviderOperation> ops) throws IOException {
public void addParser() throws IOException {
String name = null;
String serverId = null;
String parentId = null;
@ -198,61 +146,19 @@ public class FolderSyncParser extends Parser {
}
}
if (mValidFolderTypes.contains(type)) {
Folder folder = easStore.new EasFolder(name, serverId, type);
EasStore.EasFolder folder = easStore.new EasFolder(name, serverId, type);
folderList.add(folder);
// Mailbox m = new Mailbox();
// m.mDisplayName = name;
// m.mServerId = serverId;
// m.mAccountKey = mAccountId;
// m.mType = Mailbox.TYPE_MAIL;
// // Note that all mailboxes default to checking "never" (i.e. manual sync only)
// // We set specific intervals for inbox, contacts, and (eventually) calendar
// m.mSyncInterval = Mailbox.CHECK_INTERVAL_NEVER;
// switch (type) {
// case INBOX_TYPE:
// m.mType = Mailbox.TYPE_INBOX;
// m.mSyncInterval = mAccount.mSyncInterval;
// break;
// case CONTACTS_TYPE:
// m.mType = Mailbox.TYPE_CONTACTS;
// m.mSyncInterval = mAccount.mSyncInterval;
// break;
// case OUTBOX_TYPE:
// // TYPE_OUTBOX mailboxes are known by SyncManager to sync whenever they aren't
// // empty. The value of mSyncFrequency is ignored for this kind of mailbox.
// m.mType = Mailbox.TYPE_OUTBOX;
// break;
// case SENT_TYPE:
// m.mType = Mailbox.TYPE_SENT;
// break;
// case DRAFTS_TYPE:
// m.mType = Mailbox.TYPE_DRAFTS;
// break;
// case DELETED_TYPE:
// m.mType = Mailbox.TYPE_TRASH;
// break;
// case CALENDAR_TYPE:
// m.mType = Mailbox.TYPE_CALENDAR;
// m.mSyncInterval = mAccount.mSyncInterval;
// break;
// }
//
// // Make boxes like Contacts and Calendar invisible in the folder list
// m.mFlagVisible = (m.mType < Mailbox.TYPE_NOT_EMAIL);
//
// if (!parentId.equals("0")) {
// m.mParentServerId = parentId;
// }
//
// userLog("Adding mailbox: ", m.mDisplayName);
// ops.add(ContentProviderOperation
// .newInsert(Mailbox.CONTENT_URI).withValues(m.toContentValues()).build());
if (parentId != null) {
folder.setParentId(parentId);
}
}
return;
}
public void updateParser(ArrayList<ContentProviderOperation> ops) throws IOException {
public void updateParser() throws IOException {
/* Right now we only do full refreshes on the folder list.
String serverId = null;
String displayName = null;
String parentId = null;
@ -272,98 +178,27 @@ public class FolderSyncParser extends Parser {
break;
}
}
// We'll make a change if one of parentId or displayName are specified
// serverId is required, but let's be careful just the same
if (serverId != null && (displayName != null || parentId != null)) {
// Cursor c = getServerIdCursor(serverId);
// try {
// // If we find the mailbox (using serverId), make the change
// if (c.moveToFirst()) {
// userLog("Updating ", serverId);
// ContentValues cv = new ContentValues();
// if (displayName != null) {
// cv.put(Mailbox.DISPLAY_NAME, displayName);
// }
// if (parentId != null) {
// cv.put(Mailbox.PARENT_SERVER_ID, parentId);
// }
// ops.add(ContentProviderOperation.newUpdate(
// ContentUris.withAppendedId(Mailbox.CONTENT_URI,
// c.getLong(0))).withValues(cv).build());
// }
// } finally {
// c.close();
// }
}
}*/
}
public void changesParser() throws IOException {
// Keep track of new boxes, deleted boxes, updated boxes
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
while (nextTag(Tags.FOLDER_CHANGES) != END) {
if (tag == Tags.FOLDER_ADD) {
addParser(ops);
addParser();
} else if (tag == Tags.FOLDER_DELETE) {
deleteParser(ops);
deleteParser();
} else if (tag == Tags.FOLDER_UPDATE) {
updateParser(ops);
updateParser();
} else if (tag == Tags.FOLDER_COUNT) {
getValueInt();
} else
} else {
skipTag();
}
}
// // The mock stream is used for junit tests, so that the parsing code can be tested
// // separately from the provider code.
// // TODO Change tests to not require this; remove references to the mock stream
// if (mMock != null) {
// mMock.setResult(null);
// return;
// }
// Create the new mailboxes in a single batch operation
// Don't save any data if the service has been stopped
// synchronized (mService.getSynchronizer()) {
if (!ops.isEmpty()/* && !mService.isStopped()*/) {
userLog("Applying ", ops.size(), " mailbox operations.");
// Execute the batch
// try {
// mContentResolver.applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
userLog("New Account SyncKey: ", easStore.getStoreSyncKey());
// } catch (RemoteException e) {
// // There is nothing to be done here; fail by returning null
// } catch (OperationApplicationException e) {
// // There is nothing to be done here; fail by returning null
// }
// // Look for sync issues and its children and delete them
// // I'm not aware of any other way to deal with this properly
// mBindArguments[0] = "Sync Issues";
// mBindArguments[1] = mAccountIdAsString;
// Cursor c = mContentResolver.query(Mailbox.CONTENT_URI,
// MAILBOX_ID_COLUMNS_PROJECTION, WHERE_DISPLAY_NAME_AND_ACCOUNT,
// mBindArguments, null);
// String parentServerId = null;
// long id = 0;
// try {
// if (c.moveToFirst()) {
// id = c.getLong(0);
// parentServerId = c.getString(1);
// }
// } finally {
// c.close();
// }
// if (parentServerId != null) {
// mContentResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id),
// null, null);
// mBindArguments[0] = parentServerId;
// mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
// mBindArguments);
// }
}
// }
}
void userLog(String ...strings) {
@ -373,5 +208,4 @@ public class FolderSyncParser extends Parser {
void userLog(String string, int num, String string2) {
Log.i(K9.LOG_TAG, string + num + string2);
}
}