summaryrefslogtreecommitdiffstats
path: root/mobile/android/search/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/search/java/org')
-rw-r--r--mobile/android/search/java/org/mozilla/search/AcceptsSearchQuery.java48
-rw-r--r--mobile/android/search/java/org/mozilla/search/Constants.java20
-rw-r--r--mobile/android/search/java/org/mozilla/search/PostSearchFragment.java243
-rw-r--r--mobile/android/search/java/org/mozilla/search/PreSearchFragment.java218
-rw-r--r--mobile/android/search/java/org/mozilla/search/SearchActivity.java436
-rw-r--r--mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java118
-rw-r--r--mobile/android/search/java/org/mozilla/search/SearchWidget.java135
-rw-r--r--mobile/android/search/java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java82
-rw-r--r--mobile/android/search/java/org/mozilla/search/autocomplete/SearchBar.java201
-rw-r--r--mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java263
-rw-r--r--mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java36
-rw-r--r--mobile/android/search/java/org/mozilla/search/ui/FacetBar.java124
12 files changed, 0 insertions, 1924 deletions
diff --git a/mobile/android/search/java/org/mozilla/search/AcceptsSearchQuery.java b/mobile/android/search/java/org/mozilla/search/AcceptsSearchQuery.java
deleted file mode 100644
index e54b9a9fc..000000000
--- a/mobile/android/search/java/org/mozilla/search/AcceptsSearchQuery.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search;
-
-import android.graphics.Rect;
-
-/**
- * Allows fragments to pass a search event to the main activity.
- */
-public interface AcceptsSearchQuery {
-
- /**
- * Shows search suggestions.
- * @param query
- */
- void onSuggest(String query);
-
- /**
- * Starts a search.
- *
- * @param query
- */
- void onSearch(String query);
-
- /**
- * Starts a search and animates a suggestion.
- *
- * @param query
- * @param suggestionAnimation
- */
- void onSearch(String query, SuggestionAnimation suggestionAnimation);
-
- /**
- * Handles a change to the current search query.
- *
- * @param query
- */
- void onQueryChange(String query);
-
- /**
- * Interface to specify search suggestion animation details.
- */
- public interface SuggestionAnimation {
- public Rect getStartBounds();
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/Constants.java b/mobile/android/search/java/org/mozilla/search/Constants.java
deleted file mode 100644
index 8e8a17600..000000000
--- a/mobile/android/search/java/org/mozilla/search/Constants.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search;
-
-/**
- * Key should not be stored here. For more info on storing keys, see
- * https://github.com/ericedens/FirefoxSearch/issues/3
- */
-public class Constants {
-
- public static final String ABOUT_BLANK = "about:blank";
-}
diff --git a/mobile/android/search/java/org/mozilla/search/PostSearchFragment.java b/mobile/android/search/java/org/mozilla/search/PostSearchFragment.java
deleted file mode 100644
index 8a26c49dd..000000000
--- a/mobile/android/search/java/org/mozilla/search/PostSearchFragment.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search;
-
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-import android.support.v4.content.ContextCompat;
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.GeckoApplication;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.search.SearchEngine;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-
-import android.annotation.SuppressLint;
-import android.content.ActivityNotFoundException;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.support.v4.app.Fragment;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.webkit.WebChromeClient;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-public class PostSearchFragment extends Fragment {
-
- private static final String LOG_TAG = "PostSearchFragment";
-
- private SearchEngine engine;
-
- private ProgressBar progressBar;
- private WebView webview;
- private View errorView;
-
- private String resultsPageHost;
-
- @SuppressLint("SetJavaScriptEnabled")
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View mainView = inflater.inflate(R.layout.search_fragment_post_search, container, false);
-
- progressBar = (ProgressBar) mainView.findViewById(R.id.progress_bar);
-
- webview = (WebView) mainView.findViewById(R.id.webview);
- webview.setWebChromeClient(new ChromeClient());
- webview.setWebViewClient(new ResultsWebViewClient());
-
- // This is required for our greasemonkey terror script.
- webview.getSettings().setJavaScriptEnabled(true);
-
- return mainView;
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- webview.setWebChromeClient(null);
- webview.setWebViewClient(null);
- webview = null;
- progressBar = null;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
-
- GeckoApplication.watchReference(getActivity(), this);
- }
-
- public void startSearch(SearchEngine engine, String query) {
- this.engine = engine;
-
- final String url = engine.resultsUriForQuery(query);
- // Only load urls if the url is different than the webview's current url.
- if (!TextUtils.equals(webview.getUrl(), url)) {
- resultsPageHost = null;
- webview.loadUrl(Constants.ABOUT_BLANK);
- webview.loadUrl(url);
- }
- }
-
- /**
- * A custom WebViewClient that intercepts every page load. This allows
- * us to decide whether to load the url here, or send it to Android
- * as an intent. It also handles network errors.
- */
- private class ResultsWebViewClient extends WebViewClient {
-
- // Whether or not there is a network error.
- private boolean networkError;
-
- @Override
- public void onPageStarted(WebView view, final String url, Bitmap favicon) {
- // Reset the error state.
- networkError = false;
- }
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- // Ignore about:blank URL loads and the first results page we try to load.
- if (TextUtils.equals(url, Constants.ABOUT_BLANK) || resultsPageHost == null) {
- return false;
- }
-
- String host = null;
- try {
- host = new URL(url).getHost();
- } catch (MalformedURLException e) {
- Log.e(LOG_TAG, "Error getting host from URL loading in webview", e);
- }
-
- // If the host name is the same as the results page, don't override the URL load, but
- // do update the query in the search bar if possible.
- if (TextUtils.equals(resultsPageHost, host)) {
- // This won't work for results pages that redirect (e.g. Google in different country)
- final String query = engine.queryForResultsUrl(url);
- if (!TextUtils.isEmpty(query)) {
- ((AcceptsSearchQuery) getActivity()).onQueryChange(query);
- }
- return false;
- }
-
- try {
- // If the url URI does not have an intent scheme, the intent data will be the entire
- // URI and its action will be ACTION_VIEW.
- final Intent i = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
-
- // If the intent URI didn't specify a package, open this in Fennec.
- if (i.getPackage() == null) {
- i.setClassName(view.getContext().getPackageName(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
- Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL,
- TelemetryContract.Method.CONTENT, "search-result");
- } else {
- Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
- TelemetryContract.Method.INTENT, "search-result");
- }
-
- i.addCategory(Intent.CATEGORY_BROWSABLE);
- i.setComponent(null);
- i.setSelector(null);
-
- startActivity(i);
- return true;
- } catch (URISyntaxException e) {
- Log.e(LOG_TAG, "Error parsing intent URI", e);
- } catch (SecurityException e) {
- Log.e(LOG_TAG, "SecurityException handling arbitrary intent content");
- } catch (ActivityNotFoundException e) {
- Log.e(LOG_TAG, "Intent not actionable");
- }
-
- return false;
- }
-
- // We are suppressing the 'deprecation' warning because the new method is only available starting with API
- // level 23 and that's much higher than our current minSdkLevel (1208580).
- @SuppressWarnings("deprecation")
- @Override
- public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
- Log.e(LOG_TAG, "Error loading search results: " + description);
-
- networkError = true;
-
- if (errorView == null) {
- final ViewStub errorViewStub = (ViewStub) getView().findViewById(R.id.error_view_stub);
- errorView = errorViewStub.inflate();
-
- ((ImageView) errorView.findViewById(R.id.empty_image)).setImageResource(R.drawable.network_error);
- ((TextView) errorView.findViewById(R.id.empty_title)).setText(R.string.network_error_title);
-
- final TextView message = (TextView) errorView.findViewById(R.id.empty_message);
- message.setText(R.string.network_error_message);
- message.setTextColor(ContextCompat.getColor(view.getContext(), R.color.network_error_link));
- message.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(new Intent(Settings.ACTION_SETTINGS));
- }
- });
- }
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- // Make sure the error view is hidden if the network error was fixed.
- if (errorView != null) {
- errorView.setVisibility(networkError ? View.VISIBLE : View.GONE);
- webview.setVisibility(networkError ? View.GONE : View.VISIBLE);
- }
-
- if (!TextUtils.equals(url, Constants.ABOUT_BLANK) && resultsPageHost == null) {
- try {
- resultsPageHost = new URL(url).getHost();
- } catch (MalformedURLException e) {
- Log.e(LOG_TAG, "Error getting host from results page URL", e);
- }
- }
- }
- }
-
- /**
- * A custom WebChromeClient that allows us to inject CSS into
- * the head of the HTML and to monitor pageload progress.
- *
- * We use the WebChromeClient because it provides a hook to the titleReceived
- * event. Once the title is available, the page will have started parsing the
- * head element. The script injects its CSS into the head element.
- */
- private class ChromeClient extends WebChromeClient {
-
- @Override
- public void onReceivedTitle(final WebView view, String title) {
- view.loadUrl(engine.getInjectableJs());
- }
-
- @Override
- public void onProgressChanged(WebView view, int newProgress) {
- if (newProgress < 100) {
- if (progressBar.getVisibility() == View.INVISIBLE) {
- progressBar.setVisibility(View.VISIBLE);
- }
- progressBar.setProgress(newProgress);
- } else {
- progressBar.setVisibility(View.INVISIBLE);
- }
- }
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java b/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java
deleted file mode 100644
index 107b82c5c..000000000
--- a/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.CursorLoader;
-import android.support.v4.content.Loader;
-import android.support.v4.widget.SimpleCursorAdapter;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.widget.AdapterView;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import org.mozilla.gecko.GeckoApplication;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserContract.SearchHistory;
-import org.mozilla.gecko.widget.SwipeDismissListViewTouchListener;
-import org.mozilla.gecko.widget.SwipeDismissListViewTouchListener.OnDismissCallback;
-import org.mozilla.search.AcceptsSearchQuery.SuggestionAnimation;
-
-/**
- * This fragment is responsible for managing the card stream.
- */
-public class PreSearchFragment extends Fragment {
-
- private static final String LOG_TAG = "PreSearchFragment";
-
- private AcceptsSearchQuery searchListener;
- private SimpleCursorAdapter cursorAdapter;
-
- private ListView listView;
- private View emptyView;
-
- private static final String[] PROJECTION = new String[]{ SearchHistory.QUERY, SearchHistory._ID };
-
- // Limit search history query results to 10 items.
- private static final int SEARCH_HISTORY_LIMIT = 10;
-
- private static final Uri SEARCH_HISTORY_URI = SearchHistory.CONTENT_URI.buildUpon().
- appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(SEARCH_HISTORY_LIMIT)).build();
-
- private static final int LOADER_ID_SEARCH_HISTORY = 1;
-
- public PreSearchFragment() {
- // Mandatory empty constructor for Android's Fragment.
- }
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
-
- if (context instanceof AcceptsSearchQuery) {
- searchListener = (AcceptsSearchQuery) context;
- } else {
- throw new ClassCastException(context.toString() + " must implement AcceptsSearchQuery.");
- }
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- searchListener = null;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getLoaderManager().initLoader(LOADER_ID_SEARCH_HISTORY, null, new SearchHistoryLoaderCallbacks());
- cursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.search_history_row, null,
- PROJECTION, new int[]{R.id.site_name}, 0);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- getLoaderManager().destroyLoader(LOADER_ID_SEARCH_HISTORY);
- cursorAdapter.swapCursor(null);
- cursorAdapter = null;
-
- GeckoApplication.watchReference(getActivity(), this);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- final View mainView = inflater.inflate(R.layout.search_fragment_pre_search, container, false);
-
- // Initialize listview.
- listView = (ListView) mainView.findViewById(R.id.list_view);
- listView.setAdapter(cursorAdapter);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final String query = getQueryAtPosition(position);
- if (!TextUtils.isEmpty(query)) {
- final Rect startBounds = new Rect();
- view.getGlobalVisibleRect(startBounds);
-
- Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.SUGGESTION, "history");
-
- searchListener.onSearch(query, new SuggestionAnimation() {
- @Override
- public Rect getStartBounds() {
- return startBounds;
- }
- });
- }
- }
- });
-
- // Create a ListView-specific touch listener. ListViews are given special treatment because
- // by default they handle touches for their list items... i.e. they're in charge of drawing
- // the pressed state (the list selector), handling list item clicks, etc.
- final SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(listView, new OnDismissCallback() {
- @Override
- public void onDismiss(ListView listView, final int position) {
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- final String query = getQueryAtPosition(position);
- final int deleted = getActivity().getContentResolver().delete(
- SearchHistory.CONTENT_URI,
- SearchHistory.QUERY + " = ?",
- new String[] { query });
-
- if (deleted < 1) {
- Log.w(LOG_TAG, "Search query not deleted: " + query);
- }
- return null;
- }
- }.execute();
- }
- });
- listView.setOnTouchListener(touchListener);
-
- // Setting this scroll listener is required to ensure that during ListView scrolling,
- // we don't look for swipes.
- listView.setOnScrollListener(touchListener.makeScrollListener());
-
- // Setting this recycler listener is required to make sure animated views are reset.
- listView.setRecyclerListener(touchListener.makeRecyclerListener());
-
- return mainView;
- }
-
- private String getQueryAtPosition(int position) {
- final Cursor c = cursorAdapter.getCursor();
- if (c == null || !c.moveToPosition(position)) {
- return null;
- }
- return c.getString(c.getColumnIndexOrThrow(SearchHistory.QUERY));
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- listView.setAdapter(null);
- listView = null;
- emptyView = null;
- }
-
- private void updateUiFromCursor(Cursor c) {
- if (c != null && c.getCount() > 0) {
- return;
- }
-
- if (emptyView == null) {
- final ViewStub emptyViewStub = (ViewStub) getView().findViewById(R.id.empty_view_stub);
- emptyView = emptyViewStub.inflate();
-
- ((ImageView) emptyView.findViewById(R.id.empty_image)).setImageResource(R.drawable.icon_search_empty_firefox);
- ((TextView) emptyView.findViewById(R.id.empty_title)).setText(R.string.search_empty_title);
- ((TextView) emptyView.findViewById(R.id.empty_message)).setText(R.string.search_empty_message);
-
- listView.setEmptyView(emptyView);
- }
- }
-
- private class SearchHistoryLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
- @Override
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- return new CursorLoader(getActivity(), SEARCH_HISTORY_URI, PROJECTION, null, null,
- SearchHistory.DATE_LAST_VISITED + " DESC");
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
- if (cursorAdapter != null) {
- cursorAdapter.swapCursor(c);
- }
- updateUiFromCursor(c);
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- if (cursorAdapter != null) {
- cursorAdapter.swapCursor(null);
- }
- }
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/SearchActivity.java b/mobile/android/search/java/org/mozilla/search/SearchActivity.java
deleted file mode 100644
index b013d77b4..000000000
--- a/mobile/android/search/java/org/mozilla/search/SearchActivity.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search;
-
-import android.support.annotation.NonNull;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.Locales;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserContract.SearchHistory;
-import org.mozilla.gecko.distribution.Distribution;
-import org.mozilla.gecko.search.SearchEngine;
-import org.mozilla.gecko.search.SearchEngineManager;
-import org.mozilla.gecko.search.SearchEngineManager.SearchEngineCallback;
-import org.mozilla.search.autocomplete.SearchBar;
-import org.mozilla.search.autocomplete.SuggestionsFragment;
-
-import android.content.AsyncQueryHandler;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-
-/**
- * The main entrance for the Android search intent.
- * <p/>
- * State management is delegated to child fragments. Fragments communicate
- * with each other by passing messages through this activity.
- */
-public class SearchActivity extends Locales.LocaleAwareFragmentActivity
- implements AcceptsSearchQuery, SearchEngineCallback {
-
- private static final String LOGTAG = "GeckoSearchActivity";
-
- private static final String KEY_SEARCH_STATE = "search_state";
- private static final String KEY_EDIT_STATE = "edit_state";
- private static final String KEY_QUERY = "query";
-
- static enum SearchState {
- PRESEARCH,
- POSTSEARCH
- }
-
- static enum EditState {
- WAITING,
- EDITING
- }
-
- // Default states when activity is created.
- private SearchState searchState = SearchState.PRESEARCH;
- private EditState editState = EditState.WAITING;
-
- @NonNull
- private SearchEngineManager searchEngineManager; // Contains reference to Context - DO NOT LEAK!
-
- // Only accessed on the main thread.
- private SearchEngine engine;
-
- private SuggestionsFragment suggestionsFragment;
- private PostSearchFragment postSearchFragment;
-
- private AsyncQueryHandler queryHandler;
-
- // Main views in layout.
- private SearchBar searchBar;
- private View preSearch;
- private View postSearch;
-
- private View settingsButton;
-
- private View suggestions;
-
- private static final int SUGGESTION_TRANSITION_DURATION = 300;
- private static final Interpolator SUGGESTION_TRANSITION_INTERPOLATOR =
- new AccelerateDecelerateInterpolator();
-
- // View used for suggestion animation.
- private View animationCard;
-
- // Suggestion card background padding.
- private int cardPaddingX;
- private int cardPaddingY;
-
- /**
- * An empty implementation of AsyncQueryHandler to avoid the "HandlerLeak" warning from Android
- * Lint. See also {@see org.mozilla.gecko.util.WeakReferenceHandler}.
- */
- private static class AsyncQueryHandlerImpl extends AsyncQueryHandler {
- public AsyncQueryHandlerImpl(final ContentResolver that) {
- super(that);
- }
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- GeckoAppShell.ensureCrashHandling();
-
- super.onCreate(savedInstanceState);
- setContentView(R.layout.search_activity_main);
-
- suggestionsFragment = (SuggestionsFragment) getSupportFragmentManager().findFragmentById(R.id.suggestions);
- postSearchFragment = (PostSearchFragment) getSupportFragmentManager().findFragmentById(R.id.postsearch);
-
- searchEngineManager = new SearchEngineManager(this, Distribution.init(getApplicationContext()));
- searchEngineManager.setChangeCallback(this);
-
- // Initialize the fragments with the selected search engine.
- searchEngineManager.getEngine(this);
-
- queryHandler = new AsyncQueryHandlerImpl(getContentResolver());
-
- searchBar = (SearchBar) findViewById(R.id.search_bar);
- searchBar.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setEditState(EditState.EDITING);
- }
- });
-
- searchBar.setTextListener(new SearchBar.TextListener() {
- @Override
- public void onChange(String text) {
- // Only load suggestions if we're in edit mode.
- if (editState == EditState.EDITING) {
- suggestionsFragment.loadSuggestions(text);
- }
- }
-
- @Override
- public void onSubmit(String text) {
- // Don't submit an empty query.
- final String trimmedQuery = text.trim();
- if (!TextUtils.isEmpty(trimmedQuery)) {
- onSearch(trimmedQuery);
- }
- }
-
- @Override
- public void onFocusChange(boolean hasFocus) {
- setEditState(hasFocus ? EditState.EDITING : EditState.WAITING);
- }
- });
-
- preSearch = findViewById(R.id.presearch);
- postSearch = findViewById(R.id.postsearch);
-
- settingsButton = findViewById(R.id.settings_button);
-
- // Apply click handler to settings button.
- settingsButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(new Intent(SearchActivity.this, SearchPreferenceActivity.class));
- }
- });
-
- suggestions = findViewById(R.id.suggestions);
-
- animationCard = findViewById(R.id.animation_card);
-
- cardPaddingX = getResources().getDimensionPixelSize(R.dimen.search_row_padding);
- cardPaddingY = getResources().getDimensionPixelSize(R.dimen.search_row_padding);
-
- if (savedInstanceState != null) {
- setSearchState(SearchState.valueOf(savedInstanceState.getString(KEY_SEARCH_STATE)));
- setEditState(EditState.valueOf(savedInstanceState.getString(KEY_EDIT_STATE)));
-
- final String query = savedInstanceState.getString(KEY_QUERY);
- searchBar.setText(query);
-
- // If we're in the postsearch state, we need to re-do the query.
- if (searchState == SearchState.POSTSEARCH) {
- startSearch(query);
- }
- } else {
- // If there isn't a state to restore, the activity will start in the presearch state,
- // and we should enter editing mode to bring up the keyboard.
- setEditState(EditState.EDITING);
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- searchEngineManager.unregisterListeners();
- engine = null;
- suggestionsFragment = null;
- postSearchFragment = null;
- queryHandler = null;
- searchBar = null;
- preSearch = null;
- postSearch = null;
- settingsButton = null;
- suggestions = null;
- animationCard = null;
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- Telemetry.startUISession(TelemetryContract.Session.SEARCH_ACTIVITY);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- Telemetry.stopUISession(TelemetryContract.Session.SEARCH_ACTIVITY);
- }
-
- @Override
- public void onNewIntent(Intent intent) {
- // Reset the activity in the presearch state if it was launched from a new intent.
- setSearchState(SearchState.PRESEARCH);
-
- // Enter editing mode and reset the query. We must reset the query after entering
- // edit mode in order for the suggestions to update.
- setEditState(EditState.EDITING);
- searchBar.setText("");
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- outState.putString(KEY_SEARCH_STATE, searchState.toString());
- outState.putString(KEY_EDIT_STATE, editState.toString());
- outState.putString(KEY_QUERY, searchBar.getText());
- }
-
- @Override
- public void onSuggest(String query) {
- searchBar.setText(query);
- }
-
- @Override
- public void onSearch(String query) {
- onSearch(query, null);
- }
-
- @Override
- public void onSearch(String query, SuggestionAnimation suggestionAnimation) {
- storeQuery(query);
-
- try {
- //BrowserHealthRecorder.recordSearchDelayed("activity", engine.getIdentifier());
- } catch (Exception e) {
- // This should never happen: it'll only throw if the
- // search location is wrong. But let's not tempt fate.
- Log.w(LOGTAG, "Unable to record search.");
- }
-
- startSearch(query);
-
- if (suggestionAnimation != null) {
- searchBar.setText(query);
- // Animate the suggestion card if start bounds are specified.
- animateSuggestion(suggestionAnimation);
- } else {
- // Otherwise immediately switch to the results view.
- setEditState(EditState.WAITING);
- setSearchState(SearchState.POSTSEARCH);
- }
- }
-
- @Override
- public void onQueryChange(String query) {
- searchBar.setText(query);
- }
-
- private void startSearch(final String query) {
- if (engine != null) {
- postSearchFragment.startSearch(engine, query);
- return;
- }
-
- // engine will only be null if startSearch is called before the getEngine
- // call in onCreate is completed.
- searchEngineManager.getEngine(new SearchEngineCallback() {
- @Override
- public void execute(SearchEngine engine) {
- // TODO: If engine is null, we should show an error message.
- if (engine != null) {
- postSearchFragment.startSearch(engine, query);
- }
- }
- });
- }
-
- /**
- * This method is called when we fetch the current engine in onCreate,
- * as well as whenever the current engine changes. This method will only
- * ever be called on the main thread.
- *
- * @param engine The current search engine.
- */
- @Override
- public void execute(SearchEngine engine) {
- // TODO: If engine is null, we should show an error message.
- if (engine == null) {
- return;
- }
- this.engine = engine;
- suggestionsFragment.setEngine(engine);
- searchBar.setEngine(engine);
- }
-
- /**
- * Animates search suggestion item to fill the results view area.
- *
- * @param suggestionAnimation
- */
- private void animateSuggestion(final SuggestionAnimation suggestionAnimation) {
- final Rect startBounds = suggestionAnimation.getStartBounds();
- final Rect endBounds = new Rect();
- animationCard.getGlobalVisibleRect(endBounds, null);
-
- // Vertically translate the animated card to align with the start bounds.
- final float cardStartY = startBounds.centerY() - endBounds.centerY();
-
- // Account for card background padding when calculating start scale.
- final float startScaleX = (float) (startBounds.width() - cardPaddingX * 2) / endBounds.width();
- final float startScaleY = (float) (startBounds.height() - cardPaddingY * 2) / endBounds.height();
-
- animationCard.setVisibility(View.VISIBLE);
-
- final AnimatorSet set = new AnimatorSet();
- set.playTogether(
- ObjectAnimator.ofFloat(animationCard, "translationY", cardStartY, 0),
- ObjectAnimator.ofFloat(animationCard, "alpha", 0.5f, 1),
- ObjectAnimator.ofFloat(animationCard, "scaleX", startScaleX, 1f),
- ObjectAnimator.ofFloat(animationCard, "scaleY", startScaleY, 1f)
- );
-
- set.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- // Don't do anything if the activity is destroyed before the animation ends.
- if (searchEngineManager == null) {
- return;
- }
-
- setEditState(EditState.WAITING);
- setSearchState(SearchState.POSTSEARCH);
-
- // We need to manually clear the animation for the views to be hidden on gingerbread.
- animationCard.clearAnimation();
- animationCard.setVisibility(View.INVISIBLE);
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
- });
-
- set.setDuration(SUGGESTION_TRANSITION_DURATION);
- set.setInterpolator(SUGGESTION_TRANSITION_INTERPOLATOR);
-
- set.start();
- }
-
- private void setEditState(EditState editState) {
- if (this.editState == editState) {
- return;
- }
- this.editState = editState;
-
- updateSettingsButtonVisibility();
-
- searchBar.setActive(editState == EditState.EDITING);
- suggestions.setVisibility(editState == EditState.EDITING ? View.VISIBLE : View.INVISIBLE);
- }
-
- private void setSearchState(SearchState searchState) {
- if (this.searchState == searchState) {
- return;
- }
- this.searchState = searchState;
-
- updateSettingsButtonVisibility();
-
- preSearch.setVisibility(searchState == SearchState.PRESEARCH ? View.VISIBLE : View.INVISIBLE);
- postSearch.setVisibility(searchState == SearchState.POSTSEARCH ? View.VISIBLE : View.INVISIBLE);
- }
-
- private void updateSettingsButtonVisibility() {
- // Show button on launch screen when keyboard is down.
- if (searchState == SearchState.PRESEARCH && editState == EditState.WAITING) {
- settingsButton.setVisibility(View.VISIBLE);
- } else {
- settingsButton.setVisibility(View.INVISIBLE);
- }
- }
-
- @Override
- public void onBackPressed() {
- if (editState == EditState.EDITING) {
- setEditState(EditState.WAITING);
- } else if (searchState == SearchState.POSTSEARCH) {
- setSearchState(SearchState.PRESEARCH);
- } else {
- super.onBackPressed();
- }
- }
-
- /**
- * Store the search query in Fennec's search history database.
- */
- private void storeQuery(String query) {
- final ContentValues cv = new ContentValues();
- cv.put(SearchHistory.QUERY, query);
- // Setting 0 for the token, since we only have one type of insert.
- // Setting null for the cookie, since we don't handle the result of the insert.
- queryHandler.startInsert(0, null, SearchHistory.CONTENT_URI, cv);
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java b/mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
deleted file mode 100644
index 6d33da130..000000000
--- a/mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search;
-
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.Locales;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserContract;
-
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.util.Log;
-import android.view.MenuItem;
-import android.widget.Toast;
-
-/**
- * This activity allows users to modify the settings for the search activity.
- *
- * A note on implementation: At the moment, we don't have tablet-specific designs.
- * Therefore, this implementation uses the old-style PreferenceActivity. When
- * we start optimizing for tablets, we can migrate to Fennec's PreferenceFragment
- * implementation.
- *
- * TODO: Change this to PreferenceFragment when we stop supporting devices older than SDK 11.
- */
-public class SearchPreferenceActivity extends PreferenceActivity {
-
- private static final String LOG_TAG = "SearchPreferenceActivity";
-
- public static final String PREF_CLEAR_HISTORY_KEY = "search.not_a_preference.clear_history";
-
- @Override
- @SuppressWarnings("deprecation")
- protected void onCreate(Bundle savedInstanceState) {
- Locales.initializeLocale(getApplicationContext());
- super.onCreate(savedInstanceState);
-
- getPreferenceManager().setSharedPreferencesName(GeckoSharedPrefs.APP_PREFS_NAME);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- if (getActionBar() != null) {
- getActionBar().setDisplayHomeAsUpEnabled(true);
- }
- }
- }
-
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- setupPrefsScreen();
- }
-
- @SuppressWarnings("deprecation")
- private void setupPrefsScreen() {
- addPreferencesFromResource(R.xml.search_preferences);
-
- // Attach click listener to clear history button.
- final Preference clearHistoryButton = findPreference(PREF_CLEAR_HISTORY_KEY);
- clearHistoryButton.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(SearchPreferenceActivity.this);
- dialogBuilder.setNegativeButton(android.R.string.cancel, null);
- dialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Telemetry.sendUIEvent(TelemetryContract.Event.SANITIZE, TelemetryContract.Method.MENU, "search-history");
- clearHistory();
- }
- });
- dialogBuilder.setMessage(R.string.pref_clearHistory_dialogMessage);
- dialogBuilder.show();
- return false;
- }
- });
- }
-
- private void clearHistory() {
- final AsyncTask<Void, Void, Boolean> clearHistoryTask = new AsyncTask<Void, Void, Boolean>() {
- @Override
- protected Boolean doInBackground(Void... params) {
- final int numDeleted = getContentResolver().delete(
- BrowserContract.SearchHistory.CONTENT_URI, null, null);
- return numDeleted >= 0;
- }
-
- @Override
- protected void onPostExecute(Boolean success) {
- if (success) {
- getContentResolver().notifyChange(BrowserContract.SearchHistory.CONTENT_URI, null);
- Toast.makeText(SearchPreferenceActivity.this, SearchPreferenceActivity.this.getResources()
- .getString(R.string.pref_clearHistory_confirmation), Toast.LENGTH_SHORT).show();
- } else {
- Log.e(LOG_TAG, "Error clearing search history.");
- }
- }
- };
- clearHistoryTask.execute();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == android.R.id.home) {
- finish();
- return true;
- }
- return false;
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/SearchWidget.java b/mobile/android/search/java/org/mozilla/search/SearchWidget.java
deleted file mode 100644
index 8f69cc22c..000000000
--- a/mobile/android/search/java/org/mozilla/search/SearchWidget.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search;
-
-import org.mozilla.gecko.AboutPages;
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProvider;
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.widget.RemoteViews;
-
-/* Provides a really simple widget with two buttons, one to launch Fennec
- * and one to launch the search activity. All intents are actually sent back
- * here and then forwarded on to start the real activity. */
-public class SearchWidget extends AppWidgetProvider {
- final private static String LOGTAG = "GeckoSearchWidget";
-
- final public static String ACTION_LAUNCH_BROWSER = "org.mozilla.widget.LAUNCH_BROWSER";
- final public static String ACTION_LAUNCH_SEARCH = "org.mozilla.widget.LAUNCH_SEARCH";
- final public static String ACTION_LAUNCH_NEW_TAB = "org.mozilla.widget.LAUNCH_NEW_TAB";
-
- @TargetApi(16)
- @Override
- public void onUpdate(final Context context, final AppWidgetManager manager, final int[] ids) {
- for (int id : ids) {
- final Bundle bundle;
- if (AppConstants.Versions.feature16Plus) {
- bundle = manager.getAppWidgetOptions(id);
- } else {
- bundle = null;
- }
- addView(manager, context, id, bundle);
- }
-
- super.onUpdate(context, manager, ids);
- }
-
- @TargetApi(16)
- @Override
- public void onAppWidgetOptionsChanged(final Context context,
- final AppWidgetManager manager,
- final int id,
- final Bundle options) {
- addView(manager, context, id, options);
- if (AppConstants.Versions.feature16Plus) {
- super.onAppWidgetOptionsChanged(context, manager, id, options);
- }
- }
-
- @Override
- public void onReceive(final Context context, final Intent intent) {
- // This will hold the intent to redispatch.
- final Intent redirect;
- switch (intent.getAction()) {
- case ACTION_LAUNCH_BROWSER:
- redirect = buildRedirectIntent(Intent.ACTION_MAIN,
- context.getPackageName(),
- AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS,
- intent);
- Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
- TelemetryContract.Method.WIDGET, "browser");
- break;
- case ACTION_LAUNCH_NEW_TAB:
- redirect = buildRedirectIntent(Intent.ACTION_VIEW,
- context.getPackageName(),
- AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS,
- intent);
- Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
- TelemetryContract.Method.WIDGET, "new-tab");
- break;
- case ACTION_LAUNCH_SEARCH:
- redirect = buildRedirectIntent(Intent.ACTION_VIEW,
- context.getPackageName(),
- AppConstants.MOZ_ANDROID_SEARCH_INTENT_CLASS,
- intent);
- Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
- TelemetryContract.Method.WIDGET, "search");
- break;
- default:
- redirect = null;
- }
-
- if (redirect != null) {
- context.startActivity(redirect);
- }
-
- super.onReceive(context, intent);
- }
-
- // Utility to create the view for this widget and attach any event listeners to it
- private void addView(final AppWidgetManager manager, final Context context, final int id, final Bundle options) {
- final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.search_widget);
-
- addClickIntent(context, views, R.id.search_button, ACTION_LAUNCH_SEARCH);
- addClickIntent(context, views, R.id.new_tab_button, ACTION_LAUNCH_NEW_TAB);
- // Clicking the logo also launches the browser
- addClickIntent(context, views, R.id.logo_button, ACTION_LAUNCH_BROWSER);
-
- manager.updateAppWidget(id, views);
- }
-
- // Utility for adding a pending intent to be fired when a View is clicked.
- private void addClickIntent(final Context context, final RemoteViews views, final int viewId, final String action) {
- final Intent intent = new Intent(context, SearchWidget.class);
- intent.setAction(action);
- intent.setData(Uri.parse(AboutPages.HOME));
- final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
- views.setOnClickPendingIntent(viewId, pendingIntent);
- }
-
- // Utility for building an intent to be redispatched (i.e. to launch the browser or the search intent).
- private Intent buildRedirectIntent(final String action, final String pkg, final String className, final Intent source) {
- final Intent activity = new Intent(action);
- if (pkg != null && className != null) {
- activity.setClassName(pkg, className);
- }
- activity.setData(source.getData());
- activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- return activity;
- }
-
-}
diff --git a/mobile/android/search/java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java b/mobile/android/search/java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java
deleted file mode 100644
index 5a0cc8fb6..000000000
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search.autocomplete;
-
-import java.util.List;
-
-import org.mozilla.gecko.R;
-import org.mozilla.search.AcceptsSearchQuery;
-import org.mozilla.search.autocomplete.SuggestionsFragment.Suggestion;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-/**
- * The adapter that is used to populate the autocomplete rows.
- */
-class AutoCompleteAdapter extends ArrayAdapter<Suggestion> {
-
- private final AcceptsSearchQuery searchListener;
-
- private final LayoutInflater inflater;
-
- public AutoCompleteAdapter(Context context) {
- // Uses '0' for the template id since we are overriding getView
- // and supplying our own view.
- super(context, 0);
-
- if (context instanceof AcceptsSearchQuery) {
- searchListener = (AcceptsSearchQuery) context;
- } else {
- throw new ClassCastException(context.toString() + " must implement AcceptsSearchQuery.");
- }
-
- // Disable notifying on change. We will notify ourselves in update.
- setNotifyOnChange(false);
-
- inflater = LayoutInflater.from(context);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = inflater.inflate(R.layout.search_suggestions_row, null);
- }
-
- final Suggestion suggestion = getItem(position);
-
- final TextView textView = (TextView) convertView.findViewById(R.id.auto_complete_row_text);
- textView.setText(suggestion.display);
-
- final View jumpButton = convertView.findViewById(R.id.auto_complete_row_jump_button);
- jumpButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- searchListener.onSuggest(suggestion.value);
- }
- });
-
- return convertView;
- }
-
- /**
- * Updates adapter content with new list of search suggestions.
- *
- * @param suggestions List of search suggestions.
- */
- public void update(List<Suggestion> suggestions) {
- clear();
- if (suggestions != null) {
- for (Suggestion s : suggestions) {
- add(s);
- }
- }
- notifyDataSetChanged();
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/autocomplete/SearchBar.java b/mobile/android/search/java/org/mozilla/search/autocomplete/SearchBar.java
deleted file mode 100644
index 6225c050b..000000000
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/SearchBar.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search.autocomplete;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.gfx.BitmapUtils;
-import org.mozilla.gecko.search.SearchEngine;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-public class SearchBar extends FrameLayout {
-
- private final EditText editText;
- private final ImageButton clearButton;
- private final ImageView engineIcon;
-
- private final Drawable focusedBackground;
- private final Drawable defaultBackground;
-
- private final InputMethodManager inputMethodManager;
-
- private TextListener listener;
-
- private boolean active;
-
- public interface TextListener {
- public void onChange(String text);
- public void onSubmit(String text);
- public void onFocusChange(boolean hasFocus);
- }
-
- // Deprecation warnings suppressed to allow building with API level 22
- @SuppressWarnings("deprecation")
- public SearchBar(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- LayoutInflater.from(context).inflate(R.layout.search_bar, this);
-
- editText = (EditText) findViewById(R.id.edit_text);
- editText.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if (listener != null) {
- listener.onChange(s.toString());
- }
-
- updateClearButtonVisibility();
- }
- });
-
- // Attach a listener for the "search" key on the keyboard.
- editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if (listener != null &&
- (actionId == EditorInfo.IME_ACTION_UNSPECIFIED || actionId == EditorInfo.IME_ACTION_SEARCH)) {
- // The user searched without using search engine suggestions.
- Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.ACTIONBAR, "text");
- listener.onSubmit(v.getText().toString());
- return true;
- }
- return false;
- }
- });
-
- editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- if (listener != null) {
- listener.onFocusChange(hasFocus);
- }
- }
- });
-
- clearButton = (ImageButton) findViewById(R.id.clear_button);
- clearButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- editText.setText("");
- }
- });
- engineIcon = (ImageView) findViewById(R.id.engine_icon);
-
- focusedBackground = getResources().getDrawable(R.drawable.edit_text_focused);
- defaultBackground = getResources().getDrawable(R.drawable.edit_text_default);
-
- inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- }
-
- public void setText(String text) {
- editText.setText(text);
-
- // Move cursor to end of search input.
- editText.setSelection(text.length());
- }
-
- public String getText() {
- return editText.getText().toString();
- }
-
- public void setEngine(SearchEngine engine) {
- final String iconURL = engine.getIconURL();
- final Bitmap bitmap = BitmapUtils.getBitmapFromDataURI(iconURL);
- final BitmapDrawable d = new BitmapDrawable(getResources(), bitmap);
- engineIcon.setImageDrawable(d);
- engineIcon.setContentDescription(engine.getName());
-
- // Update the focused background color.
- int color = BitmapUtils.getDominantColor(bitmap);
-
- // BitmapUtils#getDominantColor ignores black and white pixels, but it will
- // return white if no dominant color was found. We don't want to create a
- // white underline for the search bar, so we default to black instead.
- if (color == Color.WHITE) {
- color = Color.BLACK;
- }
- focusedBackground.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
-
- editText.setHint(getResources().getString(R.string.search_bar_hint, engine.getName()));
- }
-
- @SuppressWarnings("deprecation")
- public void setActive(boolean active) {
- if (this.active == active) {
- return;
- }
- this.active = active;
-
- updateClearButtonVisibility();
-
- editText.setFocusable(active);
- editText.setFocusableInTouchMode(active);
-
- final int leftDrawable = active ? R.drawable.search_icon_active : R.drawable.search_icon_inactive;
- editText.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, 0, 0, 0);
-
- // We can't use a selector drawable because we apply a color filter to the focused
- // background at run time.
- // TODO: setBackgroundDrawable is deprecated in API level 16
- editText.setBackgroundDrawable(active ? focusedBackground : defaultBackground);
-
- if (active) {
- editText.requestFocus();
- inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
- } else {
- editText.clearFocus();
- inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
- }
- }
-
- private void updateClearButtonVisibility() {
- // Only show the clear button when there is text in the input.
- final boolean visible = active && (editText.getText().length() > 0);
- clearButton.setVisibility(visible ? View.VISIBLE : View.GONE);
- engineIcon.setVisibility(visible ? View.GONE : View.VISIBLE);
- }
-
- public void setTextListener(TextListener listener) {
- this.listener = listener;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent e) {
- // When the view is active, pass touch events to child views.
- // Otherwise, intercept touch events to allow click listeners on the view to
- // fire no matter where the user clicks.
- return !active;
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java b/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java
deleted file mode 100644
index ce935e437..000000000
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search.autocomplete;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import android.support.v4.content.ContextCompat;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.search.SearchEngine;
-import org.mozilla.gecko.SuggestClient;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.search.AcceptsSearchQuery;
-import org.mozilla.search.AcceptsSearchQuery.SuggestionAnimation;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.AsyncTaskLoader;
-import android.support.v4.content.Loader;
-import android.text.SpannableString;
-import android.text.style.ForegroundColorSpan;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ListView;
-
-/**
- * A fragment to show search suggestions.
- */
-public class SuggestionsFragment extends Fragment {
-
- private static final String LOG_TAG = "SuggestionsFragment";
-
- private static final int LOADER_ID_SUGGESTION = 0;
- private static final String KEY_SEARCH_TERM = "search_term";
-
- // Timeout for the suggestion client to respond
- private static final int SUGGESTION_TIMEOUT = 3000;
-
- // Number of search suggestions to show.
- private static final int SUGGESTION_MAX = 5;
-
- public static final String GECKO_SEARCH_TERMS_URL_PARAM = "__searchTerms__";
-
- private AcceptsSearchQuery searchListener;
-
- // Suggest client gets setup outside of the normal fragment lifecycle, therefore
- // clients should ensure that this isn't null before using it.
- private SuggestClient suggestClient;
- private SuggestionLoaderCallbacks suggestionLoaderCallbacks;
-
- private AutoCompleteAdapter autoCompleteAdapter;
-
- // Holds the list of search suggestions.
- private ListView suggestionsList;
-
- public SuggestionsFragment() {
- // Required empty public constructor
- }
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
-
- if (context instanceof AcceptsSearchQuery) {
- searchListener = (AcceptsSearchQuery) context;
- } else {
- throw new ClassCastException(context.toString() + " must implement AcceptsSearchQuery.");
- }
-
- suggestionLoaderCallbacks = new SuggestionLoaderCallbacks();
- autoCompleteAdapter = new AutoCompleteAdapter(context);
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
-
- searchListener = null;
- suggestionLoaderCallbacks = null;
- autoCompleteAdapter = null;
- suggestClient = null;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- suggestionsList = (ListView) inflater.inflate(R.layout.search_sugestions, container, false);
- suggestionsList.setAdapter(autoCompleteAdapter);
-
- // Attach listener for tapping on a suggestion.
- suggestionsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final Suggestion suggestion = (Suggestion) suggestionsList.getItemAtPosition(position);
-
- final Rect startBounds = new Rect();
- view.getGlobalVisibleRect(startBounds);
-
- // The user tapped on a suggestion from the search engine.
- Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.SUGGESTION, position);
-
- searchListener.onSearch(suggestion.value, new SuggestionAnimation() {
- @Override
- public Rect getStartBounds() {
- return startBounds;
- }
- });
- }
- });
-
- return suggestionsList;
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
-
- if (null != suggestionsList) {
- suggestionsList.setOnItemClickListener(null);
- suggestionsList.setAdapter(null);
- suggestionsList = null;
- }
- }
-
- public void setEngine(SearchEngine engine) {
- suggestClient = new SuggestClient(getActivity(), engine.getSuggestionTemplate(GECKO_SEARCH_TERMS_URL_PARAM),
- SUGGESTION_TIMEOUT, SUGGESTION_MAX, true);
- }
-
- public void loadSuggestions(String query) {
- final Bundle args = new Bundle();
- args.putString(KEY_SEARCH_TERM, query);
- final LoaderManager loaderManager = getLoaderManager();
-
- // Ensure that we don't try to restart a loader that doesn't exist. This becomes
- // an issue because SuggestionLoaderCallbacks.onCreateLoader can return null
- // as a loader if we don't have a suggestClient available yet.
- if (loaderManager.getLoader(LOADER_ID_SUGGESTION) == null) {
- loaderManager.initLoader(LOADER_ID_SUGGESTION, args, suggestionLoaderCallbacks);
- } else {
- loaderManager.restartLoader(LOADER_ID_SUGGESTION, args, suggestionLoaderCallbacks);
- }
- }
-
- public static class Suggestion {
-
- public final String value;
- public final SpannableString display;
- public final ForegroundColorSpan colorSpan;
-
- public Suggestion(String value, String searchTerm, int suggestionHighlightColor) {
- this.value = value;
-
- display = new SpannableString(value);
-
- colorSpan = new ForegroundColorSpan(suggestionHighlightColor);
-
- // Highlight mixed-case matches.
- final int start = value.toLowerCase().indexOf(searchTerm.toLowerCase());
- if (start >= 0) {
- display.setSpan(colorSpan, start, start + searchTerm.length(), 0);
- }
- }
- }
-
- private class SuggestionLoaderCallbacks implements LoaderManager.LoaderCallbacks<List<Suggestion>> {
- @Override
- public Loader<List<Suggestion>> onCreateLoader(int id, Bundle args) {
- // We drop the user's search if suggestclient isn't ready. This happens if the
- // user is really fast and starts typing before we can read shared prefs.
- if (suggestClient != null) {
- return new SuggestionAsyncLoader(getActivity(), suggestClient, args.getString(KEY_SEARCH_TERM));
- }
- Log.e(LOG_TAG, "Autocomplete setup failed; suggestClient not ready yet.");
- return null;
- }
-
- @Override
- public void onLoadFinished(Loader<List<Suggestion>> loader, List<Suggestion> suggestions) {
- // Only show the ListView if there are suggestions in it.
- if (suggestions.size() > 0) {
- autoCompleteAdapter.update(suggestions);
- suggestionsList.setVisibility(View.VISIBLE);
- } else {
- suggestionsList.setVisibility(View.INVISIBLE);
- }
- }
-
- @Override
- public void onLoaderReset(Loader<List<Suggestion>> loader) { }
- }
-
- private static class SuggestionAsyncLoader extends AsyncTaskLoader<List<Suggestion>> {
- private final SuggestClient suggestClient;
- private final String searchTerm;
- private List<Suggestion> suggestions;
- private final int suggestionHighlightColor;
-
- public SuggestionAsyncLoader(Context context, SuggestClient suggestClient, String searchTerm) {
- super(context);
- this.suggestClient = suggestClient;
- this.searchTerm = searchTerm;
- this.suggestions = null;
-
- // Color of search term match in search suggestion
- suggestionHighlightColor = ContextCompat.getColor(context, R.color.suggestion_highlight);
- }
-
- @Override
- public List<Suggestion> loadInBackground() {
- final List<String> values = suggestClient.query(searchTerm);
-
- final List<Suggestion> result = new ArrayList<Suggestion>(values.size());
- for (String value : values) {
- result.add(new Suggestion(value, searchTerm, suggestionHighlightColor));
- }
-
- return result;
- }
-
- @Override
- public void deliverResult(List<Suggestion> suggestions) {
- this.suggestions = suggestions;
-
- if (isStarted()) {
- super.deliverResult(suggestions);
- }
- }
-
- @Override
- protected void onStartLoading() {
- if (suggestions != null) {
- deliverResult(suggestions);
- }
-
- if (takeContentChanged() || suggestions == null) {
- forceLoad();
- }
- }
-
- @Override
- protected void onStopLoading() {
- cancelLoad();
- }
-
- @Override
- protected void onReset() {
- super.onReset();
-
- onStopLoading();
- suggestions = null;
- }
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java b/mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java
deleted file mode 100644
index 727ad8105..000000000
--- a/mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.widget.EditText;
-
-/**
- * An EditText subclass that loses focus when the keyboard
- * is dismissed.
- */
-public class BackCaptureEditText extends EditText {
- public BackCaptureEditText(Context context) {
- super(context);
- }
-
- public BackCaptureEditText(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public BackCaptureEditText(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public boolean onKeyPreIme(int keyCode, KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
- clearFocus();
- }
- return super.onKeyPreIme(keyCode, event);
- }
-}
diff --git a/mobile/android/search/java/org/mozilla/search/ui/FacetBar.java b/mobile/android/search/java/org/mozilla/search/ui/FacetBar.java
deleted file mode 100644
index 7fcf3dc9b..000000000
--- a/mobile/android/search/java/org/mozilla/search/ui/FacetBar.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.search.ui;
-
-import org.mozilla.gecko.R;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.widget.RadioButton;
-import android.widget.RadioGroup;
-
-public class FacetBar extends RadioGroup {
-
- // Ensure facets have equal width and match the bar's height. Supplying these
- // in styles.xml/FacetButtonStyle does not work. See:
- // http://stackoverflow.com/questions/24213193/android-ignores-layout-weight-parameter-from-styles-xml
- private static final RadioGroup.LayoutParams FACET_LAYOUT_PARAMS =
- new RadioGroup.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f);
-
- // A loud default color to make it obvious that setUnderlineColor should be called.
- private int underlineColor = Color.RED;
-
- // Used for assigning unique view ids when facet buttons are being created.
- private int nextButtonId = 0;
-
- public FacetBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Add a new button to the facet bar.
- *
- * @param facetName The text to be used in the button.
- */
- public void addFacet(String facetName) {
- addFacet(facetName, false);
- }
-
- /**
- * Add a new button to the facet bar.
- *
- * @param facetName The text to be used in the button.
- * @param checked Whether the button should be checked. If true, the
- * onCheckChange listener *will* be fired.
- */
- public void addFacet(String facetName, boolean checked) {
- final FacetButton button = new FacetButton(getContext(), facetName, underlineColor);
-
- // The ids are used internally by RadioGroup to manage which button is
- // currently checked. Since we are programmatically creating the buttons,
- // we need to manually assign an id.
- button.setId(nextButtonId++);
-
- // Ensure the buttons are equally spaced.
- button.setLayoutParams(FACET_LAYOUT_PARAMS);
-
- // If true, this will fire the onCheckChange listener.
- button.setChecked(checked);
-
- addView(button);
- }
-
- /**
- * Update the brand color for all of the buttons.
- */
- public void setUnderlineColor(int underlineColor) {
- this.underlineColor = underlineColor;
-
- if (getChildCount() > 0) {
- for (int i = 0; i < getChildCount(); i++) {
- ((FacetButton) getChildAt(i)).setUnderlineColor(underlineColor);
- }
- }
- }
-
- /**
- * A custom TextView that includes a bottom border. The bottom border
- * can have a custom color and thickness.
- */
- private static class FacetButton extends RadioButton {
-
- private final Paint underlinePaint = new Paint();
-
- public FacetButton(Context context, String text, int color) {
- super(context, null, R.attr.facetButtonStyle);
-
- setText(text);
-
- underlinePaint.setStyle(Paint.Style.STROKE);
- underlinePaint.setStrokeWidth(getResources().getDimension(R.dimen.facet_button_underline_thickness));
- underlinePaint.setColor(color);
- }
-
- @Override
- public void setChecked(boolean checked) {
- super.setChecked(checked);
-
- // Force the button to redraw to update the underline state.
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (isChecked()) {
- // Translate the line upward so that it isn't clipped by the button's boundary.
- // We divide by 2 since, without offset, the line would be drawn with its
- // midpoint at the bottom of the button -- half of the stroke going up,
- // and half of the stroke getting clipped.
- final float yPos = getHeight() - underlinePaint.getStrokeWidth() / 2;
- canvas.drawLine(0, yPos, getWidth(), yPos, underlinePaint);
- }
- }
-
- public void setUnderlineColor(int color) {
- underlinePaint.setColor(color);
- }
- }
-}