New account spinner
- Don't use the action bar spinner. Instead use a custom view to show the current account. (It's not a spinner; now we show the dropdown list by ourselves, which gives us more detailed control.) - Also show the current mailbox name/unread count with the account name. - Removed the mailbox info loader in ABC. Instead, now the AccountSelectorAdapter loader loads the current account/mailbox name, and the unread count as extras. - Now ABC.Callback.onMailboxSelected passed an account ID as well as a mailbox ID. - There's new code paths that can cause the "fragment transaction in onLoadFinished" exception. We need to fix this properly, but for now we just use commitAllowingStateLoss(). Bug 4948352 Change-Id: I73bb8b7530f8328ca1c86382ac0a54086ad061d7
This commit is contained in:
parent
ad6c48b2d3
commit
4689cb7100
|
@ -1,30 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 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.
|
||||
-->
|
||||
|
||||
<!--
|
||||
TextView for the collapsed account spinner.
|
||||
TODO: Need to widen maxWidth dynamically when the mailbox name isn't shown
|
||||
on the action bar.
|
||||
-->
|
||||
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/display_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="@dimen/action_bar_account_name_max_width"
|
||||
style="@style/action_bar_account_name"
|
||||
/>
|
|
@ -1,43 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 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.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/action_bar_mailbox_name_left_margin"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/mailbox_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:maxWidth="@dimen/action_bar_mailbox_name_max_width"
|
||||
android:textSize="18dp"
|
||||
android:textColor="@color/text_ternary_color"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="left|center"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/unread_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginLeft="16dp"
|
||||
style="@style/action_bar_unread_count"
|
||||
android:gravity="center"
|
||||
/>
|
||||
</LinearLayout>
|
|
@ -26,8 +26,8 @@
|
|||
android:layout_height="0dip"
|
||||
>
|
||||
<include
|
||||
android:id="@+id/current_mailbox_container"
|
||||
layout="@layout/action_bar_current_mailbox"
|
||||
android:id="@+id/account_spinner"
|
||||
layout="@layout/action_bar_spinner"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
<include
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2011 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.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/account_spinner_width"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
style="@android:style/Widget.Holo.Spinner"
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/spinner_line_1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:textSize="16dip"
|
||||
android:textColor="@color/text_primary_color"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="left|center_vertical"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/spinner_line_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12dip"
|
||||
android:textColor="@color/text_primary_color"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="left|center_vertical"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/spinner_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dip"
|
||||
android:textSize="16dip"
|
||||
android:textColor="@color/text_primary_color"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="none"
|
||||
android:gravity="center"
|
||||
/>
|
||||
</LinearLayout>
|
|
@ -17,6 +17,8 @@
|
|||
<!--
|
||||
Not a RelativeLayout - we want to hide @id/email_address at runtime and then @id/display_name
|
||||
should be center-vertical
|
||||
|
||||
Popup width is set at runtime from @dimen/account_spinner_dropdown_width
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
@ -25,12 +27,11 @@
|
|||
android:orientation="horizontal"
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:maxWidth="@dimen/account_spinner_dropdown_account_name_max_width"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center|left"
|
||||
>
|
||||
|
@ -38,14 +39,12 @@
|
|||
android:id="@+id/display_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="@dimen/account_spinner_dropdown_account_name_max_width"
|
||||
style="@style/action_bar_account_name"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/email_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="@dimen/account_spinner_dropdown_account_name_max_width"
|
||||
style="@style/action_bar_account_name_secondary"
|
||||
/>
|
||||
</LinearLayout>
|
|
@ -53,7 +53,8 @@
|
|||
<dimen name="setup_item_inset_left">0dip</dimen>
|
||||
<dimen name="setup_item_inset_right">0dip</dimen>
|
||||
|
||||
<dimen name="account_spinner_dropdown_account_name_max_width">352dip</dimen>
|
||||
<dimen name="account_spinner_width">250dip</dimen>
|
||||
<dimen name="account_spinner_dropdown_width">300dip</dimen>
|
||||
|
||||
<!-- MessageListItem -->
|
||||
<dimen name="senders_font_size">14sp</dimen>
|
||||
|
|
|
@ -1153,6 +1153,9 @@ save attachment.</string>
|
|||
<!-- The hint used in the search box when searching a single mailbox [CHAR LIMIT=35] -->
|
||||
<string name="search_mailbox_hint">Search <xliff:g example="Inbox">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Title shown on the action bar on the mailbox list screen. [CHAR LIMIT=16] -->
|
||||
<string name="action_bar_mailbox_list_title">Folders</string>
|
||||
|
||||
<!-- STOPSHIP Temporary UI DO NOT TRANSLATE-->
|
||||
<!-- In Mailbox setings, label for email check frequency selector -->
|
||||
<string name="mailbox_options_check_frequency_label">Folder check frequency</string>
|
||||
|
|
|
@ -71,10 +71,7 @@ public class FolderProperties {
|
|||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup names of localized special mailboxes
|
||||
*/
|
||||
private String getDisplayName(int type, long mailboxId) {
|
||||
public String getCombinedMailboxName(long mailboxId) {
|
||||
// Special combined mailboxes
|
||||
int resId = 0;
|
||||
|
||||
|
@ -91,13 +88,21 @@ public class FolderProperties {
|
|||
if (resId != 0) {
|
||||
return mContext.getString(resId);
|
||||
}
|
||||
|
||||
if (type < mSpecialMailbox.length) {
|
||||
return mSpecialMailbox[type];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup names of localized special mailboxes
|
||||
*/
|
||||
private String getDisplayName(int type, long mailboxId) {
|
||||
String name = getCombinedMailboxName(mailboxId);
|
||||
|
||||
if ((name == null) && (type < mSpecialMailbox.length)) {
|
||||
name = mSpecialMailbox[type];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the display name for a mailbox for UI. For normal mailboxes, it just returns
|
||||
* {@code originalDisplayName}, but for special mailboxes (such as combined mailboxes) it
|
||||
|
|
|
@ -24,12 +24,14 @@ import com.android.email.data.ClosingMatrixCursor;
|
|||
import com.android.email.data.ThrottlingCursorLoader;
|
||||
import com.android.emailcommon.provider.Account;
|
||||
import com.android.emailcommon.provider.EmailContent;
|
||||
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
||||
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
|
||||
import com.android.emailcommon.provider.Mailbox;
|
||||
import com.android.emailcommon.utility.Utility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
|
@ -50,10 +52,16 @@ import android.widget.TextView;
|
|||
public class AccountSelectorAdapter extends CursorAdapter {
|
||||
/** meta data column for an message count (unread or total, depending on row) */
|
||||
private static final String MESSAGE_COUNT = "unreadCount";
|
||||
|
||||
/** meta data column for the row type; used for display purposes */
|
||||
private static final String ROW_TYPE = "rowType";
|
||||
|
||||
/** meta data position of the currently selected account in the drop-down list */
|
||||
private static final String ACCOUNT_POSITION = "accountPosition";
|
||||
|
||||
/** "account id" virtual column name for the matrix cursor */
|
||||
private static final String ACCOUNT_ID = "accountId";
|
||||
|
||||
private static final int ROW_TYPE_HEADER = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
|
||||
@SuppressWarnings("unused")
|
||||
private static final int ROW_TYPE_MAILBOX = 0;
|
||||
|
@ -77,6 +85,7 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
Account.EMAIL_ADDRESS,
|
||||
MESSAGE_COUNT,
|
||||
ACCOUNT_POSITION,
|
||||
ACCOUNT_ID,
|
||||
};
|
||||
|
||||
/** Sort order. Show the default account first. */
|
||||
|
@ -92,8 +101,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
* @param context a context
|
||||
* @param accountId the ID of the currently viewed account
|
||||
*/
|
||||
public static Loader<Cursor> createLoader(Context context, long accountId) {
|
||||
return new AccountsLoader(context, accountId, UiUtilities.useTwoPane(context));
|
||||
public static Loader<Cursor> createLoader(Context context, long accountId, long mailboxId) {
|
||||
return new AccountsLoader(context, accountId, mailboxId, UiUtilities.useTwoPane(context));
|
||||
}
|
||||
|
||||
public AccountSelectorAdapter(Context context) {
|
||||
|
@ -103,22 +112,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Invoked when the action bar needs the view of the text in the bar itself. The default
|
||||
* is to show just the display name of the cursor at the given position.
|
||||
*/
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if (!isAccountItem(position)) {
|
||||
// asked to show a recent mailbox; instead, show the account associated w/ the mailbox
|
||||
int newPosition = getAccountPosition(position);
|
||||
if (newPosition != UNKNOWN_POSITION) {
|
||||
position = newPosition;
|
||||
}
|
||||
}
|
||||
return super.getView(position, convertView, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* The account selector view can contain one of four types of row data:
|
||||
* <ol>
|
||||
* <li>headers</li>
|
||||
|
@ -132,26 +127,27 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
* mailboxes display an unread count; whereas "show all folders" does not. To determine
|
||||
* if a particular row is "show all folders" verify that a) it's not an account row and
|
||||
* b) it's ID is {@link Mailbox#NO_MAILBOX}.
|
||||
*
|
||||
* TODO Use recycled views. ({@link #getViewTypeCount} and {@link #getItemViewType})
|
||||
*/
|
||||
@Override
|
||||
public View getDropDownView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
Cursor c = getCursor();
|
||||
c.moveToPosition(position);
|
||||
|
||||
View view;
|
||||
if (c.getInt(c.getColumnIndex(ROW_TYPE)) == ROW_TYPE_HEADER) {
|
||||
view = mInflater.inflate(R.layout.account_selector_dropdown_header, parent, false);
|
||||
view = mInflater.inflate(R.layout.action_bar_spinner_dropdown_header, parent, false);
|
||||
final TextView displayNameView = (TextView) view.findViewById(R.id.display_name);
|
||||
final String displayName = getDisplayName(c);
|
||||
displayNameView.setText(displayName);
|
||||
} else {
|
||||
view = mInflater.inflate(R.layout.account_selector_dropdown, parent, false);
|
||||
view = mInflater.inflate(R.layout.action_bar_spinner_dropdown, parent, false);
|
||||
final TextView displayNameView = (TextView) view.findViewById(R.id.display_name);
|
||||
final TextView emailAddressView = (TextView) view.findViewById(R.id.email_address);
|
||||
final TextView unreadCountView = (TextView) view.findViewById(R.id.unread_count);
|
||||
|
||||
final String displayName = getDisplayName(position);
|
||||
final String emailAddress = getAccountEmailAddress(position);
|
||||
final String displayName = getDisplayName(c);
|
||||
final String emailAddress = getAccountEmailAddress(c);
|
||||
|
||||
displayNameView.setText(displayName);
|
||||
|
||||
|
@ -163,12 +159,12 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
emailAddressView.setText(emailAddress);
|
||||
}
|
||||
|
||||
boolean isAccount = isAccountItem(position);
|
||||
boolean isAccount = isAccountItem(c);
|
||||
long id = getId(c);
|
||||
if (isAccount || id != Mailbox.NO_MAILBOX) {
|
||||
unreadCountView.setVisibility(View.VISIBLE);
|
||||
unreadCountView.setText(UiUtilities.getMessageCountForUi(mContext,
|
||||
getAccountUnreadCount(position), true));
|
||||
getAccountUnreadCount(c), true));
|
||||
} else {
|
||||
unreadCountView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
@ -177,14 +173,13 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
TextView textView = (TextView) view.findViewById(R.id.display_name);
|
||||
textView.setText(getDisplayName(cursor));
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
return null; // we don't reuse views. This method never gets called.
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
return mInflater.inflate(R.layout.account_selector, parent, false);
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
// we don't reuse views. This method never gets called.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -209,6 +204,10 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
public boolean isAccountItem(int position) {
|
||||
Cursor c = getCursor();
|
||||
c.moveToPosition(position);
|
||||
return isAccountItem(c);
|
||||
}
|
||||
|
||||
public boolean isAccountItem(Cursor c) {
|
||||
return (c.getLong(c.getColumnIndex(ROW_TYPE)) == ROW_TYPE_ACCOUNT);
|
||||
}
|
||||
|
||||
|
@ -218,24 +217,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
return (c.getLong(c.getColumnIndex(ROW_TYPE)) == ROW_TYPE_MAILBOX);
|
||||
}
|
||||
|
||||
private String getDisplayName(int position) {
|
||||
final Cursor c = getCursor();
|
||||
return c.moveToPosition(position) ? getDisplayName(c) : null;
|
||||
}
|
||||
|
||||
private String getAccountEmailAddress(int position) {
|
||||
final Cursor c = getCursor();
|
||||
return c.moveToPosition(position) ? getAccountEmailAddress(c) : null;
|
||||
}
|
||||
|
||||
private int getAccountUnreadCount(int position) {
|
||||
final Cursor c = getCursor();
|
||||
return c.moveToPosition(position) ? getMessageCount(c) : 0;
|
||||
}
|
||||
|
||||
int getAccountPosition(int position) {
|
||||
final Cursor c = getCursor();
|
||||
return c.moveToPosition(position) ? getAccountPosition(c) : UNKNOWN_POSITION;
|
||||
private int getAccountUnreadCount(Cursor c) {
|
||||
return getMessageCount(c);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,6 +228,24 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
return c.getLong(c.getColumnIndex(EmailContent.RECORD_ID));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ID of the account / mailbox for a row
|
||||
*/
|
||||
public long getId(int position) {
|
||||
final Cursor c = getCursor();
|
||||
return c.moveToPosition(position) ? getId(c) : Account.NO_ACCOUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ID of the account for a row
|
||||
*/
|
||||
public long getAccountId(int position) {
|
||||
final Cursor c = getCursor();
|
||||
return c.moveToPosition(position)
|
||||
? c.getLong(c.getColumnIndex(ACCOUNT_ID))
|
||||
: Account.NO_ACCOUNT;
|
||||
}
|
||||
|
||||
/** Returns the account name extracted from the given cursor. */
|
||||
static String getDisplayName(Cursor cursor) {
|
||||
return cursor.getString(cursor.getColumnIndex(Account.DISPLAY_NAME));
|
||||
|
@ -263,9 +264,13 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
return cursor.getInt(cursor.getColumnIndex(MESSAGE_COUNT));
|
||||
}
|
||||
|
||||
/** Returns the account position extracted from the given cursor. */
|
||||
private static int getAccountPosition(Cursor cursor) {
|
||||
return cursor.getInt(cursor.getColumnIndex(ACCOUNT_POSITION));
|
||||
private static String sCombinedViewDisplayName;
|
||||
private static String getCombinedViewDisplayName(Context c) {
|
||||
if (sCombinedViewDisplayName == null) {
|
||||
sCombinedViewDisplayName = c.getResources().getString(
|
||||
R.string.mailbox_list_account_selector_combined_view);
|
||||
}
|
||||
return sCombinedViewDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,16 +283,18 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
static class AccountsLoader extends ThrottlingCursorLoader {
|
||||
private final Context mContext;
|
||||
private final long mAccountId;
|
||||
private final long mMailboxId;
|
||||
private final boolean mUseTwoPane; // Injectable for test
|
||||
private final FolderProperties mFolderProperties;
|
||||
|
||||
@VisibleForTesting
|
||||
AccountsLoader(Context context, long accountId, boolean useTwoPane) {
|
||||
AccountsLoader(Context context, long accountId, long mailboxId, boolean useTwoPane) {
|
||||
// Super class loads a regular account cursor, but we replace it in loadInBackground().
|
||||
super(context, Account.CONTENT_URI, ACCOUNT_PROJECTION, null, null,
|
||||
ORDER_BY);
|
||||
mContext = context;
|
||||
mAccountId = accountId;
|
||||
mMailboxId = mailboxId;
|
||||
mFolderProperties = FolderProperties.getInstance(mContext);
|
||||
mUseTwoPane = useTwoPane;
|
||||
}
|
||||
|
@ -300,17 +307,19 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
= new CursorWithExtras(ADAPTER_PROJECTION, accountsCursor);
|
||||
final int accountPosition = addAccountsToCursor(resultCursor, accountsCursor);
|
||||
addRecentsToCursor(resultCursor, accountPosition);
|
||||
return Utility.CloseTraceCursorWrapper.get(resultCursor);
|
||||
|
||||
resultCursor.setAccountMailboxInfo(getContext(), mAccountId, mMailboxId);
|
||||
return resultCursor;
|
||||
}
|
||||
|
||||
/** Adds the account list [with extra meta data] to the given matrix cursor */
|
||||
private int addAccountsToCursor(CursorWithExtras matrixCursor, Cursor accountCursor) {
|
||||
int accountPosition = UNKNOWN_POSITION;
|
||||
accountCursor.moveToPosition(-1);
|
||||
|
||||
// Add a header for the accounts
|
||||
String header =
|
||||
mContext.getString(R.string.mailbox_list_account_selector_account_header);
|
||||
addRow(matrixCursor, ROW_TYPE_HEADER, 0L, header, null, 0, UNKNOWN_POSITION);
|
||||
addHeaderRow(matrixCursor, mContext.getString(
|
||||
R.string.mailbox_list_account_selector_account_header));
|
||||
|
||||
matrixCursor.mAccountCount = accountCursor.getCount();
|
||||
int totalUnread = 0;
|
||||
|
@ -323,7 +332,7 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
final String name = getDisplayName(accountCursor);
|
||||
final String emailAddress = getAccountEmailAddress(accountCursor);
|
||||
addRow(matrixCursor, ROW_TYPE_ACCOUNT, accountId, name, emailAddress, unread,
|
||||
UNKNOWN_POSITION);
|
||||
UNKNOWN_POSITION, accountId);
|
||||
totalUnread += unread;
|
||||
if (accountId == mAccountId) {
|
||||
accountPosition = currentPosition;
|
||||
|
@ -333,12 +342,12 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
// Add "combined view" if more than one account exists
|
||||
final int countAccounts = accountCursor.getCount();
|
||||
if (countAccounts > 1) {
|
||||
final String name = mContext.getResources().getString(
|
||||
R.string.mailbox_list_account_selector_combined_view);
|
||||
final String accountCount = mContext.getResources().getQuantityString(
|
||||
R.plurals.number_of_accounts, countAccounts, countAccounts);
|
||||
addRow(matrixCursor, ROW_TYPE_ACCOUNT, Account.ACCOUNT_ID_COMBINED_VIEW,
|
||||
name, accountCount, totalUnread, UNKNOWN_POSITION);
|
||||
getCombinedViewDisplayName(mContext),
|
||||
accountCount, totalUnread, UNKNOWN_POSITION,
|
||||
Account.ACCOUNT_ID_COMBINED_VIEW);
|
||||
|
||||
// Increment the account count for the combined account.
|
||||
matrixCursor.mAccountCount++;
|
||||
|
@ -373,9 +382,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
|
||||
if (!mUseTwoPane) {
|
||||
// "Recent mailboxes" header
|
||||
String mailboxHeader = mContext.getString(
|
||||
R.string.mailbox_list_account_selector_mailbox_header_fmt, emailAddress);
|
||||
addRow(matrixCursor, ROW_TYPE_HEADER, 0L, mailboxHeader, null, 0, UNKNOWN_POSITION);
|
||||
addHeaderRow(matrixCursor, mContext.getString(
|
||||
R.string.mailbox_list_account_selector_mailbox_header_fmt, emailAddress));
|
||||
}
|
||||
|
||||
if (recentCount > 0) {
|
||||
|
@ -389,7 +397,7 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
String name = mContext.getString(
|
||||
R.string.mailbox_list_account_selector_show_all_folders);
|
||||
addRow(matrixCursor, ROW_TYPE_MAILBOX, Mailbox.NO_MAILBOX, name, null, 0,
|
||||
accountPosition);
|
||||
accountPosition, mAccountId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,33 +416,114 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
}
|
||||
addRow(matrixCursor, ROW_TYPE_MAILBOX, mailboxId,
|
||||
mFolderProperties.getDisplayName(c), null,
|
||||
mFolderProperties.getMessageCount(c), accountPosition);
|
||||
mFolderProperties.getMessageCount(c), accountPosition, mAccountId);
|
||||
}
|
||||
|
||||
private void addHeaderRow(MatrixCursor cursor, String name) {
|
||||
addRow(cursor, ROW_TYPE_HEADER, 0L, name, null, 0, UNKNOWN_POSITION,
|
||||
Account.NO_ACCOUNT);
|
||||
}
|
||||
|
||||
/** Adds a row to the given cursor */
|
||||
private void addRow(MatrixCursor cursor, int rowType, long id, String name,
|
||||
String emailAddress, int messageCount, int listPosition) {
|
||||
String emailAddress, int messageCount, int listPosition, long accountId) {
|
||||
cursor.newRow()
|
||||
.add(rowType)
|
||||
.add(id)
|
||||
.add(name)
|
||||
.add(emailAddress)
|
||||
.add(messageCount)
|
||||
.add(listPosition);
|
||||
.add(listPosition)
|
||||
.add(accountId);
|
||||
}
|
||||
}
|
||||
|
||||
/** Cursor with some extra meta data. */
|
||||
static class CursorWithExtras extends ClosingMatrixCursor {
|
||||
|
||||
/** Number of account elements, including the combined account row. */
|
||||
private int mAccountCount;
|
||||
/** Number of recent mailbox elements */
|
||||
private int mRecentCount;
|
||||
|
||||
private boolean mAccountExists;
|
||||
|
||||
/**
|
||||
* Account ID that's loaded.
|
||||
*/
|
||||
private long mAccountId;
|
||||
private String mAccountDisplayName;
|
||||
|
||||
/**
|
||||
* Mailbox ID that's loaded.
|
||||
*/
|
||||
private long mMailboxId;
|
||||
private String mMailboxDisplayName;
|
||||
private int mMailboxMessageCount;
|
||||
|
||||
private CursorWithExtras(String[] columnNames, Cursor innerCursor) {
|
||||
super(columnNames, innerCursor);
|
||||
}
|
||||
|
||||
private static final String[] ACCOUNT_INFO_PROJECTION = new String[] {
|
||||
AccountColumns.DISPLAY_NAME,
|
||||
};
|
||||
private static final String[] MAILBOX_INFO_PROJECTION = new String[] {
|
||||
MailboxColumns.ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE,
|
||||
MailboxColumns.UNREAD_COUNT, MailboxColumns.MESSAGE_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the current account/mailbox info.
|
||||
*/
|
||||
private void setAccountMailboxInfo(Context context, long accountId, long mailboxId) {
|
||||
mAccountId = accountId;
|
||||
mMailboxId = mailboxId;
|
||||
|
||||
// Get account info
|
||||
if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
|
||||
// We need to treat ACCOUNT_ID_COMBINED_VIEW specially...
|
||||
mAccountExists = true;
|
||||
mAccountDisplayName = getCombinedViewDisplayName(context);
|
||||
mMailboxDisplayName = FolderProperties.getInstance(context)
|
||||
.getCombinedMailboxName(mMailboxId);
|
||||
|
||||
// TODO Would be nicer to show message count for combined mailboxes too..
|
||||
mMailboxMessageCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
mAccountDisplayName = Utility.getFirstRowString(context,
|
||||
ContentUris.withAppendedId(Account.CONTENT_URI, accountId),
|
||||
ACCOUNT_INFO_PROJECTION, null, null, null, 0, null);
|
||||
if (mAccountDisplayName == null) {
|
||||
// Account gone!
|
||||
mAccountExists = false;
|
||||
return;
|
||||
}
|
||||
mAccountExists = true;
|
||||
|
||||
// If mailbox not specified, done.
|
||||
if (mMailboxId == Mailbox.NO_MAILBOX) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get mailbox info
|
||||
final ContentResolver r = context.getContentResolver();
|
||||
final Cursor mailboxCursor = r.query(
|
||||
ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
|
||||
MAILBOX_INFO_PROJECTION, null, null, null);
|
||||
try {
|
||||
if (mailboxCursor.moveToFirst()) {
|
||||
final FolderProperties fp = FolderProperties.getInstance(context);
|
||||
mMailboxDisplayName = fp.getDisplayName(mailboxCursor);
|
||||
mMailboxMessageCount = fp.getMessageCount(mailboxCursor);
|
||||
}
|
||||
} finally {
|
||||
mailboxCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cursor position of the item with the given ID. Or {@link #UNKNOWN_POSITION}
|
||||
* if the given ID does not exist.
|
||||
|
@ -456,5 +545,32 @@ public class AccountSelectorAdapter extends CursorAdapter {
|
|||
public int getRecentMailboxCount() {
|
||||
return mRecentCount;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return mAccountId;
|
||||
}
|
||||
|
||||
public String getAccountDisplayName() {
|
||||
return mAccountDisplayName;
|
||||
}
|
||||
|
||||
public long getMailboxId() {
|
||||
return mMailboxId;
|
||||
}
|
||||
|
||||
public String getMailboxDisplayName() {
|
||||
return mMailboxDisplayName;
|
||||
}
|
||||
|
||||
public int getMailboxMessageCount() {
|
||||
return mMailboxMessageCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the specified accuont exists.
|
||||
*/
|
||||
public boolean accountExists() {
|
||||
return mAccountExists;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,30 +16,29 @@
|
|||
|
||||
package com.android.email.activity;
|
||||
|
||||
import com.android.email.R;
|
||||
import com.android.emailcommon.provider.Account;
|
||||
import com.android.emailcommon.provider.Mailbox;
|
||||
import com.android.emailcommon.utility.Utility;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.LoaderManager;
|
||||
import android.app.LoaderManager.LoaderCallbacks;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ListPopupWindow;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.email.FolderProperties;
|
||||
import com.android.email.R;
|
||||
import com.android.email.data.ThrottlingCursorLoader;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.provider.Account;
|
||||
import com.android.emailcommon.provider.EmailContent;
|
||||
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
|
||||
import com.android.emailcommon.provider.Mailbox;
|
||||
|
||||
/**
|
||||
* Manages the account name and the custom view part on the action bar.
|
||||
*
|
||||
|
@ -68,25 +67,29 @@ public class ActionBarController {
|
|||
|
||||
private static final int LOADER_ID_ACCOUNT_LIST
|
||||
= EmailActivity.ACTION_BAR_CONTROLLER_LOADER_ID_BASE + 0;
|
||||
private static final int LOADER_ID_MAILBOX
|
||||
= EmailActivity.ACTION_BAR_CONTROLLER_LOADER_ID_BASE + 1;
|
||||
|
||||
private final Context mContext;
|
||||
private final LoaderManager mLoaderManager;
|
||||
private final ActionBar mActionBar;
|
||||
|
||||
/** "Folders" label shown with account name on 1-pane mailbox list */
|
||||
private final String mAllFoldersLabel;
|
||||
|
||||
private final View mActionBarCustomView;
|
||||
private final View mMailboxNameContainer;
|
||||
private final TextView mMailboxNameView;
|
||||
private final TextView mUnreadCountView;
|
||||
private final View mAccountSpinner;
|
||||
private final TextView mAccountSpinnerLine1View;
|
||||
private final TextView mAccountSpinnerLine2View;
|
||||
private final TextView mAccountSpinnerCountView;
|
||||
|
||||
private final View mSearchContainer;
|
||||
private final SearchView mSearchView;
|
||||
|
||||
private final ActionBarNavigationCallback mActionBarNavigationCallback =
|
||||
new ActionBarNavigationCallback();
|
||||
private final AccountDropdownPopup mAccountDropdown;
|
||||
|
||||
private final AccountSelectorAdapter mAccountsSelectorAdapter;
|
||||
private AccountSelectorAdapter.CursorWithExtras mAccountCursor;
|
||||
|
||||
private AccountSelectorAdapter.CursorWithExtras mCursor;
|
||||
|
||||
/** The current account ID; used to determine if the account has changed. */
|
||||
private long mLastAccountIdForDirtyCheck = Account.NO_ACCOUNT;
|
||||
|
||||
|
@ -103,6 +106,20 @@ public class ActionBarController {
|
|||
}
|
||||
|
||||
public interface Callback {
|
||||
/** Values for {@link #getTitleMode}. Show only account name */
|
||||
public static final int TITLE_MODE_ACCOUNT_NAME_ONLY = 0;
|
||||
/** Show the current account name with "Folders" */
|
||||
public static final int TITLE_MODE_ACCOUNT_WITH_ALL_FOLDERS_LABEL = 1;
|
||||
/** Show the current account name and the current mailbox name */
|
||||
public static final int TITLE_MODE_ACCOUNT_WITH_MAILBOX = 2;
|
||||
/**
|
||||
* Show the current message subject. Actual subject is obtained via
|
||||
* {@link #getMessageSubject()}.
|
||||
*
|
||||
* NOT IMPLEMENTED YET
|
||||
*/
|
||||
public static final int TITLE_MODE_MESSAGE_SUBJECT = 3;
|
||||
|
||||
/** @return true if an account is selected. */
|
||||
public boolean isAccountSelected();
|
||||
|
||||
|
@ -118,8 +135,13 @@ public class ActionBarController {
|
|||
*/
|
||||
public long getMailboxId();
|
||||
|
||||
/** @return true if the current mailbox name should be shown. */
|
||||
public boolean shouldShowMailboxName();
|
||||
/**
|
||||
* @return constants such as {@link #TITLE_MODE_ACCOUNT_NAME_ONLY}.
|
||||
*/
|
||||
public int getTitleMode();
|
||||
|
||||
/** @see #TITLE_MODE_MESSAGE_SUBJECT */
|
||||
public String getMessageSubject();
|
||||
|
||||
/** @return the "UP" arrow should be shown. */
|
||||
public boolean shouldShowUp();
|
||||
|
@ -132,10 +154,12 @@ public class ActionBarController {
|
|||
|
||||
/**
|
||||
* Invoked when a recent mailbox is selected on the account spinner.
|
||||
*
|
||||
* @param accountId ID of the selected account, or {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
|
||||
* @param mailboxId The ID of the selected mailbox, or {@link Mailbox#NO_MAILBOX} if the
|
||||
* special option "show all mailboxes" was selected.
|
||||
*/
|
||||
public void onMailboxSelected(long mailboxId);
|
||||
public void onMailboxSelected(long accountId, long mailboxId);
|
||||
|
||||
/** Called when no accounts are found in the database. */
|
||||
public void onNoAccountsFound();
|
||||
|
@ -159,42 +183,58 @@ public class ActionBarController {
|
|||
mLoaderManager = loaderManager;
|
||||
mActionBar = actionBar;
|
||||
mCallback = callback;
|
||||
mAllFoldersLabel = mContext.getResources().getString(
|
||||
R.string.action_bar_mailbox_list_title);
|
||||
mAccountsSelectorAdapter = new AccountSelectorAdapter(mContext);
|
||||
|
||||
mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE
|
||||
| ActionBar.DISPLAY_SHOW_HOME
|
||||
| ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
// Configure action bar.
|
||||
mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
|
||||
// Prepare the custom view
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
mActionBarCustomView = inflater.inflate(R.layout.action_bar_custom_view, null);
|
||||
final ActionBar.LayoutParams customViewLayout = new ActionBar.LayoutParams(
|
||||
ActionBar.LayoutParams.MATCH_PARENT,
|
||||
ActionBar.LayoutParams.WRAP_CONTENT,
|
||||
ActionBar.LayoutParams.MATCH_PARENT);
|
||||
customViewLayout.setMargins(0 , 0, 0, 0);
|
||||
customViewLayout.setMargins(0, 0, 0, 0);
|
||||
mActionBar.setCustomView(mActionBarCustomView, customViewLayout);
|
||||
|
||||
// Mailbox name / unread count
|
||||
mMailboxNameContainer = UiUtilities.getView(mActionBarCustomView,
|
||||
R.id.current_mailbox_container);
|
||||
mMailboxNameView = UiUtilities.getView(mMailboxNameContainer, R.id.mailbox_name);
|
||||
mUnreadCountView = UiUtilities.getView(mMailboxNameContainer, R.id.unread_count);
|
||||
// Account spinner
|
||||
mAccountSpinner = UiUtilities.getView(mActionBarCustomView, R.id.account_spinner);
|
||||
|
||||
mAccountSpinnerLine1View = UiUtilities.getView(mActionBarCustomView, R.id.spinner_line_1);
|
||||
mAccountSpinnerLine2View = UiUtilities.getView(mActionBarCustomView, R.id.spinner_line_2);
|
||||
mAccountSpinnerCountView = UiUtilities.getView(mActionBarCustomView, R.id.spinner_count);
|
||||
|
||||
// Search
|
||||
mSearchContainer = UiUtilities.getView(mActionBarCustomView, R.id.search_container);
|
||||
mSearchView = UiUtilities.getView(mSearchContainer, R.id.search_view);
|
||||
mSearchView.setSubmitButtonEnabled(true);
|
||||
mSearchView.setOnQueryTextListener(mOnQueryText);
|
||||
|
||||
// Account dropdown
|
||||
mAccountDropdown = new AccountDropdownPopup(mContext);
|
||||
mAccountDropdown.setAdapter(mAccountsSelectorAdapter);
|
||||
|
||||
mAccountSpinner.setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if (mAccountsSelectorAdapter.getCount() > 0) {
|
||||
mAccountDropdown.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Must be called from {@link UIControllerBase#onActivityCreated()} */
|
||||
public void onActivityCreated() {
|
||||
loadAccounts();
|
||||
refresh();
|
||||
}
|
||||
|
||||
/** Must be called from {@link UIControllerBase#onActivityDestroy()} */
|
||||
public void onActivityDestroy() {
|
||||
if (mAccountDropdown.isShowing()) {
|
||||
mAccountDropdown.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/** Must be called from {@link UIControllerBase#onSaveInstanceState} */
|
||||
|
@ -234,11 +274,6 @@ public class ActionBarController {
|
|||
}
|
||||
mSearchMode = MODE_SEARCH;
|
||||
|
||||
// Need to force it to mode "standard" to hide it.
|
||||
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
mActionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
|
||||
mSearchContainer.setVisibility(View.VISIBLE);
|
||||
|
||||
// Focus on the search input box and throw up the IME if specified.
|
||||
// TODO: HACK. this is a workaround IME not popping up.
|
||||
mSearchView.setIconified(false);
|
||||
|
@ -251,11 +286,6 @@ public class ActionBarController {
|
|||
return;
|
||||
}
|
||||
mSearchMode = MODE_NORMAL;
|
||||
mSearchContainer.setVisibility(View.GONE);
|
||||
mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
|
||||
|
||||
// Force update of account list when we exit search.
|
||||
updateAccountList();
|
||||
|
||||
refresh();
|
||||
mCallback.onSearchExit();
|
||||
|
@ -277,187 +307,141 @@ public class ActionBarController {
|
|||
|
||||
/** Refreshes the action bar display. */
|
||||
public void refresh() {
|
||||
// The actual work is in refreshInernal(), but we don't call it directly here, because:
|
||||
// 1. refresh() is called very often.
|
||||
// 2. to avoid nested fragment transaction.
|
||||
// refresh is often called during a fragment transaction, but updateTitle() may call
|
||||
// a callback which would initiate another fragment transaction.
|
||||
final Handler h = Utility.getMainThreadHandler();
|
||||
h.removeCallbacks(mRefreshRunnable);
|
||||
h.post(mRefreshRunnable);
|
||||
}
|
||||
|
||||
private final Runnable mRefreshRunnable = new Runnable() {
|
||||
@Override public void run() {
|
||||
refreshInernal();
|
||||
}
|
||||
};
|
||||
private void refreshInernal() {
|
||||
final boolean showUp = isInSearchMode() || mCallback.shouldShowUp();
|
||||
mActionBar.setDisplayOptions(showUp
|
||||
? ActionBar.DISPLAY_HOME_AS_UP : 0, ActionBar.DISPLAY_HOME_AS_UP);
|
||||
|
||||
if (isInSearchMode()) {
|
||||
mMailboxNameContainer.setVisibility(View.GONE);
|
||||
} else {
|
||||
mMailboxNameContainer.setVisibility(mCallback.shouldShowMailboxName()
|
||||
? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
// Update the account list only when the account has changed.
|
||||
if (mLastAccountIdForDirtyCheck != mCallback.getUIAccountId()) {
|
||||
mLastAccountIdForDirtyCheck = mCallback.getUIAccountId();
|
||||
// If the selected account changes, reload the cursor to update the recent mailboxes
|
||||
if (mLastAccountIdForDirtyCheck != Account.NO_ACCOUNT) {
|
||||
mLoaderManager.destroyLoader(LOADER_ID_ACCOUNT_LIST);
|
||||
loadAccounts();
|
||||
} else {
|
||||
updateAccountList();
|
||||
}
|
||||
}
|
||||
|
||||
// Update current mailbox info
|
||||
final long accountId = mCallback.getUIAccountId();
|
||||
final long mailboxId = mCallback.getMailboxId();
|
||||
if (mailboxId == Mailbox.NO_MAILBOX) {
|
||||
clearMailboxInfo();
|
||||
} else {
|
||||
if (mLastMailboxIdForDirtyCheck != mailboxId) {
|
||||
mLastMailboxIdForDirtyCheck = mailboxId;
|
||||
loadMailboxInfo(mailboxId);
|
||||
if ((mLastAccountIdForDirtyCheck != accountId)
|
||||
|| (mLastMailboxIdForDirtyCheck != mailboxId)) {
|
||||
mLastAccountIdForDirtyCheck = accountId;
|
||||
mLastMailboxIdForDirtyCheck = mailboxId;
|
||||
|
||||
if (accountId != Account.NO_ACCOUNT) {
|
||||
loadAccountMailboxInfo(accountId, mailboxId);
|
||||
}
|
||||
}
|
||||
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load account cursor, and update the action bar.
|
||||
* Load account/mailbox info, and account/recent mailbox list.
|
||||
*/
|
||||
private void loadAccounts() {
|
||||
mLoaderManager.initLoader(LOADER_ID_ACCOUNT_LIST, null,
|
||||
private void loadAccountMailboxInfo(final long accountId, final long mailboxId) {
|
||||
mLoaderManager.restartLoader(LOADER_ID_ACCOUNT_LIST, null,
|
||||
new LoaderCallbacks<Cursor>() {
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
return AccountSelectorAdapter.createLoader(mContext, mCallback.getUIAccountId());
|
||||
return AccountSelectorAdapter.createLoader(mContext, accountId, mailboxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
||||
mAccountCursor = (AccountSelectorAdapter.CursorWithExtras) data;
|
||||
updateAccountList();
|
||||
mCursor = (AccountSelectorAdapter.CursorWithExtras) data;
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
mAccountCursor = null;
|
||||
updateAccountList();
|
||||
mCursor = null;
|
||||
updateTitle();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the LOADER_ID_ACCOUNT_LIST loader loads the data. Update the account spinner
|
||||
* on the action bar.
|
||||
* Update the "title" part.
|
||||
*/
|
||||
private void updateAccountList() {
|
||||
mAccountsSelectorAdapter.swapCursor(mAccountCursor);
|
||||
private void updateTitle() {
|
||||
mAccountsSelectorAdapter.swapCursor(mCursor);
|
||||
|
||||
if (mSearchMode == MODE_SEARCH) {
|
||||
// In search mode, so we don't care about the account list - it'll get updated when
|
||||
// it goes visible again.
|
||||
if (mCursor == null) {
|
||||
// Initial load not finished.
|
||||
mActionBarCustomView.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
mActionBarCustomView.setVisibility(View.VISIBLE);
|
||||
|
||||
final ActionBar ab = mActionBar;
|
||||
if (mAccountCursor == null) {
|
||||
// Cursor not ready or closed.
|
||||
ab.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
|
||||
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
return;
|
||||
}
|
||||
|
||||
final int count = mAccountCursor.getAccountCount() + mAccountCursor.getRecentMailboxCount();
|
||||
if (count == 0) {
|
||||
if (mCursor.getAccountCount() == 0) {
|
||||
mCallback.onNoAccountsFound();
|
||||
return;
|
||||
}
|
||||
|
||||
// If only one account, don't show the drop down.
|
||||
int selectedPosition = mAccountCursor.getPosition(mCallback.getUIAccountId());
|
||||
if (count == 1) {
|
||||
// Show the account name as the title.
|
||||
ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
|
||||
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
if (selectedPosition >= 0) {
|
||||
mAccountCursor.moveToPosition(selectedPosition);
|
||||
ab.setTitle(AccountSelectorAdapter.getDisplayName(mAccountCursor));
|
||||
}
|
||||
if ((mCursor.getAccountId() != Account.NO_ACCOUNT) && !mCursor.accountExists()) {
|
||||
// Accoutn specified, but not exists. Switch to the default account.
|
||||
mCallback.onAccountSelected(Account.getDefaultAccountId(mContext));
|
||||
|
||||
// STOPSHIP If in search mode, we should close the activity. Probably
|
||||
// we should jsut call onSearchExit() instead?
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the drop down list.
|
||||
if (ab.getNavigationMode() != ActionBar.NAVIGATION_MODE_LIST) {
|
||||
ab.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
|
||||
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
|
||||
ab.setListNavigationCallbacks(mAccountsSelectorAdapter, mActionBarNavigationCallback);
|
||||
if (mSearchMode == MODE_SEARCH) {
|
||||
// In search mode, so we don't care about the account list - it'll get updated when
|
||||
// it goes visible again.
|
||||
mAccountSpinner.setVisibility(View.GONE);
|
||||
mSearchContainer.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
// Find the currently selected account, and select it.
|
||||
if (selectedPosition >= 0) {
|
||||
ab.setSelectedNavigationItem(selectedPosition);
|
||||
|
||||
final int mTitleMode = mCallback.getTitleMode();
|
||||
|
||||
// TODO Handle TITLE_MODE_MESSAGE_SUBJECT
|
||||
|
||||
// Account spinner visible.
|
||||
mAccountSpinner.setVisibility(View.VISIBLE);
|
||||
mSearchContainer.setVisibility(View.GONE);
|
||||
|
||||
// Get mailbox name
|
||||
final String mailboxName;
|
||||
if (mTitleMode == Callback.TITLE_MODE_ACCOUNT_WITH_ALL_FOLDERS_LABEL) {
|
||||
mailboxName = mAllFoldersLabel;
|
||||
} else if (mTitleMode == Callback.TITLE_MODE_ACCOUNT_WITH_MAILBOX) {
|
||||
mailboxName = mCursor.getMailboxDisplayName();
|
||||
} else {
|
||||
mailboxName = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class ActionBarNavigationCallback implements ActionBar.OnNavigationListener {
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
|
||||
if (mAccountsSelectorAdapter.isAccountItem(itemPosition)
|
||||
&& itemId != mCallback.getUIAccountId()) {
|
||||
mCallback.onAccountSelected(itemId);
|
||||
} else if (mAccountsSelectorAdapter.isMailboxItem(itemPosition)) {
|
||||
mCallback.onMailboxSelected(itemId);
|
||||
// We need to update the selection, otherwise the user is unable to select the
|
||||
// recent folder a second time w/o first selecting another item in the spinner
|
||||
int selectedPosition = mAccountsSelectorAdapter.getAccountPosition(itemPosition);
|
||||
if (selectedPosition != AccountSelectorAdapter.UNKNOWN_POSITION) {
|
||||
mActionBar.setSelectedNavigationItem(selectedPosition);
|
||||
}
|
||||
} else {
|
||||
Log.i(Logging.LOG_TAG,
|
||||
"Invalid type selected in ActionBarController at index " + itemPosition);
|
||||
}
|
||||
return true;
|
||||
if (TextUtils.isEmpty(mailboxName)) {
|
||||
mAccountSpinnerLine1View.setText(mCursor.getAccountDisplayName());
|
||||
|
||||
// Only here we change the visibility of line 2, so line 1 will be vertically-centered.
|
||||
mAccountSpinnerLine2View.setVisibility(View.GONE);
|
||||
} else {
|
||||
mAccountSpinnerLine1View.setText(mailboxName);
|
||||
mAccountSpinnerLine2View.setVisibility(View.VISIBLE); // Make sure it's visible again.
|
||||
mAccountSpinnerLine2View.setText(mCursor.getAccountDisplayName());
|
||||
}
|
||||
}
|
||||
mAccountSpinnerCountView.setText(UiUtilities.getMessageCountForUi(
|
||||
mContext, mCursor.getMailboxMessageCount(), true));
|
||||
|
||||
private static final String[] MAILBOX_NAME_COUNT_PROJECTION = new String[] {
|
||||
MailboxColumns.ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE,
|
||||
MailboxColumns.UNREAD_COUNT, MailboxColumns.MESSAGE_COUNT
|
||||
};
|
||||
boolean spinnerEnabled = (mCursor.getAccountCount() + mCursor.getRecentMailboxCount()) > 1;
|
||||
|
||||
private void loadMailboxInfo(final long mailboxId) {
|
||||
clearMailboxInfo();
|
||||
if (mailboxId < 0) {
|
||||
// TODO FIXME
|
||||
return; // Can't get combined mailbox name with this
|
||||
if (spinnerEnabled) {
|
||||
mAccountSpinner.setClickable(true);
|
||||
} else {
|
||||
mAccountSpinner.setClickable(false);
|
||||
// TODO There's nothing to select -- we should remove the spinner triangle.
|
||||
// (The small triangle shown at the right bottom corner)
|
||||
}
|
||||
mLoaderManager.restartLoader(LOADER_ID_MAILBOX, null,
|
||||
new LoaderCallbacks<Cursor>() {
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
return new ThrottlingCursorLoader(mContext,
|
||||
ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
|
||||
MAILBOX_NAME_COUNT_PROJECTION, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
if (!cursor.moveToFirst()) {
|
||||
clearMailboxInfo();
|
||||
return;
|
||||
}
|
||||
// Update action bar
|
||||
FolderProperties fp = FolderProperties.getInstance(mContext);
|
||||
updateMailboxInfo(
|
||||
fp.getDisplayName(cursor),
|
||||
fp.getMessageCount(cursor)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearMailboxInfo() {
|
||||
updateMailboxInfo("", 0);
|
||||
}
|
||||
|
||||
private void updateMailboxInfo(String mailboxName, int count) {
|
||||
mMailboxNameView.setText(mailboxName);
|
||||
mUnreadCountView.setText(UiUtilities.getMessageCountForUi(mContext, count, true));
|
||||
}
|
||||
|
||||
private final SearchView.OnQueryTextListener mOnQueryText
|
||||
|
@ -475,4 +459,44 @@ public class ActionBarController {
|
|||
}
|
||||
};
|
||||
|
||||
private void onAccountSpinnerItemClicked(int position) {
|
||||
if (mAccountsSelectorAdapter == null) { // just in case...
|
||||
return;
|
||||
}
|
||||
final long accountId = mAccountsSelectorAdapter.getAccountId(position);
|
||||
|
||||
if (mAccountsSelectorAdapter.isAccountItem(position)) {
|
||||
mCallback.onAccountSelected(accountId);
|
||||
} else if (mAccountsSelectorAdapter.isMailboxItem(position)) {
|
||||
mCallback.onMailboxSelected(accountId,
|
||||
mAccountsSelectorAdapter.getId(position));
|
||||
}
|
||||
}
|
||||
|
||||
// Based on Spinner.DropdownPopup
|
||||
private class AccountDropdownPopup extends ListPopupWindow {
|
||||
public AccountDropdownPopup(Context context) {
|
||||
super(context);
|
||||
|
||||
setAnchorView(mAccountSpinner);
|
||||
setModal(true);
|
||||
setPromptPosition(POSITION_PROMPT_ABOVE);
|
||||
setOnItemClickListener(new OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
|
||||
onAccountSpinnerItemClicked(position);
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
setWidth(mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.account_spinner_dropdown_width));
|
||||
setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
|
||||
super.show();
|
||||
// List view is instantiated in super.show(), so we need to do this after...
|
||||
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,6 +190,11 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
private long mParentMailboxId;
|
||||
private long mHighlightedMailboxId;
|
||||
|
||||
/**
|
||||
* Becomes {@code true} once we determine which mailbox to use as the parent.
|
||||
*/
|
||||
private boolean mParentDetermined;
|
||||
|
||||
/**
|
||||
* ID of the mailbox that should be highlighted when the next cursor is loaded.
|
||||
*/
|
||||
|
@ -551,7 +556,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
/**
|
||||
* @return {@code true} if top-level mailboxes are shown. {@code false} otherwise.
|
||||
*/
|
||||
public boolean isRoot() {
|
||||
private boolean isRoot() {
|
||||
return mParentMailboxId == Mailbox.NO_MAILBOX;
|
||||
}
|
||||
|
||||
|
@ -580,6 +585,19 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the fragment is showing nested mailboxes and we can go one level up.
|
||||
* {@code false} otherwise, meaning we're showing the top level mailboxes *OR*
|
||||
* we're still loading initial data and we can't determine if we're going to show
|
||||
* top-level or not.
|
||||
*/
|
||||
public boolean canNavigateUp() {
|
||||
if (!mParentDetermined) {
|
||||
return false; // We can't determine yet...
|
||||
}
|
||||
return !isRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* A task to determine what parent mailbox ID/highlighted mailbox ID to use for the "UP"
|
||||
* navigation, given the current parent mailbox ID, the highlighted mailbox ID, and {@link
|
||||
|
@ -781,6 +799,8 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
mListAdapter.swapCursor(null);
|
||||
setListShown(false);
|
||||
} else {
|
||||
mParentDetermined = true; // Okay now we're sure which mailbox is the parent.
|
||||
|
||||
mListAdapter.swapCursor(cursor);
|
||||
setListShown(true);
|
||||
|
||||
|
|
|
@ -431,12 +431,12 @@ abstract class UIControllerBase implements MailboxListFragment.Callback,
|
|||
/**
|
||||
* Show the default view for the given account.
|
||||
*
|
||||
* No-op if the given account is already selected.
|
||||
*
|
||||
* @param accountId ID of the account to load. Can be {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
|
||||
* Must never be {@link Account#NO_ACCOUNT}.
|
||||
* @param forceShowInbox If {@code false} and the given account is already selected, do nothing.
|
||||
* If {@code false}, we always change the view even if the account is selected.
|
||||
*/
|
||||
public final void switchAccount(long accountId) {
|
||||
public final void switchAccount(long accountId, boolean forceShowInbox) {
|
||||
|
||||
if (Account.isSecurityHold(mActivity, accountId)) {
|
||||
ActivityHelper.showSecurityHoldDialog(mActivity, accountId);
|
||||
|
@ -444,7 +444,7 @@ abstract class UIControllerBase implements MailboxListFragment.Callback,
|
|||
return;
|
||||
}
|
||||
|
||||
if (accountId == getUIAccountId()) {
|
||||
if (accountId == getUIAccountId() && !forceShowInbox) {
|
||||
// Do nothing if the account is already selected. Not even going back to the inbox.
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,9 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
// MailboxListFragment.Callback
|
||||
@Override
|
||||
public void onAccountSelected(long accountId) {
|
||||
switchAccount(accountId);
|
||||
// It's from combined view, so "forceShowInbox" doesn't really matter.
|
||||
// (We're always switching accounts.)
|
||||
switchAccount(accountId, true);
|
||||
}
|
||||
|
||||
// MailboxListFragment.Callback
|
||||
|
@ -94,7 +96,7 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public void onMailboxNotFound() {
|
||||
switchAccount(getUIAccountId());
|
||||
switchAccount(getUIAccountId(), true);
|
||||
}
|
||||
|
||||
// MessageListFragment.Callback
|
||||
|
@ -202,15 +204,26 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
// This is all temporary as we'll have a different action bar controller for 1-pane.
|
||||
private class ActionBarControllerCallback implements ActionBarController.Callback {
|
||||
@Override
|
||||
public boolean shouldShowMailboxName() {
|
||||
return false; // no mailbox name/unread count.
|
||||
public int getTitleMode() {
|
||||
if (isMailboxListInstalled()) {
|
||||
return TITLE_MODE_ACCOUNT_WITH_ALL_FOLDERS_LABEL;
|
||||
}
|
||||
// TODO Return TITLE_MODE_MESSAGE_SUBJECT if isMessageViewInstalled()
|
||||
return TITLE_MODE_ACCOUNT_WITH_MAILBOX;
|
||||
}
|
||||
|
||||
public String getMessageSubject() {
|
||||
if (isMessageViewInstalled()) {
|
||||
return "TODO: Return current message subject here";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowUp() {
|
||||
return isMessageViewInstalled()
|
||||
|| (isMailboxListInstalled() && !getMailboxListFragment().isRoot());
|
||||
|| (isMailboxListInstalled() && getMailboxListFragment().canNavigateUp());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -224,11 +237,11 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMailboxSelected(long mailboxId) {
|
||||
public void onMailboxSelected(long accountId, long mailboxId) {
|
||||
if (mailboxId == Mailbox.NO_MAILBOX) {
|
||||
showAllMailboxes();
|
||||
} else {
|
||||
openMailbox(getUIAccountId(), mailboxId);
|
||||
openMailbox(accountId, mailboxId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +252,7 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
|
||||
@Override
|
||||
public void onAccountSelected(long accountId) {
|
||||
switchAccount(accountId);
|
||||
switchAccount(accountId, true); // Always go to inbox
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -434,7 +447,8 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
*/
|
||||
private void commitFragmentTransaction(FragmentTransaction ft) {
|
||||
if (!ft.isEmpty()) {
|
||||
ft.commit();
|
||||
// STOPSHIP Don't use AllowingStateLoss. See b/4519430
|
||||
ft.commitAllowingStateLoss();
|
||||
mFragmentManager.executePendingTransactions();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,10 +44,7 @@ import java.util.Set;
|
|||
* so that we can easily switch between synchronous and asynchronous transactions.
|
||||
*/
|
||||
class UIControllerTwoPane extends UIControllerBase implements
|
||||
ThreePaneLayout.Callback,
|
||||
MailboxListFragment.Callback,
|
||||
MessageListFragment.Callback,
|
||||
MessageViewFragment.Callback {
|
||||
ThreePaneLayout.Callback {
|
||||
@VisibleForTesting
|
||||
static final int MAILBOX_REFRESH_MIN_INTERVAL = 30 * 1000; // in milliseconds
|
||||
|
||||
|
@ -75,8 +72,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
// ThreePaneLayoutCallback
|
||||
@Override
|
||||
public void onVisiblePanesChanged(int previousVisiblePanes) {
|
||||
refreshActionBar();
|
||||
|
||||
// If the right pane is gone, remove the message view.
|
||||
final int visiblePanes = mThreePane.getVisiblePanes();
|
||||
|
||||
|
@ -89,6 +84,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
if (isMessageListInstalled()) {
|
||||
getMessageListFragment().onHidden((visiblePanes & ThreePaneLayout.PANE_MIDDLE) == 0);
|
||||
}
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
// MailboxListFragment$Callback
|
||||
|
@ -103,7 +99,9 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
// MailboxListFragment$Callback
|
||||
@Override
|
||||
public void onAccountSelected(long accountId) {
|
||||
switchAccount(accountId);
|
||||
// It's from combined view, so "forceShowInbox" doesn't really matter.
|
||||
// (We're always switching accounts.)
|
||||
switchAccount(accountId, true);
|
||||
}
|
||||
|
||||
// MailboxListFragment$Callback
|
||||
|
@ -427,7 +425,8 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
Log.d(Logging.LOG_TAG, this + " commitFragmentTransaction: " + ft);
|
||||
}
|
||||
if (!ft.isEmpty()) {
|
||||
ft.commit();
|
||||
// STOPSHIP Don't use AllowingStateLoss. See b/4519430
|
||||
ft.commitAllowingStateLoss();
|
||||
mFragmentManager.executePendingTransactions();
|
||||
}
|
||||
}
|
||||
|
@ -818,12 +817,12 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
|
||||
@Override
|
||||
public void onAccountSelected(long accountId) {
|
||||
switchAccount(accountId);
|
||||
switchAccount(accountId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMailboxSelected(long mailboxId) {
|
||||
openMailbox(getUIAccountId(), mailboxId);
|
||||
public void onMailboxSelected(long accountId, long mailboxId) {
|
||||
openMailbox(accountId, mailboxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -833,9 +832,32 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowMailboxName() {
|
||||
// Show when the left pane is hidden.
|
||||
return (mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_LEFT) == 0;
|
||||
public int getTitleMode() {
|
||||
final int visiblePanes = mThreePane.getVisiblePanes();
|
||||
if ((mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_LEFT) != 0) {
|
||||
// Mailbox list visible
|
||||
return TITLE_MODE_ACCOUNT_NAME_ONLY;
|
||||
}
|
||||
if ((mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_MIDDLE) != 0) {
|
||||
// Message list + message view
|
||||
return TITLE_MODE_ACCOUNT_WITH_MAILBOX;
|
||||
}
|
||||
if ((mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_RIGHT) != 0) {
|
||||
// Message view only (message list collapsed)
|
||||
// TODO return TITLE_MODE_MESSAGE_SUBJECT
|
||||
return TITLE_MODE_ACCOUNT_WITH_MAILBOX;
|
||||
}
|
||||
|
||||
// Shouldn't happen, but just in case
|
||||
return TITLE_MODE_ACCOUNT_NAME_ONLY;
|
||||
}
|
||||
|
||||
public String getMessageSubject() {
|
||||
if (isMessageViewInstalled()) {
|
||||
return "TODO: Return current message subject here";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -843,7 +865,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
final int visiblePanes = mThreePane.getVisiblePanes();
|
||||
final boolean leftPaneHidden = ((visiblePanes & ThreePaneLayout.PANE_LEFT) == 0);
|
||||
return leftPaneHidden
|
||||
|| (isMailboxListInstalled() && !getMailboxListFragment().isRoot());
|
||||
|| (isMailboxListInstalled() && getMailboxListFragment().canNavigateUp());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -52,7 +52,7 @@ public class AccountSelectorAdapterAccountsLoaderTest extends LoaderTestCase {
|
|||
{
|
||||
// Only 1 account -- no combined view row.
|
||||
Loader<Cursor> l = new AccountSelectorAdapter.AccountsLoader(mProviderContext, 0L,
|
||||
true);
|
||||
0L, true);
|
||||
AccountSelectorAdapter.CursorWithExtras result =
|
||||
(AccountSelectorAdapter.CursorWithExtras) getLoaderResultSynchronously(l);
|
||||
assertEquals(1, result.getAccountCount());
|
||||
|
@ -64,7 +64,7 @@ public class AccountSelectorAdapterAccountsLoaderTest extends LoaderTestCase {
|
|||
{
|
||||
// 2 accounts -- with combined view row, so returns 3 account rows.
|
||||
Loader<Cursor> l = new AccountSelectorAdapter.AccountsLoader(mProviderContext, 0L,
|
||||
true);
|
||||
0L, true);
|
||||
AccountSelectorAdapter.CursorWithExtras result =
|
||||
(AccountSelectorAdapter.CursorWithExtras) getLoaderResultSynchronously(l);
|
||||
assertEquals(3, result.getAccountCount());
|
||||
|
|
Loading…
Reference in New Issue