Check for active accounts in compose

If there are none, then just go to "add account" screen

Change-Id: I3a9a0bfa919b84cc5183a6a8f0f11c762c02867a
diff --git a/res/layout/compose.xml b/res/layout/compose.xml
index 132063d..a45e227 100644
--- a/res/layout/compose.xml
+++ b/res/layout/compose.xml
@@ -15,70 +15,83 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="match_parent"
-    android:layout_width="match_parent"
-    android:orientation="vertical"
-    android:background="@android:color/white">
+    android:layout_width="match_parent">
+    <RelativeLayout
+        android:id="@+id/wait"
+        android:visibility="gone"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:layout_gravity="center"/>
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:orientation="vertical"
+        android:background="@android:color/white"
+        android:visibility="gone"
+        android:id="@+id/compose">
 
-    <ScrollView
-      android:id="@+id/compose_scrollview"
-      android:fillViewport="true"
-      android:layout_height="0dip"
-      android:layout_weight="1"
-      android:layout_width="match_parent">
+        <ScrollView
+            android:id="@+id/compose_scrollview"
+            android:fillViewport="true"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+            android:layout_width="match_parent">
 
-        <LinearLayout android:id="@+id/content"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:animateLayoutChanges="true"
-            android:paddingLeft="16dip"
-            android:paddingRight="16dip">
-
-            <include layout="@layout/compose_from"/>
-
-            <LinearLayout android:layout_height="wrap_content"
+            <LinearLayout android:id="@+id/content"
+                android:orientation="vertical"
                 android:layout_width="match_parent"
-                android:orientation="horizontal">
+                android:layout_height="match_parent"
+                android:animateLayoutChanges="true"
+                android:paddingLeft="16dip"
+                android:paddingRight="16dip">
 
-                <include layout="@layout/compose_recipients"
+                <include layout="@layout/compose_from"/>
+
+                <LinearLayout android:layout_height="wrap_content"
                     android:layout_width="match_parent"
+                    android:orientation="horizontal">
+
+                    <include layout="@layout/compose_recipients"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_weight="1"/>
+
+                </LinearLayout>
+
+                <!--  Attachments -->
+                <com.android.mail.compose.AttachmentsView android:id="@+id/attachments"
                     android:layout_height="wrap_content"
-                    android:layout_weight="1"/>
+                    android:layout_width="match_parent"
+                    android:orientation="vertical"
+                    android:animateLayoutChanges="true"
+                    android:paddingTop="8dip"
+                    android:paddingRight="5dip"
+                    android:paddingBottom="0dip"
+                    android:paddingLeft="5dip"
+                    android:visibility="gone">
+                    <include layout="@layout/compose_attachments" />
+                </com.android.mail.compose.AttachmentsView>
+                <!-- Body -->
+                <include layout="@layout/compose_body"/>
+
+                <!-- Quoted text -->
+                <com.android.mail.compose.QuotedTextView android:id="@+id/quoted_text_view"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:visibility="gone" />
+
+                <View android:id="@+id/composearea_tap_trap_bottom"
+                    android:clickable="true"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:background="@color/compose_background_color"/>
 
             </LinearLayout>
 
-            <!--  Attachments -->
-            <com.android.mail.compose.AttachmentsView android:id="@+id/attachments"
-                android:layout_height="wrap_content"
-                android:layout_width="match_parent"
-                android:orientation="vertical"
-                android:animateLayoutChanges="true"
-                android:paddingTop="8dip"
-                android:paddingRight="5dip"
-                android:paddingBottom="0dip"
-                android:paddingLeft="5dip"
-                android:visibility="gone">
-                <include layout="@layout/compose_attachments" />
-            </com.android.mail.compose.AttachmentsView>
-            <!-- Body -->
-            <include layout="@layout/compose_body"/>
+        </ScrollView>
 
-            <!-- Quoted text -->
-            <com.android.mail.compose.QuotedTextView android:id="@+id/quoted_text_view"
-                android:layout_height="wrap_content"
-                android:layout_width="match_parent"
-                android:visibility="gone" />
-
-            <View android:id="@+id/composearea_tap_trap_bottom"
-                android:clickable="true"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:background="@color/compose_background_color"/>
-
-        </LinearLayout>
-
-    </ScrollView>
-
-</LinearLayout>
+    </LinearLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/wait_for_compose.xml b/res/layout/wait_for_compose.xml
new file mode 100644
index 0000000..95e06c5
--- /dev/null
+++ b/res/layout/wait_for_compose.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012 Google Inc.
+     Licensed to 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.
+-->
+
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/white"
+    android:gravity="center"
+    android:layout_gravity="center"
+    android:id="@+id/wait_for_sync_wrapper">
+
+    <ProgressBar
+        android:indeterminate="true"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/progress_spinner"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/wait_for_sync_title"
+        android:id="@+id/wait_for_sync_title"
+        android:layout_toRightOf="@id/progress_spinner"
+        android:layout_marginLeft="4dip"
+        android:layout_marginTop="8dip"
+        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ </RelativeLayout>
diff --git a/src/com/android/mail/compose/ComposeActivity.java b/src/com/android/mail/compose/ComposeActivity.java
index 7615550..ca3cfec 100644
--- a/src/com/android/mail/compose/ComposeActivity.java
+++ b/src/com/android/mail/compose/ComposeActivity.java
@@ -23,6 +23,9 @@
 import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.Dialog;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
 import android.app.LoaderManager;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -82,6 +85,7 @@
 import com.android.mail.providers.UIProvider.AccountCapabilities;
 import com.android.mail.providers.UIProvider.DraftType;
 import com.android.mail.ui.MailActivity;
+import com.android.mail.ui.WaitFragment;
 import com.android.mail.utils.AccountUtils;
 import com.android.mail.utils.LogTag;
 import com.android.mail.utils.LogUtils;
@@ -185,7 +189,9 @@
     private static final String EXTRA_FOCUS_SELECTION_END = null;
     private static final String EXTRA_MESSAGE = "extraMessage";
     private static final int REFERENCE_MESSAGE_LOADER = 0;
+    private static final int LOADER_ACCOUNT_CURSOR = 1;
     private static final String EXTRA_SELECTED_ACCOUNT = "selectedAccount";
+    private static final String TAG_WAIT = "wait-fragment";
 
     /**
      * A single thread for running tasks in the background.
@@ -237,6 +243,7 @@
     private RecipientTextWatcher mCcListener;
     private RecipientTextWatcher mBccListener;
     private Uri mRefMessageUri;
+    private Bundle mSavedInstanceState;
 
 
     /**
@@ -291,6 +298,12 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.compose);
+        mSavedInstanceState = savedInstanceState;
+        checkValidAccounts();
+    }
+
+    private void finishCreate() {
+        Bundle savedInstanceState = mSavedInstanceState;
         findViews();
         Intent intent = getIntent();
         Message message;
@@ -371,6 +384,32 @@
         finishSetup(action, intent, savedInstanceState, showQuotedText);
     }
 
+    private void checkValidAccounts() {
+        mAccounts = AccountUtils.getAccounts(this);
+        if (mAccounts == null || mAccounts.length == 0) {
+            final Intent noAccountIntent = MailAppProvider.getNoAccountIntent(this);
+            if (noAccountIntent != null) {
+                startActivityForResult(noAccountIntent, RESULT_CREATE_ACCOUNT);
+            }
+        } else {
+            // If none of the accounts are syncing. setup a watcher.
+            boolean anySyncing = false;
+            for (Account a : mAccounts) {
+                if (a.isAccountIntialized()) {
+                    anySyncing = true;
+                    break;
+                }
+            }
+            if (!anySyncing) {
+                // There are accounts, but none are sync'd, which is just like having no accounts.
+                mAccounts = null;
+                getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);
+                return;
+            }
+            finishCreate();
+        }
+    }
+
     private Account obtainAccount(Intent intent) {
         Account account = null;
         Object accountExtra = null;
@@ -387,12 +426,11 @@
                 accountExtra = Uri.parse(lastAccountUri);
             }
         }
-        final Account[] syncingAccounts = AccountUtils.getSyncingAccounts(this);
-        if (syncingAccounts.length > 0) {
+        if (mAccounts != null && mAccounts.length > 0) {
             if (accountExtra instanceof String && !TextUtils.isEmpty((String) accountExtra)) {
                 // For backwards compatibility, we need to check account
                 // names.
-                for (Account a : syncingAccounts) {
+                for (Account a : mAccounts) {
                     if (a.name.equals(accountExtra)) {
                         account = a;
                     }
@@ -400,13 +438,14 @@
             } else if (accountExtra instanceof Uri) {
                 // The uri of the last viewed account is what is stored in
                 // the current code base.
-                for (Account a : syncingAccounts) {
+                for (Account a : mAccounts) {
                     if (a.uri.equals(accountExtra)) {
                         account = a;
                     }
                 }
-            } else {
-                account = syncingAccounts[0];
+            }
+            if (account == null) {
+                account = mAccounts[0];
             }
         }
         return account;
@@ -492,7 +531,7 @@
         // Update the from spinner as other accounts
         // may now be available.
         if (mFromSpinner != null && mAccount != null) {
-            mFromSpinner.asyncInitFromSpinner(mComposeMode, mAccount);
+            mFromSpinner.asyncInitFromSpinner(mComposeMode, mAccount, mAccounts);
         }
     }
 
@@ -514,10 +553,19 @@
 
     @Override
     protected final void onActivityResult(int request, int result, Intent data) {
-        mAddingAttachment = false;
-
-        if (result == RESULT_OK && request == RESULT_PICK_ATTACHMENT) {
+        if (request == RESULT_PICK_ATTACHMENT && result == RESULT_OK) {
             addAttachmentAndUpdateView(data);
+            mAddingAttachment = false;
+        } else if (request == RESULT_CREATE_ACCOUNT) {
+                // We were waiting for the user to create an account
+            if (result != RESULT_OK) {
+                finish();
+            } else {
+                // Watch for accounts to show up!
+                // restart the loader to get the updated list of accounts
+                getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);
+                showWaitFragment(null);
+            }
         }
     }
 
@@ -542,6 +590,10 @@
     @Override
     public final void onSaveInstanceState(Bundle state) {
         super.onSaveInstanceState(state);
+        // We have no accounts so there is nothing to compose, and therefore, nothing to save.
+        if (mAccounts == null || mAccounts.length == 0) {
+            return;
+        }
         // The framework is happy to save and restore the selection but only if it also saves and
         // restores the contents of the edit text. That's a lot of text to put in a bundle so we do
         // this manually.
@@ -661,7 +713,7 @@
         if (action == EDIT_DRAFT && mDraft.draftType == UIProvider.DraftType.COMPOSE) {
             action = COMPOSE;
         }
-        mFromSpinner.asyncInitFromSpinner(action, mAccount);
+        mFromSpinner.asyncInitFromSpinner(action, mAccount, mAccounts);
         if (bundle != null) {
             if (bundle.containsKey(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)) {
                 mReplyFromAccount = ReplyFromAccount.deserialize(mAccount,
@@ -806,6 +858,7 @@
     }
 
     private void findViews() {
+        findViewById(R.id.compose).setVisibility(View.VISIBLE);
         mCcBccButton = (Button) findViewById(R.id.add_cc_bcc);
         if (mCcBccButton != null) {
             mCcBccButton.setOnClickListener(this);
@@ -1524,6 +1577,10 @@
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         super.onCreateOptionsMenu(menu);
+        // Don't render any menu items when there are no accounts.
+        if (mAccounts == null || mAccounts.length == 0) {
+            return true;
+        }
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.compose_menu, menu);
         mSave = menu.findItem(R.id.save);
@@ -1602,6 +1659,16 @@
         return !handled ? super.onOptionsItemSelected(item) : handled;
     }
 
+    @Override
+    public void onBackPressed() {
+        // If we are showing the wait fragment, just exit.
+        if (getWaitFragment() != null) {
+            finish();
+        } else {
+            super.onBackPressed();
+        }
+    }
+
     private void onAppUpPressed() {
         if (mLaunchedFromEmail) {
             // If this was started from Gmail, simply treat app up as the system back button, so
@@ -1741,6 +1808,7 @@
     private int mRequestId;
     private String mSignature;
     private AttachmentTypeSelectorAdapter mAttachmentTypeSelectorAdapter;
+    private Account[] mAccounts;
 
     @VisibleForTesting
     public static class SendOrSaveMessage {
@@ -2685,34 +2753,93 @@
             case REFERENCE_MESSAGE_LOADER:
                 return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null,
                         null, null);
+            case LOADER_ACCOUNT_CURSOR:
+                return new CursorLoader(this, MailAppProvider.getAccountsUri(),
+                        UIProvider.ACCOUNTS_PROJECTION, null, null, null);
         }
         return null;
     }
 
     @Override
     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
-        if (data != null && data.moveToFirst()) {
-            mRefMessage = new Message(data);
-            // We set these based on EXTRA_TO.
-            mRefMessage.to = null;
-            mRefMessage.from = null;
-            Intent intent = getIntent();
-            int action = intent.getIntExtra(EXTRA_ACTION, COMPOSE);
-            initFromRefMessage(action, mAccount.name);
-            finishSetup(action, intent, null, true);
-            if (action != FORWARD) {
-                String to = intent.getStringExtra(EXTRA_TO);
-                if (!TextUtils.isEmpty(to)) {
-                    clearChangeListeners();
-                    mTo.append(to);
-                    initChangeListeners();
+        int id = loader.getId();
+        switch (id) {
+            case REFERENCE_MESSAGE_LOADER:
+                if (data != null && data.moveToFirst()) {
+                    mRefMessage = new Message(data);
+                    // We set these based on EXTRA_TO.
+                    mRefMessage.to = null;
+                    mRefMessage.from = null;
+                    Intent intent = getIntent();
+                    int action = intent.getIntExtra(EXTRA_ACTION, COMPOSE);
+                    initFromRefMessage(action, mAccount.name);
+                    finishSetup(action, intent, null, true);
+                    if (action != FORWARD) {
+                        String to = intent.getStringExtra(EXTRA_TO);
+                        if (!TextUtils.isEmpty(to)) {
+                            clearChangeListeners();
+                            mTo.append(to);
+                            initChangeListeners();
+                        }
+                    }
+                } else {
+                    finish();
                 }
-            }
-        } else {
-            finish();
+                break;
+            case LOADER_ACCOUNT_CURSOR:
+                if (data != null && data.moveToFirst()) {
+                    // there are accounts now!
+                    Account account;
+                    ArrayList<Account> accounts = new ArrayList<Account>();
+                    ArrayList<Account> initializedAccounts = new ArrayList<Account>();
+                    do {
+                        account = new Account(data);
+                        if (account.isAccountIntialized()) {
+                            initializedAccounts.add(account);
+                        }
+                        accounts.add(account);
+                    } while (data.moveToNext());
+                    if (initializedAccounts.size() > 0) {
+                        findViewById(R.id.wait).setVisibility(View.GONE);
+                        getLoaderManager().destroyLoader(LOADER_ACCOUNT_CURSOR);
+                        findViewById(R.id.compose).setVisibility(View.VISIBLE);
+                        mAccounts = accounts.toArray(new Account[initializedAccounts.size()]);
+                        finishCreate();
+                        invalidateOptionsMenu();
+                    } else {
+                        // Show "waiting"
+                        account = accounts.size() > 0 ? accounts.get(0) : null;
+                        showWaitFragment(account);
+                    }
+                }
+                break;
         }
     }
 
+    private void showWaitFragment(Account account) {
+        WaitFragment fragment = getWaitFragment();
+        if (fragment != null) {
+            fragment.updateAccount(account);
+        } else {
+            findViewById(R.id.wait).setVisibility(View.VISIBLE);
+            replaceFragment(WaitFragment.newInstance(account, true),
+                    FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_WAIT);
+        }
+    }
+
+    private WaitFragment getWaitFragment() {
+        return (WaitFragment) getFragmentManager().findFragmentByTag(TAG_WAIT);
+    }
+
+    private int replaceFragment(Fragment fragment, int transition, String tag) {
+        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+        fragmentTransaction.addToBackStack(null);
+        fragmentTransaction.setTransition(transition);
+        fragmentTransaction.replace(R.id.wait, fragment, tag);
+        final int transactionId = fragmentTransaction.commitAllowingStateLoss();
+        return transactionId;
+    }
+
     @Override
     public void onLoaderReset(Loader<Cursor> arg0) {
         // Do nothing.
diff --git a/src/com/android/mail/compose/FromAddressSpinner.java b/src/com/android/mail/compose/FromAddressSpinner.java
index 1efdf01..d402f55 100644
--- a/src/com/android/mail/compose/FromAddressSpinner.java
+++ b/src/com/android/mail/compose/FromAddressSpinner.java
@@ -95,10 +95,12 @@
      *            accounts. Otherwise, show just the account this was launched
      *            with.
      * @param currentAccount Account used to launch activity.
+     * @param syncing accounts
      */
-    public void asyncInitFromSpinner(int action, Account currentAccount) {
+    public void asyncInitFromSpinner(int action, Account currentAccount,
+            Account[] syncingAccounts) {
         if (action == ComposeActivity.COMPOSE) {
-            Account[] result = AccountUtils.getSyncingAccounts(getContext());
+            Account[] result = syncingAccounts;
             mAccounts = AccountUtils
                     .mergeAccountLists(mAccounts, result, true /* prioritizeAccountList */);
         } else {
diff --git a/src/com/android/mail/ui/WaitFragment.java b/src/com/android/mail/ui/WaitFragment.java
index 8be3ffa..e922104 100644
--- a/src/com/android/mail/ui/WaitFragment.java
+++ b/src/com/android/mail/ui/WaitFragment.java
@@ -38,19 +38,29 @@
     // Keys used to pass data to {@link WaitFragment}.
     private static final String ACCOUNT_KEY = "account";
 
+    private static final String COMPOSE_KEY = "isCompose";
+
     private static final int MANUAL_SYNC_LOADER = 0;
 
+
     private Account mAccount;
 
     private LayoutInflater mInflater;
 
     private ViewGroup mContainer;
 
+    private boolean mCompose;
+
     public static WaitFragment newInstance(Account account) {
+        return newInstance(account, false);
+    }
+
+    public static WaitFragment newInstance(Account account, boolean compose) {
         WaitFragment fragment = new WaitFragment();
 
         final Bundle args = new Bundle();
         args.putParcelable(ACCOUNT_KEY, account);
+        args.putBoolean(COMPOSE_KEY, compose);
         fragment.setArguments(args);
         return fragment;
     }
@@ -61,6 +71,7 @@
 
         Bundle args = getArguments();
         mAccount = (Account)args.getParcelable(ACCOUNT_KEY);
+        mCompose = args.getBoolean(COMPOSE_KEY, false);
     }
 
     @Override
@@ -76,14 +87,17 @@
 
         // Clear any views in the container.
         mContainer.removeAllViews();
-        if ((mAccount.syncStatus & SyncStatus.MANUAL_SYNC_REQUIRED) ==
-                SyncStatus.MANUAL_SYNC_REQUIRED) {
+        if (mAccount != null
+                && (mAccount.syncStatus & SyncStatus.MANUAL_SYNC_REQUIRED)
+                    == SyncStatus.MANUAL_SYNC_REQUIRED) {
             // A manual sync is required
             root = mInflater.inflate(R.layout.wait_for_manual_sync, mContainer, false);
 
             root.findViewById(R.id.manual_sync).setOnClickListener(this);
             root.findViewById(R.id.change_sync_settings).setOnClickListener(this);
 
+        } else if (mCompose) {
+            root = mInflater.inflate(R.layout.wait_for_compose, mContainer, false);
         } else {
             root = mInflater.inflate(R.layout.wait_for_sync, mContainer, false);
         }
@@ -91,7 +105,7 @@
         return root;
     }
 
-    void updateAccount(Account account) {
+    public void updateAccount(Account account) {
         mAccount = account;
         getContent();
     }
diff --git a/src/com/android/mail/utils/AccountUtils.java b/src/com/android/mail/utils/AccountUtils.java
index 416c0bb..0db885d 100644
--- a/src/com/android/mail/utils/AccountUtils.java
+++ b/src/com/android/mail/utils/AccountUtils.java
@@ -94,4 +94,29 @@
         }
         return accounts.toArray(new Account[accounts.size()]);
     }
+
+    /**
+     * Synchronous method which returns registered accounts.
+     * @param context
+     * @return
+     */
+    public static Account[] getAccounts(Context context) {
+        final ContentResolver resolver = context.getContentResolver();
+        Cursor accountsCursor = null;
+        final List<Account> accounts = Lists.newArrayList();
+        try {
+            accountsCursor = resolver.query(MailAppProvider.getAccountsUri(),
+                    UIProvider.ACCOUNTS_PROJECTION, null, null, null);
+            if (accountsCursor != null) {
+                while (accountsCursor.moveToNext()) {
+                    accounts.add(new Account(accountsCursor));
+                }
+            }
+        } finally {
+            if (accountsCursor != null) {
+                accountsCursor.close();
+            }
+        }
+        return accounts.toArray(new Account[accounts.size()]);
+    }
 }