Folder.java revision 2615aea2ce57f5fa3a9cd2e672282818aee6ce94
1/******************************************************************************* 2 * Copyright (C) 2012 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 *******************************************************************************/ 17 18package com.android.mail.providers; 19 20import android.content.Context; 21import android.content.CursorLoader; 22import android.database.Cursor; 23import android.graphics.drawable.PaintDrawable; 24import android.net.Uri; 25import android.net.Uri.Builder; 26import android.os.Parcel; 27import android.os.Parcelable; 28import android.text.TextUtils; 29import android.view.View; 30import android.widget.ImageView; 31 32import com.android.mail.utils.LogTag; 33import com.android.mail.utils.LogUtils; 34import com.android.mail.utils.Utils; 35 36import com.google.common.base.Objects; 37import com.google.common.collect.ImmutableList; 38import com.google.common.collect.Maps; 39 40import java.util.ArrayList; 41import java.util.Collection; 42import java.util.Collections; 43import java.util.HashMap; 44import java.util.Map; 45import java.util.regex.Pattern; 46 47/** 48 * A folder is a collection of conversations, and perhaps other folders. 49 */ 50public class Folder implements Parcelable, Comparable<Folder> { 51 /** 52 * 53 */ 54 private static final String FOLDER_UNINITIALIZED = "Uninitialized!"; 55 56 // TODO: remove this once we figure out which folder is returning a "null" string as the 57 // conversation list uri 58 private static final String NULL_STRING_URI = "null"; 59 private static final String LOG_TAG = LogTag.getLogTag(); 60 61 // Variables used to cache folders that are being processed. 62 private static HashMap<Integer, Folder> sCachedFolders = Maps.newHashMap(); 63 private static Account sFoldersCacheAccount; 64 65 // Try to match the order of members with the order of constants in UIProvider. 66 67 /** 68 * Unique id of this folder. 69 */ 70 public int id; 71 72 /** 73 * The content provider URI that returns this folder for this account. 74 */ 75 public Uri uri; 76 77 /** 78 * The human visible name for this folder. 79 */ 80 public String name; 81 82 /** 83 * The possible capabilities that this folder supports. 84 */ 85 public int capabilities; 86 87 /** 88 * Whether or not this folder has children folders. 89 */ 90 public boolean hasChildren; 91 92 /** 93 * How large the synchronization window is: how many days worth of data is retained on the 94 * device. 95 */ 96 public int syncWindow; 97 98 /** 99 * The content provider URI to return the list of conversations in this 100 * folder. 101 */ 102 public Uri conversationListUri; 103 104 /** 105 * The content provider URI to return the list of child folders of this folder. 106 */ 107 public Uri childFoldersListUri; 108 109 /** 110 * The number of messages that are unread in this folder. 111 */ 112 public int unreadCount; 113 114 /** 115 * The total number of messages in this folder. 116 */ 117 public int totalCount; 118 119 /** 120 * The content provider URI to force a refresh of this folder. 121 */ 122 public Uri refreshUri; 123 124 /** 125 * The current sync status of the folder 126 */ 127 public int syncStatus; 128 129 /** 130 * A packed integer containing the last synced result, and the request code. The 131 * value is (requestCode << 4) | syncResult 132 * syncResult is a value from {@link UIProvider.LastSyncResult} 133 * requestCode is a value from: {@link UIProvider.SyncStatus}, 134 */ 135 public int lastSyncResult; 136 137 /** 138 * Folder type. 0 is default. 139 */ 140 public int type; 141 142 /** 143 * Icon for this folder; 0 implies no icon. 144 */ 145 public long iconResId; 146 147 public String bgColor; 148 public String fgColor; 149 150 /** 151 * The content provider URI to request additional conversations 152 */ 153 public Uri loadMoreUri; 154 155 /** 156 * The possibly empty name of this folder with full hierarchy. 157 * The expected format is: parent/folder1/folder2/folder3/folder4 158 */ 159 public String hierarchicalDesc; 160 161 /** 162 * Parent folder of this folder, or null if there is none. This is set as 163 * part of the execution of the application and not obtained or stored via 164 * the provider. 165 */ 166 public Folder parent; 167 168 /** An immutable, empty conversation list */ 169 public static final Collection<Folder> EMPTY = Collections.emptyList(); 170 171 public static final String SPLITTER = "^*^"; 172 private static final Pattern SPLITTER_REGEX = Pattern.compile("\\^\\*\\^"); 173 public static final String FOLDERS_SPLIT = "^**^"; 174 private static final Pattern FOLDERS_SPLIT_REGEX = Pattern.compile("\\^\\*\\*\\^"); 175 176 public Folder(Parcel in) { 177 id = in.readInt(); 178 uri = in.readParcelable(null); 179 name = in.readString(); 180 capabilities = in.readInt(); 181 // 1 for true, 0 for false. 182 hasChildren = in.readInt() == 1; 183 syncWindow = in.readInt(); 184 conversationListUri = in.readParcelable(null); 185 childFoldersListUri = in.readParcelable(null); 186 unreadCount = in.readInt(); 187 totalCount = in.readInt(); 188 refreshUri = in.readParcelable(null); 189 syncStatus = in.readInt(); 190 lastSyncResult = in.readInt(); 191 type = in.readInt(); 192 iconResId = in.readLong(); 193 bgColor = in.readString(); 194 fgColor = in.readString(); 195 loadMoreUri = in.readParcelable(null); 196 hierarchicalDesc = in.readString(); 197 parent = in.readParcelable(null); 198 } 199 200 public Folder(Cursor cursor) { 201 id = cursor.getInt(UIProvider.FOLDER_ID_COLUMN); 202 uri = Uri.parse(cursor.getString(UIProvider.FOLDER_URI_COLUMN)); 203 name = cursor.getString(UIProvider.FOLDER_NAME_COLUMN); 204 capabilities = cursor.getInt(UIProvider.FOLDER_CAPABILITIES_COLUMN); 205 // 1 for true, 0 for false. 206 hasChildren = cursor.getInt(UIProvider.FOLDER_HAS_CHILDREN_COLUMN) == 1; 207 syncWindow = cursor.getInt(UIProvider.FOLDER_SYNC_WINDOW_COLUMN); 208 String convList = cursor.getString(UIProvider.FOLDER_CONVERSATION_LIST_URI_COLUMN); 209 conversationListUri = !TextUtils.isEmpty(convList) ? Uri.parse(convList) : null; 210 String childList = cursor.getString(UIProvider.FOLDER_CHILD_FOLDERS_LIST_COLUMN); 211 childFoldersListUri = (hasChildren && !TextUtils.isEmpty(childList)) ? Uri.parse(childList) 212 : null; 213 unreadCount = cursor.getInt(UIProvider.FOLDER_UNREAD_COUNT_COLUMN); 214 totalCount = cursor.getInt(UIProvider.FOLDER_TOTAL_COUNT_COLUMN); 215 String refresh = cursor.getString(UIProvider.FOLDER_REFRESH_URI_COLUMN); 216 refreshUri = !TextUtils.isEmpty(refresh) ? Uri.parse(refresh) : null; 217 syncStatus = cursor.getInt(UIProvider.FOLDER_SYNC_STATUS_COLUMN); 218 lastSyncResult = cursor.getInt(UIProvider.FOLDER_LAST_SYNC_RESULT_COLUMN); 219 type = cursor.getInt(UIProvider.FOLDER_TYPE_COLUMN); 220 iconResId = cursor.getLong(UIProvider.FOLDER_ICON_RES_ID_COLUMN); 221 bgColor = cursor.getString(UIProvider.FOLDER_BG_COLOR_COLUMN); 222 fgColor = cursor.getString(UIProvider.FOLDER_FG_COLOR_COLUMN); 223 String loadMore = cursor.getString(UIProvider.FOLDER_LOAD_MORE_URI_COLUMN); 224 loadMoreUri = !TextUtils.isEmpty(loadMore) ? Uri.parse(loadMore) : null; 225 hierarchicalDesc = cursor.getString(UIProvider.FOLDER_HIERARCHICAL_DESC_COLUMN); 226 parent = null; 227 } 228 229 @Override 230 public void writeToParcel(Parcel dest, int flags) { 231 dest.writeInt(id); 232 dest.writeParcelable(uri, 0); 233 dest.writeString(name); 234 dest.writeInt(capabilities); 235 // 1 for true, 0 for false. 236 dest.writeInt(hasChildren ? 1 : 0); 237 dest.writeInt(syncWindow); 238 dest.writeParcelable(conversationListUri, 0); 239 dest.writeParcelable(childFoldersListUri, 0); 240 dest.writeInt(unreadCount); 241 dest.writeInt(totalCount); 242 dest.writeParcelable(refreshUri, 0); 243 dest.writeInt(syncStatus); 244 dest.writeInt(lastSyncResult); 245 dest.writeInt(type); 246 dest.writeLong(iconResId); 247 dest.writeString(bgColor); 248 dest.writeString(fgColor); 249 dest.writeParcelable(loadMoreUri, 0); 250 dest.writeString(hierarchicalDesc); 251 dest.writeParcelable(parent, 0); 252 } 253 254 /** 255 * Construct a folder that queries for search results. Do not call on the UI 256 * thread. 257 */ 258 public static CursorLoader forSearchResults(Account account, String query, Context context) { 259 if (account.searchUri != null) { 260 Builder searchBuilder = account.searchUri.buildUpon(); 261 searchBuilder.appendQueryParameter(UIProvider.SearchQueryParameters.QUERY, query); 262 Uri searchUri = searchBuilder.build(); 263 return new CursorLoader(context, searchUri, UIProvider.FOLDERS_PROJECTION, null, null, 264 null); 265 } 266 return null; 267 } 268 269 public static HashMap<Uri, Folder> hashMapForFolders(ArrayList<Folder> rawFolders) { 270 final HashMap<Uri, Folder> folders = new HashMap<Uri, Folder>(); 271 for (Folder f : rawFolders) { 272 folders.put(f.uri, f); 273 } 274 return folders; 275 } 276 277 private static Uri getValidUri(String uri) { 278 if (TextUtils.isEmpty(uri)) { 279 return null; 280 } 281 return Uri.parse(uri); 282 } 283 284 /** 285 * Constructor that leaves everything uninitialized. 286 */ 287 private Folder() { 288 name = FOLDER_UNINITIALIZED; 289 } 290 291 /** 292 * Creates a new instance of a folder object that is <b>not</b> initialized. The caller is 293 * expected to fill in the details. This resulting instance is not guaranteed to work 294 * correctly, and might break functionality. Use at your own risk!! 295 * @return a new instance of an unsafe folder. 296 */ 297 public static Folder newUnsafeInstance() { 298 return new Folder(); 299 } 300 301 @SuppressWarnings("hiding") 302 public static final Creator<Folder> CREATOR = new Creator<Folder>() { 303 @Override 304 public Folder createFromParcel(Parcel source) { 305 return new Folder(source); 306 } 307 308 @Override 309 public Folder[] newArray(int size) { 310 return new Folder[size]; 311 } 312 }; 313 314 @Override 315 public int describeContents() { 316 // Return a sort of version number for this parcelable folder. Starting with zero. 317 return 0; 318 } 319 320 @Override 321 public boolean equals(Object o) { 322 if (o == null || !(o instanceof Folder)) { 323 return false; 324 } 325 return Objects.equal(uri, ((Folder) o).uri); 326 } 327 328 @Override 329 public int hashCode() { 330 return uri == null ? 0 : uri.hashCode(); 331 } 332 333 @Override 334 public int compareTo(Folder other) { 335 return name.compareToIgnoreCase(other.name); 336 } 337 338 /** 339 * Create a Folder map from a string of serialized folders. This can only be done on the output 340 * of {@link #serialize(Map)}. 341 * @param serializedFolder A string obtained from {@link #serialize(Map)} 342 * @return a Map of folder name to folder. 343 */ 344 public static Map<String, Folder> parseFoldersFromString(String serializedFoldersString) { 345 if (TextUtils.isEmpty(serializedFoldersString)) { 346 return null; 347 } 348 Map<String, Folder> folderMap = Maps.newHashMap(); 349 ArrayList<Folder> folders = Folder.getFoldersArray(serializedFoldersString); 350 for (Folder folder : folders) { 351 if (folder.name != FOLDER_UNINITIALIZED) { 352 folderMap.put(folder.name, folder); 353 } 354 } 355 return folderMap; 356 } 357 358 /** 359 * Returns a boolean indicating whether network activity (sync) is occuring for this folder. 360 */ 361 public boolean isSyncInProgress() { 362 return UIProvider.SyncStatus.isSyncInProgress(syncStatus); 363 } 364 365 /** 366 * Serialize the given list of folders 367 * @param folderMap A valid map of folder names to Folders 368 * @return a string containing a serialized output of folder maps. 369 */ 370 public static String serialize(Map<String, Folder> folderMap) { 371 return getSerializedFolderString(folderMap.values()); 372 } 373 374 public boolean supportsCapability(int capability) { 375 return (capabilities & capability) != 0; 376 } 377 378 // Show black text on a transparent swatch for system folders, effectively hiding the 379 // swatch (see bug 2431925). 380 public static void setFolderBlockColor(Folder folder, View colorBlock) { 381 if (colorBlock == null) { 382 return; 383 } 384 boolean showBg = !TextUtils.isEmpty(folder.bgColor); 385 final int backgroundColor = showBg ? Integer.parseInt(folder.bgColor) : 0; 386 if (backgroundColor == Utils.getDefaultFolderBackgroundColor(colorBlock.getContext())) { 387 showBg = false; 388 } 389 if (!showBg) { 390 colorBlock.setBackgroundDrawable(null); 391 colorBlock.setVisibility(View.GONE); 392 } else { 393 PaintDrawable paintDrawable = new PaintDrawable(); 394 paintDrawable.getPaint().setColor(backgroundColor); 395 colorBlock.setBackgroundDrawable(paintDrawable); 396 colorBlock.setVisibility(View.VISIBLE); 397 } 398 } 399 400 public static void setIcon(Folder folder, ImageView iconView) { 401 if (iconView == null) { 402 return; 403 } 404 final long icon = folder.iconResId; 405 if (icon > 0) { 406 iconView.setImageResource((int)icon); 407 iconView.setVisibility(View.VISIBLE); 408 } else { 409 iconView.setVisibility(View.INVISIBLE); 410 } 411 } 412 413 /** 414 * Return if the type of the folder matches a provider defined folder. 415 */ 416 public boolean isProviderFolder() { 417 return type != UIProvider.FolderType.DEFAULT; 418 } 419 420 public int getBackgroundColor(int defaultColor) { 421 return TextUtils.isEmpty(bgColor) ? defaultColor : Integer.parseInt(bgColor); 422 } 423 424 public int getForegroundColor(int defaultColor) { 425 return TextUtils.isEmpty(fgColor) ? defaultColor : Integer.parseInt(fgColor); 426 } 427 428 public static String getSerializedFolderString(Collection<Folder> folders) { 429 final StringBuilder folderList = new StringBuilder(); 430 int i = 0; 431 for (Folder folderEntry : folders) { 432 folderList.append(Folder.toString(folderEntry)); 433 if (i < folders.size()) { 434 folderList.append(FOLDERS_SPLIT); 435 } 436 i++; 437 } 438 return folderList.toString(); 439 } 440 441 public static void onAccountChanged(Account account) { 442 if (sFoldersCacheAccount == null 443 || !Objects.equal(account.uri, sFoldersCacheAccount.uri)) { 444 sFoldersCacheAccount = account; 445 sCachedFolders.clear(); 446 } 447 } 448 449 public static Folder fromString(String inString) { 450 if (TextUtils.isEmpty(inString)) { 451 return null; 452 } 453 final Folder f = new Folder(); 454 int indexOf = inString.indexOf(SPLITTER); 455 int id = -1; 456 if (indexOf != -1) { 457 id = Integer.valueOf(inString.substring(0, indexOf)); 458 if (sCachedFolders != null && sCachedFolders.containsKey(id)) { 459 return sCachedFolders.get(id); 460 } 461 } else { 462 // If no separator was found, we can't parse this folder and the 463 // TextUtils.split call would also fail. Return null. 464 LogUtils.w(LOG_TAG, "Problem parsing folderId: original string: %s", inString); 465 return null; 466 } 467 final String[] split = TextUtils.split(inString, SPLITTER_REGEX); 468 if (split.length < 20) { 469 return null; 470 } 471 f.id = id; 472 f.uri = Folder.getValidUri(split[1]); 473 f.name = split[2]; 474 f.hasChildren = Integer.parseInt(split[3]) != 0; 475 f.capabilities = Integer.parseInt(split[4]); 476 f.syncWindow = Integer.parseInt(split[5]); 477 f.conversationListUri = getValidUri(split[6]); 478 f.childFoldersListUri = getValidUri(split[7]); 479 f.unreadCount = Integer.parseInt(split[8]); 480 f.totalCount = Integer.parseInt(split[9]); 481 f.refreshUri = getValidUri(split[10]); 482 f.syncStatus = Integer.parseInt(split[11]); 483 f.lastSyncResult = Integer.parseInt(split[12]); 484 f.type = Integer.parseInt(split[13]); 485 f.iconResId = Integer.parseInt(split[14]); 486 f.bgColor = split[15]; 487 f.fgColor = split[16]; 488 f.loadMoreUri = getValidUri(split[17]); 489 f.hierarchicalDesc = split[18]; 490 f.parent = Folder.fromString(split[19]); 491 sCachedFolders.put(f.id, f); 492 return f; 493 } 494 495 /** 496 * Create a string representation of a folder. 497 */ 498 public static String createAsString(int id, Uri uri, String name, boolean hasChildren, 499 int capabilities, int syncWindow, Uri convListUri, Uri childFoldersListUri, 500 int unreadCount, int totalCount, Uri refreshUri, int syncStatus, int lastSyncResult, 501 int type, long iconResId, String bgColor, String fgColor, Uri loadMore, 502 String hierarchicalDesc, Folder parent) { 503 StringBuilder builder = new StringBuilder(); 504 builder.append(id); 505 builder.append(SPLITTER); 506 builder.append(uri); 507 builder.append(SPLITTER); 508 builder.append(name); 509 builder.append(SPLITTER); 510 builder.append(hasChildren ? 1 : 0); 511 builder.append(SPLITTER); 512 builder.append(capabilities); 513 builder.append(SPLITTER); 514 builder.append(syncWindow); 515 builder.append(SPLITTER); 516 builder.append(convListUri); 517 builder.append(SPLITTER); 518 builder.append(childFoldersListUri); 519 builder.append(SPLITTER); 520 builder.append(unreadCount); 521 builder.append(SPLITTER); 522 builder.append(totalCount); 523 builder.append(SPLITTER); 524 builder.append(refreshUri); 525 builder.append(SPLITTER); 526 builder.append(syncStatus); 527 builder.append(SPLITTER); 528 builder.append(lastSyncResult); 529 builder.append(SPLITTER); 530 builder.append(type); 531 builder.append(SPLITTER); 532 builder.append(iconResId); 533 builder.append(SPLITTER); 534 builder.append(bgColor != null ? bgColor : ""); 535 builder.append(SPLITTER); 536 builder.append(fgColor != null ? fgColor : ""); 537 builder.append(SPLITTER); 538 builder.append(loadMore); 539 builder.append(SPLITTER); 540 builder.append(hierarchicalDesc); 541 builder.append(SPLITTER); 542 if (parent != null) { 543 builder.append(Folder.toString(parent)); 544 } else { 545 builder.append(""); 546 } 547 return builder.toString(); 548 } 549 550 public static String toString(Folder folder) { 551 return createAsString(folder.id, folder.uri, folder.name, folder.hasChildren, 552 folder.capabilities, folder.syncWindow, folder.conversationListUri, 553 folder.childFoldersListUri, folder.unreadCount, folder.totalCount, 554 folder.refreshUri, folder.syncStatus, folder.lastSyncResult, folder.type, 555 folder.iconResId, folder.bgColor, folder.fgColor, folder.loadMoreUri, 556 folder.hierarchicalDesc, folder.parent); 557 } 558 559 /** 560 * Returns a comma separated list of folder URIs for all the folders in the collection. 561 * @param folders 562 * @return 563 */ 564 public final static String getUriString(Collection<Folder> folders) { 565 final StringBuilder uris = new StringBuilder(); 566 boolean first = true; 567 for (Folder f : folders) { 568 if (first) { 569 first = false; 570 } else { 571 uris.append(','); 572 } 573 uris.append(f.uri.toString()); 574 } 575 return uris.toString(); 576 } 577 578 579 /** 580 * Get an array of folders from a rawFolders string. 581 */ 582 public static ArrayList<Folder> getFoldersArray(String rawFolders) { 583 if (TextUtils.isEmpty(rawFolders)) { 584 return null; 585 } 586 ArrayList<Folder> folders = new ArrayList<Folder>(); 587 String[] split = TextUtils.split(rawFolders, FOLDERS_SPLIT_REGEX); 588 Folder f; 589 for (String folder : split) { 590 f = Folder.fromString(folder); 591 if (f != null) { 592 folders.add(f); 593 } 594 } 595 return folders; 596 } 597 598 /** 599 * Get just the uri's from an arraylist of folders. 600 */ 601 public final static String[] getUriArray(ArrayList<Folder> folders) { 602 if (folders == null || folders.size() == 0) { 603 return new String[0]; 604 } 605 String[] folderUris = new String[folders.size()]; 606 int i = 0; 607 for (Folder folder : folders) { 608 folderUris[i] = folder.uri.toString(); 609 i++; 610 } 611 return folderUris; 612 } 613 614 /** 615 * Returns true if a conversation assigned to the needle will be assigned to the collection of 616 * folders in the haystack. False otherwise. This method is safe to call with null 617 * arguments. 618 * This method returns true under two circumstances 619 * <ul><li> If the URI of the needle was found in the collection of URIs that comprise the 620 * haystack. 621 * </li><li> If the needle is of the type Inbox, and at least one of the folders in the haystack 622 * are of type Inbox. <em>Rationale</em>: there are special folders that are marked as inbox, 623 * and the user might not have the control to assign conversations to them. This happens for 624 * the Priority Inbox in Gmail. When you assign a conversation to an Inbox folder, it will 625 * continue to appear in the Priority Inbox. However, the URI of Priority Inbox and Inbox will 626 * be different. So a direct equality check is insufficient. 627 * </li></ul> 628 * @param haystack a collection of folders, possibly overlapping 629 * @param needle a folder 630 * @return true if a conversation inside the needle will be in the folders in the haystack. 631 */ 632 public final static boolean containerIncludes(Collection<Folder> haystack, Folder needle) { 633 // If the haystack is empty, it cannot contain anything. 634 if (haystack == null || haystack.size() <= 0) { 635 return false; 636 } 637 // The null folder exists everywhere. 638 if (needle == null) { 639 return true; 640 } 641 boolean hasInbox = false; 642 // Get currently active folder info and compare it to the list 643 // these conversations have been given; if they no longer contain 644 // the selected folder, delete them from the list. 645 final Uri toFind = needle.uri; 646 for (Folder f : haystack) { 647 if (toFind.equals(f.uri)) { 648 return true; 649 } 650 hasInbox |= (f.type == UIProvider.FolderType.INBOX); 651 } 652 // Did not find the URI of needle directly. If the needle is an Inbox and one of the folders 653 // was an inbox, then the needle is contained (check Javadoc for explanation). 654 final boolean needleIsInbox = (needle.type == UIProvider.FolderType.INBOX); 655 return needleIsInbox ? hasInbox : false; 656 } 657 658 /** 659 * Returns a boolean indicating whether this Folder object has been initialized 660 */ 661 public boolean isInitialized() { 662 return name != FOLDER_UNINITIALIZED && conversationListUri != null && 663 !NULL_STRING_URI.equals(conversationListUri.toString()); 664 } 665 666 /** 667 * Returns a collection of a single folder. This method always returns a valid collection 668 * even if the input folder is null. 669 * @param in a folder, possibly null. 670 * @return a collection of the folder. 671 */ 672 public static Collection<Folder> listOf(Folder in) { 673 final Collection<Folder> target = (in == null) ? EMPTY : ImmutableList.of(in); 674 return target; 675 } 676 677 /** 678 * Return if this is the trash folder. 679 */ 680 public boolean isTrash() { 681 return type == UIProvider.FolderType.TRASH; 682 } 683 684 /** 685 * Return if this is a draft folder. 686 */ 687 public boolean isDraft() { 688 return type == UIProvider.FolderType.DRAFT; 689 } 690 691 /** 692 * Whether this folder supports only showing important messages. 693 */ 694 public boolean isImportantOnly() { 695 return supportsCapability( 696 UIProvider.FolderCapabilities.ONLY_IMPORTANT); 697 } 698 699 /** 700 * Whether this is the special folder just used to display all mail for an account. 701 */ 702 public boolean isViewAll() { 703 return type == UIProvider.FolderType.ALL_MAIL; 704 } 705 706 /** 707 * True if the previous sync was successful, false otherwise. 708 * @return 709 */ 710 public final boolean wasSyncSuccessful() { 711 return ((lastSyncResult & 0x0f) == UIProvider.LastSyncResult.SUCCESS); 712 } 713 714 /** 715 * Don't use this for ANYTHING but the FolderListAdapter. It does not have 716 * all the fields. 717 */ 718 public static Folder getDeficientDisplayOnlyFolder(Cursor cursor) { 719 Folder f = Folder.newUnsafeInstance(); 720 f.id = cursor.getInt(UIProvider.FOLDER_ID_COLUMN); 721 f.uri = Utils.getValidUri(cursor.getString(UIProvider.FOLDER_URI_COLUMN)); 722 f.unreadCount = cursor.getInt(UIProvider.FOLDER_UNREAD_COUNT_COLUMN); 723 f.conversationListUri = Utils.getValidUri(cursor 724 .getString(UIProvider.FOLDER_CONVERSATION_LIST_URI_COLUMN)); 725 f.type = cursor.getInt(UIProvider.FOLDER_TYPE_COLUMN); 726 f.capabilities = cursor.getInt(UIProvider.FOLDER_CAPABILITIES_COLUMN); 727 f.bgColor = cursor.getString(UIProvider.FOLDER_BG_COLOR_COLUMN); 728 f.name = cursor.getString(UIProvider.FOLDER_NAME_COLUMN); 729 return f; 730 } 731} 732