post-login: update weather chip UI
This cl updated the weather chip UI by moving the temperature degree from subtitle to add-on. In this case, the glanceables chip add-on can be not only the calendar join button but also weather temperature label. Therefore, we modify the BirchItem APIs to allow a more flexible type of add-on. The weather temperature label consists of a degree label and a unit (Fahrenheit v.s. Celsius) label which have different font types. We a BoxLayoutView to hold the two labels. The updated weather chip is manually tested and the screenshot is uploaded to the bug comment. Bug: b:342417531 Change-Id: I4383ca5c352828cb86eba9ff6e1f265968a296e3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5766894 Reviewed-by: James Cook <jamescook@chromium.org> Commit-Queue: Xiaodan Zhu <zxdan@chromium.org> Cr-Commit-Position: refs/heads/main@{#1338199}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
515cd28c2a
commit
2c21d866ee
@ -2916,6 +2916,8 @@ component("ash") {
|
||||
"wm/overview/birch/birch_bar_controller.h",
|
||||
"wm/overview/birch/birch_bar_menu_model_adapter.cc",
|
||||
"wm/overview/birch/birch_bar_menu_model_adapter.h",
|
||||
"wm/overview/birch/birch_bar_util.cc",
|
||||
"wm/overview/birch/birch_bar_util.h",
|
||||
"wm/overview/birch/birch_bar_view.cc",
|
||||
"wm/overview/birch/birch_bar_view.h",
|
||||
"wm/overview/birch/birch_chip_button.cc",
|
||||
|
@ -8546,6 +8546,15 @@ To shut down the device, press and hold the power button on the device again.
|
||||
<message name="IDS_ASH_BIRCH_LOST_MEDIA_VIDEO_CONFERENCE_TAB_SUBTITLE" desc="The subtitle for a suggestion chip for a video conference tab that is currently ongoing. Note: The 'Ongoing' is supposed to indicate the status of the tab, not the identity of the tab. 'Switch to tab' is an action/verb that switches to the tab if the item is pressed.">
|
||||
Ongoing · Switch to tab
|
||||
</message>
|
||||
<message name="IDS_ASH_BIRCH_WEATHER_SUBTITLE" desc="The subtitle for a weather suggestion chip">
|
||||
Current weather
|
||||
</message>
|
||||
<message name="IDS_ASH_BIRCH_WEATHER_FAHREHEIT_SYMBOL" desc="The symbol of Fahrenheit degree.">
|
||||
°F
|
||||
</message>
|
||||
<message name="IDS_ASH_BIRCH_WEATHER_CELSIUS_SYMBOL" desc="The symbol of Celsius degree.">
|
||||
°C
|
||||
</message>
|
||||
<message name="IDS_ASH_BIRCH_MENU_SHOW_SUGGESTIONS" desc="Context menu item that toggles the list of suggestion actions in informed restore/overview UI">
|
||||
Show suggestions
|
||||
</message>
|
||||
|
@ -0,0 +1 @@
|
||||
014426a9a4d6ebf5c3246908917fd29caa5e068d
|
@ -0,0 +1 @@
|
||||
f37eca08ae7cb057fbdbc90e99ff13006d48a180
|
@ -0,0 +1 @@
|
||||
ca134262c685260c530692c9e350c35fb27b94b0
|
@ -219,6 +219,21 @@ void BirchItem::RegisterProfilePrefs(PrefRegistrySimple* registry) {
|
||||
registry->RegisterBooleanPref(prefs::kBirchUseCelsius, false);
|
||||
}
|
||||
|
||||
std::u16string BirchItem::GetAccessibleName() const {
|
||||
return title_ + u" " + subtitle_;
|
||||
}
|
||||
|
||||
void BirchItem::PerformAddonAction() {}
|
||||
|
||||
BirchAddonType BirchItem::GetAddonType() const {
|
||||
return BirchAddonType::kNone;
|
||||
}
|
||||
|
||||
std::u16string BirchItem::GetAddonAccessibleName() const {
|
||||
CHECK(addon_label_.has_value());
|
||||
return *addon_label_;
|
||||
}
|
||||
|
||||
void BirchItem::RecordActionMetrics() {
|
||||
// Record that the whole bar was activated.
|
||||
base::UmaHistogramBoolean("Ash.Birch.Bar.Activate", true);
|
||||
@ -257,7 +272,7 @@ BirchCalendarItem::BirchCalendarItem(const std::u16string& title,
|
||||
event_id_(event_id),
|
||||
response_status_(response_status) {
|
||||
if (ShouldShowJoinButton()) {
|
||||
set_secondary_action(
|
||||
set_addon_label(
|
||||
l10n_util::GetStringUTF16(IDS_ASH_BIRCH_CALENDAR_JOIN_BUTTON));
|
||||
}
|
||||
}
|
||||
@ -298,7 +313,7 @@ void BirchCalendarItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kNewForegroundTab);
|
||||
}
|
||||
|
||||
void BirchCalendarItem::PerformSecondaryAction() {
|
||||
void BirchCalendarItem::PerformAddonAction() {
|
||||
if (!conference_url_.is_valid()) {
|
||||
LOG(ERROR) << "No conference URL for calendar item";
|
||||
return;
|
||||
@ -316,6 +331,15 @@ void BirchCalendarItem::LoadIcon(LoadIconCallback callback) const {
|
||||
SecondaryIconType::kNoIcon);
|
||||
}
|
||||
|
||||
BirchAddonType BirchCalendarItem::GetAddonType() const {
|
||||
return addon_label().has_value() ? BirchAddonType::kButton
|
||||
: BirchAddonType::kNone;
|
||||
}
|
||||
|
||||
std::u16string BirchCalendarItem::GetAddonAccessibleName() const {
|
||||
return l10n_util::GetStringUTF16(IDS_ASH_BIRCH_CALENDAR_JOIN_BUTTON_TOOLTIP);
|
||||
}
|
||||
|
||||
// static
|
||||
std::u16string BirchCalendarItem::GetSubtitle(base::Time start_time,
|
||||
base::Time end_time,
|
||||
@ -421,10 +445,6 @@ void BirchAttachmentItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kNewForegroundTab);
|
||||
}
|
||||
|
||||
void BirchAttachmentItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchAttachmentItem::LoadIcon(LoadIconCallback callback) const {
|
||||
DownloadImageFromUrl(icon_url_,
|
||||
ui::ImageModel::FromImageSkia(chromeos::GetIconFromType(
|
||||
@ -489,10 +509,6 @@ void BirchFileItem::PerformAction() {
|
||||
NewWindowDelegate::GetPrimary()->OpenFile(file_path_);
|
||||
}
|
||||
|
||||
void BirchFileItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchFileItem::LoadIcon(LoadIconCallback callback) const {
|
||||
DownloadImageFromUrl(
|
||||
GURL(icon_url_),
|
||||
@ -518,10 +534,13 @@ BirchWeatherItem::BirchWeatherItem(const std::u16string& weather_description,
|
||||
float temp_f,
|
||||
const GURL& icon_url,
|
||||
const ui::ImageModel& backup_icon)
|
||||
: BirchItem(weather_description, GetSubtitle(temp_f)),
|
||||
: BirchItem(weather_description,
|
||||
l10n_util::GetStringUTF16(IDS_ASH_BIRCH_WEATHER_SUBTITLE)),
|
||||
temp_f_(temp_f),
|
||||
icon_url_(icon_url),
|
||||
backup_icon_(backup_icon) {}
|
||||
backup_icon_(backup_icon) {
|
||||
set_addon_label(base::NumberToString16(GetTemperature(temp_f)));
|
||||
}
|
||||
|
||||
BirchWeatherItem::BirchWeatherItem(BirchWeatherItem&&) = default;
|
||||
|
||||
@ -555,17 +574,39 @@ void BirchWeatherItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kNewForegroundTab);
|
||||
}
|
||||
|
||||
void BirchWeatherItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchWeatherItem::LoadIcon(LoadIconCallback callback) const {
|
||||
DownloadImageFromUrl(icon_url_, backup_icon_, SecondaryIconType::kNoIcon,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
std::u16string BirchWeatherItem::GetAccessibleName() const {
|
||||
const int temp = GetTemperature(temp_f_);
|
||||
std::u16string temp_str =
|
||||
UseCelsius()
|
||||
? l10n_util::GetStringFUTF16Int(
|
||||
IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS, temp)
|
||||
: l10n_util::GetStringFUTF16Int(
|
||||
IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT, temp);
|
||||
return subtitle() + u" " + title() + u" " + temp_str;
|
||||
}
|
||||
|
||||
void BirchWeatherItem::PerformAddonAction() {
|
||||
// Perform same action as the item.
|
||||
PerformAction();
|
||||
}
|
||||
|
||||
BirchAddonType BirchWeatherItem::GetAddonType() const {
|
||||
return UseCelsius() ? BirchAddonType::kWeatherTempLabelC
|
||||
: BirchAddonType::kWeatherTempLabelF;
|
||||
}
|
||||
|
||||
// static
|
||||
std::u16string BirchWeatherItem::GetSubtitle(float temp_f) {
|
||||
int BirchWeatherItem::GetTemperature(float temp_f) {
|
||||
return static_cast<int>(UseCelsius() ? (temp_f - 32) * 5 / 9 : temp_f);
|
||||
}
|
||||
|
||||
// static
|
||||
bool BirchWeatherItem::UseCelsius() {
|
||||
// Tests may not have a pref service.
|
||||
bool use_celsius = false;
|
||||
PrefService* pref_service = GetPrefService();
|
||||
@ -574,13 +615,7 @@ std::u16string BirchWeatherItem::GetSubtitle(float temp_f) {
|
||||
} else {
|
||||
CHECK_IS_TEST();
|
||||
}
|
||||
return use_celsius
|
||||
? l10n_util::GetStringFUTF16Int(
|
||||
IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS,
|
||||
static_cast<int>((temp_f - 32) * 5 / 9))
|
||||
: l10n_util::GetStringFUTF16Int(
|
||||
IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT,
|
||||
static_cast<int>(temp_f));
|
||||
return use_celsius;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -651,10 +686,6 @@ void BirchTabItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kSwitchToTab);
|
||||
}
|
||||
|
||||
void BirchTabItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchTabItem::LoadIcon(LoadIconCallback callback) const {
|
||||
GetFaviconImage(favicon_url_, /*is_page_url=*/false, backup_icon_,
|
||||
secondary_icon_type_, std::move(callback));
|
||||
@ -726,10 +757,6 @@ void BirchLastActiveItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kSwitchToTab);
|
||||
}
|
||||
|
||||
void BirchLastActiveItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchLastActiveItem::LoadIcon(LoadIconCallback callback) const {
|
||||
std::move(callback).Run(icon_, SecondaryIconType::kNoIcon);
|
||||
}
|
||||
@ -802,10 +829,6 @@ void BirchMostVisitedItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kSwitchToTab);
|
||||
}
|
||||
|
||||
void BirchMostVisitedItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchMostVisitedItem::LoadIcon(LoadIconCallback callback) const {
|
||||
std::move(callback).Run(icon_, SecondaryIconType::kNoIcon);
|
||||
}
|
||||
@ -876,10 +899,6 @@ void BirchSelfShareItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kSwitchToTab);
|
||||
}
|
||||
|
||||
void BirchSelfShareItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchSelfShareItem::LoadIcon(LoadIconCallback callback) const {
|
||||
GetFaviconImage(url_, /*is_page_url=*/true, backup_icon_,
|
||||
secondary_icon_type_, std::move(callback));
|
||||
@ -958,10 +977,6 @@ void BirchLostMediaItem::PerformAction() {
|
||||
}
|
||||
}
|
||||
|
||||
void BirchLostMediaItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchLostMediaItem::LoadIcon(LoadIconCallback callback) const {
|
||||
GetFaviconImage(source_url_, /*is_page_url=*/true, backup_icon_,
|
||||
secondary_icon_type_, std::move(callback));
|
||||
@ -1004,9 +1019,7 @@ std::string BirchCoralItem::ToString() const {
|
||||
void BirchCoralItem::PerformAction() {
|
||||
// TODO(yulunwu) add actions
|
||||
}
|
||||
void BirchCoralItem::PerformSecondaryAction() {
|
||||
// TODO(yulunwu) add actions
|
||||
}
|
||||
|
||||
void BirchCoralItem::LoadIcon(LoadIconCallback callback) const {
|
||||
// TODO(yulunwu) load icons
|
||||
}
|
||||
@ -1048,10 +1061,6 @@ void BirchReleaseNotesItem::PerformAction() {
|
||||
NewWindowDelegate::Disposition::kNewForegroundTab);
|
||||
}
|
||||
|
||||
void BirchReleaseNotesItem::PerformSecondaryAction() {
|
||||
NOTREACHED_IN_MIGRATION();
|
||||
}
|
||||
|
||||
void BirchReleaseNotesItem::LoadIcon(LoadIconCallback callback) const {
|
||||
std::move(callback).Run(
|
||||
ui::ResourceBundle::GetSharedInstance().GetThemedLottieImageNamed(
|
||||
|
@ -53,6 +53,15 @@ enum class SecondaryIconType {
|
||||
kMaxValue = kNoIcon,
|
||||
};
|
||||
|
||||
// These values are used to determine the types of chip add-ons which is an
|
||||
// additional UI component like the join button of calendar item.
|
||||
enum class BirchAddonType {
|
||||
kNone, // No add-ons.
|
||||
kButton, // A button with an action, e,g. the calendar join button.
|
||||
kWeatherTempLabelF, // A label for weather temperature in Fahrenheit.
|
||||
kWeatherTempLabelC, // A label for weather temperature in Celsius.
|
||||
};
|
||||
|
||||
// The base item which is stored by the birch model.
|
||||
class ASH_EXPORT BirchItem {
|
||||
public:
|
||||
@ -74,12 +83,6 @@ class ASH_EXPORT BirchItem {
|
||||
// Perform the action associated with this item (e.g. open a document).
|
||||
virtual void PerformAction() = 0;
|
||||
|
||||
// Performs the secondary action associated with this item, if the action has
|
||||
// a secondary action. When the secondary action is available,
|
||||
// `secondary_action()` will be set to the user-friendly secondary action
|
||||
// name.
|
||||
virtual void PerformSecondaryAction() = 0;
|
||||
|
||||
// Loads the icon for this image. This may invoke the callback immediately
|
||||
// (e.g. with a local icon) or there may be a delay for a network fetch.
|
||||
// The `SecondaryIconType` passed to `BirchChipButton` allows the view to set
|
||||
@ -92,21 +95,28 @@ class ASH_EXPORT BirchItem {
|
||||
// taps on it).
|
||||
void RecordActionMetrics();
|
||||
|
||||
virtual std::u16string GetAccessibleName() const;
|
||||
|
||||
// Performs the action associated with the add-on of this item (e.g. joining a
|
||||
// meeting for Calendar). When the add-on action is available, `addon_label()`
|
||||
// will be set to the user-friendly action name.
|
||||
virtual void PerformAddonAction();
|
||||
virtual BirchAddonType GetAddonType() const;
|
||||
virtual std::u16string GetAddonAccessibleName() const;
|
||||
|
||||
const std::u16string& title() const { return title_; }
|
||||
const std::u16string& subtitle() const { return subtitle_; }
|
||||
|
||||
void set_ranking(float ranking) { ranking_ = ranking; }
|
||||
float ranking() const { return ranking_; }
|
||||
|
||||
const std::optional<std::u16string> secondary_action() const {
|
||||
return secondary_action_;
|
||||
}
|
||||
std::optional<std::u16string> addon_label() const { return addon_label_; }
|
||||
|
||||
static void set_action_count_for_test(int value) { action_count_ = value; }
|
||||
|
||||
protected:
|
||||
void set_secondary_action(const std::u16string& action_name) {
|
||||
secondary_action_ = action_name;
|
||||
void set_addon_label(const std::u16string& addon_label) {
|
||||
addon_label_ = addon_label;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -116,9 +126,9 @@ class ASH_EXPORT BirchItem {
|
||||
// The subtitle to be displayed in birch chip UI.
|
||||
std::u16string subtitle_;
|
||||
|
||||
// If the item has a secondary action (e.g. Joining a meeting for Calendar),
|
||||
// the name of the action to display in the UI.
|
||||
std::optional<std::u16string> secondary_action_;
|
||||
// The label for add-on component of the chip, e.g. "Join" on calendar join
|
||||
// button.
|
||||
std::optional<std::u16string> addon_label_;
|
||||
|
||||
float ranking_; // Lower is better.
|
||||
|
||||
@ -154,8 +164,10 @@ class ASH_EXPORT BirchCalendarItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void PerformAddonAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
BirchAddonType GetAddonType() const override;
|
||||
std::u16string GetAddonAccessibleName() const override;
|
||||
|
||||
const base::Time& start_time() const { return start_time_; }
|
||||
const base::Time& end_time() const { return end_time_; }
|
||||
@ -211,7 +223,6 @@ class ASH_EXPORT BirchAttachmentItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const GURL& file_url() const { return file_url_; }
|
||||
@ -249,7 +260,6 @@ class ASH_EXPORT BirchFileItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const base::Time& timestamp() const { return timestamp_; }
|
||||
@ -293,7 +303,6 @@ class ASH_EXPORT BirchTabItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const GURL& url() const { return url_; }
|
||||
@ -334,7 +343,6 @@ class ASH_EXPORT BirchLastActiveItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const GURL& url() const { return url_; }
|
||||
@ -362,7 +370,6 @@ class ASH_EXPORT BirchMostVisitedItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const GURL& url() const { return url_; }
|
||||
@ -395,7 +402,6 @@ class ASH_EXPORT BirchSelfShareItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const std::u16string& guid() const { return guid_; }
|
||||
@ -439,7 +445,6 @@ class ASH_EXPORT BirchLostMediaItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const GURL& source_url() const { return source_url_; }
|
||||
@ -474,13 +479,16 @@ class ASH_EXPORT BirchWeatherItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
std::u16string GetAccessibleName() const override;
|
||||
void PerformAddonAction() override;
|
||||
BirchAddonType GetAddonType() const override;
|
||||
|
||||
float temp_f() const { return temp_f_; }
|
||||
|
||||
private:
|
||||
static std::u16string GetSubtitle(float temp_f);
|
||||
static int GetTemperature(float temp_f);
|
||||
static bool UseCelsius();
|
||||
|
||||
float temp_f_;
|
||||
GURL icon_url_;
|
||||
@ -501,7 +509,6 @@ class ASH_EXPORT BirchCoralItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
private:
|
||||
@ -524,7 +531,6 @@ class ASH_EXPORT BirchReleaseNotesItem : public BirchItem {
|
||||
BirchItemType GetType() const override;
|
||||
std::string ToString() const override;
|
||||
void PerformAction() override;
|
||||
void PerformSecondaryAction() override;
|
||||
void LoadIcon(LoadIconCallback callback) const override;
|
||||
|
||||
const base::Time& first_seen() const { return first_seen_; }
|
||||
|
@ -184,8 +184,8 @@ TEST_F(BirchItemTest, Calendar_PerformAction_BothConferenceAndCalendar) {
|
||||
EXPECT_EQ(new_window_delegate_->last_opened_url_,
|
||||
GURL("http://calendar.com/"));
|
||||
|
||||
EXPECT_TRUE(item.secondary_action());
|
||||
item.PerformSecondaryAction();
|
||||
EXPECT_TRUE(item.addon_label());
|
||||
item.PerformAddonAction();
|
||||
EXPECT_EQ(new_window_delegate_->last_opened_url_, GURL("http://meet.com/"));
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ TEST_F(BirchItemTest, Calendar_PerformAction_Histograms) {
|
||||
histograms.ExpectBucketCount("Ash.Birch.Chip.Activate",
|
||||
BirchItemType::kCalendar, 1);
|
||||
|
||||
item.PerformSecondaryAction();
|
||||
item.PerformAddonAction();
|
||||
histograms.ExpectBucketCount("Ash.Birch.Bar.Activate", true, 2);
|
||||
histograms.ExpectBucketCount("Ash.Birch.Chip.Activate",
|
||||
BirchItemType::kCalendar, 2);
|
||||
@ -220,8 +220,8 @@ TEST_F(BirchItemTest, Calendar_PerformAction_CalendarOnly) {
|
||||
EXPECT_EQ(new_window_delegate_->last_opened_url_,
|
||||
GURL("http://calendar.com/"));
|
||||
|
||||
EXPECT_FALSE(item.secondary_action());
|
||||
item.PerformSecondaryAction();
|
||||
EXPECT_FALSE(item.addon_label());
|
||||
item.PerformAddonAction();
|
||||
EXPECT_EQ(new_window_delegate_->last_opened_url_,
|
||||
GURL("http://calendar.com/"));
|
||||
}
|
||||
@ -238,7 +238,7 @@ TEST_F(BirchItemTest, Calendar_PerformAction_NoURL) {
|
||||
EXPECT_EQ(new_window_delegate_->last_opened_url_, GURL());
|
||||
}
|
||||
|
||||
TEST_F(BirchItemTest, Calendar_ShouldShowSecondaryAction) {
|
||||
TEST_F(BirchItemTest, Calendar_ShouldShowAddonAction) {
|
||||
base::Time now = base::Time::Now();
|
||||
|
||||
// Create an event with a conference URL, but in the future.
|
||||
@ -250,7 +250,7 @@ TEST_F(BirchItemTest, Calendar_ShouldShowSecondaryAction) {
|
||||
/*all_day_event=*/false);
|
||||
|
||||
// The meeting is in the future, so don't show the "Join" button.
|
||||
EXPECT_FALSE(item0.secondary_action().has_value());
|
||||
EXPECT_FALSE(item0.addon_label().has_value());
|
||||
|
||||
// Create a meeting happening right now.
|
||||
BirchCalendarItem item1(u"item1",
|
||||
@ -262,7 +262,7 @@ TEST_F(BirchItemTest, Calendar_ShouldShowSecondaryAction) {
|
||||
/*all_day_event=*/false);
|
||||
|
||||
// The meeting is happening now, so show the "Join" button.
|
||||
EXPECT_TRUE(item1.secondary_action().has_value());
|
||||
EXPECT_TRUE(item1.addon_label().has_value());
|
||||
|
||||
// Create a meeting starting in the next few minutes.
|
||||
BirchCalendarItem item2(u"item2", /*start_time=*/now + base::Minutes(3),
|
||||
@ -273,7 +273,7 @@ TEST_F(BirchItemTest, Calendar_ShouldShowSecondaryAction) {
|
||||
/*all_day_event=*/false);
|
||||
|
||||
// The meeting is very soon, so show the "Join" button.
|
||||
EXPECT_TRUE(item2.secondary_action().has_value());
|
||||
EXPECT_TRUE(item2.addon_label().has_value());
|
||||
}
|
||||
|
||||
TEST_F(BirchItemTest, Calendar_Subtitle_Ongoing) {
|
||||
@ -448,18 +448,18 @@ TEST_F(BirchItemTest, Weather_PerformAction_Histograms) {
|
||||
// Weather item subtitles require an ash::Shell for the pref service.
|
||||
using BirchWeatherItemTest = AshTestBase;
|
||||
|
||||
TEST_F(BirchWeatherItemTest, SubtitleInFahrenheit) {
|
||||
TEST_F(BirchWeatherItemTest, AddonLabelInFahrenheit) {
|
||||
GetPrefService()->SetBoolean(prefs::kBirchUseCelsius, false);
|
||||
BirchWeatherItem item(u"item", 72.f, GURL("http://icon.com/"),
|
||||
ui::ImageModel());
|
||||
EXPECT_EQ(item.subtitle(), u"72\xB0 F");
|
||||
EXPECT_EQ(item.addon_label(), u"72");
|
||||
}
|
||||
|
||||
TEST_F(BirchWeatherItemTest, SubtitleInCelsius) {
|
||||
TEST_F(BirchWeatherItemTest, AddonLabelInCelsius) {
|
||||
GetPrefService()->SetBoolean(prefs::kBirchUseCelsius, true);
|
||||
BirchWeatherItem item(u"item", 72.f, GURL("http://icon.com/"),
|
||||
ui::ImageModel());
|
||||
EXPECT_EQ(item.subtitle(), u"22\xB0 C");
|
||||
EXPECT_EQ(item.addon_label(), u"22");
|
||||
}
|
||||
|
||||
TEST_F(BirchItemTest, Tab_Subtitle_Recent) {
|
||||
|
@ -77,12 +77,12 @@ class TestBirchItem : public BirchItem {
|
||||
public:
|
||||
TestBirchItem(const std::u16string& title,
|
||||
const std::u16string& subtitle,
|
||||
const std::optional<std::u16string>& secondary_action,
|
||||
const std::optional<std::u16string>& addon_label,
|
||||
float ranking = 1.0f)
|
||||
: BirchItem(title, subtitle) {
|
||||
set_ranking(ranking);
|
||||
if (secondary_action) {
|
||||
set_secondary_action(*secondary_action);
|
||||
if (addon_label) {
|
||||
set_addon_label(*addon_label);
|
||||
}
|
||||
}
|
||||
TestBirchItem(const BirchItem&) = delete;
|
||||
@ -95,7 +95,6 @@ class TestBirchItem : public BirchItem {
|
||||
return std::string("Test item ") + base::UTF16ToUTF8(title());
|
||||
}
|
||||
void PerformAction() override {}
|
||||
void PerformSecondaryAction() override {}
|
||||
void LoadIcon(LoadIconCallback callback) const override {
|
||||
std::move(callback).Run(
|
||||
ui::ImageModel::FromVectorIcon(kSettingsIcon, SK_ColorBLACK, 20),
|
||||
@ -1595,12 +1594,12 @@ TEST_P(BirchBarLayoutTest, ResponsiveLayout) {
|
||||
// Add test chips to the bar in landscape mode.
|
||||
std::vector<std::unique_ptr<BirchItem>> items_;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
std::optional<std::u16string> secondary_action;
|
||||
std::optional<std::u16string> addon_label;
|
||||
if (i % 2) {
|
||||
secondary_action = u"add-on";
|
||||
addon_label = u"add-on";
|
||||
}
|
||||
auto item = std::make_unique<TestBirchItem>(u"title", u"subtitle",
|
||||
secondary_action);
|
||||
auto item =
|
||||
std::make_unique<TestBirchItem>(u"title", u"subtitle", addon_label);
|
||||
birch_bar_view->AddChip(item.get());
|
||||
items_.emplace_back(std::move(item));
|
||||
EXPECT_EQ(birch_bar_widget->GetWindowBoundsInScreen(),
|
||||
|
66
ash/wm/overview/birch/birch_bar_util.cc
Normal file
66
ash/wm/overview/birch/birch_bar_util.cc
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/wm/overview/birch/birch_bar_util.h"
|
||||
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/pill_button.h"
|
||||
#include "ash/style/typography.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
#include "ui/views/layout/box_layout_view.h"
|
||||
#include "ui/views/view_class_properties.h"
|
||||
|
||||
namespace ash::birch_bar_util {
|
||||
|
||||
namespace {
|
||||
|
||||
// The layout parameters of add-ons.
|
||||
constexpr gfx::Insets kAddonMargins = gfx::Insets::VH(0, 16);
|
||||
constexpr int kWeatherTempLabelSpacing = 2;
|
||||
|
||||
// The font of add-on label.
|
||||
constexpr TypographyToken kWeatherTempLabelFont =
|
||||
TypographyToken::kCrosDisplay3Regular;
|
||||
constexpr TypographyToken kWeatherUnitLabelFont = TypographyToken::kCrosTitle1;
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<views::Button> CreateAddonButton(
|
||||
views::Button::PressedCallback callback,
|
||||
const std::u16string& label) {
|
||||
auto button = std::make_unique<PillButton>(
|
||||
std::move(callback), label, PillButton::Type::kSecondaryWithoutIcon);
|
||||
button->SetProperty(views::kMarginsKey, kAddonMargins);
|
||||
return button;
|
||||
}
|
||||
|
||||
std::unique_ptr<views::View> CreateWeatherTemperatureView(
|
||||
const std::u16string& temp_str,
|
||||
bool fahrenheit) {
|
||||
views::Label* temp = nullptr;
|
||||
views::Label* unit = nullptr;
|
||||
|
||||
auto weather_view =
|
||||
views::Builder<views::BoxLayoutView>()
|
||||
.SetBetweenChildSpacing(kWeatherTempLabelSpacing)
|
||||
.SetCrossAxisAlignment(views::BoxLayout::CrossAxisAlignment::kStart)
|
||||
.SetProperty(views::kMarginsKey, kAddonMargins)
|
||||
.SetFocusBehavior(views::View::FocusBehavior::NEVER)
|
||||
.AddChildren(
|
||||
views::Builder<views::Label>().CopyAddressTo(&temp).SetText(
|
||||
temp_str),
|
||||
views::Builder<views::Label>().CopyAddressTo(&unit).SetText(
|
||||
l10n_util::GetStringUTF16(
|
||||
fahrenheit ? IDS_ASH_BIRCH_WEATHER_FAHREHEIT_SYMBOL
|
||||
: IDS_ASH_BIRCH_WEATHER_CELSIUS_SYMBOL)))
|
||||
.Build();
|
||||
|
||||
auto* typography_provider = TypographyProvider::Get();
|
||||
typography_provider->StyleLabel(kWeatherTempLabelFont, *temp);
|
||||
typography_provider->StyleLabel(kWeatherUnitLabelFont, *unit);
|
||||
|
||||
return weather_view;
|
||||
}
|
||||
|
||||
} // namespace ash::birch_bar_util
|
29
ash/wm/overview/birch/birch_bar_util.h
Normal file
29
ash/wm/overview/birch/birch_bar_util.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_UTIL_H_
|
||||
#define ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ui/views/controls/button/button.h"
|
||||
|
||||
namespace ash::birch_bar_util {
|
||||
|
||||
// Creates a button for the glanceables chip with given `callback` and `label`,
|
||||
// e.g. the join button of calendar chip.
|
||||
std::unique_ptr<views::Button> CreateAddonButton(
|
||||
views::Button::PressedCallback callback,
|
||||
const std::u16string& label);
|
||||
|
||||
// Creates a weather temperature view which consists of two labels, one is for
|
||||
// the temperature degree and the other is for the degree unit (Fahrenheit v.s.
|
||||
// Celsius).
|
||||
std::unique_ptr<views::View> CreateWeatherTemperatureView(
|
||||
const std::u16string& temp_str,
|
||||
bool fahrenheit);
|
||||
|
||||
} // namespace ash::birch_bar_util
|
||||
|
||||
#endif // ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_UTIL_H_
|
@ -9,10 +9,10 @@
|
||||
#include "ash/shell.h"
|
||||
#include "ash/shell_delegate.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/pill_button.h"
|
||||
#include "ash/style/typography.h"
|
||||
#include "ash/wm/overview/birch/birch_bar_constants.h"
|
||||
#include "ash/wm/overview/birch/birch_bar_controller.h"
|
||||
#include "ash/wm/overview/birch/birch_bar_util.h"
|
||||
#include "ash/wm/overview/birch/birch_chip_context_menu_model.h"
|
||||
#include "base/types/cxx23_to_underlying.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
@ -200,19 +200,32 @@ void BirchChipButton::Init(BirchItem* item) {
|
||||
|
||||
SetCallback(
|
||||
base::BindRepeating(&BirchItem::PerformAction, base::Unretained(item_)));
|
||||
if (item_->secondary_action().has_value()) {
|
||||
auto* button = SetAddon(std::make_unique<PillButton>(
|
||||
base::BindRepeating(&BirchItem::PerformSecondaryAction,
|
||||
base::Unretained(item_)),
|
||||
*item_->secondary_action(), PillButton::Type::kSecondaryWithoutIcon));
|
||||
button->SetProperty(views::kMarginsKey, gfx::Insets::VH(0, 16));
|
||||
button->SetTooltipText(
|
||||
l10n_util::GetStringUTF16(IDS_ASH_BIRCH_CALENDAR_JOIN_BUTTON_TOOLTIP));
|
||||
|
||||
const auto addon_type = item_->GetAddonType();
|
||||
// Add add-ons according to the add-on type.
|
||||
switch (addon_type) {
|
||||
case BirchAddonType::kButton: {
|
||||
auto button = birch_bar_util::CreateAddonButton(
|
||||
base::BindRepeating(&BirchItem::PerformAddonAction,
|
||||
base::Unretained(item_)),
|
||||
*item_->addon_label());
|
||||
button->SetTooltipText(item->GetAddonAccessibleName());
|
||||
SetAddon(std::move(button));
|
||||
break;
|
||||
}
|
||||
case BirchAddonType::kWeatherTempLabelC:
|
||||
case BirchAddonType::kWeatherTempLabelF:
|
||||
SetAddon(birch_bar_util::CreateWeatherTemperatureView(
|
||||
*item_->addon_label(),
|
||||
addon_type == BirchAddonType::kWeatherTempLabelF));
|
||||
break;
|
||||
case BirchAddonType::kNone:
|
||||
break;
|
||||
}
|
||||
item_->LoadIcon(base::BindOnce(&BirchChipButton::SetIconImage,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
|
||||
SetAccessibleName(item_->title() + u" " + item_->subtitle());
|
||||
SetAccessibleName(item_->GetAccessibleName());
|
||||
}
|
||||
|
||||
const BirchItem* BirchChipButton::GetItem() const {
|
||||
@ -383,8 +396,7 @@ void BirchChipButton::ExecuteCommand(int command_id, int event_flags) {
|
||||
}
|
||||
}
|
||||
|
||||
void BirchChipButton::SetAddonInternal(
|
||||
std::unique_ptr<views::View> addon_view) {
|
||||
void BirchChipButton::SetAddon(std::unique_ptr<views::View> addon_view) {
|
||||
if (addon_view_) {
|
||||
RemoveChildViewT(addon_view_);
|
||||
} else {
|
||||
|
@ -38,13 +38,6 @@ class BirchChipButton : public BirchChipButtonBase,
|
||||
// Chip configuration methods.
|
||||
void Init(BirchItem* item);
|
||||
|
||||
template <typename T>
|
||||
T* SetAddon(std::unique_ptr<T> addon_view) {
|
||||
T* ptr = addon_view.get();
|
||||
SetAddonInternal(std::move(addon_view));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// BirchChipButtonBase:
|
||||
const BirchItem* GetItem() const override;
|
||||
BirchItem* GetItem() override;
|
||||
@ -56,10 +49,7 @@ class BirchChipButton : public BirchChipButtonBase,
|
||||
private:
|
||||
class ChipMenuController;
|
||||
|
||||
void SetAddonInternal(std::unique_ptr<views::View> addon_view);
|
||||
|
||||
// The callback when the removal button or removal panel is pressed.
|
||||
void OnRemoveComponentPressed();
|
||||
void SetAddon(std::unique_ptr<views::View> addon_view);
|
||||
|
||||
void StylizeIconForItemType(BirchItemType type,
|
||||
SecondaryIconType secondary_icon_type);
|
||||
@ -88,7 +78,6 @@ class BirchChipButton : public BirchChipButtonBase,
|
||||
|
||||
BEGIN_VIEW_BUILDER(/*no export*/, BirchChipButton, BirchChipButtonBase)
|
||||
VIEW_BUILDER_METHOD(Init, BirchItem*)
|
||||
VIEW_BUILDER_VIEW_TYPE_PROPERTY(views::View, Addon)
|
||||
END_VIEW_BUILDER
|
||||
|
||||
} // namespace ash
|
||||
|
Reference in New Issue
Block a user