RecentFolderList.java revision e173d396447016a18c5b59c92422c3e85630ee91
1/** 2 * Copyright (c) 2011, Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mail.ui; 18 19import android.content.ContentValues; 20import android.content.Context; 21import android.database.Cursor; 22import android.net.Uri; 23import android.os.AsyncTask; 24 25import com.android.mail.providers.Account; 26import com.android.mail.providers.Folder; 27import com.android.mail.providers.Settings; 28import com.android.mail.utils.LogUtils; 29import com.android.mail.utils.LruCache; 30 31import java.util.ArrayList; 32import java.util.Collections; 33import java.util.Comparator; 34import java.util.List; 35 36/** 37 * A self-updating list of folder canonical names for the N most recently touched folders, ordered 38 * from least-recently-touched to most-recently-touched. N is a fixed size determined upon 39 * creation. 40 * 41 * RecentFoldersCache returns lists of this type, and will keep them updated when observers are 42 * registered on them. 43 * 44 */ 45public final class RecentFolderList { 46 private static final String TAG = "RecentFolderList"; 47 /** The application context */ 48 private final Context mContext; 49 /** The AbstractActivityController that created us*/ 50 private final AbstractActivityController mController; 51 /** The current account */ 52 private Account mAccount = null; 53 54 private final LruCache<String, Folder> mFolderCache; 55 /** 56 * We want to show at most five recent folders 57 */ 58 private final static int MAX_RECENT_FOLDERS = 5; 59 /** 60 * We exclude the default inbox for the account and the current folder; these might be the 61 * same, but we'll allow for both 62 */ 63 private final static int MAX_EXCLUDED_FOLDERS = 2; 64 65 /** 66 * Compare based on alphanumeric name of the folder, ignoring case. 67 */ 68 private static final Comparator<Folder> ALPHABET_IGNORECASE = new Comparator<Folder>() { 69 @Override 70 public int compare(Folder lhs, Folder rhs) { 71 return lhs.name.compareToIgnoreCase(rhs.name); 72 } 73 }; 74 /** 75 * Class to store the recent folder list asynchronously. 76 */ 77 private class StoreRecent extends AsyncTask<Void, Void, Void> { 78 final Account mAccount; 79 final Folder mFolder; 80 81 public StoreRecent(Account account, Folder folder) { 82 mAccount = account; 83 mFolder = folder; 84 } 85 86 @Override 87 protected Void doInBackground(Void... v) { 88 if (mAccount == null) { 89 LogUtils.w(TAG, "No account set for setting recent folders?"); 90 return null; 91 } 92 Uri uri = mAccount.recentFolderListUri; 93 if (uri != null) { 94 ContentValues values = new ContentValues(); 95 values.put(mFolder.uri.toString(), System.currentTimeMillis()); 96 // TODO: Remove when well tested 97 LogUtils.i(TAG, "Save: " + mFolder.name); 98 mContext.getContentResolver().update(uri, values, null, null); 99 } 100 return null; 101 } 102 } 103 104 /** 105 * Create a Recent Folder List from the given account. This will query the UIProvider to 106 * retrieve the RecentFolderList from persistent storage (if any). 107 * @param account 108 */ 109 public RecentFolderList(Context context, AbstractActivityController controller) { 110 mFolderCache = new LruCache<String, Folder>(MAX_RECENT_FOLDERS); 111 mContext = context; 112 mController = controller; 113 } 114 115 /** 116 * Change the current account. When a cursor over the recent folders for this account is 117 * available, the client <b>must</b> call {@link #loadFromUiProvider(Cursor)} with the updated 118 * cursor. Till then, the recent account list will be empty. 119 * @param account the new current account 120 */ 121 public void setCurrentAccount(Account account) { 122 mAccount = account; 123 mFolderCache.clear(); 124 } 125 126 /** 127 * Load the account information from the UI provider given the cursor over the recent folders. 128 * @param c a cursor over the recent folders. 129 */ 130 public void loadFromUiProvider(Cursor c) { 131 if (mAccount == null || c == null) { 132 return; 133 } 134 int i = 0; 135 while (c.moveToNext()) { 136 Folder folder = new Folder(c); 137 mFolderCache.putElement(folder.uri.toString(), folder); 138 // TODO: Remove when well tested 139 LogUtils.i(TAG, "Account " + mAccount.name + ", Recent: " + folder.name); 140 if (++i == (MAX_RECENT_FOLDERS + MAX_EXCLUDED_FOLDERS)) 141 break; 142 } 143 } 144 145 /** 146 * Marks the given folder as 'accessed' by the user interface, its entry is updated in the 147 * recent folder list, and the current time is written to the provider 148 * @param folder the folder we touched 149 */ 150 public void touchFolder(Folder folder) { 151 mFolderCache.putElement(folder.uri.toString(), folder); 152 new StoreRecent(mAccount, folder).execute(); 153 } 154 155 /** 156 * Generate a sorted list of recent folders, excluding the passed in folder (if any) and 157 * the current account's default inbox 158 * @param excludedFolder the folder to be excluded (typically the current folder) 159 */ 160 public ArrayList<Folder> getRecentFolderList(Folder excludedFolder) { 161 ArrayList<Uri> excludedUris = new ArrayList<Uri>(); 162 if (excludedFolder != null) { 163 excludedUris.add(excludedFolder.uri); 164 } 165 Settings settings = mController.getSettings(); 166 if (settings != null) { 167 // This could already be in the list, but that's ok 168 excludedUris.add(settings.defaultInbox); 169 } 170 final List<Folder> recent = new ArrayList<Folder>(mFolderCache.values()); 171 Collections.sort(recent, ALPHABET_IGNORECASE); 172 ArrayList<Folder> recentFolders = new ArrayList<Folder>(); 173 for (Folder f : recent) { 174 if (!excludedUris.contains(f.uri)) { 175 recentFolders.add(f); 176 } 177 if (recentFolders.size() == MAX_RECENT_FOLDERS) break; 178 } 179 return recentFolders; 180 } 181} 182