Merge "Hookup search in the UI."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0259a28..6641114 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -33,6 +33,9 @@
android:icon="@mipmap/ic_launcher_mail"
android:label="@string/app_name"
android:theme="@style/UnifiedEmailTheme" >
+ <!-- Enable search in all activities -->
+ <meta-data android:name="android.app.default_searchable"
+ android:value=".ui.MailActivity" />
<!-- TODO: add a permission on this -->
<activity
android:label="@string/app_name"
@@ -48,6 +51,11 @@
<data android:scheme="content"/>
<data android:mimeType="application/mail-ls" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.SEARCH" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
</activity>
<activity android:name=".compose.ComposeActivity">
<intent-filter>
diff --git a/res/layout-sw600dp/actionbar_view.xml b/res/layout-sw600dp/actionbar_view.xml
index 3a4f37d..ef66230 100644
--- a/res/layout-sw600dp/actionbar_view.xml
+++ b/res/layout-sw600dp/actionbar_view.xml
@@ -16,7 +16,7 @@
limitations under the License.
-->
-<com.android.mail.ui.MailActionBar
+<com.android.mail.ui.ActionBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:email="http://schemas.android.com/apk/res/com.android.mail"
android:orientation="horizontal"
@@ -30,4 +30,4 @@
<include layout="@layout/actionbar_subject" />
-</com.android.mail.ui.MailActionBar>
+</com.android.mail.ui.ActionBarView>
diff --git a/res/layout/actionbar_view.xml b/res/layout/actionbar_view.xml
index 4d658c0..eae0e18 100644
--- a/res/layout/actionbar_view.xml
+++ b/res/layout/actionbar_view.xml
@@ -20,7 +20,7 @@
The custom action bar view Gmail uses (containing drop down account spinner,
label, and subject).
-->
-<com.android.mail.ui.MailActionBar xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.mail.ui.ActionBarView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:email="http://schemas.android.com/apk/res/com.android.mail"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -30,4 +30,4 @@
<include layout="@layout/actionbar_subject" />
-</com.android.mail.ui.MailActionBar>
+</com.android.mail.ui.ActionBarView>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 85adc73..b9b6b60 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -201,9 +201,6 @@
<!-- Attachment description for unknown files [CHAR LIMIT=30]-->
<string name="attachment_unknown"><xliff:g id="attachmentExtension">%s</xliff:g> File</string>
- <!-- Shown in light gray in the Search box when no text has been entered [CHAR LIMIT=30] -->
- <string name="search_hint">Search mail</string>
-
<!-- Webview Context Menu Strings -->
<!-- Title of dialog for choosing which activity to share a link with. [CHAR LIMIT=50]-->
<string name="choosertitle_sharevia">Share via</string>
@@ -513,7 +510,6 @@
</plurals>
<!-- Manage folders mode, sync option: don't synchronize any conversation with this folder [CHAR LIMIT=100] -->
<string name="sync_none">Sync: None</string>
-
<!-- Title for dialog encouraging users enable sync for a currently non-synced folder [CHAR LIMIT=30] -->
<string name="folder_sync_for_widget_title">Sync folder</string>
@@ -526,4 +522,12 @@
<!-- Folder selection dialog -->
<!-- Title for change folders dialog [CHAR LIMIT=30] -->
<string name="folder_selection_dialog_title">Change folders</string>
+
+ <!-- Search -->
+ <!-- Title of the search dialog -->
+ <string name="search_title" translatable="false">Unified Email</string>
+ <!-- Shown in light gray in the Search box when no text has been entered [CHAR LIMIT=20]-->
+ <string name="search_hint">Search mail</string>
+ <!-- Search Results: Text for status of the search when the results are completely loaded [CHAR LIMIT=10] -->
+ <string name="search_results_loaded"><xliff:g id="searchCount">%1$d</xliff:g></string>
</resources>
diff --git a/res/xml/searchable.xml b/res/xml/searchable.xml
new file mode 100644
index 0000000..66a07c2
--- /dev/null
+++ b/res/xml/searchable.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<searchable xmlns:android="http://schemas.android.com/apk/res/android"
+ android:label="@string/search_title"
+ android:hint="@string/search_hint"
+ android:icon="@drawable/ic_menu_search_holo_light"
+ android:searchSuggestIntentAction="android.intent.action.SEARCH"
+ android:imeOptions="actionSearch"
+ android:searchSuggestSelection="query LIKE ?" />
diff --git a/src/com/android/mail/ConversationListContext.java b/src/com/android/mail/ConversationListContext.java
index fa6bbb0..0bda52e 100644
--- a/src/com/android/mail/ConversationListContext.java
+++ b/src/com/android/mail/ConversationListContext.java
@@ -23,10 +23,14 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.text.TextUtils;
+
import com.android.mail.providers.Account;
import com.android.mail.providers.Folder;
import com.android.mail.providers.Settings;
import com.android.mail.providers.UIProvider;
+import com.android.mail.utils.Utils;
+import com.google.common.base.Preconditions;
import java.util.ArrayList;
@@ -43,7 +47,7 @@
public class ConversationListContext {
private static final String EXTRA_ACCOUNT = "account";
public static final String EXTRA_FOLDER = "folder";
- private static final String EXTRA_SEARCH_QUERY = "query";
+ public static final String EXTRA_SEARCH_QUERY = "query";
/**
* A matcher for data URI's that specify conversation list info.
@@ -125,36 +129,11 @@
}
/**
- * Resolves an intent and builds an appropriate context for it.
+ * Builds a context object for viewing a conversation list for a search query.
*/
- public static ConversationListContext forIntent(Context context, Account callerAccount,
- Intent intent) {
- Account account = callerAccount;
- String action = intent.getAction();
- // TODO(viki): Implement the other intents: Intent.SEARCH,
- // Intent.PROVIDER_CHANGED.
- if (Intent.ACTION_VIEW.equals(action) && intent.getData() != null) {
- // TODO(viki): Look through the URI to find the account and the
- // folder.
- }
- Folder folder = (Folder) intent.getParcelableExtra(EXTRA_FOLDER);
- if (folder == null) {
- Cursor cursor = null;
- try {
- cursor = context.getContentResolver().query(callerAccount.folderListUri,
- UIProvider.FOLDERS_PROJECTION, null, null, null);
- if (cursor != null) {
- cursor.moveToFirst();
- folder = new Folder(cursor);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- }
- return forFolder(context, account, folder);
+ public static ConversationListContext forSearchQuery(Account account, Folder folder,
+ String query) {
+ return new ConversationListContext(account, Preconditions.checkNotNull(query), folder);
}
/**
@@ -176,7 +155,7 @@
* @return true if list is showing search results. False otherwise
*/
public boolean isSearchResult() {
- return false;
+ return !TextUtils.isEmpty(searchQuery);
}
/**
diff --git a/src/com/android/mail/providers/Folder.java b/src/com/android/mail/providers/Folder.java
index 8c730b7..72e3227 100644
--- a/src/com/android/mail/providers/Folder.java
+++ b/src/com/android/mail/providers/Folder.java
@@ -19,6 +19,7 @@
import android.database.Cursor;
import android.net.Uri;
+import android.net.Uri.Builder;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -146,6 +147,8 @@
private static final String FOLDER_SEPARATOR = "^**^";
+ public static final Uri SEARCH_RESULTS_URI = Uri.parse("content://fakeSearchResults/");
+
public Folder(Parcel in) {
id = in.readString();
uri = in.readParcelable(null);
@@ -230,6 +233,17 @@
return out.toString();
}
+ public static Folder forSearchResults(Account account, String query) {
+ Folder searchFolder = new Folder();
+ Builder searchBuilder = account.searchUri.buildUpon();
+ searchBuilder.appendQueryParameter(UIProvider.SearchQueryParameters.QUERY, query);
+ Uri searchUri = searchBuilder.build();
+ searchFolder.uri = SEARCH_RESULTS_URI;
+ searchFolder.conversationListUri = searchUri;
+ searchFolder.refreshUri = searchUri;
+ return searchFolder;
+ }
+
/**
* Construct a new Folder instance from a previously serialized string.
* @param serializedFolder string obtained from {@link #serialize()} on a valid folder.
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index 0bf375b..988001d 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -21,6 +21,8 @@
import android.app.ActionBar.LayoutParams;
import android.app.Activity;
import android.app.Dialog;
+import android.app.SearchManager;
+import android.app.SearchableInfo;
import android.content.ContentResolver;
import android.content.Context;
import android.content.CursorLoader;
@@ -40,6 +42,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
+import android.widget.SearchView;
import android.widget.Toast;
import com.android.mail.R;
@@ -113,7 +116,6 @@
private AsyncRefreshTask mAsyncRefreshTask;
private MenuItem mRefreshItem;
- private MenuItem mHelpItem;
private View mRefreshActionView;
private boolean mRefreshInProgress;
private final Handler mHandler = new Handler();
@@ -174,16 +176,6 @@
}
@Override
- public void enterSearchMode() {
- // TODO(viki): Auto-generated method stub
- }
-
- @Override
- public void exitSearchMode() {
- // TODO(viki): Auto-generated method stub
- }
-
- @Override
public Account getCurrentAccount() {
return mAccount;
}
@@ -214,18 +206,13 @@
// TODO(viki): Auto-generated method stub
}
- @Override
- public void handleSearchRequested() {
- // TODO(viki): Auto-generated method stub
- }
-
/**
* Initialize the action bar. This is not visible to OnePaneController and
* TwoPaneController so they cannot override this behavior.
*/
private void initCustomActionBarView() {
ActionBar actionBar = mActivity.getActionBar();
- mActionBarView = (MailActionBar) LayoutInflater.from(mContext).inflate(
+ mActionBarView = (ActionBarView) LayoutInflater.from(mContext).inflate(
R.layout.actionbar_view, null);
if (actionBar != null && mActionBarView != null) {
@@ -256,10 +243,10 @@
onSettingsChanged(null);
restartSettingsLoader();
mActionBarView.setAccount(mAccount);
+ mActivity.invalidateOptionsMenu();
// Account changed; existing folder is invalid.
mFolder = null;
fetchAccountFolderInfo();
- updateHelpMenuItem();
}
}
@@ -360,8 +347,8 @@
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = mActivity.getMenuInflater();
inflater.inflate(mActionBarView.getOptionsMenuId(), menu);
+ mActionBarView.onCreateOptionsMenu(menu);
mRefreshItem = menu.findItem(R.id.refresh);
- mHelpItem = menu.findItem(R.id.help_info_menu_item);
return true;
}
@@ -436,11 +423,6 @@
}
@Override
- public void onPause() {
- isLoaderInitialized = false;
- }
-
- @Override
public void onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
// TODO(viki): Auto-generated method stub
@@ -462,17 +444,13 @@
mRefreshItem.setActionView(null);
}
}
-
- // Show/hide the help menu item
- updateHelpMenuItem();
+ mActionBarView.prepareOptionsMenu(menu);
return true;
}
- private void updateHelpMenuItem() {
- if (mHelpItem != null) {
- mHelpItem.setVisible(mAccount != null
- && mAccount.supportsCapability(AccountCapabilities.HELP_CONTENT));
- }
+ @Override
+ public void onPause() {
+ isLoaderInitialized = false;
}
@Override
@@ -494,8 +472,13 @@
}
@Override
- public void onSearchRequested() {
- // TODO(viki): Auto-generated method stub
+ public void onSearchRequested(String query) {
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_SEARCH);
+ intent.putExtra(ConversationListContext.EXTRA_SEARCH_QUERY, query);
+ intent.putExtra(Utils.EXTRA_ACCOUNT, mAccount);
+ intent.setComponent(mActivity.getComponentName());
+ mActivity.startActivity(intent);
}
@Override
@@ -568,17 +551,17 @@
* @param savedState
*/
protected void restoreState(Bundle savedState) {
+ final Intent intent = mActivity.getIntent();
if (savedState != null) {
restoreListContext(savedState);
mAccount = savedState.getParcelable(SAVED_ACCOUNT);
restartSettingsLoader();
- } else {
- final Intent intent = mActivity.getIntent();
- if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
+ } else if (intent != null) {
+ if (Intent.ACTION_VIEW.equals(intent.getAction())) {
if (intent.hasExtra(Utils.EXTRA_ACCOUNT)) {
mAccount = ((Account) intent.getParcelableExtra(Utils.EXTRA_ACCOUNT));
mActivity.getLoaderManager().restartLoader(ACCOUNT_SETTINGS_LOADER, null, this);
- updateHelpMenuItem();
+ mActivity.invalidateOptionsMenu();
}
if (intent.hasExtra(Utils.EXTRA_FOLDER)) {
// Open the folder.
@@ -593,9 +576,18 @@
showConversation((Conversation) intent
.getParcelableExtra(Utils.EXTRA_CONVERSATION));
}
+ } else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+ mViewMode.enterSearchResultsListMode();
+ mAccount = ((Account) intent.getParcelableExtra(Utils.EXTRA_ACCOUNT));
+ Folder searchFolder = Folder.forSearchResults(mAccount, intent
+ .getStringExtra(ConversationListContext.EXTRA_SEARCH_QUERY));
+ setFolder(searchFolder);
+ mConvListContext = ConversationListContext.forSearchQuery(mAccount, searchFolder,
+ Utils.mailSearchQueryForIntent(intent));
+ showConversationList(mConvListContext);
}
}
- // Create the accounts loader; this loads the acount switch spinner.
+ // Create the accounts loader; this loads the account switch spinner.
mActivity.getLoaderManager().initLoader(ACCOUNT_CURSOR_LOADER, null, this);
}
@@ -624,7 +616,11 @@
public void onConversationSelected(Conversation conversation) {
mCurrentConversation = conversation;
showConversation(mCurrentConversation);
- mViewMode.enterConversationMode();
+ if (mConvListContext != null && mConvListContext.isSearchResult()) {
+ mViewMode.enterSearchResultsConversationMode();
+ } else {
+ mViewMode.enterConversationMode();
+ }
}
/**
@@ -637,8 +633,11 @@
return new CursorLoader(mContext, AccountCacheProvider.getAccountsUri(),
UIProvider.ACCOUNTS_PROJECTION, null, null, null);
} else if (id == FOLDER_CURSOR_LOADER) {
- return new CursorLoader(mActivity.getActivityContext(), mFolder.uri,
- UIProvider.FOLDERS_PROJECTION, null, null, null);
+ // Don't bother running a cursor loader for the search results folder.
+ if (!mFolder.uri.equals(Folder.SEARCH_RESULTS_URI)) {
+ return new CursorLoader(mActivity.getActivityContext(), mFolder.uri,
+ UIProvider.FOLDERS_PROJECTION, null, null, null);
+ }
} else if (id == ACCOUNT_SETTINGS_LOADER) {
if (mAccount.settingsQueryUri != null) {
return new CursorLoader(mActivity.getActivityContext(), mAccount.settingsQueryUri,
diff --git a/src/com/android/mail/ui/ActionBarView.java b/src/com/android/mail/ui/ActionBarView.java
index b44ce55..13b5312 100644
--- a/src/com/android/mail/ui/ActionBarView.java
+++ b/src/com/android/mail/ui/ActionBarView.java
@@ -1,118 +1,342 @@
-/*******************************************************************************
- * Copyright (C) 2012 Google Inc.
- * Licensed to The Android Open Source Project.
+/*
+ * 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
+ * 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
+ * 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.
- *******************************************************************************/
+ * 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.ActionBar;
+import android.app.SearchManager;
+import android.app.SearchableInfo;
import android.app.ActionBar.OnNavigationListener;
+import android.content.Context;
import android.os.Bundle;
+import android.util.AttributeSet;
import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.SearchView;
+import android.widget.SearchView.OnQueryTextListener;
+import android.widget.SpinnerAdapter;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.android.mail.R;
+import com.android.mail.AccountSpinnerAdapter;
+import com.android.mail.ConversationListContext;
import com.android.mail.providers.Account;
+import com.android.mail.providers.UIProvider.AccountCapabilities;
import com.android.mail.providers.Folder;
/**
- * ActionBarView simplifies supporting both MailActionBar and MailActionBarDeprecated (used for
- * pre-v14 devices).
+ * View to manage the various states of the Mail Action Bar
+ *
+ * TODO(viki): Include ConversationSubjectDisplayer here as well.
*/
-
-public interface ActionBarView extends OnNavigationListener, ViewMode.ModeChangeListener {
+public final class ActionBarView extends LinearLayout implements OnNavigationListener,
+ ViewMode.ModeChangeListener, OnQueryTextListener {
/**
- * Initialize the ActionBarView
- * @param activity
- * @param callback
- * @param viewMode
- * @param actionBar
+ * This interface is used to send notifications back to the calling
+ * activity. MenuHandler takes care of updating the provider, so this
+ * interface should be used for notification purposes only (such as updating
+ * the UI).
*/
- void initialize(RestrictedActivity activity, ActivityController controller, ViewMode viewMode,
- ActionBar actionBar);
+ // TODO(viki): This callback is currently unused and may be entirely unnecessary in the new
+ // code, where the Actionbar is switched into navigation mode, relying on the framework for most
+ // heavy lifting. Also, we can switch ViewMode to the appropriate mode and rely on all UI
+ // components updating through ViewMode change listeners.
+ public interface Callback {
+ /**
+ * Returns the current account.
+ */
+ Account getCurrentAccount();
+
+ /**
+ * Called when the TwoPaneActionBar wants to get the current conversation list context.
+ */
+ ConversationListContext getCurrentListContext();
+
+ /**
+ * Invoked when the user is already viewing search results
+ * and enters a new query.
+ * @param string Query
+ */
+ void reloadSearch(String string);
+
+ void showFolderList();
+
+ void startActionBarStatusCursorLoader(String account);
+
+ void stopActionBarStatusCursorLoader(String account);
+ }
+
+ private String[] mAccountNames;
+ private ActionBar mActionBar;
+ private RestrictedActivity mActivity;
+ private ActivityController mCallback;
+ private View mFolderView;
+ /**
+ * The current mode of the ActionBar. This references constants in {@link ViewMode}
+ */
+ private int mMode = ViewMode.UNKNOWN;
+
+ private MenuItem mSearch;
+ AccountSpinnerAdapter mSpinner;
+ /**
+ * The account currently being shown
+ */
+ private Account mAccount;
+
+ // TODO(viki): This is a SnippetTextView in the Gmail source code. Resolve.
+ private TextView mSubjectView;
+ private SearchView mSearchWidget;
+ private MenuItem mHelpItem;
+
+ public ActionBarView(Context context) {
+ this(context, null);
+ }
+
+ public ActionBarView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ActionBarView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // If the mode is valid, then set the initial menu
+ if (mMode == ViewMode.UNKNOWN) {
+ return false;
+ }
+ MenuItem search = menu.findItem(R.id.search);
+ if (search != null) {
+ mSearchWidget = (SearchView) search.getActionView();
+ SearchManager searchManager = (SearchManager) mActivity.getActivityContext()
+ .getSystemService(Context.SEARCH_SERVICE);
+ if (searchManager != null) {
+ SearchableInfo info = searchManager.getSearchableInfo(mActivity.getComponentName());
+ mSearchWidget.setSearchableInfo(info);
+ mSearchWidget.setOnQueryTextListener(this);
+ }
+ }
+ mHelpItem = menu.findItem(R.id.help_info_menu_item);
+ return true;
+ }
+
+ public int getOptionsMenuId() {
+ // Relies on the ordering of the view modes, since they are integer constants.
+ final int[] modeMenu = {
+ // 0: UNKNOWN
+ R.menu.conversation_list_menu,
+ // 1: CONVERSATION
+ R.menu.conversation_actions,
+ // 2: CONVERSATION_LIST
+ R.menu.conversation_list_menu,
+ // 3: FOLDER_LIST
+ R.menu.folder_list_menu,
+ // 4: SEARCH_RESULTS_LIST
+ R.menu.conversation_list_search_results_actions,
+ // 5: SEARCH_RESULTS_CONVERSATION
+ R.menu.conversation_actions
+ };
+ return modeMenu[mMode];
+ }
+
+ public void handleRestore(Bundle savedInstanceState) {
+ }
+
+ public void handleSaveInstanceState(Bundle outState) {
+ }
+
+ public void initialize(RestrictedActivity activity, ActivityController callback,
+ ViewMode viewMode, ActionBar actionBar) {
+ mActionBar = actionBar;
+ mCallback = callback;
+ mActivity = activity;
+
+ mSpinner = new AccountSpinnerAdapter(getContext());
+ // Set the mode to Navigation mode and listen on navigation changes.
+ mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+ mActionBar.setListNavigationCallbacks(mSpinner, this);
+ }
+
+ public void setAccounts(Account[] accounts) {
+ Account currentAccount = mCallback.getCurrentAccount();
+ mSpinner.setAccounts(accounts);
+ mSpinner.setCurrentAccount(currentAccount);
+ int position = -1;
+ for (position = 0; position < accounts.length; position++) {
+ if (accounts[position].equals(currentAccount)) {
+ break;
+ }
+ }
+ if (position >= accounts.length) {
+ position = 0;
+ }
+ mActionBar.setSelectedNavigationItem(position);
+ }
/**
- * Handle handleRestore from the Android framework.
- * @param savedInstanceState
+ * Called by the owner of the ActionBar to set the
+ * folder that is currently being displayed.
*/
- void handleRestore(Bundle savedInstanceState);
+ public void setFolder(Folder folder) {
+ mSpinner.setCurrentFolder(folder);
+ mSpinner.notifyDataSetChanged();
+ }
/**
- * Handle onResume from the Android framework.
+ * Called by the owner of the ActionBar to set the
+ * account that is currently being displayed.
*/
- void onResume();
+ public void setAccount(Account account) {
+ mSpinner.setCurrentAccount(account);
+ mSpinner.notifyDataSetChanged();
+ }
+
+ @Override
+ public boolean onNavigationItemSelected(int position, long id) {
+ final int type = mSpinner.getItemViewType(position);
+ switch (type) {
+ case AccountSpinnerAdapter.TYPE_ACCOUNT:
+ // Get the capabilities associated with this account.
+ final Object item = mSpinner.getItem(position);
+ assert (item instanceof Account);
+ mCallback.onAccountChanged((Account) mSpinner.getItem(position));
+ break;
+ case AccountSpinnerAdapter.TYPE_FOLDER:
+ final Object folder = mSpinner.getItem(position);
+ assert (folder instanceof Folder);
+ mCallback.onFolderChanged((Folder) folder);
+ break;
+ }
+ return false;
+ }
+
+ public void onPause() {
+ }
+
+ public void onResume() {
+ }
+
+ public void onStatusResult(String account, int status) {
+ // Update the inbox folder if required
+ mCallback.stopActionBarStatusCursorLoader(account);
+ }
+
+ public void onViewModeChanged(int newMode) {
+ mMode = newMode;
+ // Always update the options menu and redraw. This will read the new mode and redraw
+ // the options menu.
+ mActivity.invalidateOptionsMenu();
+ }
/**
- * Handle onPause from the Android framework.
+ * If shouldSetView is true, then the view is made visible, otherwise its visiblity is View.GONE
+ * @param view the view whose visibility is modified
+ * @param shouldSetView if true, the view is made visible, GONE otherwise
*/
- void onPause();
+ private void setVisibility(int resourceId, boolean shouldSetView) {
+ final View view = findViewById(resourceId);
+ assert (view != null);
+ final int visibility = shouldSetView ? View.VISIBLE : View.GONE;
+ view.setVisibility(visibility);
+ }
- /**
- * @param outState
- */
- void handleSaveInstanceState(Bundle outState);
+ public boolean prepareOptionsMenu(Menu menu) {
+ // We start out with every option enabled. Based on the current view, we disable actions
+ // that are possible.
+ if (mSubjectView != null){
+ mSubjectView.setVisibility(GONE);
+ }
+ if (mFolderView != null){
+ mFolderView.setVisibility(GONE);
+ }
+ if (mAccount == null) {
+ return false;
+ }
- /**
- * Update the folder that the user is currently viewing
- * @param folder
- */
- void setFolder(Folder folder);
+ if (mHelpItem != null) {
+ mHelpItem.setVisible(mAccount != null
+ && mAccount.supportsCapability(AccountCapabilities.HELP_CONTENT));
+ }
+ switch (mMode){
+ case ViewMode.UNKNOWN:
+ if (mSearch != null){
+ mSearch.collapseActionView();
+ }
+ break;
+ case ViewMode.CONVERSATION_LIST:
+ // Show compose, search, labels, and sync based on the account
+ // The only option that needs to be disabled is search
+ setVisibility(R.id.search, mAccount.supportsCapability(
+ AccountCapabilities.FOLDER_SERVER_SEARCH));
+ break;
+ case ViewMode.CONVERSATION:
+ setVisibility(R.id.y_button, mAccount.supportsCapability(
+ AccountCapabilities.ARCHIVE));
+ setVisibility(R.id.report_spam, mAccount.supportsCapability(
+ AccountCapabilities.REPORT_SPAM));
+ setVisibility(R.id.mute, mAccount.supportsCapability(AccountCapabilities.MUTE));
+ break;
+ case ViewMode.SEARCH_RESULTS_LIST:
+ mActionBar.setDisplayHomeAsUpEnabled(true);
+ if (mSearch != null) {
+ mSearch.expandActionView();
+ }
+ break;
+ case ViewMode.SEARCH_RESULTS_CONVERSATION:
+ mActionBar.setDisplayHomeAsUpEnabled(true);
+ break;
+ case ViewMode.FOLDER_LIST:
+ break;
+ }
+ return false;
+ }
- /**
- * Update the account that the user is currently viewing
- * @param account
- */
- void setAccount(Account account);
+ public void removeBackButton() {
+ if (mActionBar == null) {
+ return;
+ }
+ mActionBar.setDisplayOptions(
+ ActionBar.DISPLAY_SHOW_HOME,
+ ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME);
+ mActivity.getActionBar().setHomeButtonEnabled(false);
+ }
- /**
- * Returns the menu ID for the menu in this actionbar.
- * @return the Menu ID for the menu.
- */
- int getOptionsMenuId();
+ public void setBackButton() {
+ if (mActionBar == null){
+ return;
+ }
+ mActionBar.setDisplayOptions(
+ ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME,
+ ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME);
+ mActivity.getActionBar().setHomeButtonEnabled(true);
+ }
- /**
- * Shows a back button in the top left. We have progressed one level into the application.
- */
- void setBackButton();
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ mActivity.onSearchRequested(query);
+ return true;
+ }
- /**
- * Removes any back button from the top left. We have returned to the top of the application.
- */
- void removeBackButton();
-
- /**
- * Prepares all the icons that go inside the options menu. This depends on the context of
- * the action bar.
- * @param menu
- */
- boolean prepareOptionsMenu(Menu menu);
-
- /**
- * Creates the first time options menu.
- * @param menu
- */
- boolean createOptionsMenu(Menu menu);
-
- /**
- * Updates the action bar based on a new status received from the server.
- * @param account
- * @param status
- */
- void onStatusResult(String account, int status);
-
- /**
- * Sets the list of accounts in the drop-down navigation.
- * @param accounts the array of accounts to be set.
- */
- void setAccounts(Account[] accounts);
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ // TODO Auto-generated method stub
+ return false;
+ }
}
diff --git a/src/com/android/mail/ui/ActivityController.java b/src/com/android/mail/ui/ActivityController.java
index 2db0bb6..69781fb 100644
--- a/src/com/android/mail/ui/ActivityController.java
+++ b/src/com/android/mail/ui/ActivityController.java
@@ -22,7 +22,6 @@
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
-import android.view.ActionMode;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@@ -40,7 +39,7 @@
* or respond to user action.
*/
public interface ActivityController extends MenuCallback, LayoutListener, SubjectDisplayChanger,
- ModeChangeListener, MailActionBar.Callback, StarHandler, ConversationListCallbacks,
+ ModeChangeListener, ActionBarView.Callback, StarHandler, ConversationListCallbacks,
FolderChangeListener, AccountChangeListener, LoaderManager.LoaderCallbacks<Cursor> {
// As far as possible, the methods here that correspond to Activity lifecycle have the same name
@@ -189,7 +188,7 @@
/**
* @see android.app.Activity#onSearchRequested()
*/
- void onSearchRequested();
+ void onSearchRequested(String query);
/**
* Called by the Mail activity on Activity stop.
diff --git a/src/com/android/mail/ui/ConversationListFragment.java b/src/com/android/mail/ui/ConversationListFragment.java
index e415050..12afa26 100644
--- a/src/com/android/mail/ui/ConversationListFragment.java
+++ b/src/com/android/mail/ui/ConversationListFragment.java
@@ -172,6 +172,20 @@
}
/**
+ * Show the header if the current conversation list is showing search results.
+ */
+ private void updateSearchResultHeader(int count) {
+ // Only show the header if the context is for a search result
+ final Resources res = getResources();
+ final boolean showHeader = isSearchResult();
+ if (showHeader) {
+ mSearchStatusTextView.setText(res.getString(R.string.search_results_header));
+ mSearchResultCountTextView
+ .setText(res.getString(R.string.search_results_loaded, count));
+ }
+ }
+
+ /**
* Initializes all internal state for a rendering.
*/
private void initializeUiForFirstDisplay() {
@@ -499,8 +513,9 @@
@Override
public Loader<ConversationCursor> onCreateLoader(int id, Bundle args) {
+ configureSearchResultHeader();
return new ConversationCursorLoader((Activity) mActivity,
- UIProvider.CONVERSATION_PROJECTION, mFolder.conversationListUri);
+ UIProvider.CONVERSATION_PROJECTION, mFolder.conversationListUri);
}
@Override
@@ -508,7 +523,7 @@
mConversationListCursor = data;
mListAdapter.swapCursor(mConversationListCursor);
mConversationListCursor.addListener(this);
- configureSearchResultHeader();
+ updateSearchResultHeader(data != null ? data.getCount() : 0);
}
@Override
diff --git a/src/com/android/mail/ui/FolderSelectionActivity.java b/src/com/android/mail/ui/FolderSelectionActivity.java
index bbf8093..7df84c9 100644
--- a/src/com/android/mail/ui/FolderSelectionActivity.java
+++ b/src/com/android/mail/ui/FolderSelectionActivity.java
@@ -268,4 +268,9 @@
public Settings getSettings() {
return null;
}
+
+ @Override
+ public boolean onSearchRequested(String query) {
+ return false;
+ }
}
diff --git a/src/com/android/mail/ui/MailActionBar.java b/src/com/android/mail/ui/MailActionBar.java
deleted file mode 100644
index 8f107ef..0000000
--- a/src/com/android/mail/ui/MailActionBar.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.mail.ui;
-
-import android.app.ActionBar;
-import android.app.ActionBar.OnNavigationListener;
-import android.content.Context;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.SpinnerAdapter;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.mail.R;
-import com.android.mail.AccountSpinnerAdapter;
-import com.android.mail.ConversationListContext;
-import com.android.mail.providers.Account;
-import com.android.mail.providers.UIProvider.AccountCapabilities;
-import com.android.mail.providers.Folder;
-
-/**
- * View to manage the various states of the Mail Action Bar
- *
- * TODO(viki): Include ConversationSubjectDisplayer here as well.
- */
-public final class MailActionBar extends LinearLayout implements ActionBarView {
- /**
- * This interface is used to send notifications back to the calling
- * activity. MenuHandler takes care of updating the provider, so this
- * interface should be used for notification purposes only (such as updating
- * the UI).
- */
- // TODO(viki): This callback is currently unused and may be entirely unnecessary in the new
- // code, where the Actionbar is switched into navigation mode, relying on the framework for most
- // heavy lifting. Also, we can switch ViewMode to the appropriate mode and rely on all UI
- // components updating through ViewMode change listeners.
- public interface Callback {
- /**
- * Enter search mode
- */
- void enterSearchMode();
-
- /**
- * Exits search mode
- */
- void exitSearchMode();
-
- /**
- * Returns the current account.
- */
- Account getCurrentAccount();
-
- /**
- * Called when the TwoPaneActionBar wants to get the current conversation list context.
- */
- ConversationListContext getCurrentListContext();
-
- /**
- * Invoked when the user is already viewing search results
- * and enters a new query.
- * @param string Query
- */
- void reloadSearch(String string);
-
- void showFolderList();
-
- void startActionBarStatusCursorLoader(String account);
-
- void stopActionBarStatusCursorLoader(String account);
- }
-
- private String[] mAccountNames;
- private ActionBar mActionBar;
- private RestrictedActivity mActivity;
- private ActivityController mCallback;
- private View mFolderView;
- /**
- * The current mode of the ActionBar. This references constants in {@link ViewMode}
- */
- private int mMode = ViewMode.UNKNOWN;
-
- private MenuItem mRefreshItem;
-
- private MenuItem mSearch;
- AccountSpinnerAdapter mSpinner;
- /**
- * The account currently being shown
- */
- private Account mAccount;
-
- // TODO(viki): This is a SnippetTextView in the Gmail source code. Resolve.
- private TextView mSubjectView;
-
- public MailActionBar(Context context) {
- this(context, null);
- }
-
- public MailActionBar(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public MailActionBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public boolean createOptionsMenu(Menu menu) {
- // If the mode is valid, then set the initial menu
- if (mMode == ViewMode.UNKNOWN) {
- return false;
- }
- mActivity.getMenuInflater().inflate(getOptionsMenuId(), menu);
- // mSearch = menu.findItem(R.id.search);
- // mRefreshItem = menu.findItem(R.id.refresh);
- return true;
- }
-
- @Override
- public int getOptionsMenuId() {
- // Relies on the ordering of the view modes, since they are integer constants.
- final int[] modeMenu = {
- // 0: UNKNOWN
- R.menu.conversation_list_menu,
- // 1: CONVERSATION
- R.menu.conversation_actions,
- // 2: CONVERSATION_LIST
- R.menu.conversation_list_menu,
- // 3: FOLDER_LIST
- R.menu.folder_list_menu,
- // 4: SEARCH_RESULTS
- R.menu.conversation_list_menu
- };
- return modeMenu[mMode];
- }
-
- @Override
- public void handleRestore(Bundle savedInstanceState) {
- }
-
- @Override
- public void handleSaveInstanceState(Bundle outState) {
- }
-
- @Override
- public void initialize(RestrictedActivity activity, ActivityController callback, ViewMode viewMode,
- ActionBar actionBar) {
- mActionBar = actionBar;
- mCallback = callback;
- mActivity = activity;
-
- mSpinner = new AccountSpinnerAdapter(getContext());
- // Set the mode to Navigation mode and listen on navigation changes.
- mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- mActionBar.setListNavigationCallbacks(mSpinner, this);
- }
-
- @Override
- public void setAccounts(Account[] accounts) {
- Account currentAccount = mCallback.getCurrentAccount();
- mSpinner.setAccounts(accounts);
- mSpinner.setCurrentAccount(currentAccount);
- int position = -1;
- for (position = 0; position < accounts.length; position++) {
- if (accounts[position].equals(currentAccount)) {
- break;
- }
- }
- if (position >= accounts.length) {
- position = 0;
- }
- mActionBar.setSelectedNavigationItem(position);
- }
-
- /**
- * Called by the owner of the ActionBar to set the
- * folder that is currently being displayed.
- */
- @Override
- public void setFolder(Folder folder) {
- mSpinner.setCurrentFolder(folder);
- mSpinner.notifyDataSetChanged();
- }
-
- /**
- * Called by the owner of the ActionBar to set the
- * account that is currently being displayed.
- */
- @Override
- public void setAccount(Account account) {
- mSpinner.setCurrentAccount(account);
- mSpinner.notifyDataSetChanged();
- }
-
- @Override
- public boolean onNavigationItemSelected(int position, long id) {
- final int type = mSpinner.getItemViewType(position);
- switch (type) {
- case AccountSpinnerAdapter.TYPE_ACCOUNT:
- // Get the capabilities associated with this account.
- final Object item = mSpinner.getItem(position);
- assert (item instanceof Account);
- mCallback.onAccountChanged((Account) mSpinner.getItem(position));
- break;
- case AccountSpinnerAdapter.TYPE_FOLDER:
- final Object folder = mSpinner.getItem(position);
- assert (folder instanceof Folder);
- mCallback.onFolderChanged((Folder) folder);
- break;
- }
- return false;
- }
-
- @Override
- public void onPause() {
- }
-
- @Override
- public void onResume() {
- }
-
- @Override
- public void onStatusResult(String account, int status) {
- // Update the inbox folder if required
- mCallback.stopActionBarStatusCursorLoader(account);
- }
-
- @Override
- public void onViewModeChanged(int newMode) {
- mMode = newMode;
- // Always update the options menu and redraw. This will read the new mode and redraw
- // the options menu.
- mActivity.invalidateOptionsMenu();
- }
-
- /**
- * If shouldSetView is true, then the view is made visible, otherwise its visiblity is View.GONE
- * @param view the view whose visibility is modified
- * @param shouldSetView if true, the view is made visible, GONE otherwise
- */
- private void setVisibility(int resourceId, boolean shouldSetView) {
- final View view = findViewById(resourceId);
- assert (view != null);
- final int visibility = shouldSetView ? View.VISIBLE : View.GONE;
- view.setVisibility(visibility);
- }
-
- @Override
- public boolean prepareOptionsMenu(Menu menu) {
- // We start out with every option enabled. Based on the current view, we disable actions
- // that are possible.
- if (mSubjectView != null){
- mSubjectView.setVisibility(GONE);
- }
- if (mFolderView != null){
- mFolderView.setVisibility(GONE);
- }
-
- switch (mMode){
- case ViewMode.UNKNOWN:
- if (mSearch != null){
- mSearch.collapseActionView();
- }
- break;
- case ViewMode.CONVERSATION_LIST:
- // Show compose, search, labels, and sync based on the account
- // The only option that needs to be disabled is search
- setVisibility(R.id.search, mAccount.supportsCapability(
- AccountCapabilities.FOLDER_SERVER_SEARCH));
- break;
- case ViewMode.CONVERSATION:
- setVisibility(R.id.y_button, mAccount.supportsCapability(
- AccountCapabilities.ARCHIVE));
- setVisibility(R.id.report_spam, mAccount.supportsCapability(
- AccountCapabilities.REPORT_SPAM));
- setVisibility(R.id.mute, mAccount.supportsCapability(AccountCapabilities.MUTE));
- break;
- case ViewMode.SEARCH_RESULTS:
- mActionBar.setDisplayHomeAsUpEnabled(true);
- if (mSearch != null) {
- mSearch.collapseActionView();
- }
- case ViewMode.FOLDER_LIST:
- break;
- }
- return false;
- }
-
- @Override
- public void removeBackButton() {
- if (mActionBar == null) {
- return;
- }
- mActionBar.setDisplayOptions(
- ActionBar.DISPLAY_SHOW_HOME,
- ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME);
- mActivity.getActionBar().setHomeButtonEnabled(false);
- }
-
- @Override
- public void setBackButton() {
- if (mActionBar == null){
- return;
- }
- mActionBar.setDisplayOptions(
- ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME,
- ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME);
- mActivity.getActionBar().setHomeButtonEnabled(true);
- }
-}
diff --git a/src/com/android/mail/ui/MailActivity.java b/src/com/android/mail/ui/MailActivity.java
index 8ed9134..5b3663e 100644
--- a/src/com/android/mail/ui/MailActivity.java
+++ b/src/com/android/mail/ui/MailActivity.java
@@ -201,8 +201,8 @@
}
@Override
- public boolean onSearchRequested() {
- mController.onSearchRequested();
+ public boolean onSearchRequested(String query) {
+ mController.onSearchRequested(query);
return true;
}
diff --git a/src/com/android/mail/ui/MenuCallback.java b/src/com/android/mail/ui/MenuCallback.java
index 4c4ef3d..c992f70 100644
--- a/src/com/android/mail/ui/MenuCallback.java
+++ b/src/com/android/mail/ui/MenuCallback.java
@@ -27,11 +27,6 @@
// Called MenuHandler.ActivityCallback in the previous code.
public interface MenuCallback extends HelpCallback {
/**
- * Invoked when the user requests search mode
- */
- void handleSearchRequested();
-
- /**
* Invoked when user starts drag and drop mode.
*/
void onStartDragMode();
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index 9074050..e655b27 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -80,8 +80,10 @@
// If the settings aren't loaded yet, we may not know what the default
// inbox is, so err toward this being the account inbox.
if ((mCachedSettings != null && mConvListContext != null && !inInbox())
- || (mode == ViewMode.CONVERSATION_LIST && mConvListContext.isSearchResult())
- || mode == ViewMode.CONVERSATION || mode == ViewMode.FOLDER_LIST) {
+ || mode == ViewMode.SEARCH_RESULTS_LIST
+ || mode == ViewMode.SEARCH_RESULTS_CONVERSATION
+ || mode == ViewMode.CONVERSATION
+ || mode == ViewMode.FOLDER_LIST) {
mActionBarView.setBackButton();
} else {
mActionBarView.removeBackButton();
@@ -116,15 +118,16 @@
public void showConversationList(ConversationListContext listContext) {
// TODO(viki): Check if the account has been changed since the previous
// time.
- mViewMode.enterConversationListMode();
+ if (listContext != null && listContext.isSearchResult()) {
+ mViewMode.enterSearchResultsListMode();
+ } else {
+ mViewMode.enterConversationListMode();
+ }
final boolean accountChanged = false;
// TODO(viki): This account transition looks strange in two pane mode.
// Revisit as the app is coming together and improve the look and feel.
final int transition = accountChanged ? FragmentTransaction.TRANSIT_FRAGMENT_FADE
: FragmentTransaction.TRANSIT_FRAGMENT_OPEN;
- if (listContext == null) {
- listContext = getCurrentListContext();
- }
Fragment conversationListFragment = ConversationListFragment.newInstance(listContext);
if (!inInbox()) {
// Maintain fragment transaction history so we can get back to the
@@ -142,7 +145,11 @@
@Override
public void showConversation(Conversation conversation) {
- mViewMode.enterConversationMode();
+ if (mConvListContext != null && mConvListContext.isSearchResult()) {
+ mViewMode.enterSearchResultsConversationMode();
+ } else {
+ mViewMode.enterConversationMode();
+ }
mLastConversationTransactionId = replaceFragment(
ConversationViewFragment.newInstance(mAccount, conversation),
FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
@@ -187,6 +194,8 @@
if (mode == ViewMode.FOLDER_LIST) {
mLastFolderListTransactionId = INVALID_ID;
transitionToInbox();
+ } else if (mode == ViewMode.SEARCH_RESULTS_LIST) {
+ mActivity.finish();
} else if (mode == ViewMode.CONVERSATION_LIST && !inInbox()) {
if (isTransactionIdValid(mLastFolderListTransactionId)) {
// Go back to previous label list.
@@ -196,7 +205,7 @@
// Go back to Inbox.
transitionToInbox();
}
- } else if (mode == ViewMode.CONVERSATION) {
+ } else if (mode == ViewMode.CONVERSATION || mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
transitionBackToConversationListMode();
} else {
mActivity.finish();
@@ -234,18 +243,25 @@
@Override
public boolean onUpPressed() {
int mode = mViewMode.getMode();
- if ((!inInbox() && mode == ViewMode.CONVERSATION_LIST) || mode == ViewMode.CONVERSATION
- || mode == ViewMode.FOLDER_LIST) {
+ if (mode == ViewMode.SEARCH_RESULTS_LIST) {
+ mActivity.finish();
+ } else if ((!inInbox() && mode == ViewMode.CONVERSATION_LIST)
+ || mode == ViewMode.CONVERSATION
+ || mode == ViewMode.FOLDER_LIST
+ || mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
// Same as go back.
mActivity.onBackPressed();
- } else if (mode == ViewMode.SEARCH_RESULTS) {
- mActivity.finish();
}
return true;
}
private void transitionBackToConversationListMode() {
- mViewMode.enterConversationListMode();
+ int mode = mViewMode.getMode();
+ if (mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
+ mViewMode.enterSearchResultsListMode();
+ } else {
+ mViewMode.enterConversationListMode();
+ }
mActivity.getFragmentManager().popBackStack(mLastConversationTransactionId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
resetActionBarIcon();
diff --git a/src/com/android/mail/ui/RestrictedActivity.java b/src/com/android/mail/ui/RestrictedActivity.java
index 7fbedfc..15b25a9 100644
--- a/src/com/android/mail/ui/RestrictedActivity.java
+++ b/src/com/android/mail/ui/RestrictedActivity.java
@@ -122,7 +122,7 @@
/**
* @see android.app.Activity#onSearchRequested()
*/
- public boolean onSearchRequested();
+ public boolean onSearchRequested(String query);
/**
* @see android.app.Activity#setContentView(int)
diff --git a/src/com/android/mail/ui/TwoPaneController.java b/src/com/android/mail/ui/TwoPaneController.java
index 7b9c8a4..36e49bd 100644
--- a/src/com/android/mail/ui/TwoPaneController.java
+++ b/src/com/android/mail/ui/TwoPaneController.java
@@ -191,7 +191,7 @@
} else {
mActivity.onBackPressed();
}
- } else if (mode == ViewMode.SEARCH_RESULTS) {
+ } else if (mode == ViewMode.SEARCH_RESULTS_LIST) {
mActivity.finish();
}
return true;
diff --git a/src/com/android/mail/ui/TwoPaneLayout.java b/src/com/android/mail/ui/TwoPaneLayout.java
index 07b39a2..ec8dfa5 100644
--- a/src/com/android/mail/ui/TwoPaneLayout.java
+++ b/src/com/android/mail/ui/TwoPaneLayout.java
@@ -312,7 +312,7 @@
switch (currentMode) {
case ViewMode.CONVERSATION:
// Fallthrough
- case ViewMode.SEARCH_RESULTS:
+ case ViewMode.SEARCH_RESULTS_CONVERSATION:
if (isConversationListCollapsible()) {
return totalWidth;
}
@@ -665,7 +665,8 @@
break;
case ViewMode.FOLDER_LIST:
break;
- case ViewMode.SEARCH_RESULTS:
+ case ViewMode.SEARCH_RESULTS_LIST:
+ case ViewMode.SEARCH_RESULTS_CONVERSATION:
// Show search results here
break;
}
diff --git a/src/com/android/mail/ui/ViewMode.java b/src/com/android/mail/ui/ViewMode.java
index 40aad55..ac2d28e 100644
--- a/src/com/android/mail/ui/ViewMode.java
+++ b/src/com/android/mail/ui/ViewMode.java
@@ -56,7 +56,11 @@
/**
* Mode when showing results from user search.
*/
- public static final int SEARCH_RESULTS = 4;
+ public static final int SEARCH_RESULTS_LIST = 4;
+ /**
+ * Mode when showing results from user search.
+ */
+ public static final int SEARCH_RESULTS_CONVERSATION = 5;
/**
* Uncertain mode. The mode has not been initialized.
*/
@@ -121,6 +125,26 @@
}
/**
+ * Requests a transition of the mode to show a list of search results as the
+ * prominent view.
+ *
+ * @return Whether or not a change occurred.
+ */
+ public boolean enterSearchResultsListMode() {
+ return setModeInternal(SEARCH_RESULTS_LIST);
+ }
+
+ /**
+ * Requests a transition of the mode to show a conversation that was part of
+ * search results.
+ *
+ * @return Whether or not a change occurred.
+ */
+ public boolean enterSearchResultsConversationMode() {
+ return setModeInternal(SEARCH_RESULTS_CONVERSATION);
+ }
+
+ /**
* @return The current mode.
*/
public int getMode() {
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index e06613d..c9032fd 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -18,6 +18,7 @@
import com.google.common.collect.Maps;
+import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -683,4 +684,13 @@
final Intent settingsIntent = new Intent(Intent.ACTION_EDIT, account.settingsIntentUri);
context.startActivity(settingsIntent);
}
+
+ /**
+ * Retrieves the mailbox search query associated with an intent (or null if not available),
+ * doing proper sanitizing (e.g. trims whitespace).
+ */
+ public static String mailSearchQueryForIntent(Intent intent) {
+ String query = intent.getStringExtra(SearchManager.QUERY);
+ return TextUtils.isEmpty(query) ? null : query.trim();
+ }
}