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