Commit 81fc4c5f authored by Jenny Zhang's avatar Jenny Zhang Committed by Commit Bot

Show recommended apps in Zero State suggestions window.

TBR=xiyuan@chromium.org

Bug: 854238
Change-Id: I0268b4fbe9e6bc813fe2e7e5d4dfea72084f4102
Reviewed-on: https://chromium-review.googlesource.com/1145761
Commit-Queue: Jenny Zhang <jennyz@chromium.org>
Reviewed-by: default avatarAlex Newcomer <newcomer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577283}
parent fe66a0f2
......@@ -168,12 +168,30 @@ void AppListMainView::QueryChanged(search_box::SearchBoxViewBase* sender) {
base::string16 raw_query = search_model_->search_box()->text();
base::string16 query;
base::TrimWhitespace(raw_query, base::TRIM_ALL, &query);
bool should_show_search = !query.empty();
bool should_show_search =
features::IsZeroStateSuggestionsEnabled()
? search_box_view_->is_search_box_active() || !query.empty()
: !query.empty();
contents_view_->ShowSearchResults(should_show_search);
delegate_->StartSearch(raw_query);
}
void AppListMainView::ActiveChanged(search_box::SearchBoxViewBase* sender) {
if (!features::IsZeroStateSuggestionsEnabled())
return;
// Show zero state suggestions when search box is activated with an empty
// query.
if (search_box_view_->is_search_box_active()) {
base::string16 raw_query = search_model_->search_box()->text();
base::string16 query;
base::TrimWhitespace(raw_query, base::TRIM_ALL, &query);
if (query.empty())
search_box_view_->ShowZeroStateSuggestions();
}
}
void AppListMainView::BackButtonPressed() {
if (!contents_view_->Back())
app_list_view_->Dismiss();
......
......@@ -91,7 +91,7 @@ class APP_LIST_EXPORT AppListMainView
// Overridden from SearchBoxViewDelegate:
void QueryChanged(search_box::SearchBoxViewBase* sender) override;
void BackButtonPressed() override;
void ActiveChanged(search_box::SearchBoxViewBase* sender) override {}
void ActiveChanged(search_box::SearchBoxViewBase* sender) override;
AppListViewDelegate* delegate_; // Owned by parent view (AppListView).
AppListModel* model_; // Unowned; ownership is handled by |delegate_|.
......
......@@ -1277,26 +1277,51 @@ void AppListView::StartCloseAnimation(base::TimeDelta animation_duration) {
app_list_main_view_->contents_view()->FadeOutOnClose(animation_duration);
}
void AppListView::SetStateFromSearchBoxView(bool search_box_is_empty) {
void AppListView::SetStateFromSearchBoxView(bool search_box_is_empty,
bool triggered_by_contents_change) {
switch (app_list_state_) {
case AppListViewState::PEEKING:
if (!search_box_is_empty)
SetState(AppListViewState::HALF);
if (features::IsZeroStateSuggestionsEnabled()) {
if (!search_box_is_empty || search_box_view()->is_search_box_active())
SetState(AppListViewState::HALF);
} else {
if (!search_box_is_empty)
SetState(AppListViewState::HALF);
}
break;
case AppListViewState::HALF:
if (search_box_is_empty)
SetState(AppListViewState::PEEKING);
if (features::IsZeroStateSuggestionsEnabled()) {
if (search_box_is_empty && !triggered_by_contents_change)
SetState(AppListViewState::PEEKING);
} else {
if (search_box_is_empty)
SetState(AppListViewState::PEEKING);
}
break;
case AppListViewState::FULLSCREEN_SEARCH:
if (search_box_is_empty) {
SetState(AppListViewState::FULLSCREEN_ALL_APPS);
app_list_main_view()->contents_view()->SetActiveState(
ash::AppListState::kStateApps);
if (features::IsZeroStateSuggestionsEnabled()) {
if (search_box_is_empty && !triggered_by_contents_change) {
SetState(AppListViewState::FULLSCREEN_ALL_APPS);
app_list_main_view()->contents_view()->SetActiveState(
ash::AppListState::kStateApps);
}
} else {
if (search_box_is_empty) {
SetState(AppListViewState::FULLSCREEN_ALL_APPS);
app_list_main_view()->contents_view()->SetActiveState(
ash::AppListState::kStateApps);
}
}
break;
case AppListViewState::FULLSCREEN_ALL_APPS:
if (!search_box_is_empty)
SetState(AppListViewState::FULLSCREEN_SEARCH);
if (features::IsZeroStateSuggestionsEnabled()) {
if (!search_box_is_empty ||
(search_box_is_empty && triggered_by_contents_change))
SetState(AppListViewState::FULLSCREEN_SEARCH);
} else {
if (!search_box_is_empty)
SetState(AppListViewState::FULLSCREEN_SEARCH);
}
break;
case AppListViewState::CLOSED:
NOTREACHED();
......
......@@ -165,7 +165,8 @@ class APP_LIST_EXPORT AppListView : public views::WidgetDelegateView,
// Changes the app list state depending on the current |app_list_state_| and
// whether the search box is empty.
void SetStateFromSearchBoxView(bool search_box_is_empty);
void SetStateFromSearchBoxView(bool search_box_is_empty,
bool triggered_by_contents_change);
// Updates y position and opacity of app list.
void UpdateYPositionAndOpacity(int y_position_in_screen,
......
......@@ -20,6 +20,7 @@
#include "ash/app_list/views/search_result_page_view.h"
#include "ash/public/cpp/app_list/app_list_config.h"
#include "ash/public/cpp/app_list/app_list_constants.h"
#include "ash/public/cpp/app_list/app_list_features.h"
#include "ash/public/cpp/app_list/vector_icons/vector_icons.h"
#include "ash/public/cpp/wallpaper_types.h"
#include "base/macros.h"
......@@ -81,6 +82,8 @@ SearchBoxView::SearchBoxView(search_box::SearchBoxViewDelegate* delegate,
app_list_view_(app_list_view),
weak_ptr_factory_(this) {
set_is_tablet_mode(app_list_view->is_tablet_mode());
if (features::IsZeroStateSuggestionsEnabled())
set_show_close_button_when_active(true);
}
SearchBoxView::~SearchBoxView() {
......@@ -89,7 +92,8 @@ SearchBoxView::~SearchBoxView() {
void SearchBoxView::ClearSearch() {
search_box::SearchBoxViewBase::ClearSearch();
app_list_view_->SetStateFromSearchBoxView(true);
app_list_view_->SetStateFromSearchBoxView(
true, false /*triggered_by_contents_change*/);
}
views::View* SearchBoxView::GetSelectedViewInContentsView() {
......@@ -288,6 +292,11 @@ void SearchBoxView::UpdateOpacity() {
should_restore_opacity ? 1.0f : opacity);
}
void SearchBoxView::ShowZeroStateSuggestions() {
base::string16 empty_query;
ContentsChanged(search_box(), empty_query);
}
void SearchBoxView::GetWallpaperProminentColors(
AppListViewDelegate::GetWallpaperProminentColorsCallback callback) {
view_delegate_->GetWallpaperProminentColors(std::move(callback));
......@@ -315,7 +324,8 @@ void SearchBoxView::OnWallpaperProminentColorsReceived(
void SearchBoxView::ContentsChanged(views::Textfield* sender,
const base::string16& new_contents) {
search_box::SearchBoxViewBase::ContentsChanged(sender, new_contents);
app_list_view_->SetStateFromSearchBoxView(IsSearchBoxTrimmedQueryEmpty());
app_list_view_->SetStateFromSearchBoxView(
IsSearchBoxTrimmedQueryEmpty(), true /*triggered_by_contents_change*/);
}
bool SearchBoxView::HandleKeyEvent(views::Textfield* sender,
......@@ -355,6 +365,18 @@ bool SearchBoxView::HandleMouseEvent(views::Textfield* sender,
return search_box::SearchBoxViewBase::HandleMouseEvent(sender, mouse_event);
}
void SearchBoxView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
search_box::SearchBoxViewBase::ButtonPressed(sender, event);
if (!features::IsZeroStateSuggestionsEnabled())
return;
if (close_button() && sender == close_button()) {
SetSearchBoxActive(false);
}
}
void SearchBoxView::HintTextChanged() {
const app_list::SearchBoxModel* search_box_model =
search_model_->search_box();
......
......@@ -49,7 +49,10 @@ class APP_LIST_EXPORT SearchBoxView : public search_box::SearchBoxViewBase,
void SetupBackButton() override;
// Overridden from views::View:
void OnKeyEvent(ui::KeyEvent* evetn) override;
void OnKeyEvent(ui::KeyEvent* event) override;
// Overridden from views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// Updates the search box's background corner radius and color based on the
// state of AppListModel.
......@@ -71,6 +74,9 @@ class APP_LIST_EXPORT SearchBoxView : public search_box::SearchBoxViewBase,
// Updates the opacity of the searchbox.
void UpdateOpacity();
// Shows Zero State suggestions.
void ShowZeroStateSuggestions();
// Called when the wallpaper colors change.
void OnWallpaperColorsChanged();
......
......@@ -67,7 +67,8 @@ SearchResultTileItemListView::SearchResultTileItemListView(
}
SearchResultTileItemView* tile_item = new SearchResultTileItemView(
view_delegate, nullptr /* pagination model */);
view_delegate, nullptr /* pagination model */,
false /* show_in_apps_page */);
tile_item->SetParentBackgroundColor(kCardBackgroundColor);
tile_views_.push_back(tile_item);
AddChildView(tile_item);
......@@ -91,10 +92,18 @@ SearchResultBaseView* SearchResultTileItemListView::GetFirstResultView() {
}
int SearchResultTileItemListView::DoUpdate() {
base::string16 raw_query = search_box_->text();
base::string16 query;
base::TrimWhitespace(raw_query, base::TRIM_ALL, &query);
SearchResult::DisplayType display_type =
features::IsZeroStateSuggestionsEnabled()
? (query.empty() ? ash::SearchResultDisplayType::kRecommendation
: ash::SearchResultDisplayType::kTile)
: ash::SearchResultDisplayType::kTile;
std::vector<SearchResult*> display_results =
SearchModel::FilterSearchResultsByDisplayType(
results(), ash::SearchResultDisplayType::kTile,
kMaxNumSearchResultTiles);
SearchModel::FilterSearchResultsByDisplayType(results(), display_type,
kMaxNumSearchResultTiles);
SearchResult::ResultType previous_type = ash::SearchResultType::kUnknown;
......
......@@ -88,11 +88,13 @@ class BadgeBackgroundImageSource : public gfx::CanvasImageSource {
SearchResultTileItemView::SearchResultTileItemView(
AppListViewDelegate* view_delegate,
PaginationModel* pagination_model)
PaginationModel* pagination_model,
bool show_in_apps_page)
: view_delegate_(view_delegate),
pagination_model_(pagination_model),
is_play_store_app_search_enabled_(
features::IsPlayStoreAppSearchEnabled()),
show_in_apps_page_(show_in_apps_page),
weak_ptr_factory_(this) {
SetFocusBehavior(FocusBehavior::ALWAYS);
......@@ -181,12 +183,11 @@ void SearchResultTileItemView::SetSearchResult(SearchResult* item) {
SetPrice(item_->formatted_price());
const gfx::FontList& font = AppListConfig::instance().app_title_font();
if (IsSuggestedAppTile()) {
if (IsSuggestedAppTileShownInAppPage()) {
title_->SetFontList(font);
title_->SetLineHeight(font.GetHeight());
title_->SetEnabledColor(AppListConfig::instance().grid_title_color());
} else {
DCHECK_EQ(ash::SearchResultDisplayType::kTile, item_->display_type());
// Set solid color background to avoid broken text. See crbug.com/746563.
if (rating_) {
rating_->SetBackground(
......@@ -203,7 +204,8 @@ void SearchResultTileItemView::SetSearchResult(SearchResult* item) {
title_->SetMaxLines(2);
title_->SetMultiLine(
item_->display_type() == ash::SearchResultDisplayType::kTile &&
(item_->display_type() == ash::SearchResultDisplayType::kTile ||
(IsSuggestedAppTile() && !show_in_apps_page_)) &&
item_->result_type() == ash::SearchResultType::kInstalledApp);
// If the new icon is null, it's being decoded asynchronously. Not updating it
......@@ -280,7 +282,7 @@ void SearchResultTileItemView::OnFocus() {
view_delegate_->GetModel()->state() == ash::AppListState::kStateApps) {
// Go back to first page when app in suggestions container is focused.
pagination_model_->SelectPage(0, false);
} else if (!IsSuggestedAppTile()) {
} else {
ScrollRectToVisible(GetLocalBounds());
}
SetBackgroundHighlighted(true);
......@@ -305,14 +307,13 @@ void SearchResultTileItemView::PaintButtonContents(gfx::Canvas* canvas) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
if (IsSuggestedAppTile()) {
if (IsSuggestedAppTileShownInAppPage()) {
rect.ClampToCenteredSize(AppListConfig::instance().grid_focus_size());
flags.setColor(kGridSelectedColor);
canvas->DrawRoundRect(gfx::RectF(rect),
AppListConfig::instance().grid_focus_corner_radius(),
flags);
} else {
DCHECK(item_->display_type() == ash::SearchResultDisplayType::kTile);
const int kLeftRightPadding = (rect.width() - kIconSelectedSize) / 2;
rect.Inset(kLeftRightPadding, 0);
rect.set_height(kIconSelectedSize);
......@@ -492,6 +493,10 @@ bool SearchResultTileItemView::IsSuggestedAppTile() const {
item_->display_type() == ash::SearchResultDisplayType::kRecommendation;
}
bool SearchResultTileItemView::IsSuggestedAppTileShownInAppPage() const {
return IsSuggestedAppTile() && show_in_apps_page_;
}
void SearchResultTileItemView::LogAppLaunch() const {
// Only log the app launch if the class is being used as a suggested app.
if (!IsSuggestedAppTile())
......@@ -515,13 +520,12 @@ void SearchResultTileItemView::Layout() {
if (rect.IsEmpty() || !item_)
return;
if (IsSuggestedAppTile()) {
if (IsSuggestedAppTileShownInAppPage()) {
icon_->SetBoundsRect(AppListItemView::GetIconBoundsForTargetViewBounds(
rect, icon_->GetImage().size()));
title_->SetBoundsRect(AppListItemView::GetTitleBoundsForTargetViewBounds(
rect, title_->GetPreferredSize()));
} else {
DCHECK(item_->display_type() == ash::SearchResultDisplayType::kTile);
rect.Inset(0, kSearchTileTopPadding, 0, 0);
icon_->SetBoundsRect(rect);
......@@ -582,12 +586,11 @@ gfx::Size SearchResultTileItemView::CalculatePreferredSize() const {
if (!item_)
return gfx::Size();
if (IsSuggestedAppTile()) {
if (IsSuggestedAppTileShownInAppPage()) {
return gfx::Size(AppListConfig::instance().grid_tile_width(),
AppListConfig::instance().grid_tile_height());
}
DCHECK(item_->display_type() == ash::SearchResultDisplayType::kTile);
return gfx::Size(kSearchTileWidth, kSearchTileHeight);
}
......
......@@ -34,7 +34,8 @@ class APP_LIST_EXPORT SearchResultTileItemView
public AppListMenuModelAdapter::Delegate {
public:
SearchResultTileItemView(AppListViewDelegate* view_delegate,
PaginationModel* pagination_model);
PaginationModel* pagination_model,
bool show_in_apps_page);
~SearchResultTileItemView() override;
SearchResult* result() { return item_; }
......@@ -88,6 +89,8 @@ class APP_LIST_EXPORT SearchResultTileItemView
// Whether the tile view is a suggested app.
bool IsSuggestedAppTile() const;
// Whether the tile view is a suggested app and shown in apps page ui.
bool IsSuggestedAppTileShownInAppPage() const;
// Records an app being launched.
void LogAppLaunch() const;
......@@ -117,6 +120,7 @@ class APP_LIST_EXPORT SearchResultTileItemView
SkColor parent_background_color_ = SK_ColorTRANSPARENT;
const bool is_play_store_app_search_enabled_;
const bool show_in_apps_page_; // True if shown in app list's apps page.
std::unique_ptr<AppListMenuModelAdapter> context_menu_;
......
......@@ -110,8 +110,8 @@ void SuggestionsContainerView::CreateAppsGrid(int apps_num) {
tiles_layout_manager->StartRow(0, 0);
DCHECK_LE(apps_num, kNumStartPageTiles);
for (; i < apps_num; ++i) {
SearchResultTileItemView* tile_item =
new SearchResultTileItemView(view_delegate_, pagination_model_);
SearchResultTileItemView* tile_item = new SearchResultTileItemView(
view_delegate_, pagination_model_, true /* show_in_apps_page */);
tiles_layout_manager->AddView(tile_item);
AddChildView(tile_item);
tile_item->SetParentBackgroundColor(kLabelBackgroundColor);
......
......@@ -29,6 +29,8 @@ const base::Feature kEnableNewStyleLauncher{"EnableNewStyleLauncher",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kEnableContinueReading{"EnableContinueReading",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kEnableZeroStateSuggestions{
"EnableZeroStateSuggestions", base::FEATURE_DISABLED_BY_DEFAULT};
bool IsAnswerCardEnabled() {
// Not using local static variable to allow tests to change this value.
......@@ -68,6 +70,10 @@ bool IsContinueReadingEnabled() {
return base::FeatureList::IsEnabled(kEnableContinueReading);
}
bool IsZeroStateSuggestionsEnabled() {
return base::FeatureList::IsEnabled(kEnableZeroStateSuggestions);
}
std::string AnswerServerUrl() {
const std::string experiment_url =
base::GetFieldTrialParamValueByFeature(kEnableAnswerCard, "ServerUrl");
......
......@@ -50,6 +50,9 @@ ASH_PUBLIC_EXPORT extern const base::Feature kEnableNewStyleLauncher;
// when they switch from phones or tablets to Chromebook.
ASH_PUBLIC_EXPORT extern const base::Feature kEnableContinueReading;
// Enables the feature to display zero state suggestions.
ASH_PUBLIC_EXPORT extern const base::Feature kEnableZeroStateSuggestions;
bool ASH_PUBLIC_EXPORT IsAnswerCardEnabled();
bool ASH_PUBLIC_EXPORT IsAppShortcutSearchEnabled();
bool ASH_PUBLIC_EXPORT IsBackgroundBlurEnabled();
......@@ -59,6 +62,7 @@ bool ASH_PUBLIC_EXPORT IsSettingsShortcutSearchEnabled();
bool ASH_PUBLIC_EXPORT IsAppsGridGapFeatureEnabled();
bool ASH_PUBLIC_EXPORT IsNewStyleLauncherEnabled();
bool ASH_PUBLIC_EXPORT IsContinueReadingEnabled();
bool ASH_PUBLIC_EXPORT IsZeroStateSuggestionsEnabled();
std::string ASH_PUBLIC_EXPORT AnswerServerUrl();
std::string ASH_PUBLIC_EXPORT AnswerServerQuerySuffix();
......
......@@ -4124,6 +4124,10 @@ const FeatureEntry kFeatureEntries[] = {
{"enable-continue-reading", flag_descriptions::kEnableContinueReadingName,
flag_descriptions::kEnableContinueReadingDescription, kOsCrOS,
FEATURE_VALUE_TYPE(app_list::features::kEnableContinueReading)},
{"enable-zero-state-suggestions",
flag_descriptions::kEnableZeroStateSuggestionsName,
flag_descriptions::kEnableZeroStateSuggestionsDescription, kOsCrOS,
FEATURE_VALUE_TYPE(app_list::features::kEnableZeroStateSuggestions)},
#endif // OS_CHROMEOS
{"enable-bloated-renderer-detection",
......
......@@ -3420,6 +3420,12 @@ extern const char kEnableContinueReadingDescription[] =
"seamlessly continue reading a web page when they switch devices from "
"phones or tablets to Chromebooks.";
extern const char kEnableZeroStateSuggestionsName[] =
"Enable Zero State Suggetions";
extern const char kEnableZeroStateSuggestionsDescription[] =
"Enable Zero State Suggestions feature in Launcher, which will show "
"suggetions when launcher search box is active with an empty query";
#endif // defined(OS_CHROMEOS)
// Random platform combinations -----------------------------------------------
......
......@@ -2092,6 +2092,9 @@ extern const char kZipArchiverUnpackerDescription[];
extern const char kEnableContinueReadingName[];
extern const char kEnableContinueReadingDescription[];
extern const char kEnableZeroStateSuggestionsName[];
extern const char kEnableZeroStateSuggestionsDescription[];
#endif // #if defined(OS_CHROMEOS)
// Random platform combinations -----------------------------------------------
......
......@@ -27725,6 +27725,7 @@ from previous Chrome versions.
<int value="-1594298767" label="FullscreenToolbarReveal:enabled"/>
<int value="-1586642651" label="MaterialDesignExtensions:disabled"/>
<int value="-1584944853" label="TrilinearFiltering:enabled"/>
<int value="-1584499823" label="EnableZeroStateSuggestions:enabled"/>
<int value="-1583728573" label="AutofillCreditCardSigninPromo:disabled"/>
<int value="-1583533050" label="RuntimeHostPermissions:disabled"/>
<int value="-1581724231" label="ModalPermissionPrompts:enabled"/>
......@@ -28990,6 +28991,7 @@ from previous Chrome versions.
<int value="1054910800" label="enable-timezone-tracking-option"/>
<int value="1057887829" label="AutofillScanThemeDialog:disabled"/>
<int value="1059007599" label="enable-gpu-appcontainer"/>
<int value="1059698271" label="EnableZeroStateSuggestions:disabled"/>
<int value="1060319397" label="enable-data-reduction-proxy-carrier-test"/>
<int value="1062357243" label="remember-cert-error-decisions"/>
<int value="1064288458" label="OfflineRecentPages:enabled"/>
......@@ -270,6 +270,7 @@ void SearchBoxViewBase::SetSearchBoxActive(bool active) {
UpdateSearchBoxBorder();
UpdateKeyboardVisibility();
UpdateCloseButtonVisisbility();
NotifyActiveChanged();
......@@ -394,7 +395,9 @@ void SearchBoxViewBase::SetSearchBoxColor(SkColor color) {
void SearchBoxViewBase::UpdateCloseButtonVisisbility() {
if (!close_button_)
return;
bool should_show_close_button_ = !search_box_->text().empty();
bool should_show_close_button_ =
!search_box_->text().empty() ||
(show_close_button_when_active_ && is_search_box_active_);
if (close_button_->visible() == should_show_close_button_)
return;
close_button_->SetVisible(should_show_close_button_);
......
......@@ -99,6 +99,10 @@ class SEARCH_BOX_EXPORT SearchBoxViewBase : public views::WidgetDelegateView,
// Whether the search box is active.
bool is_search_box_active() const { return is_search_box_active_; }
void set_show_close_button_when_active(bool show_button) {
show_close_button_when_active_ = show_button;
}
void OnOnSearchBoxFocusedChanged();
// Whether the trimmed query in the search box is empty.
......@@ -194,6 +198,8 @@ class SEARCH_BOX_EXPORT SearchBoxViewBase : public views::WidgetDelegateView,
// Whether the search box is active.
bool is_search_box_active_ = false;
// Whether to show close button if the search box is active.
bool show_close_button_when_active_ = false;
// Whether tablet mode is active.
bool is_tablet_mode_ = false;
// The current background color.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment