vc-dlc-ui: Add warning view for kError DL state
Adding a warning label which is added for at most 2 effects. The FeatureTile fetches DLC state on construction, which eventually will propagate the state to Bubble view, where the warning labels are updated. Also added some pixel tests. go/vc-dlc-ui-pixel-things Change-Id: I819bb40c81d00a8bafb3242ce3085e3936781abf Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5522002 Reviewed-by: Andre Le <leandre@chromium.org> Auto-Submit: Alex Newcomer <newcomer@chromium.org> Commit-Queue: Alex Newcomer <newcomer@chromium.org> Cr-Commit-Position: refs/heads/main@{#1312354}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
169d071105
commit
5a7ed5d272
ash
ash_strings.grd
ash_strings_grd
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_DLC_ERROR_ONE.png.sha1IDS_ASH_VIDEO_CONFERENCE_BUBBLE_DLC_ERROR_TWO.png.sha1
resources
vector_icons
system
@ -1794,6 +1794,12 @@ You can also use the keyboard shortcut. First, highlight text, then press <ph na
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_LINUX_APP_WARNING_TEXT" desc="Text for the warning label placed inside the VC bubble when there's any linux app running.">
|
||||
Effects are not supported on linux apps
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_DLC_ERROR_ONE" desc="The text shown in a warning label when one DLC had an error downloading.">
|
||||
<ph name="UNAVAILABLE_DLC">$1<ex>Live Caption</ex></ph> is not available.
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_DLC_ERROR_TWO" desc="The text shown in a warning label when two DLCs had an error downloading.">
|
||||
<ph name="UNAVAILABLE_DLC_ONE">$1<ex>Live Caption</ex></ph>, and <ph name="UNAVAILABLE_DLC_TWO">$2<ex>Background Blur</ex></ph> are not available.
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_TOAST_SPEAK_ON_MUTE_DETECTED" desc="A toast message that we show when user tries to speak while muted on system-level.">
|
||||
Are you talking? Your mic is off. Select the mic to turn it on.
|
||||
</message>
|
||||
|
@ -0,0 +1 @@
|
||||
e922b1bc0495ee19df0bc2ecddaa6e8258fb20d8
|
@ -0,0 +1 @@
|
||||
b7d804bdb75169b7b48d067c47d52d871a3c68f4
|
@ -633,7 +633,6 @@ aggregate_vector_icons("ash_vector_icons") {
|
||||
"video_conference_camera_capturing.icon",
|
||||
"video_conference_camera_framing_on.icon",
|
||||
"video_conference_camera_muted.icon",
|
||||
"video_conference_linux_app_warning.icon",
|
||||
"video_conference_live_caption_on.icon",
|
||||
"video_conference_microphone_capturing.icon",
|
||||
"video_conference_microphone_muted.icon",
|
||||
@ -641,6 +640,7 @@ aggregate_vector_icons("ash_vector_icons") {
|
||||
"video_conference_portrait_relight_on.icon",
|
||||
"video_conference_screen_share.icon",
|
||||
"video_conference_up_chevron.icon",
|
||||
"video_conference_warning.icon",
|
||||
"visibility.icon",
|
||||
"visibility_off.icon",
|
||||
"wallpaper.icon",
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "ash/system/video_conference/bubble/bubble_view.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
#include "ash/shell.h"
|
||||
@ -19,6 +20,7 @@
|
||||
#include "ash/system/video_conference/bubble/toggle_effects_view.h"
|
||||
#include "ash/system/video_conference/effects/video_conference_tray_effects_manager.h"
|
||||
#include "ash/system/video_conference/video_conference_tray_controller.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "chromeos/crosapi/mojom/video_conference.mojom.h"
|
||||
@ -43,8 +45,10 @@ namespace ash::video_conference {
|
||||
namespace {
|
||||
|
||||
constexpr int kLinuxAppWarningViewTopPadding = 12;
|
||||
constexpr int kLinuxAppWarningViewSpacing = 1;
|
||||
constexpr int kLinuxAppWarningIconSize = 16;
|
||||
constexpr int kDLCErrorWarningLabelTopPadding = 0;
|
||||
constexpr int kWarningViewSpacing = 1;
|
||||
constexpr int kWarningIconSize = 16;
|
||||
|
||||
constexpr int kScrollViewBetweenChildSpacing = 16;
|
||||
|
||||
CameraEffectsController* GetCameraEffectsController() {
|
||||
@ -63,47 +67,40 @@ bool HasLinuxApps(const MediaApps& apps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A view that will be display when there's Linux app(s) running along with
|
||||
// other media apps, used to warn users that effects cannot be applied to Linux
|
||||
// apps.
|
||||
class LinuxAppWarningView : public views::View {
|
||||
METADATA_HEADER(LinuxAppWarningView, views::View)
|
||||
// Creates a view that will display a warning icon with text.
|
||||
std::unique_ptr<views::View> CreateWarningView(
|
||||
int warning_view_id,
|
||||
int top_padding,
|
||||
std::optional<int> warning_message = std::nullopt) {
|
||||
auto view = std::make_unique<views::View>();
|
||||
view->SetID(warning_view_id);
|
||||
view->SetLayoutManager(std::make_unique<views::FlexLayout>())
|
||||
->SetOrientation(views::LayoutOrientation::kHorizontal)
|
||||
.SetMainAxisAlignment(views::LayoutAlignment::kCenter)
|
||||
.SetCrossAxisAlignment(views::LayoutAlignment::kStretch)
|
||||
.SetInteriorMargin(gfx::Insets::TLBR(top_padding, 0, 0, 0))
|
||||
.SetDefault(
|
||||
views::kMarginsKey,
|
||||
gfx::Insets::TLBR(0, kWarningViewSpacing, 0, kWarningViewSpacing));
|
||||
|
||||
public:
|
||||
LinuxAppWarningView() {
|
||||
SetID(BubbleViewID::kLinuxAppWarningView);
|
||||
SetLayoutManager(std::make_unique<views::FlexLayout>())
|
||||
->SetOrientation(views::LayoutOrientation::kHorizontal)
|
||||
.SetMainAxisAlignment(views::LayoutAlignment::kCenter)
|
||||
.SetCrossAxisAlignment(views::LayoutAlignment::kStretch)
|
||||
.SetInteriorMargin(
|
||||
gfx::Insets::TLBR(kLinuxAppWarningViewTopPadding, 0, 0, 0))
|
||||
.SetDefault(views::kMarginsKey,
|
||||
gfx::Insets::TLBR(0, kLinuxAppWarningViewSpacing, 0,
|
||||
kLinuxAppWarningViewSpacing));
|
||||
auto icon = std::make_unique<views::ImageView>();
|
||||
icon->SetImage(ui::ImageModel::FromVectorIcon(
|
||||
kVideoConferenceWarningIcon, cros_tokens::kCrosSysOnSurfaceVariant,
|
||||
kWarningIconSize));
|
||||
view->AddChildView(std::move(icon));
|
||||
|
||||
auto icon = std::make_unique<views::ImageView>();
|
||||
icon->SetImage(ui::ImageModel::FromVectorIcon(
|
||||
kVideoConferenceLinuxAppWarningIcon,
|
||||
cros_tokens::kCrosSysOnSurfaceVariant, kLinuxAppWarningIconSize));
|
||||
AddChildView(std::move(icon));
|
||||
|
||||
auto label = std::make_unique<views::Label>();
|
||||
label->SetText(l10n_util::GetStringUTF16(
|
||||
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_LINUX_APP_WARNING_TEXT));
|
||||
TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosAnnotation2,
|
||||
*label);
|
||||
AddChildView(std::move(label));
|
||||
auto label = std::make_unique<views::Label>();
|
||||
// Set a view ID so the label can be modified if necessary.
|
||||
label->SetID(BubbleViewID::kWarningViewLabel);
|
||||
if (warning_message.has_value()) {
|
||||
label->SetText(l10n_util::GetStringUTF16(*warning_message));
|
||||
}
|
||||
TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosAnnotation2,
|
||||
*label);
|
||||
view->AddChildView(std::move(label));
|
||||
|
||||
LinuxAppWarningView(const LinuxAppWarningView&) = delete;
|
||||
LinuxAppWarningView& operator=(const LinuxAppWarningView&) = delete;
|
||||
|
||||
~LinuxAppWarningView() override = default;
|
||||
};
|
||||
|
||||
BEGIN_METADATA(LinuxAppWarningView);
|
||||
END_METADATA
|
||||
return view;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -137,7 +134,10 @@ void BubbleView::AddedToWidget() {
|
||||
|
||||
if (HasLinuxApps(*media_apps_) &&
|
||||
(has_toggle_effects || has_set_value_effects)) {
|
||||
AddChildView(std::make_unique<LinuxAppWarningView>());
|
||||
AddChildView(CreateWarningView(
|
||||
BubbleViewID::kLinuxAppWarningView,
|
||||
/*top_padding=*/kLinuxAppWarningViewTopPadding,
|
||||
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_LINUX_APP_WARNING_TEXT));
|
||||
}
|
||||
|
||||
// Create the `views::ScrollView` to house the effects sections. This has to
|
||||
@ -170,6 +170,16 @@ void BubbleView::AddedToWidget() {
|
||||
if (has_toggle_effects) {
|
||||
scroll_contents_view->AddChildView(
|
||||
std::make_unique<ToggleEffectsView>(controller_));
|
||||
auto error_warning_label_container_view =
|
||||
CreateWarningView(BubbleViewID::kDLCDownloadsInErrorView,
|
||||
/*top_padding=*/kDLCErrorWarningLabelTopPadding);
|
||||
// Visibility will for most cases be false, if a DLC has an error in
|
||||
// downloading, state updates will be fetched by any toggle effect's
|
||||
// `FeatureTile`, then pushed from the controller via
|
||||
// `OnDLCDownloadStateInError()`.
|
||||
error_warning_label_container_view->SetVisible(false);
|
||||
scroll_contents_view->AddChildView(
|
||||
std::move(error_warning_label_container_view));
|
||||
}
|
||||
if (has_set_value_effects) {
|
||||
scroll_contents_view->AddChildView(
|
||||
@ -201,6 +211,66 @@ void BubbleView::SetBackgroundReplaceUiVisible(bool visible) {
|
||||
ChildPreferredSizeChanged(set_camera_background_view_);
|
||||
}
|
||||
|
||||
void BubbleView::OnDLCDownloadStateInError(
|
||||
bool add_warning_view,
|
||||
const std::u16string& feature_tile_title_string) {
|
||||
auto* dlc_error_container_view =
|
||||
GetViewByID(BubbleViewID::kDLCDownloadsInErrorView);
|
||||
if (!dlc_error_container_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* dlc_error_label = static_cast<views::Label*>(
|
||||
dlc_error_container_view->GetViewByID(BubbleViewID::kWarningViewLabel));
|
||||
if (!dlc_error_label) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (add_warning_view) {
|
||||
if (std::size(feature_tile_error_string_ids_) == 2) {
|
||||
return;
|
||||
}
|
||||
feature_tile_error_string_ids_.emplace(feature_tile_title_string);
|
||||
} else {
|
||||
auto it = std::find(feature_tile_error_string_ids_.begin(),
|
||||
feature_tile_error_string_ids_.end(),
|
||||
feature_tile_title_string);
|
||||
if (it == feature_tile_error_string_ids_.end()) {
|
||||
return;
|
||||
}
|
||||
feature_tile_error_string_ids_.erase(it);
|
||||
}
|
||||
|
||||
// If the one and only string was removed, hide the view and reset it.
|
||||
// Otherwise update the string.
|
||||
if (feature_tile_error_string_ids_.empty()) {
|
||||
dlc_error_container_view->SetVisible(false);
|
||||
dlc_error_label->SetText(std::u16string());
|
||||
return;
|
||||
}
|
||||
|
||||
if (feature_tile_error_string_ids_.size() == 1) {
|
||||
dlc_error_label->SetText(l10n_util::GetStringFUTF16(
|
||||
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_DLC_ERROR_ONE,
|
||||
*feature_tile_error_string_ids_.begin()));
|
||||
dlc_error_container_view->SetVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only two are supported, adding more would require more custom handling for
|
||||
// the string below.
|
||||
if (feature_tile_error_string_ids_.size() > 2u) {
|
||||
return;
|
||||
}
|
||||
std::vector<std::u16string> string_ids(feature_tile_error_string_ids_.size());
|
||||
std::copy(feature_tile_error_string_ids_.begin(),
|
||||
feature_tile_error_string_ids_.end(), string_ids.begin());
|
||||
dlc_error_label->SetText(
|
||||
l10n_util::GetStringFUTF16(IDS_ASH_VIDEO_CONFERENCE_BUBBLE_DLC_ERROR_TWO,
|
||||
string_ids, /*offsets=*/nullptr));
|
||||
dlc_error_container_view->SetVisible(true);
|
||||
}
|
||||
|
||||
BEGIN_METADATA(BubbleView)
|
||||
END_METADATA
|
||||
|
||||
|
@ -37,6 +37,12 @@ class ASH_EXPORT BubbleView : public TrayBubbleView {
|
||||
BubbleView& operator=(const BubbleView&) = delete;
|
||||
~BubbleView() override;
|
||||
|
||||
// Called when DLC download state updates, used to add and update a warning
|
||||
// string.
|
||||
void OnDLCDownloadStateInError(
|
||||
bool add_warning_view,
|
||||
const std::u16string& feature_tile_title_string);
|
||||
|
||||
// views::View:
|
||||
void AddedToWidget() override;
|
||||
void ChildPreferredSizeChanged(View* child) override;
|
||||
@ -50,6 +56,9 @@ class ASH_EXPORT BubbleView : public TrayBubbleView {
|
||||
// Unowned by `BubbleView`.
|
||||
raw_ptr<VideoConferenceTrayController> controller_;
|
||||
|
||||
// String id's of all `FeatureTile`'s that have an error downloading.
|
||||
std::set<std::u16string> feature_tile_error_string_ids_;
|
||||
|
||||
const raw_ref<const MediaApps> media_apps_;
|
||||
|
||||
raw_ptr<views::View> set_camera_background_view_ = nullptr;
|
||||
|
@ -41,10 +41,19 @@ enum BubbleViewID {
|
||||
// Label which is a child of an individual "toggle" VC effect.
|
||||
kToggleEffectLabel,
|
||||
|
||||
// The label with a warning icon, indicating that effects are not available
|
||||
// The view with a warning icon and label, indicating that effects are not
|
||||
// available
|
||||
// for linux apps.
|
||||
kLinuxAppWarningView,
|
||||
|
||||
// The view with a warning icon and a custom label for each DLC which had an
|
||||
// error installing.
|
||||
kDLCDownloadsInErrorView,
|
||||
|
||||
// The label in the generic warning view which is either
|
||||
// `kLinuxAppWarningView` or `kDLCDownloadsInErrorView`.
|
||||
kWarningViewLabel,
|
||||
|
||||
// The VC bubble that will be displayed when all the running media apps are
|
||||
// Linux apps.
|
||||
kLinuxAppBubbleView,
|
||||
|
@ -131,6 +131,11 @@ class BubbleViewPixelTest
|
||||
|
||||
bool IsVcDlcUiEnabled() { return GetParam(); }
|
||||
|
||||
void ModifyDlcDownloadState(bool add_warning, std::u16string warning_label) {
|
||||
static_cast<video_conference::BubbleView*>(bubble_view())
|
||||
->OnDLCDownloadStateInError(add_warning, warning_label);
|
||||
}
|
||||
|
||||
VideoConferenceTray* video_conference_tray() {
|
||||
return StatusAreaWidgetTestHelper::GetStatusAreaWidget()
|
||||
->video_conference_tray();
|
||||
@ -413,4 +418,78 @@ TEST_P(BubbleViewPixelTest, ThreeToggleEffects) {
|
||||
/*revision_number=*/6, GetToggleEffectsView()));
|
||||
}
|
||||
|
||||
TEST_P(BubbleViewPixelTest, DLCUIInErrorShowsWarningLabelSingleError) {
|
||||
if (!IsVcDlcUiEnabled()) {
|
||||
return;
|
||||
}
|
||||
// Create a toggle effect so the warning label is available.
|
||||
controller()->GetEffectsManager().RegisterDelegate(office_bunny());
|
||||
|
||||
// Click to open the bubble, toggle effect button should be visible.
|
||||
LeftClickOn(video_conference_tray()->GetToggleBubbleButtonForTest());
|
||||
ASSERT_TRUE(bubble_view());
|
||||
ASSERT_TRUE(GetToggleEffectsView()->GetVisible());
|
||||
|
||||
// Add an error, make sure the label shows up.
|
||||
ModifyDlcDownloadState(/*add_warning=*/true, u"test-feature-name1");
|
||||
|
||||
EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
|
||||
"one-toggle-effects-view",
|
||||
/*revision_number=*/1, bubble_view()));
|
||||
|
||||
// Add one set-value effect.
|
||||
controller()->GetEffectsManager().RegisterDelegate(shaggy_fur());
|
||||
|
||||
// Hide and re-show the bubble so the set-value effect show sup.
|
||||
LeftClickOn(video_conference_tray()->GetToggleBubbleButtonForTest());
|
||||
ASSERT_FALSE(bubble_view());
|
||||
|
||||
LeftClickOn(video_conference_tray()->GetToggleBubbleButtonForTest());
|
||||
ASSERT_TRUE(bubble_view());
|
||||
|
||||
ModifyDlcDownloadState(/*add_warning=*/true, u"test-feature-name1");
|
||||
|
||||
EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
|
||||
"additional-set-value-view",
|
||||
/*revision_number=*/1, bubble_view()));
|
||||
}
|
||||
|
||||
TEST_P(BubbleViewPixelTest, DLCUIInErrorShowsWarningLabelMaxErrors) {
|
||||
if (!IsVcDlcUiEnabled()) {
|
||||
return;
|
||||
}
|
||||
// Create a toggle effect so the warning label is available.
|
||||
controller()->GetEffectsManager().RegisterDelegate(office_bunny());
|
||||
|
||||
// Click to open the bubble, toggle effect button should be visible.
|
||||
LeftClickOn(video_conference_tray()->GetToggleBubbleButtonForTest());
|
||||
ASSERT_TRUE(bubble_view());
|
||||
ASSERT_TRUE(GetToggleEffectsView()->GetVisible());
|
||||
|
||||
// Add 2 errors (the max), make sure the label shows up.
|
||||
ModifyDlcDownloadState(/*add_warning=*/true, u"test-feature-name1");
|
||||
ModifyDlcDownloadState(/*add_warning=*/true, u"test-feature-name2");
|
||||
|
||||
EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
|
||||
"one-toggle-effects-view",
|
||||
/*revision_number=*/1, bubble_view()));
|
||||
|
||||
// Add one set-value effect.
|
||||
controller()->GetEffectsManager().RegisterDelegate(shaggy_fur());
|
||||
|
||||
// Hide and re-show the bubble so the set-value effect show sup.
|
||||
LeftClickOn(video_conference_tray()->GetToggleBubbleButtonForTest());
|
||||
ASSERT_FALSE(bubble_view());
|
||||
|
||||
LeftClickOn(video_conference_tray()->GetToggleBubbleButtonForTest());
|
||||
ASSERT_TRUE(bubble_view());
|
||||
|
||||
ModifyDlcDownloadState(/*add_warning=*/true, u"test-feature-name1");
|
||||
ModifyDlcDownloadState(/*add_warning=*/true, u"test-feature-name2");
|
||||
|
||||
EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
|
||||
"additional-set-value-view",
|
||||
/*revision_number=*/1, bubble_view()));
|
||||
}
|
||||
|
||||
} // namespace ash::video_conference
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "ash/system/video_conference/bubble/bubble_view.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/constants/ash_switches.h"
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
@ -129,7 +131,8 @@ class BubbleViewTest : public AshTestBase {
|
||||
|
||||
// AshTestBase:
|
||||
void SetUp() override {
|
||||
scoped_feature_list_.InitAndEnableFeature(
|
||||
scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
|
||||
scoped_feature_list_->InitAndEnableFeature(
|
||||
features::kFeatureManagementVideoConference);
|
||||
|
||||
// Instantiates a fake controller (the real one is created in
|
||||
@ -164,6 +167,7 @@ class BubbleViewTest : public AshTestBase {
|
||||
shaggy_fur_.reset();
|
||||
super_cuteness_.reset();
|
||||
controller_.reset();
|
||||
scoped_feature_list_.reset();
|
||||
}
|
||||
|
||||
VideoConferenceTray* video_conference_tray() {
|
||||
@ -224,7 +228,7 @@ class BubbleViewTest : public AshTestBase {
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
|
||||
std::unique_ptr<FakeVideoConferenceTrayController> controller_;
|
||||
std::unique_ptr<ash::fake_video_conference::OfficeBunnyEffect> office_bunny_;
|
||||
std::unique_ptr<ash::fake_video_conference::ShaggyFurEffect> shaggy_fur_;
|
||||
@ -455,6 +459,155 @@ TEST_F(BubbleViewTest, LinuxAppWarningView) {
|
||||
EXPECT_TRUE(linux_app_warning_view()->GetVisible());
|
||||
}
|
||||
|
||||
class DLCBubbleViewTest : public BubbleViewTest {
|
||||
public:
|
||||
DLCBubbleViewTest() = default;
|
||||
DLCBubbleViewTest(const DLCBubbleViewTest&) = delete;
|
||||
DLCBubbleViewTest& operator=(const DLCBubbleViewTest&) = delete;
|
||||
~DLCBubbleViewTest() override = default;
|
||||
|
||||
// AshTestBase:
|
||||
void SetUp() override {
|
||||
scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
|
||||
scoped_feature_list_->InitAndEnableFeature(features::kVcDlcUi);
|
||||
BubbleViewTest::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Unregister toggle effects that were registered to ensure the
|
||||
// `VcTileUiControllers` are reset like they are in the production version.
|
||||
controller()->GetEffectsManager().UnregisterDelegate(office_bunny());
|
||||
BubbleViewTest::TearDown();
|
||||
scoped_feature_list_.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
|
||||
};
|
||||
|
||||
// Tests that an initialized BubbleView with no errors shows no warning label.
|
||||
TEST_F(DLCBubbleViewTest, NoError) {
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
ASSERT_TRUE(bubble_view());
|
||||
ASSERT_TRUE(bubble_view()->GetVisible());
|
||||
|
||||
// The error view is not added with no toggle effects.
|
||||
EXPECT_FALSE(bubble_view()->GetViewByID(kDLCDownloadsInErrorView));
|
||||
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
|
||||
// Add one toggle effect and reshow, the error view should be present but not
|
||||
// visible.
|
||||
controller()->GetEffectsManager().RegisterDelegate(office_bunny());
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
|
||||
auto* error_view = bubble_view()->GetViewByID(kDLCDownloadsInErrorView);
|
||||
EXPECT_TRUE(error_view);
|
||||
EXPECT_FALSE(error_view->GetVisible());
|
||||
}
|
||||
|
||||
// Tests adding and removing one error.
|
||||
TEST_F(DLCBubbleViewTest, OneError) {
|
||||
controller()->GetEffectsManager().RegisterDelegate(office_bunny());
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
|
||||
BubbleView* bubble_view_ptr = static_cast<BubbleView*>(bubble_view());
|
||||
// Pass one error to the bubble view, it should get a warning label.
|
||||
std::u16string test_feature_name = u"test_feature_name";
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/true,
|
||||
test_feature_name);
|
||||
auto* error_container_view =
|
||||
bubble_view()->GetViewByID(kDLCDownloadsInErrorView);
|
||||
auto* dlc_error_label = static_cast<views::Label*>(
|
||||
error_container_view->GetViewByID(BubbleViewID::kWarningViewLabel));
|
||||
EXPECT_TRUE(error_container_view);
|
||||
EXPECT_TRUE(dlc_error_label);
|
||||
|
||||
const std::u16string label_contents = dlc_error_label->GetText();
|
||||
// Try to add a second error for `test_feature_name`, there should be no
|
||||
// change.
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/true,
|
||||
test_feature_name);
|
||||
|
||||
EXPECT_EQ(label_contents, dlc_error_label->GetText());
|
||||
|
||||
// Remove the error, there should be a change.
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/false,
|
||||
test_feature_name);
|
||||
|
||||
EXPECT_EQ(std::u16string(), dlc_error_label->GetText());
|
||||
EXPECT_FALSE(error_container_view->GetVisible());
|
||||
}
|
||||
|
||||
// Tests adding/removing two+ errors.
|
||||
TEST_F(DLCBubbleViewTest, TwoPlusErrors) {
|
||||
controller()->GetEffectsManager().RegisterDelegate(office_bunny());
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
|
||||
BubbleView* bubble_view_ptr = static_cast<BubbleView*>(bubble_view());
|
||||
// Pass one error to the bubble view, it should get a warning label.
|
||||
std::u16string test_feature_name_1 = u"test_feature_name_1";
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/true,
|
||||
test_feature_name_1);
|
||||
auto* error_container_view =
|
||||
bubble_view()->GetViewByID(kDLCDownloadsInErrorView);
|
||||
auto* dlc_error_label = static_cast<views::Label*>(
|
||||
error_container_view->GetViewByID(BubbleViewID::kWarningViewLabel));
|
||||
EXPECT_TRUE(error_container_view);
|
||||
EXPECT_TRUE(dlc_error_label);
|
||||
|
||||
const std::u16string one_error_label = dlc_error_label->GetText();
|
||||
|
||||
// Add a second error for `test_feature_name_2`.
|
||||
std::u16string test_feature_name_2 = u"test_feature_name_2";
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/true,
|
||||
test_feature_name_2);
|
||||
const std::u16string two_error_label = dlc_error_label->GetText();
|
||||
|
||||
EXPECT_NE(one_error_label, two_error_label);
|
||||
|
||||
// Add a third error, there should be no effect as only two are supported.
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/true,
|
||||
u"feature_name_3");
|
||||
EXPECT_EQ(dlc_error_label->GetText(), two_error_label);
|
||||
|
||||
// Remove the error, the label should return to the first one.
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/false,
|
||||
test_feature_name_2);
|
||||
|
||||
EXPECT_EQ(one_error_label, dlc_error_label->GetText());
|
||||
|
||||
// Remove the first error, the label should be empty.
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/false,
|
||||
test_feature_name_1);
|
||||
|
||||
EXPECT_EQ(std::u16string(), dlc_error_label->GetText());
|
||||
EXPECT_FALSE(dlc_error_label->GetVisible());
|
||||
}
|
||||
|
||||
// Tests removing errors that are not there does not crash.
|
||||
TEST_F(DLCBubbleViewTest, ErrorsRemoved) {
|
||||
controller()->GetEffectsManager().RegisterDelegate(office_bunny());
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
|
||||
// Try to remove errors that don't exist.
|
||||
BubbleView* bubble_view_ptr = static_cast<BubbleView*>(bubble_view());
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/false,
|
||||
u"one");
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/false,
|
||||
u"two");
|
||||
bubble_view_ptr->OnDLCDownloadStateInError(/*add_warning_view=*/false,
|
||||
u"three");
|
||||
|
||||
auto* error_container_view =
|
||||
bubble_view()->GetViewByID(kDLCDownloadsInErrorView);
|
||||
auto* dlc_error_label = static_cast<views::Label*>(
|
||||
error_container_view->GetViewByID(BubbleViewID::kWarningViewLabel));
|
||||
|
||||
EXPECT_FALSE(error_container_view->GetVisible());
|
||||
EXPECT_EQ(dlc_error_label->GetText(), std::u16string());
|
||||
}
|
||||
|
||||
// The four `bool` params are as follows, if 'true':
|
||||
// 0 - The test effects depend on the camera being enabled.
|
||||
// 1 - The test effects depend on the microphone being enabled.
|
||||
|
@ -30,11 +30,21 @@ VcTileUiController::VcTileUiController(const VcHostedEffect* effect)
|
||||
: effect_(effect) {
|
||||
effect_id_ = effect->id();
|
||||
effect_state_ = effect->GetState(/*index=*/0);
|
||||
DlcserviceClient::Get()->AddObserver(this);
|
||||
auto* dlc_service_client = DlcserviceClient::Get();
|
||||
if (!dlc_service_client) {
|
||||
// `dlc_service_client` may not exist in tests.
|
||||
return;
|
||||
}
|
||||
dlc_service_client->AddObserver(this);
|
||||
}
|
||||
|
||||
VcTileUiController::~VcTileUiController() {
|
||||
DlcserviceClient::Get()->RemoveObserver(this);
|
||||
auto* dlc_service_client = DlcserviceClient::Get();
|
||||
if (!dlc_service_client) {
|
||||
// `dlc_service_client` may not exist in tests.
|
||||
return;
|
||||
}
|
||||
dlc_service_client->RemoveObserver(this);
|
||||
}
|
||||
|
||||
std::unique_ptr<FeatureTile> VcTileUiController::CreateTile() {
|
||||
@ -212,6 +222,10 @@ void VcTileUiController::OnDlcDownloadStateFetched(
|
||||
return;
|
||||
}
|
||||
|
||||
VideoConferenceTrayController::Get()->OnDlcDownloadStateFetched(
|
||||
/*add_warning=*/download_state == FeatureTile::DownloadState::kError,
|
||||
effect_state_->label_text());
|
||||
|
||||
tile_->SetDownloadState(download_state, progress);
|
||||
}
|
||||
|
||||
|
@ -412,6 +412,17 @@ void VideoConferenceTray::OnScreenSharingStateChange(bool is_capturing_screen) {
|
||||
}
|
||||
}
|
||||
|
||||
void VideoConferenceTray::OnDlcDownloadStateChanged(
|
||||
bool add_warning,
|
||||
const std::u16string& feature_tile_title) {
|
||||
auto* bubble_view = GetBubbleView();
|
||||
if (!bubble_view) {
|
||||
return;
|
||||
}
|
||||
views::AsViewClass<video_conference::BubbleView>(bubble_view)
|
||||
->OnDLCDownloadStateInError(add_warning, feature_tile_title);
|
||||
}
|
||||
|
||||
void VideoConferenceTray::OnCameraCapturingStateChange(bool is_capturing) {
|
||||
camera_icon_->SetIsCapturing(is_capturing);
|
||||
}
|
||||
|
@ -153,6 +153,9 @@ class ASH_EXPORT VideoConferenceTray
|
||||
void OnCameraCapturingStateChange(bool is_capturing) override;
|
||||
void OnMicrophoneCapturingStateChange(bool is_capturing) override;
|
||||
void OnScreenSharingStateChange(bool is_capturing_screen) override;
|
||||
void OnDlcDownloadStateChanged(
|
||||
bool add_warning,
|
||||
const std::u16string& feature_tile_title) override;
|
||||
|
||||
// VideoConferenceTrayEffectsManager::Observer:
|
||||
void OnEffectSupportStateChanged(VcEffectId effect_id,
|
||||
|
@ -370,6 +370,14 @@ void VideoConferenceTrayController::OnSpeakOnMuteNudgeOptInAction(bool opt_in) {
|
||||
ToastManager::Get()->Show(std::move(toast_data));
|
||||
}
|
||||
|
||||
void VideoConferenceTrayController::OnDlcDownloadStateFetched(
|
||||
bool add_warning,
|
||||
const std::u16string& feature_tile_title) {
|
||||
for (auto& observer : observer_list_) {
|
||||
observer.OnDlcDownloadStateChanged(add_warning, feature_tile_title);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoConferenceTrayController::CloseAllVcNudges() {
|
||||
for (size_t i = 0; i < std::size(kNudgeIds); ++i) {
|
||||
AnchoredNudgeManager::Get()->Cancel(kNudgeIds[i]);
|
||||
|
@ -63,6 +63,12 @@ class ASH_EXPORT VideoConferenceTrayController
|
||||
|
||||
// Called when the state of screen sharing is changed.
|
||||
virtual void OnScreenSharingStateChange(bool is_capturing_screen) = 0;
|
||||
|
||||
// Called when the Dlc download state is changed for `feature_tile_title` if
|
||||
// any DLC was registered for that effect.
|
||||
virtual void OnDlcDownloadStateChanged(
|
||||
bool error,
|
||||
const std::u16string& feature_tile_title) = 0;
|
||||
};
|
||||
|
||||
VideoConferenceTrayController();
|
||||
@ -122,6 +128,9 @@ class ASH_EXPORT VideoConferenceTrayController
|
||||
// speak-on-mute feature. An `opt_in` value of false means the user opted out.
|
||||
void OnSpeakOnMuteNudgeOptInAction(bool opt_in);
|
||||
|
||||
void OnDlcDownloadStateFetched(bool add_warning,
|
||||
const std::u16string& feature_tile_title);
|
||||
|
||||
// Closes all nudges that are shown anchored to the VC tray, if any.
|
||||
void CloseAllVcNudges();
|
||||
|
||||
|
Reference in New Issue
Block a user