Commit 68a5784c authored by Jeroen Dhollander's avatar Jeroen Dhollander Committed by Commit Bot

Disable suggestion chips after submitting query

When an Assistant query has been submitted, you should not be able to
interact with the suggestion chips anymore.
Mouse clicks had always been disabled, but a bug still allowed the
user to submit queries using |TAB| and |ENTER|.

This CL also introduces some extra unittests that were missing.

Bug: b/151800188
Change-Id: I15fe1b946ae92c1f74b7a98656793e4d00b2a12c
Tests: ash_unittests "AssistantPageViewTest.*" and view_unittests
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2119388Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Commit-Queue: Jeroen Dhollander <jeroendh@google.com>
Cr-Commit-Position: refs/heads/master@{#754711}
parent 4d66384d
......@@ -5,6 +5,7 @@
#include "ash/assistant/model/assistant_ui_model.h"
#include "ash/assistant/test/assistant_ash_test_base.h"
#include "ash/assistant/ui/assistant_ui_constants.h"
#include "ash/assistant/ui/main_stage/suggestion_chip_view.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom-shared.h"
......@@ -29,6 +30,13 @@ using chromeos::assistant::mojom::AssistantInteractionType;
EXPECT_EQ(interaction->type, type_); \
})
#define EXPECT_NO_INTERACTION() \
({ \
base::Optional<AssistantInteractionMetadata> interaction = \
current_interaction(); \
ASSERT_FALSE(interaction.has_value()); \
})
// Ensures that the given view has the focus. If it doesn't, this will print a
// nice error message indicating which view has the focus instead.
#define EXPECT_HAS_FOCUS(expected_) \
......@@ -172,7 +180,9 @@ class AssistantPageViewTest : public AssistantAshTestBase {
}
void PressKey(ui::KeyboardCode key_code) {
// Any key press consists of 2 events, namely |press| and |release|.
GetEventGenerator()->PressKey(key_code, /*flags=*/ui::EF_NONE);
GetEventGenerator()->ReleaseKey(key_code, /*flags=*/ui::EF_NONE);
}
void PressKeyAndWait(ui::KeyboardCode key_code) {
......@@ -180,6 +190,14 @@ class AssistantPageViewTest : public AssistantAshTestBase {
base::RunLoop().RunUntilIdle();
}
ash::SuggestionChipView* CreateAndGetSuggestionChip(
const std::string& chip_query) {
MockTextInteraction().WithSuggestionChip(chip_query);
auto suggestion_chips = GetSuggestionChips();
DCHECK_EQ(suggestion_chips.size(), 1u);
return suggestion_chips[0];
}
const views::View* GetFocusedView() {
return main_view()->GetFocusManager()->GetFocusedView();
}
......@@ -188,6 +206,54 @@ class AssistantPageViewTest : public AssistantAshTestBase {
DISALLOW_COPY_AND_ASSIGN(AssistantPageViewTest);
};
// Counts the number of Assistant interactions that are started.
class AssistantInteractionCounter
: private chromeos::assistant::mojom::AssistantInteractionSubscriber {
public:
explicit AssistantInteractionCounter(
chromeos::assistant::mojom::Assistant* service) {
service->AddAssistantInteractionSubscriber(
receiver_.BindNewPipeAndPassRemote());
}
AssistantInteractionCounter(AssistantInteractionCounter&) = delete;
AssistantInteractionCounter& operator=(AssistantInteractionCounter&) = delete;
~AssistantInteractionCounter() override = default;
int interaction_count() const { return interaction_count_; }
private:
// AssistantInteractionSubscriber implementation:
void OnInteractionStarted(
chromeos::assistant::mojom::AssistantInteractionMetadataPtr) override {
interaction_count_++;
}
void OnInteractionFinished(
chromeos::assistant::mojom::AssistantInteractionResolution) override {}
void OnHtmlResponse(const std::string& response,
const std::string& fallback) override {}
void OnSuggestionsResponse(
std::vector<chromeos::assistant::mojom::AssistantSuggestionPtr> response)
override {}
void OnTextResponse(const std::string& response) override {}
void OnTimersResponse(const std::vector<std::string>& timer_ids) override {}
void OnOpenUrlResponse(const ::GURL& url, bool in_background) override {}
void OnOpenAppResponse(chromeos::assistant::mojom::AndroidAppInfoPtr app_info,
OnOpenAppResponseCallback callback) override {}
void OnSpeechRecognitionStarted() override {}
void OnSpeechRecognitionIntermediateResult(
const std::string& high_confidence_text,
const std::string& low_confidence_text) override {}
void OnSpeechRecognitionEndOfUtterance() override {}
void OnSpeechRecognitionFinalResult(
const std::string& final_result) override {}
void OnSpeechLevelUpdated(float speech_level) override {}
void OnTtsStarted(bool due_to_error) override {}
void OnWaitStarted() override {}
mojo::Receiver<AssistantInteractionSubscriber> receiver_{this};
int interaction_count_ = 0;
};
} // namespace
TEST_F(AssistantPageViewTest, ShouldStartAtMinimumHeight) {
......@@ -373,6 +439,146 @@ TEST_F(AssistantPageViewTest,
EXPECT_FALSE(current_interaction().has_value());
}
TEST_F(AssistantPageViewTest, ShouldShowOptInViewUnlessUserHasGivenConsent) {
ShowAssistantUi();
const views::View* suggestion_chips = suggestion_chip_container();
const views::View* opt_in = opt_in_view();
SetConsentStatus(ConsentStatus::kUnauthorized);
EXPECT_TRUE(opt_in->IsDrawn());
EXPECT_FALSE(suggestion_chips->IsDrawn());
SetConsentStatus(ConsentStatus::kNotFound);
EXPECT_TRUE(opt_in->IsDrawn());
EXPECT_FALSE(suggestion_chips->IsDrawn());
SetConsentStatus(ConsentStatus::kUnknown);
EXPECT_TRUE(opt_in->IsDrawn());
EXPECT_FALSE(suggestion_chips->IsDrawn());
SetConsentStatus(ConsentStatus::kActivityControlAccepted);
EXPECT_FALSE(opt_in->IsDrawn());
EXPECT_TRUE(suggestion_chips->IsDrawn());
}
TEST_F(AssistantPageViewTest, ShouldSubmitQueryWhenClickingOnSuggestionChip) {
ShowAssistantUi();
ash::SuggestionChipView* suggestion_chip =
CreateAndGetSuggestionChip("<suggestion chip query>");
ClickOnAndWait(suggestion_chip);
EXPECT_INTERACTION_OF_TYPE(AssistantInteractionType::kText);
EXPECT_EQ("<suggestion chip query>", current_interaction()->query);
}
TEST_F(AssistantPageViewTest,
ShouldSubmitQueryWhenPressingEnterOnSuggestionChip) {
ShowAssistantUi();
ash::SuggestionChipView* suggestion_chip =
CreateAndGetSuggestionChip("<suggestion chip query>");
suggestion_chip->RequestFocus();
PressKeyAndWait(ui::KeyboardCode::VKEY_RETURN);
EXPECT_INTERACTION_OF_TYPE(AssistantInteractionType::kText);
EXPECT_EQ("<suggestion chip query>", current_interaction()->query);
}
TEST_F(AssistantPageViewTest,
ShouldNotSubmitQueryWhenPressingSpaceOnSuggestionChip) {
ShowAssistantUi();
ash::SuggestionChipView* suggestion_chip =
CreateAndGetSuggestionChip("<suggestion chip query>");
suggestion_chip->RequestFocus();
PressKeyAndWait(ui::KeyboardCode::VKEY_SPACE);
EXPECT_NO_INTERACTION();
}
TEST_F(AssistantPageViewTest,
ShouldOnlySubmitOneQueryWhenClickingSuggestionChipMultipleTimes) {
ShowAssistantUi();
ash::SuggestionChipView* suggestion_chip =
CreateAndGetSuggestionChip("<suggestion chip query>");
AssistantInteractionCounter counter{assistant_service()};
ClickOnAndWait(suggestion_chip, /*check_if_view_can_process_events=*/false);
ClickOnAndWait(suggestion_chip, /*check_if_view_can_process_events=*/false);
ClickOnAndWait(suggestion_chip, /*check_if_view_can_process_events=*/false);
ClickOnAndWait(suggestion_chip, /*check_if_view_can_process_events=*/false);
EXPECT_EQ(1, counter.interaction_count());
}
TEST_F(AssistantPageViewTest,
ShouldOnlySubmitQueryFromFirstSuggestionChipClickedOn) {
ShowAssistantUi();
MockTextInteraction()
.WithSuggestionChip("<first query>")
.WithSuggestionChip("<second query>")
.WithSuggestionChip("<third query>");
auto suggestion_chips = GetSuggestionChips();
AssistantInteractionCounter counter{assistant_service()};
ClickOnAndWait(suggestion_chips[0]);
// All next clicks should be no-ops.
ClickOnAndWait(suggestion_chips[0],
/*check_if_view_can_process_events=*/false);
ClickOnAndWait(suggestion_chips[1],
/*check_if_view_can_process_events=*/false);
ClickOnAndWait(suggestion_chips[2],
/*check_if_view_can_process_events=*/false);
EXPECT_EQ(1, counter.interaction_count());
EXPECT_EQ("<first query>", current_interaction()->query);
}
TEST_F(AssistantPageViewTest,
SuggestionChipsShouldNotBeFocusableAfterSubmittingQuery) {
ShowAssistantUi();
MockTextInteraction()
.WithSuggestionChip("<first query>")
.WithSuggestionChip("<second query>")
.WithSuggestionChip("<third query>");
auto suggestion_chips = GetSuggestionChips();
suggestion_chips[0]->RequestFocus();
PressKeyAndWait(ui::KeyboardCode::VKEY_RETURN);
for (auto* suggestion_chip : suggestion_chips) {
EXPECT_FALSE(suggestion_chip->IsFocusable())
<< "Suggestion chip '" << suggestion_chip->GetText()
<< "' is still focusable";
}
}
TEST_F(AssistantPageViewTest,
ShouldFocusTextFieldWhenSubmittingSuggestionChipInTextMode) {
ShowAssistantUiInTextMode();
ash::SuggestionChipView* suggestion_chip =
CreateAndGetSuggestionChip("<suggestion chip query>");
suggestion_chip->RequestFocus();
PressKeyAndWait(ui::KeyboardCode::VKEY_RETURN);
EXPECT_HAS_FOCUS(input_text_field());
}
TEST_F(AssistantPageViewTest,
ShouldFocusMicWhenSubmittingSuggestionChipInVoiceMode) {
ShowAssistantUi();
ash::SuggestionChipView* suggestion_chip =
CreateAndGetSuggestionChip("<suggestion chip query>");
ClickOnAndWait(voice_input_toggle());
suggestion_chip->RequestFocus();
PressKeyAndWait(ui::KeyboardCode::VKEY_RETURN);
EXPECT_HAS_FOCUS(mic_view());
}
TEST_F(AssistantPageViewTest,
ShouldFocusTextFieldWhenPressingKeyboardInputToggle) {
ShowAssistantUiInVoiceMode();
......
......@@ -92,6 +92,10 @@ views::View* AssistantTestApiImpl::keyboard_input_toggle() {
return page_view()->GetViewByID(AssistantViewID::kKeyboardInputToggle);
}
views::View* AssistantTestApiImpl::suggestion_chip_container() {
return page_view()->GetViewByID(AssistantViewID::kSuggestionContainer);
}
views::View* AssistantTestApiImpl::opt_in_view() {
return page_view()->GetViewByID(AssistantViewID::kOptInView);
}
......
......@@ -45,6 +45,7 @@ class AssistantTestApiImpl : public AssistantTestApi {
views::View* greeting_label() override;
views::View* voice_input_toggle() override;
views::View* keyboard_input_toggle() override;
views::View* suggestion_chip_container() override;
views::View* opt_in_view() override;
aura::Window* window() override;
views::View* app_list_view() override;
......
......@@ -12,6 +12,7 @@
#include "ash/assistant/test/test_assistant_client.h"
#include "ash/assistant/test/test_assistant_setup.h"
#include "ash/assistant/test/test_assistant_web_view_factory.h"
#include "ash/assistant/ui/main_stage/suggestion_chip_view.h"
#include "ash/keyboard/ui/keyboard_ui_controller.h"
#include "ash/keyboard/ui/test/keyboard_test_util.h"
#include "ash/public/cpp/assistant/assistant_state.h"
......@@ -58,6 +59,37 @@ void PressHomeButton() {
AppListShowSource::kShelfButton, base::TimeTicks::Now());
}
// Collects all child views of the given templated type.
// This includes direct and indirect children.
// For this class to work, _ChildView must:
// * Inherit from |views::View|.
// * Have a static variable called |kClassName|.
// * Return |_ChildView::kClassName| from its GetClassName() method.
template <class _ChildView>
class ChildViewCollector {
public:
using Views = std::vector<_ChildView*>;
explicit ChildViewCollector(const views::View* parent) : parent_(parent) {}
Views Get() {
Views result;
for (views::View* child : parent_->children())
Get(child, &result);
return result;
}
private:
void Get(views::View* view, Views* result) {
if (view->GetClassName() == _ChildView::kClassName)
result->push_back(static_cast<_ChildView*>(view));
for (views::View* child : view->children())
Get(child, result);
}
const views::View* parent_;
};
} // namespace
AssistantAshTestBase::AssistantAshTestBase()
......@@ -90,6 +122,9 @@ void AssistantAshTestBase::SetUp() {
test_api_->GetAssistantState()->NotifyFeatureAllowed(
mojom::AssistantAllowedState::ALLOWED);
// Set user consent so the suggestion chips are displayed.
SetConsentStatus(ConsentStatus::kActivityControlAccepted);
// Cache controller.
controller_ = Shell::Get()->assistant_controller();
DCHECK(controller_);
......@@ -140,8 +175,7 @@ void AssistantAshTestBase::SetTabletMode(bool enable) {
test_api_->SetTabletMode(enable);
}
void AssistantAshTestBase::SetConsentStatus(
chromeos::assistant::prefs::ConsentStatus consent_status) {
void AssistantAshTestBase::SetConsentStatus(ConsentStatus consent_status) {
test_api_->SetConsentStatus(consent_status);
}
......@@ -184,7 +218,7 @@ void AssistantAshTestBase::SendQueryThroughTextField(const std::string& query) {
test_api_->SendTextQuery(query);
}
void AssistantAshTestBase::TapOnAndWait(views::View* view) {
void AssistantAshTestBase::TapOnAndWait(const views::View* view) {
CheckCanProcessEvents(view);
TapAndWait(GetPointInside(view));
}
......@@ -195,8 +229,11 @@ void AssistantAshTestBase::TapAndWait(gfx::Point position) {
base::RunLoop().RunUntilIdle();
}
void AssistantAshTestBase::ClickOnAndWait(views::View* view) {
CheckCanProcessEvents(view);
void AssistantAshTestBase::ClickOnAndWait(
const views::View* view,
bool check_if_view_can_process_events) {
if (check_if_view_can_process_events)
CheckCanProcessEvents(view);
GetEventGenerator()->MoveMouseTo(GetPointInside(view));
GetEventGenerator()->ClickLeftButton();
......@@ -254,6 +291,16 @@ views::View* AssistantAshTestBase::opt_in_view() {
return test_api_->opt_in_view();
}
views::View* AssistantAshTestBase::suggestion_chip_container() {
return test_api_->suggestion_chip_container();
}
std::vector<ash::SuggestionChipView*>
AssistantAshTestBase::GetSuggestionChips() {
const views::View* container = suggestion_chip_container();
return ChildViewCollector<ash::SuggestionChipView>{container}.Get();
}
void AssistantAshTestBase::ShowKeyboard() {
auto* keyboard_controller = keyboard::KeyboardUIController::Get();
keyboard_controller->ShowKeyboard(/*lock=*/false);
......
......@@ -31,6 +31,7 @@ class AssistantController;
class AssistantInteractionController;
class AssistantInteractionModel;
class AssistantTestApi;
class SuggestionChipView;
class TestAssistantClient;
class TestAssistantService;
class TestAssistantSetup;
......@@ -41,6 +42,7 @@ class AssistantAshTestBase : public AshTestBase {
public:
using AssistantEntryPoint = chromeos::assistant::mojom::AssistantEntryPoint;
using AssistantExitPoint = chromeos::assistant::mojom::AssistantExitPoint;
using ConsentStatus = chromeos::assistant::prefs::ConsentStatus;
AssistantAshTestBase();
explicit AssistantAshTestBase(base::test::TaskEnvironment::TimeSource time);
......@@ -66,8 +68,8 @@ class AssistantAshTestBase : public AshTestBase {
void SetTabletMode(bool enable);
// Changes the user preference controlling the status of user consent.
void SetConsentStatus(chromeos::assistant::prefs::ConsentStatus);
// Change the user preference controlling the status of user consent.
void SetConsentStatus(ConsentStatus);
// Change the user setting controlling whether the user prefers voice or
// keyboard.
......@@ -111,7 +113,7 @@ class AssistantAshTestBase : public AshTestBase {
// Simulate the user tapping on the given view.
// Waits for the event to be processed.
void TapOnAndWait(views::View* view);
void TapOnAndWait(const views::View* view);
// Simulate the user tapping at the given position.
// Waits for the event to be processed.
......@@ -119,19 +121,20 @@ class AssistantAshTestBase : public AshTestBase {
// Simulate a mouse click on the given view.
// Waits for the event to be processed.
void ClickOnAndWait(views::View* view);
void ClickOnAndWait(const views::View* view,
bool check_if_view_can_process_events = true);
// Returns the current interaction. Returns |base::nullopt| if no interaction
// Return the current interaction. Returns |base::nullopt| if no interaction
// is in progress.
base::Optional<chromeos::assistant::mojom::AssistantInteractionMetadata>
current_interaction();
// Creates a new App window, and activate it.
// Create a new App window, and activate it.
// Returns a pointer to the newly created window.
// The window will be destroyed when the test is finished.
aura::Window* SwitchToNewAppWindow();
// Creates a new Widget, and activate it.
// Create a new Widget, and activate it.
// Returns a pointer to the newly created widget.
// The widget will be destroyed when the test is finished.
views::Widget* SwitchToNewWidget();
......@@ -155,9 +158,15 @@ class AssistantAshTestBase : public AshTestBase {
// Return the button to enable text mode.
views::View* keyboard_input_toggle();
// Returns the button to launch Assistant onboarding.
// Return the button to launch Assistant onboarding.
views::View* opt_in_view();
// Return the container with all the suggestion chips.
views::View* suggestion_chip_container();
// Return the suggestion chips that are currently displayed.
std::vector<ash::SuggestionChipView*> GetSuggestionChips();
// Show/Dismiss the on-screen keyboard.
void ShowKeyboard();
void DismissKeyboard();
......@@ -172,9 +181,9 @@ class AssistantAshTestBase : public AshTestBase {
AssistantInteractionController* interaction_controller();
const AssistantInteractionModel* interaction_model();
private:
TestAssistantService* assistant_service();
private:
std::unique_ptr<AssistantTestApi> test_api_;
std::unique_ptr<TestAssistantSetup> test_setup_;
std::unique_ptr<TestAssistantWebViewFactory> test_web_view_factory_;
......
......@@ -41,6 +41,12 @@ MockedAssistantInteraction& MockedAssistantInteraction::WithTextResponse(
return *this;
}
MockedAssistantInteraction& MockedAssistantInteraction::WithSuggestionChip(
const std::string& text) {
response_->AddSuggestionChip(text);
return *this;
}
MockedAssistantInteraction& MockedAssistantInteraction::WithResolution(
Resolution resolution) {
resolution_ = resolution;
......
......@@ -29,6 +29,7 @@ class MockedAssistantInteraction {
MockedAssistantInteraction& WithQuery(const std::string& text_query);
MockedAssistantInteraction& WithTextResponse(
const std::string& text_response);
MockedAssistantInteraction& WithSuggestionChip(const std::string& text);
MockedAssistantInteraction& WithResolution(Resolution);
private:
......
......@@ -9,6 +9,7 @@
#include <vector>
#include "ash/assistant/assistant_interaction_controller.h"
#include "base/unguessable_token.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -19,6 +20,8 @@ using chromeos::assistant::mojom::AssistantInteractionMetadataPtr;
using chromeos::assistant::mojom::AssistantInteractionResolution;
using chromeos::assistant::mojom::AssistantInteractionSubscriber;
using chromeos::assistant::mojom::AssistantInteractionType;
using chromeos::assistant::mojom::AssistantSuggestion;
using chromeos::assistant::mojom::AssistantSuggestionPtr;
// Subscriber that will ensure the LibAssistant contract is enforced.
// More specifically, it will ensure that:
......@@ -197,6 +200,27 @@ class TextResponse : public InteractionResponse::Response {
DISALLOW_COPY_AND_ASSIGN(TextResponse);
};
class SuggestionsResponse : public InteractionResponse::Response {
public:
explicit SuggestionsResponse(const std::string& text) : text_(text) {}
SuggestionsResponse(const SuggestionsResponse&) = delete;
SuggestionsResponse& operator=(const SuggestionsResponse&) = delete;
~SuggestionsResponse() override = default;
void SendTo(chromeos::assistant::mojom::AssistantInteractionSubscriber*
receiver) override {
std::vector<AssistantSuggestionPtr> suggestions;
suggestions.emplace_back(AssistantSuggestion::New());
auto& suggestion = suggestions.back();
suggestion->text = text_;
suggestion->id = base::UnguessableToken::Create();
receiver->OnSuggestionsResponse(std::move(suggestions));
}
private:
std::string text_;
};
class ResolutionResponse : public InteractionResponse::Response {
public:
using Resolution = InteractionResponse::Resolution;
......@@ -341,6 +365,12 @@ InteractionResponse* InteractionResponse::AddTextResponse(
return this;
}
InteractionResponse* InteractionResponse::AddSuggestionChip(
const std::string& text) {
AddResponse(std::make_unique<SuggestionsResponse>(text));
return this;
}
InteractionResponse* InteractionResponse::AddResolution(Resolution resolution) {
AddResponse(std::make_unique<ResolutionResponse>(resolution));
return this;
......
......@@ -41,6 +41,8 @@ class InteractionResponse {
// A simple textual response.
InteractionResponse* AddTextResponse(const std::string& text);
// A suggestion chip response.
InteractionResponse* AddSuggestionChip(const std::string& text);
// If used this will cause us to finish the interaction by passing the given
// |resolution| to |AssistantInteractionSubscriber::OnInteractionFinished|.
InteractionResponse* AddResolution(Resolution resolution);
......
......@@ -238,8 +238,8 @@ void AnimatedContainerView::AddElementAnimatorAndAnimateInView(
DCHECK_EQ(animator->view()->parent(), content_view());
animators_.push_back(std::move(animator));
// We don't allow processing of events while animating.
set_can_process_events_within_subtree(false);
// We don't allow interactions while animating.
DisableInteractions();
auto* animation_observer = new ui::CallbackLayerAnimationObserver(
/*animation_ended_callback=*/base::BindRepeating(
......@@ -260,9 +260,9 @@ void AnimatedContainerView::FadeOutViews() {
fade_out_in_progress_ = true;
// We don't allow processing of events while waiting for the next query
// response. The contents will be faded out, so it should not be interactive.
set_can_process_events_within_subtree(false);
// We don't allow interactions while waiting for the next query response. The
// contents will be faded out, so it should not be interactive.
DisableInteractions();
auto* animation_observer = new ui::CallbackLayerAnimationObserver(
/*animation_ended_callback=*/base::BindRepeating(
......@@ -276,6 +276,11 @@ void AnimatedContainerView::FadeOutViews() {
animation_observer->SetActive();
}
void AnimatedContainerView::SetInteractionsEnabled(bool enabled) {
for (const auto& animator : animators_)
animator->view()->SetEnabled(enabled);
}
bool AnimatedContainerView::AnimateInObserverCallback(
const base::WeakPtr<AnimatedContainerView>& weak_ptr,
const ui::CallbackLayerAnimationObserver& observer) {
......@@ -295,7 +300,7 @@ bool AnimatedContainerView::AnimateInObserverCallback(
// off prior to this animation finishing. Once all animations have completed
// interactivity will be restored and derivate classes notified.
if (!weak_ptr->IsAnimatingViews()) {
weak_ptr->set_can_process_events_within_subtree(true);
weak_ptr->EnableInteractions();
weak_ptr->OnAllViewsAnimatedIn();
}
......
......@@ -117,6 +117,10 @@ class COMPONENT_EXPORT(ASSISTANT_UI) AnimatedContainerView
void AddElementAnimatorAndAnimateInView(std::unique_ptr<ElementAnimator>);
void FadeOutViews();
void EnableInteractions() { SetInteractionsEnabled(true); }
void DisableInteractions() { SetInteractionsEnabled(false); }
void SetInteractionsEnabled(bool enabled);
static bool AnimateInObserverCallback(
const base::WeakPtr<AnimatedContainerView>& weak_ptr,
const ui::CallbackLayerAnimationObserver& observer);
......
......@@ -39,6 +39,9 @@ constexpr int kPreferredHeightDip = 32;
// SuggestionChipView ----------------------------------------------------------
// static
constexpr char SuggestionChipView::kClassName[];
SuggestionChipView::SuggestionChipView(AssistantViewDelegate* delegate,
const AssistantSuggestion* suggestion,
views::ButtonListener* listener)
......@@ -48,6 +51,10 @@ SuggestionChipView::SuggestionChipView(AssistantViewDelegate* delegate,
SuggestionChipView::~SuggestionChipView() = default;
const char* SuggestionChipView::GetClassName() const {
return kClassName;
}
gfx::Size SuggestionChipView::CalculatePreferredSize() const {
const int preferred_width = views::View::CalculatePreferredSize().width();
return gfx::Size(preferred_width, GetHeightForWidth(preferred_width));
......
......@@ -25,12 +25,15 @@ class COMPONENT_EXPORT(ASSISTANT_UI) SuggestionChipView : public views::Button {
public:
using AssistantSuggestion = chromeos::assistant::mojom::AssistantSuggestion;
static constexpr char kClassName[] = "SuggestionChipView";
SuggestionChipView(AssistantViewDelegate* delegate,
const AssistantSuggestion* suggestion,
views::ButtonListener* listener);
~SuggestionChipView() override;
// views::View:
const char* GetClassName() const override;
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int width) const override;
void ChildVisibilityChanged(views::View* child) override;
......
......@@ -105,6 +105,10 @@ class ASH_EXPORT AssistantTestApi {
// Can only be used after the Assistant UI has been shown at least once.
virtual views::View* opt_in_view() = 0;
// Returns the view containing the suggestion chips.
// Can only be used after the Assistant UI has been shown at least once.
virtual views::View* suggestion_chip_container() = 0;
// Returns the window containing the Assistant UI.
// Note that this window is shared for all components of the |AppList|.
// Can only be used after the Assistant UI has been shown at least once.
......
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