[go: nahoru, domu]

blob: e1600cf84f1def0c4c01b0abd4ddac45c76b470f [file] [log] [blame]
Avi Drissman3a215d1e2022-09-07 19:43:091// Copyright 2020 The Chromium Authors
Meilin Wang418ae712020-09-17 05:50:032// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/system/phonehub/onboarding_view.h"
6
7#include <algorithm>
8#include <memory>
Jan Wilken Dörriead587c32021-03-11 14:09:279#include <string>
Meilin Wang418ae712020-09-17 05:50:0310#include <vector>
11
12#include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h"
Meilin Wang98efd1be2020-10-01 22:25:3513#include "ash/public/cpp/system_tray_client.h"
Meilin Wangd626fde2020-10-23 17:53:3614#include "ash/root_window_controller.h"
Meilin Wang98efd1be2020-10-01 22:25:3515#include "ash/shell.h"
Meilin Wang418ae712020-09-17 05:50:0316#include "ash/strings/grit/ash_strings.h"
17#include "ash/style/ash_color_provider.h"
minch9cfa2b02021-11-12 20:42:4118#include "ash/style/pill_button.h"
Meilin Wang98efd1be2020-10-01 22:25:3519#include "ash/system/model/system_tray_model.h"
Meilin Wangd626fde2020-10-23 17:53:3620#include "ash/system/phonehub/phone_hub_content_view.h"
Meilin Wang418ae712020-09-17 05:50:0321#include "ash/system/phonehub/phone_hub_interstitial_view.h"
Tim Song85303702020-10-16 04:57:0022#include "ash/system/phonehub/phone_hub_metrics.h"
Meilin Wangd626fde2020-10-23 17:53:3623#include "ash/system/phonehub/phone_hub_tray.h"
Meilin Wang98efd1be2020-10-01 22:25:3524#include "ash/system/phonehub/phone_hub_view_ids.h"
Meilin Wangd626fde2020-10-23 17:53:3625#include "ash/system/status_area_widget.h"
26#include "ash/system/tray/tray_bubble_view.h"
Avi Drissman4de6dab2023-01-06 23:17:3527#include "base/functional/bind.h"
Arthur Sonzogni834e018f2023-04-22 10:20:0228#include "base/memory/raw_ptr.h"
Meilin Wangd626fde2020-10-23 17:53:3629#include "base/strings/strcat.h"
Henrique Ferreirofadda062022-12-01 16:27:1430#include "chromeos/ash/components/phonehub/onboarding_ui_tracker.h"
Crisrael Lucerof1392ae2023-05-12 23:17:4531#include "chromeos/constants/chromeos_features.h"
Meilin Wang418ae712020-09-17 05:50:0332#include "ui/base/l10n/l10n_util.h"
Allen Bauera66b3eed2021-05-05 02:42:1233#include "ui/base/metadata/metadata_impl_macros.h"
Meilin Wang418ae712020-09-17 05:50:0334#include "ui/base/resource/resource_bundle.h"
Andre Le09e38cd2020-11-05 19:49:1635#include "ui/chromeos/devicetype_utils.h"
Meilin Wang418ae712020-09-17 05:50:0336#include "ui/views/layout/fill_layout.h"
37
38namespace ash {
39
Tim Song85303702020-10-16 04:57:0040using phone_hub_metrics::InterstitialScreenEvent;
Tim Song947932a2020-10-31 00:38:4541using phone_hub_metrics::Screen;
Tim Song85303702020-10-16 04:57:0042
Meilin Wangd626fde2020-10-23 17:53:3643// OnboardingMainView ---------------------------------------------------------
44// Main onboarding screen with Phone Hub feature description and two buttons
45// (Get Started and Dismiss), where user can either choose to grant permission
46// to enable this feature or dismiss the screen.
Peter Kasting5aacfd492020-10-31 03:33:1447class OnboardingMainView : public PhoneHubInterstitialView {
David Yeungadb27442023-11-14 22:49:5148 METADATA_HEADER(OnboardingMainView, PhoneHubInterstitialView)
49
Meilin Wangd626fde2020-10-23 17:53:3650 public:
Henrique Ferreiro91fb61df2021-11-12 15:51:0351 OnboardingMainView(phonehub::OnboardingUiTracker* onboarding_ui_tracker,
52 OnboardingView* parent_view,
53 OnboardingView::OnboardingFlow onboarding_flow)
Meilin Wangd626fde2020-10-23 17:53:3654 : PhoneHubInterstitialView(/*show_progress=*/false),
55 onboarding_ui_tracker_(onboarding_ui_tracker),
Tim Song5a9883f52020-11-04 19:40:0356 parent_view_(parent_view),
57 onboarding_flow_(onboarding_flow) {
Meilin Wangd626fde2020-10-23 17:53:3658 SetID(PhoneHubViewID::kOnboardingMainView);
59 InitLayout();
60 }
61
Tim Song947932a2020-10-31 00:38:4562 // PhoneHubInterstitialView:
63 Screen GetScreenForMetrics() const override {
Tim Song5a9883f52020-11-04 19:40:0364 switch (onboarding_flow_) {
65 case OnboardingView::kExistingMultideviceUser:
66 return Screen::kOnboardingExistingMultideviceUser;
67 case OnboardingView::kNewMultideviceUser:
68 return Screen::kOnboardingNewMultideviceUser;
69 }
Tim Song947932a2020-10-31 00:38:4570 }
71
Meilin Wangd626fde2020-10-23 17:53:3672 private:
73 void InitLayout() {
Avery Musbach5ebb29fa2022-01-28 17:12:4874 SetImage(ui::ResourceBundle::GetSharedInstance().GetThemedLottieImageNamed(
75 IDR_PHONE_HUB_ONBOARDING_IMAGE));
Meilin Wangd626fde2020-10-23 17:53:3676 SetTitle(
77 l10n_util::GetStringUTF16(IDS_ASH_PHONE_HUB_ONBOARDING_DIALOG_TITLE));
Kyle Horimotofe7173b2021-01-14 22:32:4878 SetDescription(l10n_util::GetStringUTF16(
79 IDS_ASH_PHONE_HUB_ONBOARDING_DIALOG_DESCRIPTION));
Meilin Wangd626fde2020-10-23 17:53:3680
81 // Add "Dismiss" and "Get started" buttons.
Crisrael Lucerof1392ae2023-05-12 23:17:4582 // TODO(b/281844561): Migrate the "Dismiss" button to use
83 // |PillButton::Type::kSecondaryWithoutIcon| when the PillButton colors
84 // are updated with better contrast-ratios.
mincha0674932021-10-18 17:56:2185 auto dismiss = std::make_unique<PillButton>(
Peter Kasting5aacfd492020-10-31 03:33:1486 base::BindRepeating(&OnboardingMainView::DismissButtonPressed,
87 base::Unretained(this)),
Meilin Wangd626fde2020-10-23 17:53:3688 l10n_util::GetStringUTF16(
89 IDS_ASH_PHONE_HUB_ONBOARDING_DIALOG_DISMISS_BUTTON),
Xiaodan Zhue21746e2022-08-22 22:12:1090 PillButton::Type::kFloatingWithoutIcon, /*icon=*/nullptr);
Meilin Wangd626fde2020-10-23 17:53:3691 dismiss->SetID(PhoneHubViewID::kOnboardingDismissButton);
92 AddButton(std::move(dismiss));
93
mincha0674932021-10-18 17:56:2194 auto get_started = std::make_unique<PillButton>(
Peter Kasting5aacfd492020-10-31 03:33:1495 base::BindRepeating(&OnboardingMainView::GetStartedButtonPressed,
96 base::Unretained(this)),
Meilin Wangd626fde2020-10-23 17:53:3697 l10n_util::GetStringUTF16(
98 IDS_ASH_PHONE_HUB_ONBOARDING_DIALOG_GET_STARTED_BUTTON),
Crisrael Lucerof1392ae2023-05-12 23:17:4599 chromeos::features::IsJellyrollEnabled()
100 ? PillButton::Type::kPrimaryWithoutIcon
101 : PillButton::Type::kDefaultWithoutIcon,
102 /*icon=*/nullptr);
Meilin Wangd626fde2020-10-23 17:53:36103 get_started->SetID(PhoneHubViewID::kOnboardingGetStartedButton);
104 AddButton(std::move(get_started));
105 }
106
Peter Kasting5aacfd492020-10-31 03:33:14107 void GetStartedButtonPressed() {
Tim Songa6682b152020-11-03 21:24:24108 LogInterstitialScreenEvent(InterstitialScreenEvent::kConfirm);
Pu Shi0efed35f2023-08-07 19:21:24109 onboarding_ui_tracker_->HandleGetStarted(
110 parent_view_->IsOnboardingViewStartedFromNudge());
Peter Kasting5aacfd492020-10-31 03:33:14111 }
112
113 void DismissButtonPressed() {
Tim Songa6682b152020-11-03 21:24:24114 LogInterstitialScreenEvent(InterstitialScreenEvent::kDismiss);
Peter Kasting5aacfd492020-10-31 03:33:14115 parent_view_->ShowDismissPrompt();
116 }
117
Arthur Sonzogni834e018f2023-04-22 10:20:02118 raw_ptr<phonehub::OnboardingUiTracker, ExperimentalAsh>
119 onboarding_ui_tracker_ = nullptr;
120 raw_ptr<OnboardingView, ExperimentalAsh> parent_view_ = nullptr;
Tim Song5a9883f52020-11-04 19:40:03121 const OnboardingView::OnboardingFlow onboarding_flow_;
Meilin Wangd626fde2020-10-23 17:53:36122};
123
David Yeungadb27442023-11-14 22:49:51124BEGIN_METADATA(OnboardingMainView)
125END_METADATA
126
Meilin Wangd626fde2020-10-23 17:53:36127// OnboardingDismissPromptView ------------------------------------------------
128// A follow-up prompt screen that pops up when the user has chosen to dismiss
129// the main onboarding screen. It should not be shown again after being
130// dismissed manually by either clicking the ack button or outside the bubble.
Peter Kasting5aacfd492020-10-31 03:33:14131class OnboardingDismissPromptView : public PhoneHubInterstitialView {
David Yeungadb27442023-11-14 22:49:51132 METADATA_HEADER(OnboardingDismissPromptView, PhoneHubInterstitialView)
133
Meilin Wangd626fde2020-10-23 17:53:36134 public:
135 explicit OnboardingDismissPromptView(
Henrique Ferreiro91fb61df2021-11-12 15:51:03136 phonehub::OnboardingUiTracker* onboarding_ui_tracker)
Meilin Wangffecec382020-11-13 03:12:23137 : PhoneHubInterstitialView(/*show_progress=*/false, /*show_image=*/false),
Meilin Wangd626fde2020-10-23 17:53:36138 onboarding_ui_tracker_(onboarding_ui_tracker) {
139 SetID(PhoneHubViewID::kOnboardingDismissPromptView);
140 InitLayout();
141 }
142
143 private:
144 void InitLayout() {
145 // Adds title and description.
146 SetTitle(l10n_util::GetStringUTF16(
147 IDS_ASH_PHONE_HUB_ONBOARDING_DISMISS_DIALOG_TITLE));
Jan Wilken Dörrie85285b02021-03-11 23:38:47148 std::u16string part1 = l10n_util::GetStringUTF16(
Kyle Horimotofe7173b2021-01-14 22:32:48149 IDS_ASH_PHONE_HUB_ONBOARDING_DISMISS_DIALOG_DESCRIPTION_PART_1);
Jan Wilken Dörrie85285b02021-03-11 23:38:47150 std::u16string part2 = l10n_util::GetStringUTF16(
Meilin Wangd626fde2020-10-23 17:53:36151 IDS_ASH_PHONE_HUB_ONBOARDING_DISMISS_DIALOG_DESCRIPTION_PART_2);
152 // Uses "\n" to create a newline separator between two text paragraphs.
Jan Wilken Dörriec92a6d7242021-03-23 17:43:48153 SetDescription(base::StrCat({part1, u"\n\n", part2}));
Meilin Wangd626fde2020-10-23 17:53:36154
155 // Adds "Ok, got it" button.
mincha0674932021-10-18 17:56:21156 auto ack_button = std::make_unique<PillButton>(
Peter Kasting5aacfd492020-10-31 03:33:14157 base::BindRepeating(&OnboardingDismissPromptView::ButtonPressed,
158 base::Unretained(this)),
Meilin Wangd626fde2020-10-23 17:53:36159 l10n_util::GetStringUTF16(
160 IDS_ASH_PHONE_HUB_ONBOARDING_DISMISS_DIALOG_OK_BUTTON),
Xiaodan Zhue21746e2022-08-22 22:12:10161 PillButton::Type::kDefaultWithoutIcon, /*icon=*/nullptr);
Meilin Wangd626fde2020-10-23 17:53:36162 ack_button->SetID(PhoneHubViewID::kOnboardingDismissAckButton);
163 AddButton(std::move(ack_button));
164 }
165
Peter Kasting5aacfd492020-10-31 03:33:14166 void ButtonPressed() {
Tim Songa6682b152020-11-03 21:24:24167 LogInterstitialScreenEvent(InterstitialScreenEvent::kConfirm);
Tim Song947932a2020-10-31 00:38:45168
Andre Le4a5d5cd2020-12-08 20:04:15169 // Close Phone Hub bubble in current display.
170 views::Widget* const widget = GetWidget();
171 // |widget| is null when this function is called before the view is added to
172 // a widget (in unit tests).
173 if (!widget)
174 return;
175 int64_t current_display_id =
176 display::Screen::GetScreen()
177 ->GetDisplayNearestWindow(widget->GetNativeWindow())
178 .id();
179 Shell::GetRootWindowControllerWithDisplayId(current_display_id)
Meilin Wangd626fde2020-10-23 17:53:36180 ->GetStatusAreaWidget()
181 ->phone_hub_tray()
182 ->CloseBubble();
183 }
184
Peter Kasting5aacfd492020-10-31 03:33:14185 // PhoneHubInterstitialView:
186 void OnBubbleClose() override { onboarding_ui_tracker_->DismissSetupUi(); }
187
188 Screen GetScreenForMetrics() const override {
189 return Screen::kOnboardingDismissPrompt;
190 }
191
Arthur Sonzogni834e018f2023-04-22 10:20:02192 raw_ptr<phonehub::OnboardingUiTracker, ExperimentalAsh>
193 onboarding_ui_tracker_ = nullptr;
Meilin Wangd626fde2020-10-23 17:53:36194};
195
David Yeungadb27442023-11-14 22:49:51196BEGIN_METADATA(OnboardingDismissPromptView)
197END_METADATA
198
Meilin Wangd626fde2020-10-23 17:53:36199// OnboardingView -------------------------------------------------------------
Meilin Wang98efd1be2020-10-01 22:25:35200OnboardingView::OnboardingView(
Henrique Ferreiro91fb61df2021-11-12 15:51:03201 phonehub::OnboardingUiTracker* onboarding_ui_tracker,
Meilin Wang65319732020-11-06 20:03:18202 Delegate* delegate,
Tim Song5a9883f52020-11-04 19:40:03203 OnboardingFlow onboarding_flow)
Meilin Wang65319732020-11-06 20:03:18204 : onboarding_ui_tracker_(onboarding_ui_tracker), delegate_(delegate) {
Meilin Wang98efd1be2020-10-01 22:25:35205 SetID(PhoneHubViewID::kOnboardingView);
Meilin Wang418ae712020-09-17 05:50:03206
Meilin Wang418ae712020-09-17 05:50:03207 SetLayoutManager(std::make_unique<views::FillLayout>());
Tim Song5a9883f52020-11-04 19:40:03208 main_view_ = AddChildView(std::make_unique<OnboardingMainView>(
209 onboarding_ui_tracker_, this, onboarding_flow));
Tim Song85303702020-10-16 04:57:00210
Tim Songa6682b152020-11-03 21:24:24211 LogInterstitialScreenEvent(InterstitialScreenEvent::kShown);
Meilin Wang418ae712020-09-17 05:50:03212}
213
214OnboardingView::~OnboardingView() = default;
215
Meilin Wangd626fde2020-10-23 17:53:36216void OnboardingView::OnBubbleClose() {
217 main_view_->OnBubbleClose();
218}
219
Tim Song947932a2020-10-31 00:38:45220Screen OnboardingView::GetScreenForMetrics() const {
221 return main_view_->GetScreenForMetrics();
222}
223
Meilin Wangd626fde2020-10-23 17:53:36224void OnboardingView::ShowDismissPrompt() {
225 DCHECK(main_view_);
226
Tim Songa6682b152020-11-03 21:24:24227 LogInterstitialScreenEvent(InterstitialScreenEvent::kShown);
Tim Song947932a2020-10-31 00:38:45228
Arthur Sonzogni834e018f2023-04-22 10:20:02229 RemoveChildViewT(main_view_.get());
Meilin Wangd626fde2020-10-23 17:53:36230 main_view_ = AddChildView(
231 std::make_unique<OnboardingDismissPromptView>(onboarding_ui_tracker_));
232
Meilin Wang65319732020-11-06 20:03:18233 // We don't show status header view on top for the dismiss prompt.
234 DCHECK(delegate_);
235 delegate_->HideStatusHeaderView();
Meilin Wang418ae712020-09-17 05:50:03236}
237
Pu Shi0efed35f2023-08-07 19:21:24238bool OnboardingView::IsOnboardingViewStartedFromNudge() {
239 if (!delegate_) {
240 return false;
241 }
242
243 return delegate_->IsPhoneHubIconClickedWhenNudgeVisible();
244}
245
Meilin Wang418ae712020-09-17 05:50:03246BEGIN_METADATA(OnboardingView, views::View)
247END_METADATA
248
249} // namespace ash