0

[PhoneHub][Eche] Create connection error dialog

Created the error dialog that will open when user clicks on the warning
icon if there is a network connection error.

Screenshot: https://screenshot.googleplex.com/8Bukw64nbPYAVCs.png

Tested: manually verified the dialog behavior.
Bug: b/273664743
Change-Id: Ic3047c94e9807dc5606ef9609ffefa94bc526ac6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4336750
Reviewed-by: Crisrael Lucero <crisrael@google.com>
Reviewed-by: Jon Mann <jonmann@chromium.org>
Commit-Queue: Pu Shi <pushi@google.com>
Cr-Commit-Position: refs/heads/main@{#1118416}
This commit is contained in:
Pu Shi
2023-03-16 23:03:43 +00:00
committed by Chromium LUCI CQ
parent f02c98af32
commit d39a7e157d
12 changed files with 425 additions and 8 deletions

@ -1638,6 +1638,8 @@ component("ash") {
"system/palette/tools/magnifier_mode.h",
"system/pcie_peripheral/pcie_peripheral_notification_controller.cc",
"system/pcie_peripheral/pcie_peripheral_notification_controller.h",
"system/phonehub/app_stream_connection_error_dialog.cc",
"system/phonehub/app_stream_connection_error_dialog.h",
"system/phonehub/app_stream_launcher_item.cc",
"system/phonehub/app_stream_launcher_item.h",
"system/phonehub/app_stream_launcher_list_item.cc",

@ -6278,6 +6278,15 @@ New install
<message name="ID_ASH_ECHE_APP_STREAMING_BUBBLE_TITLE" desc="The title appear on the top of app streaming bubble">
From <ph name="PHONE_NAME">$1<ex>Pixel 7</ex></ph>
</message>
<message name="IDS_ASH_ECHE_APP_STREMING_ERROR_DIALOG_TITLE" desc="The title of dialog that appears when there is a connection error trying to stream app">
Can't stream apps
</message>
<message name="IDS_ASH_ECHE_APP_STREMING_ERROR_DIALOG_MAIN_TEXT" desc="The main description in the dialog that appears when there is a connection error trying to stream app">
This network doesn't support streaming apps from your phone. Try turning on your phone's hotspot. Learn more.
</message>
<message name="IDS_ASH_ECHE_APP_STREMING_ERROR_DIALOG_TURN_ON_HOTSPOT" desc="The button in the dialog that appears when there is a connection error trying to stream app to turn on hotspot">
Turn on hotspot
</message>
<!-- Deferred update dialog -->
<message name="IDS_DEFERRED_UPDATE_DIALOG_TITLE" desc="Title of the dialog for notifying deferred update available to be applied.">

@ -0,0 +1 @@
d51a7b6fe868ca874bcde99c4ddc0404fdfac611

@ -0,0 +1 @@
d51a7b6fe868ca874bcde99c4ddc0404fdfac611

@ -0,0 +1 @@
d51a7b6fe868ca874bcde99c4ddc0404fdfac611

@ -0,0 +1,281 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/phonehub/app_stream_connection_error_dialog.h"
#include <memory>
#include <utility>
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/view_shadow.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/style/pill_button.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/image_model.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/background.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/highlight_border.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/window/dialog_delegate.h"
#include "ui/views/window/non_client_view.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash {
namespace {
constexpr int kDialogVerticalMargin = 50;
constexpr int kDialogWidth = 330;
constexpr gfx::Insets kDialogContentInsets = gfx::Insets::VH(20, 24);
constexpr float kDialogRoundedCornerRadius = 16.0f;
constexpr int kDialogShadowElevation = 3;
constexpr int kIconSize = 25;
constexpr int kMarginBetweenIconAndTitle = 15;
constexpr int kMarginBetweenTitleAndBody = 15;
constexpr int kMarginBetweenBodyAndButtons = 20;
constexpr int kMarginBetweenButtons = 8;
// The real error dialog with content.
class ConnectionErrorDialogDelegateView : public views::WidgetDelegateView {
public:
explicit ConnectionErrorDialogDelegateView(
StartTetheringCallback start_tethering_callback)
: start_tethering_callback_(std::move(start_tethering_callback)) {
SetModalType(ui::MODAL_TYPE_WINDOW);
SetPaintToLayer();
layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma);
layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality);
view_shadow_ = std::make_unique<ViewShadow>(this, kDialogShadowElevation);
view_shadow_->SetRoundedCornerRadius(kDialogRoundedCornerRadius);
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, kDialogContentInsets));
// Add info icon.
auto* icon_row = AddChildView(std::make_unique<views::View>());
icon_row
->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets()))
->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kStart);
icon_ = icon_row->AddChildView(
std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
kPhoneHubEcheErrorStatusIcon,
AshColorProvider::Get()->GetContentLayerColor(
AshColorProvider::ContentLayerType::kIconColorWarning),
kIconSize)));
// Add dialog title.
title_ =
AddChildView(std::make_unique<views::Label>(l10n_util::GetStringUTF16(
IDS_ASH_ECHE_APP_STREMING_ERROR_DIALOG_TITLE)));
title_->SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(kMarginBetweenIconAndTitle, 0, 0, 0));
title_->SetTextContext(views::style::CONTEXT_DIALOG_TITLE);
title_->SetTextStyle(views::style::STYLE_EMPHASIZED);
title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
title_->SetAutoColorReadabilityEnabled(false);
title_->SetPaintToLayer();
title_->layer()->SetFillsBoundsOpaquely(false);
// Add dialog body.
// TODO(b/273822975): change Learn More to link.
body_ =
AddChildView(std::make_unique<views::Label>(l10n_util::GetStringUTF16(
IDS_ASH_ECHE_APP_STREMING_ERROR_DIALOG_MAIN_TEXT)));
body_->SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(kMarginBetweenTitleAndBody, 0,
kMarginBetweenBodyAndButtons, 0));
body_->SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT);
body_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
body_->SetMultiLine(true);
body_->SetAllowCharacterBreak(true);
body_->SetAutoColorReadabilityEnabled(false);
body_->SetPaintToLayer();
body_->layer()->SetFillsBoundsOpaquely(false);
// Add button row.
auto* button_row = AddChildView(std::make_unique<views::View>());
button_row
->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
kMarginBetweenButtons))
->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kEnd);
cancel_button_ = button_row->AddChildView(std::make_unique<ash::PillButton>(
views::Button::PressedCallback(base::BindRepeating(
&ConnectionErrorDialogDelegateView::OnCancelClicked,
base::Unretained(this))),
l10n_util::GetStringUTF16(IDS_APP_CANCEL),
PillButton::Type::kDefaultWithoutIcon, nullptr));
accept_button_ = button_row->AddChildView(std::make_unique<ash::PillButton>(
views::Button::PressedCallback(base::BindRepeating(
&ConnectionErrorDialogDelegateView::OnStartTetheringClicked,
base::Unretained(this))),
l10n_util::GetStringUTF16(
IDS_ASH_ECHE_APP_STREMING_ERROR_DIALOG_TURN_ON_HOTSPOT),
PillButton::Type::kPrimaryWithoutIcon, nullptr));
}
ConnectionErrorDialogDelegateView(const ConnectionErrorDialogDelegateView&) =
delete;
ConnectionErrorDialogDelegateView& operator=(
const ConnectionErrorDialogDelegateView&) = delete;
~ConnectionErrorDialogDelegateView() override = default;
// views::View:
const char* GetClassName() const override {
return "ConnectionErrorDialogDelegateView";
}
gfx::Size CalculatePreferredSize() const override {
return gfx::Size(kDialogWidth, GetHeightForWidth(kDialogWidth));
}
void OnThemeChanged() override {
views::WidgetDelegateView::OnThemeChanged();
SetBackground(views::CreateRoundedRectBackground(
AshColorProvider::Get()->GetBaseLayerColor(
AshColorProvider::BaseLayerType::kTransparent80),
kDialogRoundedCornerRadius));
SetBorder(std::make_unique<views::HighlightBorder>(
kDialogRoundedCornerRadius,
views::HighlightBorder::Type::kHighlightBorder1,
/*use_light_colors=*/false));
title_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
AshColorProvider::ContentLayerType::kTextColorPrimary));
body_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
AshColorProvider::ContentLayerType::kTextColorPrimary));
}
void OnStartTetheringClicked() {
if (start_tethering_callback_) {
std::move(start_tethering_callback_).Run();
}
GetWidget()->CloseWithReason(
views::Widget::ClosedReason::kAcceptButtonClicked);
}
void OnCancelClicked() {
GetWidget()->CloseWithReason(
views::Widget::ClosedReason::kCancelButtonClicked);
}
private:
StartTetheringCallback start_tethering_callback_;
std::unique_ptr<ViewShadow> view_shadow_;
views::ImageView* icon_ = nullptr;
views::Label* title_ = nullptr;
views::Label* body_ = nullptr;
views::Button* cancel_button_ = nullptr;
views::Button* accept_button_ = nullptr;
};
} // namespace
AppStreamConnectionErrorDialog::AppStreamConnectionErrorDialog(
views::View* host_view,
base::OnceClosure on_close_callback,
StartTetheringCallback button_callback)
: host_view_(host_view), on_close_callback_(std::move(on_close_callback)) {
auto dialog = std::make_unique<ConnectionErrorDialogDelegateView>(
std::move(button_callback));
views::Widget* const parent = host_view_->GetWidget();
widget_ = new views::Widget();
views::Widget::InitParams params;
params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
params.layer_type = ui::LAYER_NOT_DRAWN;
params.parent = parent->GetNativeWindow();
params.delegate = dialog.release();
widget_->Init(std::move(params));
// The |dialog| ownership is passed to the window hierarchy.
widget_observations_.AddObservation(widget_);
widget_observations_.AddObservation(parent);
view_observations_.AddObservation(host_view_);
view_observations_.AddObservation(widget_->GetContentsView());
}
AppStreamConnectionErrorDialog::~AppStreamConnectionErrorDialog() {
view_observations_.RemoveAllObservations();
widget_observations_.RemoveAllObservations();
if (widget_) {
widget_->Close();
widget_ = nullptr;
}
}
void AppStreamConnectionErrorDialog::UpdateBounds() {
if (!widget_) {
return;
}
gfx::Point anchor_point_in_screen(host_view_->width() / 2, 0);
views::View::ConvertPointToScreen(host_view_, &anchor_point_in_screen);
const int offset_for_frame_insets =
widget_->non_client_view() && widget_->non_client_view()->frame_view()
? widget_->non_client_view()->frame_view()->GetInsets().top()
: 0;
const int vertical_offset = kDialogVerticalMargin - offset_for_frame_insets;
gfx::Size dialog_size = widget_->GetContentsView()->GetPreferredSize();
widget_->SetBounds(
gfx::Rect(gfx::Point(anchor_point_in_screen.x() - dialog_size.width() / 2,
anchor_point_in_screen.y() + vertical_offset),
dialog_size));
}
void AppStreamConnectionErrorDialog::OnWidgetDestroying(views::Widget* widget) {
if (on_close_callback_) {
std::move(on_close_callback_).Run();
}
}
void AppStreamConnectionErrorDialog::OnWidgetBoundsChanged(
views::Widget* widget,
const gfx::Rect& new_bounds) {
if (widget == host_view_->GetWidget()) {
UpdateBounds();
}
}
void AppStreamConnectionErrorDialog::OnViewBoundsChanged(
views::View* observed_view) {
UpdateBounds();
}
void AppStreamConnectionErrorDialog::OnViewPreferredSizeChanged(
views::View* observed_view) {
UpdateBounds();
}
} // namespace ash

@ -0,0 +1,69 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_PHONEHUB_APP_STREAM_CONNECTION_ERROR_DIALOG_H_
#define ASH_SYSTEM_PHONEHUB_APP_STREAM_CONNECTION_ERROR_DIALOG_H_
#include "ash/ash_export.h"
#include "base/functional/callback.h"
#include "base/scoped_multi_source_observation.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace gfx {
class Rect;
}
using StartTetheringCallback = base::OnceCallback<void()>;
namespace ash {
// A view to anchor error dialog to Phone Hub bubble.
class ASH_EXPORT AppStreamConnectionErrorDialog : public views::WidgetObserver,
public views::ViewObserver {
public:
// TODO(b/273823160): Make the callback name more generic and take in strings
// as parameters to make the dialog available in other locations.
AppStreamConnectionErrorDialog(
views::View* host_view,
base::OnceClosure on_close_callback,
StartTetheringCallback start_tethering_callback);
AppStreamConnectionErrorDialog(const AppStreamConnectionErrorDialog& other) =
delete;
AppStreamConnectionErrorDialog& operator=(
const AppStreamConnectionErrorDialog& other) = delete;
~AppStreamConnectionErrorDialog() override;
// Repositions the dialog widget bounds relative to the current host view
// bounds.
void UpdateBounds();
// views::WidgetObserver:
void OnWidgetDestroying(views::Widget* widget) override;
void OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) override;
// views::ViewObserver:
void OnViewBoundsChanged(views::View* observed_view) override;
void OnViewPreferredSizeChanged(views::View* observed_view) override;
views::Widget* widget() { return widget_; }
private:
views::Widget* widget_ = nullptr;
views::View* const host_view_;
base::OnceClosure on_close_callback_;
base::ScopedMultiSourceObservation<views::Widget, views::WidgetObserver>
widget_observations_{this};
base::ScopedMultiSourceObservation<views::View, views::ViewObserver>
view_observations_{this};
};
} // namespace ash
#endif // ASH_SYSTEM_PHONEHUB_APP_STREAM_CONNECTION_ERROR_DIALOG_H_

@ -8,6 +8,7 @@
#include "ash/constants/ash_features.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/phonehub/app_stream_connection_error_dialog.h"
#include "ash/system/phonehub/camera_roll_view.h"
#include "ash/system/phonehub/multidevice_feature_opt_in_view.h"
#include "ash/system/phonehub/phone_hub_recent_apps_view.h"
@ -17,6 +18,7 @@
#include "ash/system/phonehub/task_continuation_view.h"
#include "ash/system/phonehub/ui_constants.h"
#include "ash/system/tray/tray_constants.h"
#include "chromeos/ash/components/multidevice/logging/logging.h"
#include "chromeos/ash/components/phonehub/multidevice_feature_access_manager.h"
#include "chromeos/ash/components/phonehub/phone_hub_manager.h"
#include "chromeos/ash/components/phonehub/ping_manager.h"
@ -89,7 +91,7 @@ PhoneConnectedView::PhoneConnectedView(
phone_hub_manager->GetRecentAppsInteractionHandler();
if (features::IsEcheSWAEnabled() && recent_apps_handler) {
setup_layered_view(AddChildView(std::make_unique<PhoneHubRecentAppsView>(
recent_apps_handler, phone_hub_manager)));
recent_apps_handler, phone_hub_manager, this)));
}
auto* ping_manager = phone_hub_manager->GetPingManager();
@ -135,4 +137,26 @@ phone_hub_metrics::Screen PhoneConnectedView::GetScreenForMetrics() const {
return phone_hub_metrics::Screen::kPhoneConnected;
}
void PhoneConnectedView::ShowAppStreamErrorDialog() {
if (!features::IsEcheNetworkConnectionStateEnabled()) {
return;
}
app_stream_error_dialog_ = std::make_unique<AppStreamConnectionErrorDialog>(
this,
base::BindOnce(&PhoneConnectedView::OnAppStreamErrorDialogClosed,
base::Unretained(this)),
base::BindOnce(&PhoneConnectedView::OnAppStreamErrorDialogButtonClicked,
base::Unretained(this)));
app_stream_error_dialog_->UpdateBounds();
app_stream_error_dialog_->widget()->Show();
}
void PhoneConnectedView::OnAppStreamErrorDialogClosed() {
app_stream_error_dialog_.reset();
}
void PhoneConnectedView::OnAppStreamErrorDialogButtonClicked() {
// TODO(b/273823627): Add method to enable hotspot.
}
} // namespace ash

@ -6,6 +6,7 @@
#define ASH_SYSTEM_PHONEHUB_PHONE_CONNECTED_VIEW_H_
#include "ash/ash_export.h"
#include "ash/system/phonehub/app_stream_connection_error_dialog.h"
#include "ash/system/phonehub/phone_hub_content_view.h"
#include "chromeos/ash/components/phonehub/phone_hub_manager.h"
#include "ui/views/view.h"
@ -31,8 +32,15 @@ class PhoneConnectedView : public PhoneHubContentView {
// PhoneHubContentView:
phone_hub_metrics::Screen GetScreenForMetrics() const override;
void ShowAppStreamErrorDialog();
private:
void OnAppStreamErrorDialogClosed();
void OnAppStreamErrorDialogButtonClicked();
phonehub::PhoneHubManager* phone_hub_manager_;
std::unique_ptr<AppStreamConnectionErrorDialog> app_stream_error_dialog_;
};
} // namespace ash

@ -13,6 +13,7 @@
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/phonehub/phone_connected_view.h"
#include "ash/system/phonehub/phone_hub_more_apps_button.h"
#include "ash/system/phonehub/phone_hub_recent_app_button.h"
#include "ash/system/phonehub/phone_hub_view_ids.h"
@ -28,6 +29,7 @@
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/background.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
@ -67,7 +69,7 @@ constexpr int kRecentAppsHeaderSpacing = 220;
class HeaderView : public views::View {
public:
HeaderView() {
explicit HeaderView(views::ImageButton::PressedCallback callback) {
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>());
layout->set_main_axis_alignment(
views::BoxLayout::MainAxisAlignment::kCenter);
@ -92,7 +94,8 @@ class HeaderView : public views::View {
AshColorProvider::ContentLayerType::kTextColorPrimary));
if (features::IsEcheNetworkConnectionStateEnabled()) {
error_button_ = AddChildView(std::make_unique<views::ImageButton>());
error_button_ =
AddChildView(std::make_unique<views::ImageButton>(callback));
gfx::ImageSkia image = gfx::CreateVectorIcon(
kPhoneHubEcheErrorStatusIcon,
AshColorProvider::Get()->GetContentLayerColor(
@ -138,15 +141,19 @@ class PhoneHubRecentAppsView::PlaceholderView : public views::Label {
PhoneHubRecentAppsView::PhoneHubRecentAppsView(
phonehub::RecentAppsInteractionHandler* recent_apps_interaction_handler,
phonehub::PhoneHubManager* phone_hub_manager)
phonehub::PhoneHubManager* phone_hub_manager,
PhoneConnectedView* connected_view)
: recent_apps_interaction_handler_(recent_apps_interaction_handler),
phone_hub_manager_(phone_hub_manager) {
phone_hub_manager_(phone_hub_manager),
connected_view_(connected_view) {
SetID(PhoneHubViewID::kPhoneHubRecentAppsView);
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStart);
AddChildView(std::make_unique<HeaderView>());
AddChildView(std::make_unique<HeaderView>(
base::BindRepeating(&PhoneHubRecentAppsView::ShowConnectionErrorDialog,
base::Unretained(this))));
recent_app_buttons_view_ =
AddChildView(std::make_unique<RecentAppButtonsView>());
placeholder_view_ = AddChildView(std::make_unique<PlaceholderView>());
@ -316,6 +323,12 @@ void PhoneHubRecentAppsView::SwitchToFullAppsList() {
->SetShouldShowMiniLauncher(true);
}
void PhoneHubRecentAppsView::ShowConnectionErrorDialog() {
if (features::IsEcheNetworkConnectionStateEnabled()) {
connected_view_->ShowAppStreamErrorDialog();
}
}
std::unique_ptr<views::View> PhoneHubRecentAppsView::GenerateMoreAppsButton() {
if (features::IsEcheLauncherIconsInMoreAppsButtonEnabled()) {
return std::make_unique<PhoneHubMoreAppsButton>(

@ -8,6 +8,7 @@
#include <memory>
#include "ash/ash_export.h"
#include "ash/system/phonehub/phone_connected_view.h"
#include "base/gtest_prod_util.h"
#include "chromeos/ash/components/phonehub/recent_apps_interaction_handler.h"
#include "ui/views/controls/button/image_button.h"
@ -28,7 +29,8 @@ class ASH_EXPORT PhoneHubRecentAppsView
public:
explicit PhoneHubRecentAppsView(
phonehub::RecentAppsInteractionHandler* recent_apps_interaction_handler,
phonehub::PhoneHubManager* phone_hub_manager);
phonehub::PhoneHubManager* phone_hub_manager,
PhoneConnectedView* connected_view);
~PhoneHubRecentAppsView() override;
PhoneHubRecentAppsView(PhoneHubRecentAppsView&) = delete;
PhoneHubRecentAppsView operator=(PhoneHubRecentAppsView&) = delete;
@ -73,6 +75,8 @@ class ASH_EXPORT PhoneHubRecentAppsView
// Switch to full apps list view.
void SwitchToFullAppsList();
void ShowConnectionErrorDialog();
// Generate more apps button.
std::unique_ptr<views::View> GenerateMoreAppsButton();
@ -82,6 +86,7 @@ class ASH_EXPORT PhoneHubRecentAppsView
nullptr;
phonehub::PhoneHubManager* phone_hub_manager_ = nullptr;
PlaceholderView* placeholder_view_ = nullptr;
PhoneConnectedView* connected_view_ = nullptr;
};
} // namespace ash

@ -5,6 +5,7 @@
#include "ash/system/phonehub/phone_hub_recent_apps_view.h"
#include "ash/constants/ash_features.h"
#include "ash/system/phonehub/phone_connected_view.h"
#include "ash/system/phonehub/phone_hub_recent_app_button.h"
#include "ash/test/ash_test_base.h"
#include "base/test/scoped_feature_list.h"
@ -45,7 +46,8 @@ class RecentAppButtonsViewTest : public AshTestBase {
/*disabled_features=*/{});
phone_hub_recent_apps_view_ = std::make_unique<PhoneHubRecentAppsView>(
&fake_recent_apps_interaction_handler_, &fake_phone_hub_manager_);
&fake_recent_apps_interaction_handler_, &fake_phone_hub_manager_,
connected_view_);
}
void TearDown() override {
@ -90,6 +92,7 @@ class RecentAppButtonsViewTest : public AshTestBase {
phonehub::FakeRecentAppsInteractionHandler
fake_recent_apps_interaction_handler_;
phonehub::FakePhoneHubManager fake_phone_hub_manager_;
PhoneConnectedView* connected_view_;
base::test::ScopedFeatureList feature_list_;
};