coral: Add max saved group toast when limit is hit
At the moment, the rest of feature is not implemented, so this will not show up in production. It does get the ball rolling on some piping work and creating a test fixture though. Test: ash_unittests CoralControllerTest.MaxCoralSavedGroupLimit Change-Id: I4a2f28b7070de1b38bc76128fa6595abdd6b9929 Fixed: 366264124 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6012939 Reviewed-by: Michele Fan <michelefan@chromium.org> Commit-Queue: Sammie Quon <sammiequon@chromium.org> Reviewed-by: Ahmed Fakhry <afakhry@chromium.org> Reviewed-by: Alex Newcomer <newcomer@chromium.org> Reviewed-by: Daniel Andersson <dandersson@chromium.org> Cr-Commit-Position: refs/heads/main@{#1382768}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
98bae582dc
commit
c25b103480
ash
components/desks_storage/core
desk_model.hdesk_model_wrapper.ccdesk_model_wrapper.hdesk_sync_bridge.ccdesk_sync_bridge.hfake_desk_sync_bridge.ccfake_desk_sync_bridge.hlocal_desk_data_manager.cclocal_desk_data_manager.h
tools/metrics/histograms/metadata/ash
@@ -8829,6 +8829,9 @@ To shut down the device, press and hold the power button on the device again.
|
||||
<message name="IDS_ASH_BIRCH_CORAL_ADDON_SELECTOR_HIDDEN" translateable="false" desc="The accessible name for the birch coral button selector UI.">
|
||||
Show
|
||||
</message>
|
||||
<message name="IDS_ASH_BIRCH_CORAL_SAVED_GROUPS_MAX_NUM_REACHED" translateable="false" desc="Message shown to users when they attempt to save a new coral group when the maximum number of coral saved groups has been reached.">
|
||||
Maximum number of saved groups reached.
|
||||
</message>
|
||||
|
||||
<!-- Graduation app strings -->
|
||||
<message name="IDS_ASH_GRADUATION_NUDGE_TEXT" desc="Text shown in nudge that is displayed after the Content Transfer app becomes available.">
|
||||
|
@@ -325,7 +325,8 @@ enum class ToastCatalogName {
|
||||
kOnTaskUrlBlocked = 55,
|
||||
kCopyImageToClipboardAction = 56,
|
||||
kCaptureModeTextCopied = 57,
|
||||
kMaxValue = kCaptureModeTextCopied
|
||||
kCoralSavedGroupLimitMax = 58,
|
||||
kMaxValue = kCoralSavedGroupLimitMax
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
@@ -13,23 +13,36 @@
|
||||
#include "ash/shell.h"
|
||||
#include "ash/system/toast/toast_manager_impl.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "ash/test/ash_test_helper.h"
|
||||
#include "ash/wm/coral/coral_test_util.h"
|
||||
#include "ash/wm/desks/desk.h"
|
||||
#include "ash/wm/desks/desks_controller.h"
|
||||
#include "ash/wm/desks/desks_test_util.h"
|
||||
#include "ash/wm/desks/templates/saved_desk_test_helper.h"
|
||||
#include "ash/wm/desks/templates/saved_desk_test_util.h"
|
||||
#include "ash/wm/overview/birch/birch_bar_controller.h"
|
||||
#include "ash/wm/overview/birch/birch_bar_menu_model_adapter.h"
|
||||
#include "ash/wm/overview/birch/birch_chip_button.h"
|
||||
#include "ash/wm/overview/birch/birch_chip_context_menu_model.h"
|
||||
#include "ash/wm/overview/overview_controller.h"
|
||||
#include "ash/wm/overview/overview_utils.h"
|
||||
#include "ash/wm/snap_group/snap_group_controller.h"
|
||||
#include "ash/wm/snap_group/snap_group_test_util.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "ui/aura/client/aura_constants.h"
|
||||
#include "ui/views/controls/menu/menu_item_view.h"
|
||||
#include "ui/views/controls/menu/submenu_view.h"
|
||||
#include "ui/views/view_utils.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class CoralControllerTest : public AshTestBase {
|
||||
public:
|
||||
CoralControllerTest() {
|
||||
feature_list_.InitWithFeatures(
|
||||
{features::kCoralFeature, features::kCoralSavedDeskFeature}, {});
|
||||
}
|
||||
|
||||
void ClickFirstCoralButton() {
|
||||
DeskSwitchAnimationWaiter waiter;
|
||||
BirchChipButton* coral_button = GetFirstCoralButton();
|
||||
@@ -38,6 +51,12 @@ class CoralControllerTest : public AshTestBase {
|
||||
waiter.Wait();
|
||||
}
|
||||
|
||||
void AddCoralEntry(const std::string& name) {
|
||||
AddSavedDeskEntry(ash_test_helper()->saved_desk_test_helper()->desk_model(),
|
||||
base::Uuid::GenerateRandomV4(), name, base::Time::Now(),
|
||||
DeskTemplateType::kCoral);
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
AshTestBase::SetUp();
|
||||
|
||||
@@ -66,7 +85,7 @@ class CoralControllerTest : public AshTestBase {
|
||||
private:
|
||||
std::unique_ptr<TestBirchClient> birch_client_;
|
||||
|
||||
base::test::ScopedFeatureList feature_list_{features::kCoralFeature};
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
};
|
||||
|
||||
// Tests that clicking the in session coral button opens and activates a new
|
||||
@@ -199,4 +218,34 @@ TEST_F(CoralControllerTest, SnapGroupTwoWindowsInCoralGroup) {
|
||||
window2.get()));
|
||||
}
|
||||
|
||||
TEST_F(CoralControllerTest, MaxCoralSavedGroupLimit) {
|
||||
ash_test_helper()->saved_desk_test_helper()->WaitForDeskModels();
|
||||
|
||||
// Add enough entries to hit the max.
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
AddCoralEntry(base::NumberToString(i));
|
||||
}
|
||||
|
||||
Shell::Get()->overview_controller()->StartOverview(
|
||||
OverviewStartAction::kTests);
|
||||
|
||||
// Right click on the coral button to bring up the context menu and the save
|
||||
// as group option.
|
||||
RightClickOn(GetFirstCoralButton());
|
||||
BirchBarMenuModelAdapter* model_adapter =
|
||||
BirchBarController::Get()->chip_menu_model_adapter_for_testing();
|
||||
EXPECT_TRUE(model_adapter->IsShowingMenu());
|
||||
views::MenuItemView* save_as_group_item =
|
||||
model_adapter->root_for_testing()->GetSubmenu()->GetMenuItemAt(1);
|
||||
ASSERT_EQ(save_as_group_item->GetCommand(),
|
||||
base::to_underlying(
|
||||
BirchChipContextMenuModel::CommandId::kCoralSaveForLater));
|
||||
|
||||
// Left click on the menu item and test that the toast shows up since we
|
||||
// cannot create more coral saved groups.
|
||||
LeftClickOn(save_as_group_item);
|
||||
EXPECT_TRUE(Shell::Get()->toast_manager()->IsToastShown(
|
||||
"coral_max_saved_groups_toast"));
|
||||
}
|
||||
|
||||
} // namespace ash
|
||||
|
@@ -330,16 +330,30 @@ SavedDeskPresenter::~SavedDeskPresenter() = default;
|
||||
|
||||
size_t SavedDeskPresenter::GetEntryCount(DeskTemplateType type) const {
|
||||
auto* model = GetDeskModel();
|
||||
return type == DeskTemplateType::kTemplate
|
||||
? model->GetDeskTemplateEntryCount()
|
||||
: model->GetSaveAndRecallDeskEntryCount();
|
||||
switch (type) {
|
||||
case DeskTemplateType::kTemplate:
|
||||
return model->GetDeskTemplateEntryCount();
|
||||
case DeskTemplateType::kSaveAndRecall:
|
||||
return model->GetSaveAndRecallDeskEntryCount();
|
||||
case DeskTemplateType::kCoral:
|
||||
return model->GetCoralEntryCount();
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
size_t SavedDeskPresenter::GetMaxEntryCount(DeskTemplateType type) const {
|
||||
auto* model = GetDeskModel();
|
||||
return type == DeskTemplateType::kTemplate
|
||||
? model->GetMaxDeskTemplateEntryCount()
|
||||
: model->GetMaxSaveAndRecallDeskEntryCount();
|
||||
switch (type) {
|
||||
case DeskTemplateType::kTemplate:
|
||||
return model->GetMaxDeskTemplateEntryCount();
|
||||
case DeskTemplateType::kSaveAndRecall:
|
||||
return model->GetMaxSaveAndRecallDeskEntryCount();
|
||||
case DeskTemplateType::kCoral:
|
||||
return model->GetMaxCoralEntryCount();
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
ash::DeskTemplate* SavedDeskPresenter::FindOtherEntryWithName(
|
||||
|
@@ -6,12 +6,15 @@
|
||||
|
||||
#include "ash/birch/birch_coral_provider.h"
|
||||
#include "ash/birch/birch_item.h"
|
||||
#include "ash/constants/notifier_catalogs.h"
|
||||
#include "ash/public/cpp/coral_delegate.h"
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/icon_button.h"
|
||||
#include "ash/style/typography.h"
|
||||
#include "ash/system/toast/toast_manager_impl.h"
|
||||
#include "ash/wm/desks/templates/saved_desk_presenter.h"
|
||||
#include "ash/wm/overview/birch/birch_animation_utils.h"
|
||||
#include "ash/wm/overview/birch/birch_bar_constants.h"
|
||||
#include "ash/wm/overview/birch/birch_bar_controller.h"
|
||||
@@ -19,6 +22,8 @@
|
||||
#include "ash/wm/overview/birch/birch_chip_context_menu_model.h"
|
||||
#include "ash/wm/overview/birch/resources/grit/coral_resources.h"
|
||||
#include "ash/wm/overview/birch/tab_app_selection_host.h"
|
||||
#include "ash/wm/overview/overview_controller.h"
|
||||
#include "ash/wm/overview/overview_session.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/types/cxx23_to_underlying.h"
|
||||
@@ -89,6 +94,8 @@ constexpr ui::ColorId kSubtitleColorId = cros_tokens::kCrosSysOnSurfaceVariant;
|
||||
|
||||
constexpr gfx::Size kLoadingAnimationSize = gfx::Size(100, 20);
|
||||
|
||||
constexpr char kMaxSavedGroupsToastId[] = "coral_max_saved_groups_toast";
|
||||
|
||||
BirchSuggestionType GetSuggestionTypeFromItemType(BirchItemType item_type) {
|
||||
switch (item_type) {
|
||||
case BirchItemType::kWeather:
|
||||
@@ -452,6 +459,23 @@ void BirchChipButton::ExecuteCommand(int command_id, int event_flags) {
|
||||
break;
|
||||
case base::to_underlying(CommandId::kCoralSaveForLater): {
|
||||
CHECK_EQ(BirchItemType::kCoral, item_->GetType());
|
||||
|
||||
// Show a toast if we already have the max amount of allowed coral saved
|
||||
// groups.
|
||||
auto* saved_desk_presenter =
|
||||
OverviewController::Get()->overview_session()->saved_desk_presenter();
|
||||
if (saved_desk_presenter->GetEntryCount(DeskTemplateType::kCoral) >=
|
||||
saved_desk_presenter->GetMaxEntryCount(DeskTemplateType::kCoral)) {
|
||||
ToastData toast(kMaxSavedGroupsToastId,
|
||||
ToastCatalogName::kCoralSavedGroupLimitMax,
|
||||
l10n_util::GetStringUTF16(
|
||||
IDS_ASH_BIRCH_CORAL_SAVED_GROUPS_MAX_NUM_REACHED),
|
||||
ToastData::kDefaultToastDuration,
|
||||
/*visible_on_lock_screen=*/false);
|
||||
Shell::Get()->toast_manager()->Show(std::move(toast));
|
||||
return;
|
||||
}
|
||||
|
||||
auto* coral_provider = BirchCoralProvider::Get();
|
||||
Shell::Get()->coral_delegate()->CreateSavedDeskFromGroup(
|
||||
coral_provider->ExtractGroupById(
|
||||
|
@@ -81,7 +81,8 @@ BirchChipContextMenuModel::BirchChipContextMenuModel(
|
||||
// TODO(zxdan): Localize the strings.
|
||||
AddItemWithIcon(base::to_underlying(CommandId::kCoralNewDesk), u"Open",
|
||||
CreateIconForMenuItem(kCoralOpenIcon));
|
||||
if (features::IsCoralSavedDeskFeatureEnabled()) {
|
||||
if (features::IsCoralSavedDeskFeatureEnabled() &&
|
||||
!display::Screen::GetScreen()->InTabletMode()) {
|
||||
AddItemWithIcon(base::to_underlying(CommandId::kCoralSaveForLater),
|
||||
u"Save group for later",
|
||||
CreateIconForMenuItem(kSaveDeskForLaterIcon));
|
||||
|
@@ -166,6 +166,9 @@ class DeskModel {
|
||||
// Gets the number of desk templates currently saved.
|
||||
virtual size_t GetDeskTemplateEntryCount() const = 0;
|
||||
|
||||
// Gets the number of coral saved groups currently saved.
|
||||
virtual size_t GetCoralEntryCount() const = 0;
|
||||
|
||||
// Gets the maximum number of save and recall desks entry this storage backend
|
||||
// could hold.
|
||||
virtual size_t GetMaxSaveAndRecallDeskEntryCount() const = 0;
|
||||
@@ -174,6 +177,10 @@ class DeskModel {
|
||||
// could hold.
|
||||
virtual size_t GetMaxDeskTemplateEntryCount() const = 0;
|
||||
|
||||
// Gets the maximum number of coral saved groups this storage backend could
|
||||
// hold.
|
||||
virtual size_t GetMaxCoralEntryCount() const = 0;
|
||||
|
||||
// Returns a vector of desk template UUIDs.
|
||||
// This method assumes each implementation has a cache and can return the
|
||||
// UUIDs synchronously.
|
||||
|
@@ -127,6 +127,10 @@ size_t DeskModelWrapper::GetDeskTemplateEntryCount() const {
|
||||
policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t DeskModelWrapper::GetCoralEntryCount() const {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
size_t DeskModelWrapper::GetMaxSaveAndRecallDeskEntryCount() const {
|
||||
return save_and_recall_desks_model_->GetMaxSaveAndRecallDeskEntryCount();
|
||||
}
|
||||
@@ -136,6 +140,10 @@ size_t DeskModelWrapper::GetMaxDeskTemplateEntryCount() const {
|
||||
policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t DeskModelWrapper::GetMaxCoralEntryCount() const {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
std::set<base::Uuid> DeskModelWrapper::GetAllEntryUuids() const {
|
||||
std::set<base::Uuid> keys;
|
||||
|
||||
|
@@ -47,8 +47,10 @@ class DeskModelWrapper : public DeskModel {
|
||||
size_t GetEntryCount() const override;
|
||||
size_t GetSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetDeskTemplateEntryCount() const override;
|
||||
size_t GetCoralEntryCount() const override;
|
||||
size_t GetMaxSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetMaxDeskTemplateEntryCount() const override;
|
||||
size_t GetMaxCoralEntryCount() const override;
|
||||
std::set<base::Uuid> GetAllEntryUuids() const override;
|
||||
bool IsReady() const override;
|
||||
bool IsSyncing() const override;
|
||||
|
@@ -475,6 +475,10 @@ size_t DeskSyncBridge::GetDeskTemplateEntryCount() const {
|
||||
return template_count + policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t DeskSyncBridge::GetCoralEntryCount() const {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
// Chrome sync does not support save and recall desks yet. Return 0 for max
|
||||
// count.
|
||||
size_t DeskSyncBridge::GetMaxSaveAndRecallDeskEntryCount() const {
|
||||
@@ -485,6 +489,10 @@ size_t DeskSyncBridge::GetMaxDeskTemplateEntryCount() const {
|
||||
return kMaxTemplateCount + policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t DeskSyncBridge::GetMaxCoralEntryCount() const {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
std::set<base::Uuid> DeskSyncBridge::GetAllEntryUuids() const {
|
||||
std::set<base::Uuid> keys;
|
||||
|
||||
|
@@ -74,8 +74,10 @@ class DeskSyncBridge : public syncer::DataTypeSyncBridge, public DeskModel {
|
||||
size_t GetEntryCount() const override;
|
||||
size_t GetSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetDeskTemplateEntryCount() const override;
|
||||
size_t GetCoralEntryCount() const override;
|
||||
size_t GetMaxSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetMaxDeskTemplateEntryCount() const override;
|
||||
size_t GetMaxCoralEntryCount() const override;
|
||||
std::set<base::Uuid> GetAllEntryUuids() const override;
|
||||
bool IsReady() const override;
|
||||
// Whether this sync bridge is syncing local data to sync. This sync bridge
|
||||
|
@@ -160,6 +160,10 @@ size_t FakeDeskSyncBridge::GetDeskTemplateEntryCount() const {
|
||||
return template_count + policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t FakeDeskSyncBridge::GetCoralEntryCount() const {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
// Chrome sync does not support save and recall desks yet. Return 0 for max
|
||||
// count.
|
||||
size_t FakeDeskSyncBridge::GetMaxSaveAndRecallDeskEntryCount() const {
|
||||
@@ -170,6 +174,10 @@ size_t FakeDeskSyncBridge::GetMaxDeskTemplateEntryCount() const {
|
||||
return 6u + policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t FakeDeskSyncBridge::GetMaxCoralEntryCount() const {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
std::set<base::Uuid> FakeDeskSyncBridge::GetAllEntryUuids() const {
|
||||
std::set<base::Uuid> keys;
|
||||
|
||||
|
@@ -35,8 +35,10 @@ class FakeDeskSyncBridge : public DeskModel {
|
||||
size_t GetEntryCount() const override;
|
||||
size_t GetSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetDeskTemplateEntryCount() const override;
|
||||
size_t GetCoralEntryCount() const override;
|
||||
size_t GetMaxSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetMaxDeskTemplateEntryCount() const override;
|
||||
size_t GetMaxCoralEntryCount() const override;
|
||||
std::set<base::Uuid> GetAllEntryUuids() const override;
|
||||
bool IsReady() const override;
|
||||
// Whether this sync bridge is syncing local data to sync. This sync bridge
|
||||
|
@@ -56,7 +56,8 @@ constexpr size_t kMaxCoralDeskCount = 6u;
|
||||
|
||||
// Set of valid desk types.
|
||||
constexpr auto kValidDeskTypes = base::MakeFixedFlatSet<ash::DeskTemplateType>(
|
||||
{ash::DeskTemplateType::kTemplate, ash::DeskTemplateType::kSaveAndRecall});
|
||||
{ash::DeskTemplateType::kTemplate, ash::DeskTemplateType::kSaveAndRecall,
|
||||
ash::DeskTemplateType::kCoral});
|
||||
|
||||
// Reads a file at `fully_qualified_path` into a
|
||||
// `ash::DeskTemplate` or as `SavedDeskParseError` code. This function returns a
|
||||
@@ -398,7 +399,8 @@ void LocalDeskDataManager::DeleteAllEntries(DeleteEntryCallback callback) {
|
||||
// TODO(crbug.com/1320805): Remove this function once both desk models support
|
||||
// desk type counts.
|
||||
size_t LocalDeskDataManager::GetEntryCount() const {
|
||||
return GetSaveAndRecallDeskEntryCount() + GetDeskTemplateEntryCount();
|
||||
return GetSaveAndRecallDeskEntryCount() + GetDeskTemplateEntryCount() +
|
||||
GetCoralEntryCount();
|
||||
}
|
||||
|
||||
size_t LocalDeskDataManager::GetSaveAndRecallDeskEntryCount() const {
|
||||
@@ -410,6 +412,10 @@ size_t LocalDeskDataManager::GetDeskTemplateEntryCount() const {
|
||||
policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t LocalDeskDataManager::GetCoralEntryCount() const {
|
||||
return saved_desks_list_.at(ash::DeskTemplateType::kCoral).size();
|
||||
}
|
||||
|
||||
size_t LocalDeskDataManager::GetMaxSaveAndRecallDeskEntryCount() const {
|
||||
return kMaxSaveAndRecallDeskCount;
|
||||
}
|
||||
@@ -418,6 +424,10 @@ size_t LocalDeskDataManager::GetMaxDeskTemplateEntryCount() const {
|
||||
return kMaxDeskTemplateCount + policy_entries_.size();
|
||||
}
|
||||
|
||||
size_t LocalDeskDataManager::GetMaxCoralEntryCount() const {
|
||||
return kMaxCoralDeskCount;
|
||||
}
|
||||
|
||||
std::set<base::Uuid> LocalDeskDataManager::GetAllEntryUuids() const {
|
||||
std::set<base::Uuid> keys;
|
||||
for (const auto& type_and_saved_desks : saved_desks_list_) {
|
||||
|
@@ -105,8 +105,10 @@ class LocalDeskDataManager : public DeskModel, public AdminTemplateModel {
|
||||
size_t GetEntryCount() const override;
|
||||
size_t GetSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetDeskTemplateEntryCount() const override;
|
||||
size_t GetCoralEntryCount() const override;
|
||||
size_t GetMaxSaveAndRecallDeskEntryCount() const override;
|
||||
size_t GetMaxDeskTemplateEntryCount() const override;
|
||||
size_t GetMaxCoralEntryCount() const override;
|
||||
std::set<base::Uuid> GetAllEntryUuids() const override;
|
||||
bool IsReady() const override;
|
||||
bool IsSyncing() const override;
|
||||
|
@@ -2365,6 +2365,7 @@ chromeos/ash/components/peripheral_notification/peripheral_notification_manager.
|
||||
<int value="55" label="OnTask URL blocked"/>
|
||||
<int value="56" label="Copy Image To Clipboard Action"/>
|
||||
<int value="57" label="Capture Mode Text Copied"/>
|
||||
<int value="58" label="Coral Saved Groups Limit Max"/>
|
||||
</enum>
|
||||
|
||||
<enum name="TogglePickerAction">
|
||||
|
Reference in New Issue
Block a user