0

Mahi: Update accessible attributes on some components in main panel

- Make sure that the feedback buttons are accessed after the summary
  text/error view when traverse in the main panel.
- Make sure ChromeVox announce when retry and loading states happen.

Fixed: b:356224281, b:356211144, b:356164028
Change-Id: Ieb6a37e5f1242d9461799c749363a52bddf291b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5756236
Commit-Queue: Andre Le <leandre@chromium.org>
Reviewed-by: Ahmed Mehfooz <amehfooz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1338616}
This commit is contained in:
Andre Le
2024-08-07 18:29:00 +00:00
committed by Chromium LUCI CQ
parent bcea52f6f7
commit 441e09a0f7
9 changed files with 68 additions and 10 deletions

@ -5339,6 +5339,12 @@ No devices connected.
<message name="IDS_ASH_MAHI_LEARN_MORE_LINK_LABEL_TEXT" desc="Text for the learn more link that user can navigate to learn more about the project information">
Learn more
</message>
<message name="IDS_ASH_MAHI_LOADING_ACCESSIBLE_NAME" desc="The accessible name of the loading image in the mahi panel while waiting for the summary text or outline to load">
Results loading
</message>
<message name="IDS_ASH_MAHI_LOADED_ACCESSIBLE_NAME" desc="Text for the accessible name that announced when the results for Mahi panel is loaded">
Results loaded
</message>
<message name="IDS_ASH_MAHI_THUMBS_UP_FEEDBACK_BUTTON_ACCESSIBLE_NAME" desc="The tooltip of the thumbs up feedback button in the mahi panel">
Good output
</message>
@ -5369,6 +5375,9 @@ No devices connected.
<message name="IDS_ASH_MAHI_RETRY_LINK_LABEL_TEXT" desc="Text for the link that user can retry their previous Mahi request">
Try again
</message>
<message name="IDS_ASH_MAHI_RETRY_LINK_CLICK_ACTIVATION_ACCESSIBLE_NAME" desc="Text for the accessible name that announced when the retry link is clicked">
Retry link activated
</message>
<message name="IDS_ASH_MAHI_EDUCATIONAL_NUDGE_TITLE" desc="Title for the educational nudge used to discover the Mahi feature">
Right-click to summarize
</message>

@ -0,0 +1 @@
4663bf0372f55cc3916138e4fbc528e903dc8157

@ -0,0 +1 @@
57282cc91f3d30ba995d28f80f81a5c5567b24f4

@ -0,0 +1 @@
90d727f4598f4ce3d5a2fa8155af75543e9cc429

@ -24,6 +24,7 @@
#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
@ -120,14 +121,19 @@ class ErrorContentsView : public views::FlexLayoutView,
retry_link_->SetVisible(
mahi_utils::CalculateRetryLinkVisible(error.status));
retry_link_->SetCallback(retry_link_->GetVisible()
? base::BindRepeating(
[](MahiUiController* controller,
VisibilityState origin_state) {
controller->Retry(origin_state);
},
ui_controller_, error.origin_state)
: base::RepeatingClosure());
retry_link_->SetCallback(
retry_link_->GetVisible()
? base::BindRepeating(
[](MahiUiController* controller,
VisibilityState origin_state,
views::View* retry_link) {
controller->Retry(origin_state);
retry_link->GetViewAccessibility().AnnounceText(
l10n_util::GetStringUTF16(
IDS_ASH_MAHI_RETRY_LINK_CLICK_ACTIVATION_ACCESSIBLE_NAME));
},
ui_controller_, error.origin_state, retry_link_)
: base::RepeatingClosure());
return;
}
case MahiUiUpdateType::kAnswerLoaded:

@ -553,6 +553,9 @@ MahiPanelView::MahiPanelView(MahiUiController* ui_controller)
.SetID(mahi_constants::ViewId::kContentSourceButton)
.Build());
views::View* feedback_buttons_container;
views::View* error_status_view;
// Add a scrollable view of the panel's content, with a feedback section.
main_container_->AddChildView(
views::Builder<views::View>()
@ -569,6 +572,7 @@ MahiPanelView::MahiPanelView(MahiUiController* ui_controller)
.AddChildren(
// Add buttons for the user to give feedback on the content.
views::Builder<views::BoxLayoutView>()
.CopyAddressTo(&feedback_buttons_container)
.SetOrientation(views::BoxLayout::Orientation::kHorizontal)
.SetInsideBorderInsets(gfx::Insets::TLBR(
0, 0, 0, kFeedbackButtonIconPaddingRight))
@ -627,9 +631,15 @@ MahiPanelView::MahiPanelView(MahiUiController* ui_controller)
views::MaximumFlexSizeRule::
kUnbounded)))),
views::Builder<MahiErrorStatusView>(
std::make_unique<MahiErrorStatusView>(ui_controller_)))
std::make_unique<MahiErrorStatusView>(ui_controller_))
.CopyAddressTo(&error_status_view))
.Build());
// Put feedback buttons container after the error status view in the focus
// list since the order of traversal should be scroll view -> error status
// view -> feedback buttons.
feedback_buttons_container->InsertAfterInFocusList(error_status_view);
// Add a row for processing user input that includes a textfield, send button
// and a back to Q&A button when in the summary section.
views::FlexLayoutView* ask_question_container = nullptr;

@ -301,6 +301,8 @@ void MahiQuestionAnswerView::OnUpdated(const MahiUiUpdate& update) {
auto* answer_loading_animated_image = AddChildView(
views::Builder<views::AnimatedImageView>()
.SetID(mahi_constants::ViewId::kAnswerLoadingAnimatedImage)
.SetAccessibleName(l10n_util::GetStringUTF16(
IDS_ASH_MAHI_LOADING_ACCESSIBLE_NAME))
.SetAnimatedImage(mahi_animation_utils::GetLottieAnimationData(
IDR_MAHI_LOADING_SUMMARY_ANIMATION))
.AfterBuild(base::BindOnce([](views::AnimatedImageView* self) {

@ -6,6 +6,7 @@
#include <memory>
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/typography.h"
#include "ash/system/mahi/mahi_animation_utils.h"
#include "ash/system/mahi/mahi_constants.h"
@ -24,6 +25,7 @@
#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
#include "ui/gfx/text_constants.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/animated_image_view.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
@ -86,6 +88,8 @@ SummaryOutlinesSection::SummaryOutlinesSection(MahiUiController* ui_controller)
views::Builder<views::AnimatedImageView>()
.CopyAddressTo(&summary_loading_animated_image_)
.SetID(mahi_constants::ViewId::kSummaryLoadingAnimatedImage)
.SetAccessibleName(
l10n_util::GetStringUTF16(IDS_ASH_MAHI_LOADING_ACCESSIBLE_NAME))
.SetAnimatedImage(mahi_animation_utils::GetLottieAnimationData(
IDR_MAHI_LOADING_SUMMARY_ANIMATION))
.Build());
@ -129,6 +133,8 @@ SummaryOutlinesSection::SummaryOutlinesSection(MahiUiController* ui_controller)
.SetID(mahi_constants::ViewId::kOutlinesLoadingAnimatedImage)
.SetAnimatedImage(mahi_animation_utils::GetLottieAnimationData(
IDR_MAHI_LOADING_OUTLINES_ANIMATION))
.SetAccessibleName(
l10n_util::GetStringUTF16(IDS_ASH_MAHI_LOADING_ACCESSIBLE_NAME))
.Build());
outlines_section_container->AddChildView(
@ -179,6 +185,16 @@ void SummaryOutlinesSection::OnUpdated(const MahiUiUpdate& update) {
}
}
void SummaryOutlinesSection::AddedToWidget() {
// When the view is first constructed, we need to wait until the view is added
// to the widget to announce loading state.
if (summary_loading_animated_image_->GetVisible() ||
outlines_loading_animated_image_->GetVisible()) {
GetViewAccessibility().AnnounceText(
l10n_util::GetStringUTF16(IDS_ASH_MAHI_LOADING_ACCESSIBLE_NAME));
}
}
void SummaryOutlinesSection::HandleOutlinesLoaded(
const std::vector<chromeos::MahiOutline>& outlines) {
outlines_container_->RemoveAllChildViews();
@ -199,7 +215,10 @@ void SummaryOutlinesSection::HandleOutlinesLoaded(
outlines_loading_animated_image_->Stop();
outlines_loading_animated_image_->SetVisible(false);
// TODO(b/330643995): Show the outlines section once it is ready.
// TODO(b/330643995): Show the outlines section once it is ready. Note that
// when enabling outlines, we need to make sure that the state of fully
// loaded is announced in accessibility (similar to what is done in
// `HandleSummaryLoaded()`).
outlines_container_->SetVisible(false);
// TODO(b/333916944): Add metrics recording the outline loading animation time
@ -215,6 +234,9 @@ void SummaryOutlinesSection::HandleSummaryLoaded(
base::UmaHistogramTimes(mahi_constants::kSummaryLoadingTimeHistogramName,
base::Time::Now() - summary_start_loading_time_);
GetViewAccessibility().AnnounceText(
l10n_util::GetStringUTF16(IDS_ASH_MAHI_LOADED_ACCESSIBLE_NAME));
}
void SummaryOutlinesSection::LoadSummaryAndOutlines() {
@ -243,6 +265,9 @@ void SummaryOutlinesSection::LoadSummaryAndOutlines() {
*outlines_loading_animated_image_->animated_image()->skottie(),
IDR_MAHI_LOADING_OUTLINES_ANIMATION));
GetViewAccessibility().AnnounceText(
l10n_util::GetStringUTF16(IDS_ASH_MAHI_LOADING_ACCESSIBLE_NAME));
summary_start_loading_time_ = base::Time::Now();
ui_controller_->UpdateSummaryAndOutlines();

@ -42,6 +42,9 @@ class ASH_EXPORT SummaryOutlinesSection : public views::BoxLayoutView,
bool GetViewVisibility(VisibilityState state) const override;
void OnUpdated(const MahiUiUpdate& update) override;
// views::BoxLayoutView:
void AddedToWidget() override;
void HandleOutlinesLoaded(const std::vector<chromeos::MahiOutline>& outlines);
void HandleSummaryLoaded(const std::u16string& summary_text);