1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // 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/quick_answers/quick_answers_ui_controller.h"
6
7 #include "ash/public/cpp/assistant/controller/assistant_interaction_controller.h"
8 #include "ash/quick_answers/quick_answers_controller_impl.h"
9 #include "ash/quick_answers/ui/quick_answers_view.h"
10 #include "ash/quick_answers/ui/user_notice_view.h"
11 #include "ash/shell.h"
12 #include "ash/strings/grit/ash_strings.h"
13 #include "base/bind.h"
14 #include "base/optional.h"
15 #include "chromeos/components/quick_answers/quick_answers_model.h"
16 #include "chromeos/constants/chromeos_features.h"
17 #include "chromeos/services/assistant/public/cpp/assistant_service.h"
18 #include "mojo/public/cpp/bindings/remote.h"
19 #include "ui/aura/client/aura_constants.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/views/widget/widget.h"
22
23 using chromeos::quick_answers::QuickAnswer;
24 namespace ash {
25
QuickAnswersUiController(QuickAnswersControllerImpl * controller)26 QuickAnswersUiController::QuickAnswersUiController(
27 QuickAnswersControllerImpl* controller)
28 : controller_(controller) {}
29
~QuickAnswersUiController()30 QuickAnswersUiController::~QuickAnswersUiController() {
31 quick_answers_view_ = nullptr;
32 user_notice_view_ = nullptr;
33 }
34
CreateQuickAnswersView(const gfx::Rect & bounds,const std::string & title,const std::string & query)35 void QuickAnswersUiController::CreateQuickAnswersView(
36 const gfx::Rect& bounds,
37 const std::string& title,
38 const std::string& query) {
39 // Currently there are timing issues that causes the quick answers view is not
40 // dismissed. TODO(updowndota): Remove the special handling after the root
41 // cause is found.
42 if (quick_answers_view_) {
43 LOG(ERROR) << "Quick answers view not dismissed.";
44 CloseQuickAnswersView();
45 }
46
47 DCHECK(!user_notice_view_);
48 SetActiveQuery(query);
49 quick_answers_view_ = new QuickAnswersView(bounds, title, this);
50 quick_answers_view_->GetWidget()->ShowInactive();
51 }
52
OnQuickAnswersViewPressed()53 void QuickAnswersUiController::OnQuickAnswersViewPressed() {
54 // Route dismissal through |controller_| for logging impressions.
55 controller_->DismissQuickAnswers(/*is_active=*/true);
56
57 ash::AssistantInteractionController::Get()->StartTextInteraction(
58 query_, /*allow_tts=*/false,
59 chromeos::assistant::AssistantQuerySource::kQuickAnswers);
60 controller_->OnQuickAnswerClick();
61 }
62
CloseQuickAnswersView()63 bool QuickAnswersUiController::CloseQuickAnswersView() {
64 if (quick_answers_view_) {
65 quick_answers_view_->GetWidget()->Close();
66 quick_answers_view_ = nullptr;
67 return true;
68 }
69 return false;
70 }
71
OnRetryLabelPressed()72 void QuickAnswersUiController::OnRetryLabelPressed() {
73 controller_->OnRetryQuickAnswersRequest();
74 }
75
RenderQuickAnswersViewWithResult(const gfx::Rect & anchor_bounds,const QuickAnswer & quick_answer)76 void QuickAnswersUiController::RenderQuickAnswersViewWithResult(
77 const gfx::Rect& anchor_bounds,
78 const QuickAnswer& quick_answer) {
79 if (!quick_answers_view_)
80 return;
81
82 // QuickAnswersView was initiated with a loading page and will be updated
83 // when quick answers result from server side is ready.
84 quick_answers_view_->UpdateView(anchor_bounds, quick_answer);
85 }
86
SetActiveQuery(const std::string & query)87 void QuickAnswersUiController::SetActiveQuery(const std::string& query) {
88 query_ = query;
89 }
90
ShowRetry()91 void QuickAnswersUiController::ShowRetry() {
92 if (!quick_answers_view_)
93 return;
94
95 quick_answers_view_->ShowRetryView();
96 }
97
UpdateQuickAnswersBounds(const gfx::Rect & anchor_bounds)98 void QuickAnswersUiController::UpdateQuickAnswersBounds(
99 const gfx::Rect& anchor_bounds) {
100 if (quick_answers_view_)
101 quick_answers_view_->UpdateAnchorViewBounds(anchor_bounds);
102
103 if (user_notice_view_)
104 user_notice_view_->UpdateAnchorViewBounds(anchor_bounds);
105 }
106
CreateUserNoticeView(const gfx::Rect & anchor_bounds,const base::string16 & intent_type,const base::string16 & intent_text)107 void QuickAnswersUiController::CreateUserNoticeView(
108 const gfx::Rect& anchor_bounds,
109 const base::string16& intent_type,
110 const base::string16& intent_text) {
111 DCHECK(!quick_answers_view_);
112 DCHECK(!user_notice_view_);
113 user_notice_view_ = new quick_answers::UserNoticeView(
114 anchor_bounds, intent_type, intent_text, this);
115 user_notice_view_->GetWidget()->ShowInactive();
116 }
117
CloseUserNoticeView()118 void QuickAnswersUiController::CloseUserNoticeView() {
119 if (user_notice_view_) {
120 user_notice_view_->GetWidget()->Close();
121 user_notice_view_ = nullptr;
122 }
123 }
124
OnAcceptButtonPressed()125 void QuickAnswersUiController::OnAcceptButtonPressed() {
126 DCHECK(user_notice_view_);
127 controller_->OnUserNoticeAccepted();
128
129 // The Quick-Answer displayed should gain focus if it is created when this
130 // button is pressed.
131 if (quick_answers_view_)
132 quick_answers_view_->RequestFocus();
133 }
134
OnManageSettingsButtonPressed()135 void QuickAnswersUiController::OnManageSettingsButtonPressed() {
136 controller_->OnNoticeSettingsRequestedByUser();
137 }
138
OnDogfoodButtonPressed()139 void QuickAnswersUiController::OnDogfoodButtonPressed() {
140 // Route dismissal through |controller_| for logging impressions.
141 controller_->DismissQuickAnswers(/*is_active=*/true);
142
143 controller_->OpenQuickAnswersDogfoodLink();
144 }
145
146 } // namespace ash
147