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 18 package com.android.email.provider; 19 20 import android.app.Activity; 21 import android.app.ProgressDialog; 22 import android.content.ContentUris; 23 import android.content.ContentValues; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.database.ContentObserver; 27 import android.net.Uri; 28 import android.os.Bundle; 29 import android.os.Handler; 30 31 import com.android.email.R; 32 import com.android.emailcommon.provider.Account; 33 import com.android.emailcommon.provider.EmailContent; 34 import com.android.emailcommon.provider.Mailbox; 35 import com.android.emailcommon.provider.EmailContent.AccountColumns; 36 import com.android.emailcommon.provider.EmailContent.MailboxColumns; 37 import com.android.mail.providers.Folder; 38 import com.android.mail.utils.LogUtils; 39 40 public class FolderPickerActivity extends Activity implements FolderPickerCallback { 41 private static final String TAG = "FolderPickerActivity"; 42 public static final String MAILBOX_TYPE_EXTRA = "mailbox_type"; 43 44 private long mAccountId; 45 private int mMailboxType; 46 private AccountObserver mAccountObserver; 47 private String mAccountName; 48 private boolean mInSetup = true; 49 50 @Override onCreate(Bundle bundle)51 public void onCreate(Bundle bundle) { 52 super.onCreate(bundle); 53 Intent i = getIntent(); 54 Uri uri = i.getData(); 55 int headerId; 56 final com.android.mail.providers.Account uiAccount; 57 // If we've gotten a Uri, then this is a call from the UI in response to setupIntentUri 58 // in an account (meaning the account requires setup) 59 if (uri != null) { 60 String id = uri.getQueryParameter("account"); 61 if (id == null) { 62 LogUtils.w(TAG, "No account # in Uri?"); 63 finish(); 64 return; 65 } 66 try { 67 mAccountId = Long.parseLong(id); 68 } catch (NumberFormatException e) { 69 LogUtils.w(TAG, "Invalid account # in Uri?"); 70 finish(); 71 return; 72 } 73 // We act a bit differently if we're coming to set up the trash after account creation 74 mInSetup = !i.hasExtra(MAILBOX_TYPE_EXTRA); 75 mMailboxType = i.getIntExtra(MAILBOX_TYPE_EXTRA, Mailbox.TYPE_TRASH); 76 long trashMailboxId = Mailbox.findMailboxOfType(this, mAccountId, Mailbox.TYPE_TRASH); 77 // If we already have a trash mailbox, we're done (if in setup; a race?) 78 if (trashMailboxId != Mailbox.NO_MAILBOX && mInSetup) { 79 LogUtils.w(TAG, "Trash folder already exists"); 80 finish(); 81 return; 82 } 83 Account account = Account.restoreAccountWithId(this, mAccountId); 84 if (account == null) { 85 LogUtils.w(TAG, "No account?"); 86 finish(); 87 } else { 88 mAccountName = account.mDisplayName; 89 // Two possibilities here; either we have our folder list, or we don't 90 if ((account.mFlags & Account.FLAGS_INITIAL_FOLDER_LIST_LOADED) != 0) { 91 // If we've got them, just start up the picker dialog 92 startPickerForAccount(); 93 } else { 94 // Otherwise, wait for the folders to show up 95 waitForFolders(); 96 } 97 } 98 } else { 99 // In this case, we're coming from Settings 100 uiAccount = i.getParcelableExtra(EmailProvider.PICKER_UI_ACCOUNT); 101 mAccountName = uiAccount.getDisplayName(); 102 mAccountId = Long.parseLong(uiAccount.uri.getLastPathSegment()); 103 mMailboxType = i.getIntExtra(EmailProvider.PICKER_MAILBOX_TYPE, -1); 104 headerId = i.getIntExtra(EmailProvider.PICKER_HEADER_ID, 0); 105 if (headerId == 0) { 106 finish(); 107 return; 108 } 109 startPicker(uiAccount.folderListUri, headerId); 110 } 111 } 112 113 @Override onDestroy()114 public void onDestroy() { 115 super.onDestroy(); 116 // Clean up 117 if (mAccountObserver != null) { 118 getContentResolver().unregisterContentObserver(mAccountObserver); 119 mAccountObserver = null; 120 } 121 if (mWaitingForFoldersDialog != null) { 122 mWaitingForFoldersDialog.dismiss(); 123 mWaitingForFoldersDialog = null; 124 } 125 } 126 127 private class AccountObserver extends ContentObserver { 128 private final Context mContext; 129 AccountObserver(Context context, Handler handler)130 public AccountObserver(Context context, Handler handler) { 131 super(handler); 132 mContext = context; 133 } 134 135 @Override onChange(boolean selfChange)136 public void onChange(boolean selfChange) { 137 Account account = Account.restoreAccountWithId(mContext, mAccountId); 138 // All we care about is whether the folder list is now loaded 139 if ((account.mFlags & Account.FLAGS_INITIAL_FOLDER_LIST_LOADED) != 0 && 140 (mAccountObserver != null)) { 141 mContext.getContentResolver().unregisterContentObserver(mAccountObserver); 142 mAccountObserver = null; 143 // Bring down the ProgressDialog and show the picker 144 if (mWaitingForFoldersDialog != null) { 145 mWaitingForFoldersDialog.dismiss(); 146 mWaitingForFoldersDialog = null; 147 } 148 startPickerForAccount(); 149 } 150 } 151 } 152 153 private ProgressDialog mWaitingForFoldersDialog; 154 waitForFolders()155 private void waitForFolders() { 156 /// Show "Waiting for folders..." dialog 157 mWaitingForFoldersDialog = new ProgressDialog(this); 158 mWaitingForFoldersDialog.setIndeterminate(true); 159 mWaitingForFoldersDialog.setMessage(getString(R.string.account_waiting_for_folders_msg)); 160 mWaitingForFoldersDialog.show(); 161 162 // Listen for account changes 163 mAccountObserver = new AccountObserver(this, new Handler()); 164 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, mAccountId); 165 getContentResolver().registerContentObserver(uri, false, mAccountObserver); 166 } 167 startPickerForAccount()168 private void startPickerForAccount() { 169 int headerId = R.string.trash_folder_selection_title; 170 Uri uri = Uri.parse("content://" + EmailContent.AUTHORITY + "/uifullfolders/" + mAccountId); 171 startPicker(uri, headerId); 172 } 173 startPicker(Uri uri, int headerId)174 private void startPicker(Uri uri, int headerId) { 175 String header = getString(headerId, mAccountName); 176 FolderPickerDialog dialog = 177 new FolderPickerDialog(this, uri, this, header, !mInSetup); 178 dialog.show(); 179 } 180 181 @Override select(Folder folder)182 public void select(Folder folder) { 183 String folderId = folder.folderUri.fullUri.getLastPathSegment(); 184 Long id = Long.parseLong(folderId); 185 ContentValues values = new ContentValues(); 186 187 // If we already have a mailbox of this type, change it back to generic mail type 188 Mailbox ofType = Mailbox.restoreMailboxOfType(this, mAccountId, mMailboxType); 189 if (ofType != null) { 190 values.put(MailboxColumns.TYPE, Mailbox.TYPE_MAIL); 191 getContentResolver().update( 192 ContentUris.withAppendedId(Mailbox.CONTENT_URI, ofType.mId), values, 193 null, null); 194 } 195 196 // Change this mailbox to be of the desired type 197 Mailbox mailbox = Mailbox.restoreMailboxWithId(this, id); 198 if (mailbox != null) { 199 values.put(MailboxColumns.TYPE, mMailboxType); 200 getContentResolver().update( 201 ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailbox.mId), values, 202 null, null); 203 values.clear(); 204 // Touch the account so that UI won't bring up this picker again 205 Account account = Account.restoreAccountWithId(this, mAccountId); 206 values.put(AccountColumns.FLAGS, account.mFlags); 207 getContentResolver().update( 208 ContentUris.withAppendedId(Account.CONTENT_URI, account.mId), values, 209 null, null); 210 } 211 finish(); 212 } 213 214 @Override cancel()215 public void cancel() { 216 finish(); 217 } 218 } 219