/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.mail.ui; import android.app.Fragment; import android.app.FragmentTransaction; import android.appwidget.AppWidgetManager; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.database.DataSetObservable; import android.database.DataSetObserver; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ListView; import com.android.bitmap.BitmapCache; import com.android.mail.R; import com.android.mail.bitmap.ContactResolver; import com.android.mail.providers.Account; import com.android.mail.providers.Folder; import com.android.mail.providers.FolderWatcher; import com.android.mail.utils.LogTag; import com.android.mail.utils.LogUtils; import com.android.mail.utils.MailObservable; import com.android.mail.utils.Utils; import com.android.mail.utils.VeiledAddressMatcher; import com.android.mail.widget.WidgetProvider; import java.util.ArrayList; /** * This activity displays the list of available folders for the current account. */ public class FolderSelectionActivity extends ActionBarActivity implements OnClickListener, DialogInterface.OnClickListener, ControllableActivity, FolderSelector { public static final String EXTRA_ACCOUNT_SHORTCUT = "account-shortcut"; private static final String LOG_TAG = LogTag.getLogTag(); private static final int CONFIGURE = 0; private static final int VIEW = 1; private Account mAccount; private Folder mSelectedFolder; private boolean mConfigureShortcut; protected boolean mConfigureWidget; private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; private int mMode = -1; /** Empty placeholder for communicating to the consumer of the drawer observer. */ private final DataSetObservable mFolderOrAccountObservers = new MailObservable("FolderOrAccount"); private final AccountController mAccountController = new AccountController() { @Override public void registerAccountObserver(DataSetObserver observer) { // Do nothing } @Override public void unregisterAccountObserver(DataSetObserver observer) { // Do nothing } @Override public Account getAccount() { return mAccount; } @Override public void registerAllAccountObserver(DataSetObserver observer) { // Do nothing } @Override public void unregisterAllAccountObserver(DataSetObserver observer) { // Do nothing } @Override public Account[] getAllAccounts() { return new Account[]{mAccount}; } @Override public VeiledAddressMatcher getVeiledAddressMatcher() { return null; } @Override public void switchToDefaultInboxOrChangeAccount(Account account) { // Never gets called, so do nothing here. LogUtils.wtf(LOG_TAG,"FolderSelectionActivity.switchToDefaultInboxOrChangeAccount() " + "called when NOT expected."); } @Override public void registerFolderOrAccountChangedObserver(final DataSetObserver observer) { mFolderOrAccountObservers.registerObserver(observer); } @Override public void unregisterFolderOrAccountChangedObserver(final DataSetObserver observer) { mFolderOrAccountObservers.unregisterObserver(observer); } /** * Since there is no drawer to wait for, notifyChanged to the observers. */ @Override public void closeDrawer(final boolean hasNewFolderOrAccount, Account account, Folder folder) { mFolderOrAccountObservers.notifyChanged(); } @Override public void setFolderWatcher(FolderWatcher watcher) { // Unsupported. } @Override public boolean isDrawerPullEnabled() { // Unsupported return false; } @Override public int getFolderListViewChoiceMode() { return ListView.CHOICE_MODE_NONE; } }; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.folders_activity); final Intent intent = getIntent(); final String action = intent.getAction(); mConfigureShortcut = Intent.ACTION_CREATE_SHORTCUT.equals(action); mConfigureWidget = AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action); if (!mConfigureShortcut && !mConfigureWidget) { LogUtils.wtf(LOG_TAG, "unexpected intent: %s", intent); } if (mConfigureShortcut || mConfigureWidget) { mMode = CONFIGURE; } else { mMode = VIEW; } if (mConfigureWidget) { mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { LogUtils.wtf(LOG_TAG, "invalid widgetId"); } } mAccount = intent.getParcelableExtra(EXTRA_ACCOUNT_SHORTCUT); final Button firstButton = (Button) findViewById(R.id.first_button); firstButton.setVisibility(View.VISIBLE); // TODO(mindyp) disable the manage folders buttons until we have a manage folders screen. if (mMode == VIEW) { firstButton.setEnabled(false); } firstButton.setOnClickListener(this); createFolderListFragment(FolderListFragment.ofTopLevelTree(mAccount.folderListUri, getExcludedFolderTypes())); } /** * Create a Fragment showing this folder and its children. */ private void createFolderListFragment(Fragment fragment) { final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.content_pane, fragment); fragmentTransaction.commitAllowingStateLoss(); } /** * Gets an {@link ArrayList} of canonical names of any folders to exclude from displaying. * By default, this list is empty. * * @return An {@link ArrayList} of folder canonical names */ protected ArrayList getExcludedFolderTypes() { return new ArrayList(); } @Override protected void onResume() { super.onResume(); // TODO: (mindyp) Make sure we're operating on the same account as // before. If the user switched accounts, switch back. } @Override public void onClick(View v) { final int id = v.getId(); if (id == R.id.first_button) { if (mMode == CONFIGURE) { doCancel(); } else { // TODO (mindyp): open manage folders screen. } } } private void doCancel() { setResult(RESULT_CANCELED); finish(); } /** * Create a widget for the specified account and folder */ protected void createWidget(int id, Account account, Folder selectedFolder) { WidgetProvider.updateWidget(this, id, account, selectedFolder.type, selectedFolder.capabilities, selectedFolder.folderUri.fullUri, selectedFolder.conversationListUri, selectedFolder.name); final Intent result = new Intent(); result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id); setResult(RESULT_OK, result); finish(); } @Override public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_POSITIVE) { // The only dialog that is createWidget(mAppWidgetId, mAccount, mSelectedFolder); } else { doCancel(); } } private void onFolderChanged(Folder folder, final boolean force) { if (!folder.equals(mSelectedFolder)) { mSelectedFolder = folder; Intent resultIntent = new Intent(); if (mConfigureShortcut) { /* * Create the shortcut Intent based on it with the additional * information that we have in this activity: name of the * account, calculate the human readable name of the folder and * use it as the shortcut name, etc... */ final Intent clickIntent = Utils.createViewFolderIntent(this, mSelectedFolder.folderUri.fullUri, mAccount); resultIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, clickIntent); resultIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(this, R.mipmap.ic_launcher_shortcut_folder)); /** * Note: Email1 created shortcuts using R.mipmap#ic_launcher_email * so don't delete that resource until we have an upgrade/migration solution */ final CharSequence humanFolderName = mSelectedFolder.name; resultIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, humanFolderName); // Now ask the user what name they want for this shortcut. Pass // the // shortcut intent that we just created, the user can modify the // folder in // ShortcutNameActivity. final Intent shortcutNameIntent = new Intent(this, ShortcutNameActivity.class); shortcutNameIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_FORWARD_RESULT); shortcutNameIntent.putExtra(ShortcutNameActivity.EXTRA_FOLDER_CLICK_INTENT, resultIntent); shortcutNameIntent.putExtra(ShortcutNameActivity.EXTRA_SHORTCUT_NAME, humanFolderName); startActivity(shortcutNameIntent); finish(); } else if (mConfigureWidget) { createWidget(mAppWidgetId, mAccount, mSelectedFolder); } } } @Override public Context getActivityContext() { return this; } @Override public ViewMode getViewMode() { return null; } @Override public ConversationListCallbacks getListHandler() { return null; } @Override public ConversationCheckedSet getCheckedSet() { return null; } private Folder mNavigatedFolder; @Override public void onFolderSelected(Folder folder) { if (folder.hasChildren && !folder.equals(mNavigatedFolder)) { mNavigatedFolder = folder; // Replace this fragment with a new FolderListFragment // showing this folder's children if we are not already looking // at the child view for this folder. createFolderListFragment(FolderListFragment.ofTree(folder)); return; } onFolderChanged(folder, false /* force */); } @Override public FolderSelector getFolderSelector() { return this; } @Override public void onUndoAvailable(ToastBarOperation undoOp) { // Do nothing. } @Override public Folder getHierarchyFolder() { return null; } @Override public ConversationUpdater getConversationUpdater() { return null; } @Override public ErrorListener getErrorListener() { return null; } @Override public void setPendingToastOperation(ToastBarOperation op) { // Do nothing. } @Override public ToastBarOperation getPendingToastOperation() { return null; } @Override public FolderController getFolderController() { return null; } @Override public void onAnimationEnd(AnimatedAdapter animatedAdapter) { } @Override public AccountController getAccountController() { return mAccountController; } @Override public void onFooterViewLoadMoreClick(Folder folder) { // Unsupported } @Override public RecentFolderController getRecentFolderController() { // Unsupported return null; } @Override public DrawerController getDrawerController() { // Unsupported return null; } @Override public KeyboardNavigationController getKeyboardNavigationController() { // Unsupported return null; } @Override public boolean isAccessibilityEnabled() { // Unsupported return true; } @Override public ConversationListHelper getConversationListHelper() { // Unsupported return null; } @Override public FragmentLauncher getFragmentLauncher() { // Unsupported return null; } @Override public ContactLoaderCallbacks getContactLoaderCallbacks() { // Unsupported return null; } @Override public ContactResolver getContactResolver(ContentResolver resolver, BitmapCache bitmapCache) { // Unsupported return null; } @Override public BitmapCache getSenderImageCache() { // Unsupported return null; } @Override public void resetSenderImageCache() { // Unsupported } @Override public void showHelp(Account account, int viewMode) { // Unsupported } }