0

VC UI: Add warning view to bubble view when there's a linux app

Add function to detect if there's a linux app running and display a
warning view that effects are not supported for linux apps.

Screenshot: https://screenshot.googleplex.com/6FfbzUJqDtFZYXX

Bug: b:273820331
Change-Id: Ifb9fbef645707679d404aaa2bf2cec5dfc8c7f1c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4676519
Commit-Queue: Andre Le <leandre@chromium.org>
Reviewed-by: Alex Newcomer <newcomer@chromium.org>
Reviewed-by: James Cook <jamescook@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1170093}
This commit is contained in:
Andre Le
2023-07-13 19:55:20 +00:00
committed by Chromium LUCI CQ
parent 0588569a8c
commit 4703d20762
7 changed files with 174 additions and 3 deletions

@ -1607,6 +1607,9 @@ Style notes:
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_PORTRAIT_RELIGHT_NAME" desc="Text for name of the portrait relight effect in the VC bubble, which is a toggle and effectively adjusts the users lighting.">
Improve lighting
</message>
<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_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 @@
bd0b015e3c3dd884b02372ab4e9fdeff04794ae1

@ -544,6 +544,7 @@ aggregate_vector_icons("ash_vector_icons") {
"video_conference_camera_framing_off.icon",
"video_conference_camera_framing_on.icon",
"video_conference_camera_muted.icon",
"video_conference_linux_app_warning.icon",
"video_conference_live_caption_off.icon",
"video_conference_live_caption_on.icon",
"video_conference_microphone_muted.icon",

@ -0,0 +1,29 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 16,
MOVE_TO, 7.2f, 11.2f,
H_LINE_TO, 8.8f,
V_LINE_TO, 8,
H_LINE_TO, 7.2f,
V_LINE_TO, 11.2f,
CLOSE,
MOVE_TO, 8, 1.6f,
CUBIC_TO, 4.47f, 1.6f, 1.6f, 4.47f, 1.6f, 8,
CUBIC_TO, 1.6f, 11.53f, 4.47f, 14.4f, 8, 14.4f,
CUBIC_TO, 11.53f, 14.4f, 14.4f, 11.53f, 14.4f, 8,
CUBIC_TO, 14.4f, 4.47f, 11.53f, 1.6f, 8, 1.6f,
CLOSE,
MOVE_TO, 8, 12.8f,
CUBIC_TO, 5.35f, 12.8f, 3.2f, 10.65f, 3.2f, 8,
CUBIC_TO, 3.2f, 5.35f, 5.35f, 3.2f, 8, 3.2f,
CUBIC_TO, 10.65f, 3.2f, 12.8f, 5.35f, 12.8f, 8,
CUBIC_TO, 12.8f, 10.65f, 10.65f, 12.8f, 8, 12.8f,
CLOSE,
MOVE_TO, 7.2f, 9.6f,
H_LINE_TO, 8.8f,
V_LINE_TO, 4.8f,
H_LINE_TO, 7.2f,
V_LINE_TO, 9.6f,
CLOSE

@ -4,6 +4,11 @@
#include "ash/system/video_conference/bubble/bubble_view.h"
#include <memory>
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/typography.h"
#include "ash/system/tray/tray_bubble_view.h"
#include "ash/system/video_conference/bubble/bubble_view_ids.h"
#include "ash/system/video_conference/bubble/return_to_app_panel.h"
@ -11,7 +16,17 @@
#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/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "chromeos/crosapi/mojom/video_conference.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/image_model.h"
#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/layout/fill_layout.h"
@ -20,6 +35,68 @@
namespace ash::video_conference {
namespace {
constexpr int kLinuxAppWarningViewTopPadding = 12;
constexpr int kLinuxAppWarningViewSpacing = 1;
constexpr int kLinuxAppWarningIconSize = 16;
// Check if there's a linux app in the given `apps`.
bool HasLinuxApps(const MediaApps& apps) {
for (auto& app : apps) {
if (app->app_type == crosapi::mojom::VideoConferenceAppType::kCrostiniVm ||
app->app_type == crosapi::mojom::VideoConferenceAppType::kPluginVm ||
app->app_type == crosapi::mojom::VideoConferenceAppType::kBorealis) {
return true;
}
}
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 {
public:
METADATA_HEADER(LinuxAppWarningView);
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(
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));
}
LinuxAppWarningView(const LinuxAppWarningView&) = delete;
LinuxAppWarningView& operator=(const LinuxAppWarningView&) = delete;
~LinuxAppWarningView() override = default;
};
BEGIN_METADATA(LinuxAppWarningView, views::View);
END_METADATA
} // namespace
BubbleView::BubbleView(const InitParams& init_params,
const MediaApps& media_apps,
VideoConferenceTrayController* controller)
@ -43,6 +120,16 @@ void BubbleView::AddedToWidget() {
// a parent widget).
AddChildView(std::make_unique<ReturnToAppPanel>(media_apps_));
const bool has_toggle_effects =
controller_->effects_manager().HasToggleEffects();
const bool has_set_value_effects =
controller_->effects_manager().HasSetValueEffects();
if (HasLinuxApps(media_apps_) &&
(has_toggle_effects || has_set_value_effects)) {
AddChildView(std::make_unique<LinuxAppWarningView>());
}
// Create the `views::ScrollView` to house the effects sections. This has to
// be done here because `BubbleDialogDelegate::GetBubbleBounds` requires a
// parent widget, which isn't officially assigned until after the call to
@ -70,11 +157,11 @@ void BubbleView::AddedToWidget() {
// Make the effects sections children of the `views::FlexLayoutView`, so that
// they scroll (if more effects are present than can fit in the available
// height).
if (controller_->effects_manager().HasToggleEffects()) {
if (has_toggle_effects) {
scroll_contents_view->AddChildView(
std::make_unique<ToggleEffectsView>(controller_));
}
if (controller_->effects_manager().HasSetValueEffects()) {
if (has_set_value_effects) {
scroll_contents_view->AddChildView(
std::make_unique<SetValueEffectsView>(controller_));
}

@ -41,7 +41,11 @@ enum BubbleViewID {
// Label which is a child of an individual "toggle" VC effect.
kToggleEffectLabel,
kNextAvailableId = kToggleEffectLabel + 1,
// The label with a warning icon, indicating that effects are not available
// for linux apps.
kLinuxAppWarningView,
kNextAvailableId = kLinuxAppWarningView + 1,
};
} // namespace ash::video_conference

@ -28,6 +28,9 @@
#include "ash/test/ash_test_base.h"
#include "base/command_line.h"
#include "base/test/scoped_feature_list.h"
#include "base/unguessable_token.h"
#include "chromeos/crosapi/mojom/video_conference.mojom-shared.h"
#include "chromeos/crosapi/mojom/video_conference.mojom.h"
namespace ash::video_conference {
@ -110,6 +113,16 @@ class SnackNationForever : public VcEffectsDelegate {
absl::optional<int> state) override {}
};
crosapi::mojom::VideoConferenceMediaAppInfoPtr CreateFakeMediaApp(
const crosapi::mojom::VideoConferenceAppType app_type) {
return crosapi::mojom::VideoConferenceMediaAppInfo::New(
base::UnguessableToken::Create(),
/*last_activity_time=*/base::Time::Now(), /*is_capturing_camera=*/true,
/*is_capturing_microphone=*/true, /*is_capturing_screen=*/false,
u"Test App Name",
/*url=*/GURL(), app_type);
}
} // namespace
class BubbleViewTest : public AshTestBase {
@ -199,6 +212,11 @@ class BubbleViewTest : public AshTestBase {
video_conference::BubbleViewID::kToggleEffectsButton);
}
views::View* linux_app_warning_view() {
return bubble_view()->GetViewByID(
video_conference::BubbleViewID::kLinuxAppWarningView);
}
ash::fake_video_conference::OfficeBunnyEffect* office_bunny() {
return office_bunny_.get();
}
@ -415,6 +433,34 @@ TEST_F(BubbleViewTest, InvalidEffectState) {
EXPECT_FALSE(single_set_value_effect_view());
}
TEST_F(BubbleViewTest, LinuxAppWarningView) {
controller()->ClearMediaApps();
controller()->AddMediaApp(CreateFakeMediaApp(
/*app_type=*/crosapi::mojom::VideoConferenceAppType::kChromeApp));
// Click to open the bubble, the linux app warning view is NOT present.
LeftClickOn(toggle_bubble_button());
EXPECT_FALSE(linux_app_warning_view());
// Close the bubble.
LeftClickOn(toggle_bubble_button());
controller()->AddMediaApp(CreateFakeMediaApp(
/*app_type=*/crosapi::mojom::VideoConferenceAppType::kCrostiniVm));
// When there's a linux app alongside a non-linux app, the linux app warning
// view is present only when there's effect(s) available.
LeftClickOn(toggle_bubble_button());
EXPECT_FALSE(linux_app_warning_view());
LeftClickOn(toggle_bubble_button());
controller()->effects_manager().RegisterDelegate(office_bunny());
LeftClickOn(toggle_bubble_button());
ASSERT_TRUE(linux_app_warning_view());
EXPECT_TRUE(linux_app_warning_view()->GetVisible());
}
// 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.