mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 769145 - Part 4: Add search suggestions opt-in prompt. r=mfinkle
This commit is contained in:
parent
84f54b9036
commit
29e297f18e
@ -250,6 +250,7 @@ pref("browser.search.updateinterval", 6);
|
||||
|
||||
// disable search suggestions by default
|
||||
pref("browser.search.suggest.enabled", false);
|
||||
pref("browser.search.suggest.prompted", false);
|
||||
|
||||
// Tell the search service to load search plugins from the locale JAR
|
||||
pref("browser.search.loadFromJars", true);
|
||||
|
@ -322,9 +322,11 @@ RES_LAYOUT = \
|
||||
res/layout/awesomebar_expandable_list.xml \
|
||||
res/layout/awesomebar_folder_row.xml \
|
||||
res/layout/awesomebar_header_row.xml \
|
||||
res/layout/awesomebar_allpages_list.xml \
|
||||
res/layout/awesomebar_list.xml \
|
||||
res/layout/awesomebar_row.xml \
|
||||
res/layout/awesomebar_suggestion_item.xml \
|
||||
res/layout/awesomebar_suggestion_prompt.xml \
|
||||
res/layout/awesomebar_suggestion_row.xml \
|
||||
res/layout/awesomebar_search.xml \
|
||||
res/layout/awesomebar_tab_indicator.xml \
|
||||
|
@ -58,6 +58,8 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
private AsyncTask<String, Void, ArrayList<String>> mSuggestTask;
|
||||
private AwesomeBarCursorAdapter mCursorAdapter = null;
|
||||
private boolean mTelemetrySent = false;
|
||||
private LinearLayout mAllPagesView;
|
||||
private View mSuggestionsOptInPrompt;
|
||||
|
||||
private class SearchEntryViewHolder {
|
||||
public FlowLayout suggestionView;
|
||||
@ -81,13 +83,12 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
public TabContentFactory getFactory() {
|
||||
return new TabContentFactory() {
|
||||
public View createTabContent(String tag) {
|
||||
final ListView list = getListView();
|
||||
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
handleItemClick(parent, view, position, id);
|
||||
}
|
||||
});
|
||||
return list;
|
||||
return getAllPagesView();
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -100,9 +101,16 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
private LinearLayout getAllPagesView() {
|
||||
if (mAllPagesView == null) {
|
||||
mAllPagesView = (LinearLayout) (LayoutInflater.from(mContext).inflate(R.layout.awesomebar_allpages_list, null));
|
||||
}
|
||||
return mAllPagesView;
|
||||
}
|
||||
|
||||
public ListView getListView() {
|
||||
if (mView == null) {
|
||||
mView = (ListView) (LayoutInflater.from(mContext).inflate(R.layout.awesomebar_list, null));
|
||||
mView = getAllPagesView().findViewById(R.id.awesomebar_list);
|
||||
((Activity)mContext).registerForContextMenu(mView);
|
||||
mView.setTag(TAG);
|
||||
AwesomeBarCursorAdapter adapter = getCursorAdapter();
|
||||
@ -129,6 +137,12 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
adapter.filter(searchTerm);
|
||||
|
||||
filterSuggestions(searchTerm);
|
||||
if (mSuggestionsOptInPrompt != null) {
|
||||
int visibility = searchTerm.isEmpty() ? View.GONE : View.VISIBLE;
|
||||
if (mSuggestionsOptInPrompt.getVisibility() != visibility) {
|
||||
mSuggestionsOptInPrompt.setVisibility(visibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void filterSuggestions(String searchTerm) {
|
||||
@ -408,8 +422,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
// add additional suggestions given by this engine
|
||||
int recycledSuggestionCount = suggestionView.getChildCount();
|
||||
int suggestionCount = engine.suggestions.size();
|
||||
int i = 0;
|
||||
for (i = 0; i < suggestionCount; i++) {
|
||||
for (int i = 0; i < suggestionCount; i++) {
|
||||
String suggestion = engine.suggestions.get(i);
|
||||
View suggestionItem = null;
|
||||
|
||||
@ -429,7 +442,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
}
|
||||
|
||||
// hide extra suggestions that have been recycled
|
||||
for (++i; i < recycledSuggestionCount; i++) {
|
||||
for (int i = suggestionCount + 1; i < recycledSuggestionCount; i++) {
|
||||
suggestionView.getChildAt(i).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
@ -455,7 +468,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
* Sets suggestions associated with the current suggest engine.
|
||||
* If there is no suggest engine, this does nothing.
|
||||
*/
|
||||
public void setSuggestions(final ArrayList<String> suggestions) {
|
||||
private void setSuggestions(final ArrayList<String> suggestions) {
|
||||
if (mSuggestClient != null) {
|
||||
mSearchEngines.get(0).suggestions = suggestions;
|
||||
getCursorAdapter().notifyDataSetChanged();
|
||||
@ -465,12 +478,14 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
/**
|
||||
* Sets search engines to be shown for user-entered queries.
|
||||
*/
|
||||
public void setSearchEngines(JSONObject data) {
|
||||
private void setSearchEngines(JSONObject data) {
|
||||
try {
|
||||
String suggestEngine = data.isNull("suggestEngine") ? null : data.getString("suggestEngine");
|
||||
String suggestTemplate = data.isNull("suggestTemplate") ? null : data.getString("suggestTemplate");
|
||||
JSONObject suggest = data.getJSONObject("suggest");
|
||||
String suggestEngine = suggest.isNull("engine") ? null : suggest.getString("engine");
|
||||
String suggestTemplate = suggest.isNull("template") ? null : suggest.getString("template");
|
||||
mSuggestionsEnabled = suggest.getBoolean("enabled");
|
||||
boolean suggestionsPrompted = suggest.getBoolean("prompted");
|
||||
JSONArray engines = data.getJSONArray("searchEngines");
|
||||
mSuggestionsEnabled = data.getBoolean("suggestEnabled");
|
||||
|
||||
mSearchEngines = new ArrayList<SearchEngine>();
|
||||
for (int i = 0; i < engines.length(); i++) {
|
||||
@ -486,6 +501,11 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
mSearchEngines.add(new SearchEngine(name, icon));
|
||||
}
|
||||
}
|
||||
|
||||
// show suggestions opt-in if user hasn't been prompted
|
||||
if (!suggestionsPrompted && mSuggestClient != null) {
|
||||
showSuggestionsOptIn();
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Error getting search engine JSON", e);
|
||||
}
|
||||
@ -507,6 +527,42 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
private void showSuggestionsOptIn() {
|
||||
mSuggestionsOptInPrompt = LayoutInflater.from(mContext).inflate(R.layout.awesomebar_suggestion_prompt, getAllPagesView(), false);
|
||||
((TextView) mSuggestionsOptInPrompt.findViewById(R.id.suggestions_prompt_title))
|
||||
.setText(getResources().getString(R.string.suggestions_prompt, mSearchEngines.get(0).name));
|
||||
mSuggestionsOptInPrompt.findViewById(R.id.suggestions_prompt_yes).setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
setSuggestionsEnabled(true);
|
||||
}
|
||||
});
|
||||
mSuggestionsOptInPrompt.findViewById(R.id.suggestions_prompt_no).setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
setSuggestionsEnabled(false);
|
||||
}
|
||||
});
|
||||
mSuggestionsOptInPrompt.setVisibility(View.GONE);
|
||||
getAllPagesView().addView(mSuggestionsOptInPrompt, 0);
|
||||
}
|
||||
|
||||
private void setSuggestionsEnabled(final boolean enabled) {
|
||||
// Pref observer in gecko will also set prompted = true
|
||||
PrefsHelper.setPref("browser.search.suggest.enabled", enabled);
|
||||
|
||||
getAllPagesView().post(new Runnable() {
|
||||
public void run() {
|
||||
getAllPagesView().removeView(mSuggestionsOptInPrompt);
|
||||
mSuggestionsOptInPrompt = null;
|
||||
|
||||
if (enabled) {
|
||||
mSuggestionsEnabled = enabled;
|
||||
getCursorAdapter().notifyDataSetChanged();
|
||||
filterSuggestions(mSearchTerm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void handleMessage(String event, final JSONObject message) {
|
||||
if (event.equals("SearchEngines:Data")) {
|
||||
GeckoAppShell.getMainHandler().post(new Runnable() {
|
||||
|
@ -12,7 +12,6 @@
|
||||
<!ENTITY awesomebar_all_pages_title "Top Sites">
|
||||
<!ENTITY awesomebar_bookmarks_title "Bookmarks">
|
||||
<!ENTITY awesomebar_history_title "History">
|
||||
<!ENTITY awesomebar_search_engine "Search for \"%s\"">
|
||||
|
||||
<!ENTITY crash_reporter_title "&brandShortName; Crash Reporter">
|
||||
<!ENTITY crash_message "&brandShortName; has crashed. Your tabs should be listed on the &brandShortName; Start page when you restart.">
|
||||
@ -171,6 +170,8 @@ size. -->
|
||||
|
||||
<!ENTITY button_ok "OK">
|
||||
<!ENTITY button_cancel "Cancel">
|
||||
<!ENTITY button_yes "Yes">
|
||||
<!ENTITY button_no "No">
|
||||
<!ENTITY button_clear_data "Clear data">
|
||||
<!ENTITY button_set "Set">
|
||||
<!ENTITY button_clear "Clear">
|
||||
@ -227,6 +228,11 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
||||
from Android">
|
||||
<!ENTITY bookmarkhistory_import_wait "Please wait...">
|
||||
|
||||
<!-- Localization note (suggestions_prompt): The placeholder (%s) should
|
||||
be kept in the string; this will be replaced with the name of the search
|
||||
engine. -->
|
||||
<!ENTITY suggestions_prompt "Would you like to turn on %s search suggestions?">
|
||||
|
||||
<!ENTITY webapp_generic_name "App">
|
||||
|
||||
<!-- Updater notifications -->
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/awesomebar_list"
|
||||
android:id="@+id/awesomebar_list"/>
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/awesomebar_row_height"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="10dip">
|
||||
|
||||
<TextView android:id="@+id/suggestions_prompt_title"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:layout_marginLeft="6dip"
|
||||
android:textSize="13sp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView android:id="@+id/suggestions_prompt_yes"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:textSize="13sp"
|
||||
android:layout_marginLeft="15dip"
|
||||
android:background="@drawable/suggestion_selector"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingTop="7dp"
|
||||
android:paddingBottom="7dp"
|
||||
android:clickable="true"
|
||||
android:text="@string/button_yes" />
|
||||
|
||||
<TextView android:id="@+id/suggestions_prompt_no"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:textSize="13sp"
|
||||
android:layout_marginLeft="6dip"
|
||||
android:background="@drawable/suggestion_selector"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingTop="7dp"
|
||||
android:paddingBottom="7dp"
|
||||
android:clickable="true"
|
||||
android:text="@string/button_no" />
|
||||
|
||||
</LinearLayout>
|
@ -20,7 +20,6 @@
|
||||
<string name="awesomebar_all_pages_title">&awesomebar_all_pages_title;</string>
|
||||
<string name="awesomebar_bookmarks_title">&awesomebar_bookmarks_title;</string>
|
||||
<string name="awesomebar_history_title">&awesomebar_history_title;</string>
|
||||
<string name="awesomebar_search_engine">&awesomebar_search_engine;</string>
|
||||
|
||||
<string name="crash_reporter_title">&crash_reporter_title;</string>
|
||||
<string name="crash_message">&crash_message;</string>
|
||||
@ -167,6 +166,8 @@
|
||||
<string name="button_clear_data">&button_clear_data;</string>
|
||||
<string name="button_set">&button_set;</string>
|
||||
<string name="button_clear">&button_clear;</string>
|
||||
<string name="button_yes">&button_yes;</string>
|
||||
<string name="button_no">&button_no;</string>
|
||||
|
||||
<string name="abouthome_addons_title">&abouthome_addons_title;</string>
|
||||
<string name="abouthome_addons_browse">&abouthome_addons_browse;</string>
|
||||
@ -231,4 +232,7 @@
|
||||
<string name="updater_apply_ticker">&updater_apply_ticker;</string>
|
||||
<string name="updater_apply_select">&updater_apply_select;</string>
|
||||
|
||||
<!-- Search suggestions opt-in -->
|
||||
<string name="suggestions_prompt">&suggestions_prompt;</string>
|
||||
|
||||
</resources>
|
||||
|
@ -922,6 +922,9 @@ var BrowserApp = {
|
||||
else
|
||||
MasterPassword.setPassword(json.value);
|
||||
return;
|
||||
} else if (json.name == SearchEngines.PREF_SUGGEST_ENABLED) {
|
||||
// Enabling or disabling suggestions will prevent future prompts
|
||||
Services.prefs.setBoolPref(SearchEngines.PREF_SUGGEST_PROMPTED, true);
|
||||
}
|
||||
|
||||
// when sending to java, we normalized special preferences that use
|
||||
@ -6102,6 +6105,8 @@ OverscrollController.prototype = {
|
||||
|
||||
var SearchEngines = {
|
||||
_contextMenuId: null,
|
||||
PREF_SUGGEST_ENABLED: "browser.search.suggest.enabled",
|
||||
PREF_SUGGEST_PROMPTED: "browser.search.suggest.prompted",
|
||||
|
||||
init: function init() {
|
||||
Services.obs.addObserver(this, "SearchEngines:Get", false);
|
||||
@ -6115,7 +6120,7 @@ var SearchEngines = {
|
||||
},
|
||||
|
||||
uninit: function uninit() {
|
||||
Services.obs.removeObserver(this, "SearchEngines:Get", false);
|
||||
Services.obs.removeObserver(this, "SearchEngines:Get");
|
||||
if (this._contextMenuId != null)
|
||||
NativeWindow.contextmenus.remove(this._contextMenuId);
|
||||
},
|
||||
@ -6145,9 +6150,12 @@ var SearchEngines = {
|
||||
gecko: {
|
||||
type: "SearchEngines:Data",
|
||||
searchEngines: searchEngines,
|
||||
suggestEngine: suggestEngine,
|
||||
suggestTemplate: suggestTemplate,
|
||||
suggestEnabled: Services.prefs.getBoolPref("browser.search.suggest.enabled")
|
||||
suggest: {
|
||||
engine: suggestEngine,
|
||||
template: suggestTemplate,
|
||||
enabled: Services.prefs.getBoolPref(this.PREF_SUGGEST_ENABLED),
|
||||
prompted: Services.prefs.getBoolPref(this.PREF_SUGGEST_PROMPTED)
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user