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