Commit 96c22a25 authored by Andre Le's avatar Andre Le Committed by Commit Bot

[CrOS PhoneHub] Hook up quick actions UI to controllers.

- Create a base class for quick actions controller.
- Create silence phone controller that connect to the DND controller in PhoneHubManager. Display the icons according to the states.
- Hook up the quick actions UI in the bubble to silence phone controller. Enable hotspot and locate phone implementation will be added in the next CL.

BUG=1106937,1126208

Change-Id: I3eb511e1843cd4cb6b80316a706a2dcbc61a8e49
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2419552
Commit-Queue: Andre Le <leandre@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarTim Song <tengs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811478}
parent 25c91606
...@@ -1135,8 +1135,13 @@ component("ash") { ...@@ -1135,8 +1135,13 @@ component("ash") {
"system/phonehub/phone_hub_view_ids.h", "system/phonehub/phone_hub_view_ids.h",
"system/phonehub/phone_status_view.cc", "system/phonehub/phone_status_view.cc",
"system/phonehub/phone_status_view.h", "system/phonehub/phone_status_view.h",
"system/phonehub/quick_action_controller_base.h",
"system/phonehub/quick_action_item.cc",
"system/phonehub/quick_action_item.h",
"system/phonehub/quick_actions_view.cc", "system/phonehub/quick_actions_view.cc",
"system/phonehub/quick_actions_view.h", "system/phonehub/quick_actions_view.h",
"system/phonehub/silence_phone_quick_action_controller.cc",
"system/phonehub/silence_phone_quick_action_controller.h",
"system/phonehub/task_continuation_view.cc", "system/phonehub/task_continuation_view.cc",
"system/phonehub/task_continuation_view.h", "system/phonehub/task_continuation_view.h",
"system/power/backlights_forced_off_setter.cc", "system/power/backlights_forced_off_setter.cc",
...@@ -2120,6 +2125,7 @@ test("ash_unittests") { ...@@ -2120,6 +2125,7 @@ test("ash_unittests") {
"system/phonehub/phone_hub_notification_controller_unittest.cc", "system/phonehub/phone_hub_notification_controller_unittest.cc",
"system/phonehub/phone_hub_tray_unittest.cc", "system/phonehub/phone_hub_tray_unittest.cc",
"system/phonehub/phone_status_view_unittest.cc", "system/phonehub/phone_status_view_unittest.cc",
"system/phonehub/quick_actions_view_unittest.cc",
"system/phonehub/task_continuation_view_unittest.cc", "system/phonehub/task_continuation_view_unittest.cc",
"system/power/backlights_forced_off_setter_unittest.cc", "system/power/backlights_forced_off_setter_unittest.cc",
"system/power/peripheral_battery_notifier_unittest.cc", "system/power/peripheral_battery_notifier_unittest.cc",
......
...@@ -553,7 +553,7 @@ This file contains the strings for ash. ...@@ -553,7 +553,7 @@ This file contains the strings for ash.
<ph name="UPDATE_TEXT">$1<ex>Learn more about the latest Chromium OS update</ex></ph>. This Chromebook needs to restart to apply an update. This can take up to 1 minute. <ph name="UPDATE_TEXT">$1<ex>Learn more about the latest Chromium OS update</ex></ph>. This Chromebook needs to restart to apply an update. This can take up to 1 minute.
</message> </message>
<message name="IDS_DIALOG_TITLE_SLOW_BOOT" desc="The title of the Slow Boot Shutdown Confirmation Dialog."> <message name="IDS_DIALOG_TITLE_SLOW_BOOT" desc="The title of the Slow Boot Shutdown Confirmation Dialog.">
Restart may take awhile Restart may take awhile
</message> </message>
<message name="IDS_DIALOG_MESSAGE_SLOW_BOOT" desc="The body of the Slow Boot Shutdown Confirmation Dialog."> <message name="IDS_DIALOG_MESSAGE_SLOW_BOOT" desc="The body of the Slow Boot Shutdown Confirmation Dialog.">
Your screen will go blank for longer than usual (up to a minute) during this update. Please don't press the power button while the update is in progress. Your screen will go blank for longer than usual (up to a minute) during this update. Please don't press the power button while the update is in progress.
...@@ -1020,12 +1020,36 @@ This file contains the strings for ash. ...@@ -1020,12 +1020,36 @@ This file contains the strings for ash.
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_DISABLED_STATE_TOOLTIP" desc="The tooltip text indicating the quick actions feature is off."> <message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_DISABLED_STATE_TOOLTIP" desc="The tooltip text indicating the quick actions feature is off.">
<ph name="FEATURE_NAME">$1<ex>Silence</ex></ph> is off. <ph name="FEATURE_NAME">$1<ex>Silence</ex></ph> is off.
</message> </message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTING_STATE_TOOLTIP" desc="The tooltip text indicating the quick actions feature is currently sending a signal and try to connect to the phone.">
<ph name="FEATURE_NAME">$1<ex>Silence</ex></ph> is connecting.
</message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_NOT_CONNECTED_STATE_TOOLTIP" desc="The tooltip text indicating the quick actions feature is not available to use.">
<ph name="FEATURE_NAME">$1<ex>Enable Hotspot</ex></ph> is not connected.
</message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTED_STATE_TOOLTIP" desc="The tooltip text indicating the quick actions feature is not available to use.">
<ph name="FEATURE_NAME">$1<ex>Enable Hotspot</ex></ph> is connected.
</message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_NOT_AVAILABLE_STATE_TOOLTIP" desc="The tooltip text indicating the quick actions feature is not available to use.">
<ph name="FEATURE_NAME">$1<ex>Silence</ex></ph> is not available.
</message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_OFF_STATE" desc="Quick actions state in phone hub bubble." meaning="Quick actions feature is off."> <message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_OFF_STATE" desc="Quick actions state in phone hub bubble." meaning="Quick actions feature is off.">
Off Off
</message> </message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_ON_STATE" desc="Quick actions state in phone hub bubble." meaning="Quick actions feature is on."> <message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_ON_STATE" desc="Quick actions state in phone hub bubble." meaning="Quick actions feature is on.">
On On
</message> </message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTING_STATE" desc="Quick actions state in phone hub bubble." meaning="The feature is currently sending a signal and try to connect to the phone.">
Connecting...
</message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_NOT_CONNECTED_STATE" desc="Quick actions state in phone hub bubble." meaning="The feature is not connected to the phone.">
Not connected
</message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTED_STATE" desc="Quick actions state in phone hub bubble." meaning="The feature is connected to the phone and ready to use.">
Connected
</message>
<message name="IDS_ASH_PHONE_HUB_QUICK_ACTIONS_NOT_AVAILABLE_STATE" desc="Quick actions state in phone hub bubble." meaning="Quick actions feature is not available to use.">
Not available
</message>
<message name="IDS_ASH_PHONE_HUB_TASK_CONTINUATION_TITLE" desc="Title of the task continuation section (where users pick up unfinished task left off from their phone, currently only support web browsing) in phone hub bubble."> <message name="IDS_ASH_PHONE_HUB_TASK_CONTINUATION_TITLE" desc="Title of the task continuation section (where users pick up unfinished task left off from their phone, currently only support web browsing) in phone hub bubble.">
Continue browsing Continue browsing
</message> </message>
......
f0d2cf8683111c43c0a742492d5e39b3ba128631
\ No newline at end of file
b7c6650a313b1c1e797821eccc2feb7c957ad091
\ No newline at end of file
cf8fe0079e4e717981ba3a9afedf9280cb6d8fda
\ No newline at end of file
7de2e334fd462e24075fa72eabd0eb3b73e4f13f
\ No newline at end of file
918d925ef3041ef720077971df3a0d47bed5cc34
\ No newline at end of file
ddc04194dd9844eadd4d78cb7d05c8b85ba754e6
\ No newline at end of file
6d96fd17f94b220d46d0089f65c39d78eb35e6bf
\ No newline at end of file
36477329435864bf81335bffbb895daf3f860257
\ No newline at end of file
...@@ -70,8 +70,8 @@ class PhoneHubView : public views ::View { ...@@ -70,8 +70,8 @@ class PhoneHubView : public views ::View {
std::make_unique<NotificationOptInView>(bubble_view_)); std::make_unique<NotificationOptInView>(bubble_view_));
} }
setup_layered_view( setup_layered_view(bubble_view_->AddChildView(
bubble_view_->AddChildView(std::make_unique<QuickActionsView>())); std::make_unique<QuickActionsView>(phone_hub_manager)));
AddSeparator(); AddSeparator();
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_PHONEHUB_QUICK_ACTION_CONTROLLER_BASE_H_
#define ASH_SYSTEM_PHONEHUB_QUICK_ACTION_CONTROLLER_BASE_H_
#include "ash/ash_export.h"
#include "ash/system/phonehub/quick_action_item.h"
namespace ash {
class QuickActionItem;
// Base class for controllers of quick action item.
// To add a new quick action item, implement this class, and add to the list in
// QuickActionsView::InitQuickActionItems().
class ASH_EXPORT QuickActionControllerBase : public QuickActionItem::Delegate {
public:
virtual ~QuickActionControllerBase() = default;
// Create the view. Subclasses instantiate QuickActionItem.
// The view will be owned by views hierarchy. The view will be always deleted
// after the controller is destructed.
virtual QuickActionItem* CreateItem() = 0;
};
} // namespace ash
#endif // ASH_SYSTEM_PHONEHUB_QUICK_ACTION_CONTROLLER_BASE_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/phonehub/quick_action_item.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/tray/tray_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
namespace ash {
namespace {
constexpr int kQuickActionItemLabelSize = 14;
void ConfigureLabel(views::Label* label, bool is_primary) {
label->SetAutoColorReadabilityEnabled(false);
label->SetSubpixelRenderingEnabled(false);
label->set_can_process_events_within_subtree(false);
auto type = is_primary
? AshColorProvider::ContentLayerType::kTextColorPrimary
: AshColorProvider::ContentLayerType::kTextColorSecondary;
label->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(type));
gfx::Font default_font;
gfx::Font label_font = default_font.Derive(
kQuickActionItemLabelSize - default_font.GetFontSize(), gfx::Font::NORMAL,
gfx::Font::Weight::NORMAL);
gfx::FontList font_list(label_font);
label->SetFontList(font_list);
}
} // namespace
QuickActionItem::QuickActionItem(Delegate* delegate,
int label_id,
const gfx::VectorIcon& icon_on,
const gfx::VectorIcon& icon_off)
: delegate_(delegate), icon_on_(icon_on), icon_off_(icon_off) {
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets(),
kUnifiedFeaturePodSpacing));
layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
icon_button_ = AddChildView(
std::make_unique<FeaturePodIconButton>(this, true /* is_togglable */));
auto* label_view = AddChildView(std::make_unique<views::View>());
label_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets()));
label_ = label_view->AddChildView(
std::make_unique<views::Label>(l10n_util::GetStringUTF16(label_id)));
ConfigureLabel(label_, true /* is_primary */);
sub_label_ = label_view->AddChildView(std::make_unique<views::Label>());
ConfigureLabel(sub_label_, false /* is_primary */);
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
}
QuickActionItem::QuickActionItem(Delegate* delegate,
int label_id,
const gfx::VectorIcon& icon)
: QuickActionItem(delegate, label_id, icon, icon) {}
QuickActionItem::~QuickActionItem() = default;
void QuickActionItem::SetSubLabel(const base::string16& sub_label) {
sub_label_->SetText(sub_label);
}
void QuickActionItem::SetIconTooltip(const base::string16& text) {
icon_button_->SetTooltipText(text);
}
void QuickActionItem::SetToggled(bool toggled) {
icon_button_->SetToggled(toggled);
icon_button_->SetVectorIcon(toggled ? icon_on_ : icon_off_);
}
bool QuickActionItem::IsToggled() const {
return icon_button_->toggled();
}
const base::string16& QuickActionItem::GetItemLabel() const {
return label_->GetText();
}
void QuickActionItem::SetEnabled(bool enabled) {
View::SetEnabled(enabled);
icon_button_->SetEnabled(enabled);
if (!enabled) {
label_->SetEnabledColor(
AshColorProvider::GetDisabledColor(label_->GetEnabledColor()));
sub_label_->SetEnabledColor(
AshColorProvider::GetDisabledColor(sub_label_->GetEnabledColor()));
sub_label_->SetText(l10n_util::GetStringUTF16(
IDS_ASH_PHONE_HUB_QUICK_ACTIONS_NOT_AVAILABLE_STATE));
icon_button_->SetTooltipText(l10n_util::GetStringFUTF16(
IDS_ASH_PHONE_HUB_QUICK_ACTIONS_NOT_AVAILABLE_STATE_TOOLTIP,
GetItemLabel()));
} else {
ConfigureLabel(label_, true /* is_primary */);
ConfigureLabel(sub_label_, false /* is_primary */);
}
}
void QuickActionItem::ButtonPressed(views::Button* sender,
const ui::Event& event) {
delegate_->OnButtonPressed(IsToggled());
}
bool QuickActionItem::HasFocus() const {
return icon_button_->HasFocus() || label_->HasFocus() ||
sub_label_->HasFocus();
}
void QuickActionItem::RequestFocus() {
icon_button_->RequestFocus();
}
const char* QuickActionItem::GetClassName() const {
return "QuickActionItem";
}
} // namespace ash
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_PHONEHUB_QUICK_ACTION_ITEM_H_
#define ASH_SYSTEM_PHONEHUB_QUICK_ACTION_ITEM_H_
#include "ash/ash_export.h"
#include "ash/system/unified/feature_pod_button.h"
#include "ui/views/controls/button/button.h"
namespace views {
class Label;
}
namespace ash {
// A toggle button with labels used in the quick action view.
class QuickActionItem : public views::View, public views::ButtonListener {
public:
class Delegate {
public:
// Called when the button of the quick action item is clicked.
virtual void OnButtonPressed(bool is_now_enabled) = 0;
};
// |icon_on| and |icon_off| indicates the icons used in on/off state of the
// button.
QuickActionItem(Delegate* delegate,
int label_id,
const gfx::VectorIcon& icon_on,
const gfx::VectorIcon& icon_off);
// If only one icon is supplied, it will be used in both cases.
QuickActionItem(Delegate* delegate,
int label_id,
const gfx::VectorIcon& icon);
~QuickActionItem() override;
QuickActionItem(QuickActionItem&) = delete;
QuickActionItem operator=(QuickActionItem&) = delete;
// Set the text of sub-label shown below the label.
void SetSubLabel(const base::string16& sub_label);
// Set the tooltip text of the icon button.
void SetIconTooltip(const base::string16& text);
// Change the toggled state. If toggled, the background color of the circle
// will change.
void SetToggled(bool toggled);
bool IsToggled() const;
// Get the title/label text of the item.
const base::string16& GetItemLabel() const;
// Set the item to be enabled or disabled. When disabled, the button cannot be
// clicked and the labels are greyed out.
void SetEnabled(bool enabled);
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// views::View:
bool HasFocus() const override;
void RequestFocus() override;
const char* GetClassName() const override;
FeaturePodIconButton* icon_button() const { return icon_button_; }
private:
Delegate* delegate_ = nullptr;
// Owned by views hierarchy.
FeaturePodIconButton* icon_button_ = nullptr;
const gfx::VectorIcon& icon_on_;
const gfx::VectorIcon& icon_off_;
views::Label* label_ = nullptr;
views::Label* sub_label_ = nullptr;
};
} // namespace ash
#endif // ASH_SYSTEM_PHONEHUB_QUICK_ACTION_VIEW_H_
...@@ -4,108 +4,25 @@ ...@@ -4,108 +4,25 @@
#include "ash/system/phonehub/quick_actions_view.h" #include "ash/system/phonehub/quick_actions_view.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/phonehub/phone_hub_view_ids.h" #include "ash/system/phonehub/phone_hub_view_ids.h"
#include "ash/system/tray/tray_constants.h" #include "ash/system/phonehub/quick_action_item.h"
#include "ash/system/unified/feature_pod_button.h" #include "ash/system/phonehub/silence_phone_quick_action_controller.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
namespace ash { namespace ash {
namespace { namespace {
constexpr int kQuickActionsItemSpacing = 36;
constexpr int kQuickActionsItemLabelSize = 14;
constexpr gfx::Insets kQuickActionsViewPadding(16, 4); constexpr gfx::Insets kQuickActionsViewPadding(16, 4);
constexpr int kQuickActionsItemSpacing = 36;
void ConfigureLabel(views::Label* label, bool is_primary) {
label->SetAutoColorReadabilityEnabled(false);
label->SetSubpixelRenderingEnabled(false);
label->set_can_process_events_within_subtree(false);
auto type = is_primary
? AshColorProvider::ContentLayerType::kTextColorPrimary
: AshColorProvider::ContentLayerType::kTextColorSecondary;
label->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(type));
gfx::Font default_font;
gfx::Font label_font = default_font.Derive(
kQuickActionsItemLabelSize - default_font.GetFontSize(),
gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
gfx::FontList font_list(label_font);
label->SetFontList(font_list);
}
} // namespace } // namespace
QuickActionsItem::QuickActionsItem(views::ButtonListener* listener, QuickActionsView::QuickActionsView(
const gfx::VectorIcon& vector_icon, chromeos::phonehub::PhoneHubManager* phone_hub_manager)
int label_id) : phone_hub_manager_(phone_hub_manager) {
: icon_button_(new FeaturePodIconButton(listener, true /* is_togglable */)),
label_(new views::Label),
sub_label_(new views::Label) {
SetID(PhoneHubViewID::kQuickActionsView); SetID(PhoneHubViewID::kQuickActionsView);
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets(),
kUnifiedFeaturePodSpacing));
layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
icon_button_ = AddChildView(std::make_unique<FeaturePodIconButton>(
listener, true /* is_togglable */));
icon_button_->SetVectorIcon(vector_icon);
auto* label_view = AddChildView(std::make_unique<views::View>());
label_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets()));
label_ = label_view->AddChildView(
std::make_unique<views::Label>(l10n_util::GetStringUTF16(label_id)));
ConfigureLabel(label_, true /* is_primary */);
sub_label_ = label_view->AddChildView(std::make_unique<views::Label>());
ConfigureLabel(sub_label_, false /* is_primary */);
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
}
QuickActionsItem::~QuickActionsItem() = default;
void QuickActionsItem::SetSubLabel(const base::string16& sub_label) {
sub_label_->SetText(sub_label);
}
void QuickActionsItem::SetIconTooltip(const base::string16& text) {
icon_button_->SetTooltipText(text);
}
void QuickActionsItem::SetToggled(bool toggled) {
icon_button_->SetToggled(toggled);
}
const base::string16& QuickActionsItem::GetItemLabel() const {
return label_->GetText();
}
bool QuickActionsItem::HasFocus() const {
return icon_button_->HasFocus() || label_->HasFocus() ||
sub_label_->HasFocus();
}
void QuickActionsItem::RequestFocus() {
icon_button_->RequestFocus();
}
const char* QuickActionsItem::GetClassName() const {
return "QuickActionsItem";
}
QuickActionsView::QuickActionsView() {
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, kQuickActionsViewPadding, views::BoxLayout::Orientation::kHorizontal, kQuickActionsViewPadding,
kQuickActionsItemSpacing)); kQuickActionsItemSpacing));
...@@ -113,52 +30,21 @@ QuickActionsView::QuickActionsView() { ...@@ -113,52 +30,21 @@ QuickActionsView::QuickActionsView() {
layout->set_cross_axis_alignment( layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter); views::BoxLayout::CrossAxisAlignment::kCenter);
enable_hotspot_ = AddChildView(std::make_unique<QuickActionsItem>( InitQuickActionItems();
this, kSystemMenuPhoneIcon, IDS_ASH_PHONE_HUB_ENABLE_HOTSPOT_TITLE));
silence_phone_ = AddChildView(std::make_unique<QuickActionsItem>(
this, kSystemMenuPhoneIcon, IDS_ASH_PHONE_HUB_SILENCE_PHONE_TITLE));
locate_phone_ = AddChildView(std::make_unique<QuickActionsItem>(
this, kSystemMenuPhoneIcon, IDS_ASH_PHONE_HUB_LOCATE_PHONE_TITLE));
Update();
} }
QuickActionsView::~QuickActionsView() = default; QuickActionsView::~QuickActionsView() = default;
void QuickActionsView::ButtonPressed(views::Button* sender, void QuickActionsView::InitQuickActionItems() {
const ui::Event& event) { silence_phone_ = AddItem(std::make_unique<SilencePhoneQuickActionController>(
// TODO(leandre): implement quick actions button functionality. phone_hub_manager_->GetDoNotDisturbController()));
if (sender == enable_hotspot_->icon_button()) {
UpdateItem(enable_hotspot_, !enable_hotspot_->IsToggled());
} else if (sender == silence_phone_->icon_button()) {
UpdateItem(silence_phone_, !silence_phone_->IsToggled());
} else if (sender == locate_phone_->icon_button()) {
UpdateItem(locate_phone_, !locate_phone_->IsToggled());
} else {
NOTREACHED();
}
}
void QuickActionsView::Update() {
// TODO(leandre): Update items according to phone status.
UpdateItem(enable_hotspot_, false);
UpdateItem(silence_phone_, true);
UpdateItem(locate_phone_, false);
} }
void QuickActionsView::UpdateItem(QuickActionsItem* item, bool is_enabled) { QuickActionItem* QuickActionsView::AddItem(
item->SetToggled(is_enabled); std::unique_ptr<QuickActionControllerBase> controller) {
item->SetSubLabel(l10n_util::GetStringUTF16( auto* item = AddChildView(controller->CreateItem());
is_enabled ? IDS_ASH_PHONE_HUB_QUICK_ACTIONS_ON_STATE quick_action_controllers_.push_back(std::move(controller));
: IDS_ASH_PHONE_HUB_QUICK_ACTIONS_OFF_STATE)); return item;
int state_text_id =
is_enabled ? IDS_ASH_PHONE_HUB_QUICK_ACTIONS_ENABLED_STATE_TOOLTIP
: IDS_ASH_PHONE_HUB_QUICK_ACTIONS_DISABLED_STATE_TOOLTIP;
base::string16 tooltip_state =
l10n_util::GetStringFUTF16(state_text_id, item->GetItemLabel());
item->SetIconTooltip(
l10n_util::GetStringFUTF16(IDS_ASH_PHONE_HUB_QUICK_ACTIONS_TOGGLE_TOOLTIP,
item->GetItemLabel(), tooltip_state));
} }
} // namespace ash } // namespace ash
...@@ -6,70 +6,42 @@ ...@@ -6,70 +6,42 @@
#define ASH_SYSTEM_PHONEHUB_QUICK_ACTIONS_VIEW_H_ #define ASH_SYSTEM_PHONEHUB_QUICK_ACTIONS_VIEW_H_
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/system/unified/feature_pod_button.h" #include "chromeos/components/phonehub/phone_hub_manager.h"
#include "ui/views/controls/button/button.h" #include "ui/views/view.h"
#include "ui/views/controls/label.h"
namespace ash { namespace ash {
// A toggle button with labels used in the quick actions view. class QuickActionControllerBase;
class QuickActionsItem : public views::View { class QuickActionItem;
public:
explicit QuickActionsItem(views::ButtonListener* listener,
const gfx::VectorIcon& vector_icon,
int label_id);
~QuickActionsItem() override;
QuickActionsItem(QuickActionsItem&) = delete;
QuickActionsItem operator=(QuickActionsItem&) = delete;
// Set the text of sub-label shown below the label.
void SetSubLabel(const base::string16& sub_label);
// Set the tooltip text of the icon button.
void SetIconTooltip(const base::string16& text);
// Change the toggled state. If toggled, the background color of the circle
// will change.
void SetToggled(bool toggled);
bool IsToggled() const { return icon_button_->toggled(); }
// Get the title/label text of the item.
const base::string16& GetItemLabel() const;
// views::View:
bool HasFocus() const override;
void RequestFocus() override;
const char* GetClassName() const override;
FeaturePodIconButton* icon_button() const { return icon_button_; }
private:
// Owned by views hierarchy.
FeaturePodIconButton* icon_button_ = nullptr;
views::Label* label_ = nullptr;
views::Label* sub_label_ = nullptr;
};
// A view in Phone Hub bubble that contains toggle button for quick actions such // A view in Phone Hub bubble that contains toggle button for quick actions such
// as enable hotspot, silence phone and locate phone. // as enable hotspot, silence phone and locate phone.
class ASH_EXPORT QuickActionsView : public views::View, class ASH_EXPORT QuickActionsView : public views::View {
public views::ButtonListener {
public: public:
QuickActionsView(); explicit QuickActionsView(
chromeos::phonehub::PhoneHubManager* phone_hub_manager);
~QuickActionsView() override; ~QuickActionsView() override;
QuickActionsView(QuickActionsView&) = delete; QuickActionsView(QuickActionsView&) = delete;
QuickActionsView operator=(QuickActionsView&) = delete; QuickActionsView operator=(QuickActionsView&) = delete;
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
private: private:
void Update(); FRIEND_TEST_ALL_PREFIXES(QuickActionsViewTest, QuickActionsToggle);
void UpdateItem(QuickActionsItem* item, bool is_enabled);
// Add all the quick actions items to the view.
void InitQuickActionItems();
// Helper function to add an item to the view given its controller.
QuickActionItem* AddItem(
std::unique_ptr<QuickActionControllerBase> controller);
// Controllers of quick actions items. Owned by this.
std::vector<std::unique_ptr<QuickActionControllerBase>>
quick_action_controllers_;
chromeos::phonehub::PhoneHubManager* phone_hub_manager_ = nullptr;
QuickActionsItem* enable_hotspot_ = nullptr; // QuickActionItem for unit testing. Owned by this view.
QuickActionsItem* silence_phone_ = nullptr; QuickActionItem* silence_phone_ = nullptr;
QuickActionsItem* locate_phone_ = nullptr;
}; };
} // namespace ash } // namespace ash
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/phonehub/quick_actions_view.h"
#include "ash/system/phonehub/quick_action_item.h"
#include "ash/test/ash_test_base.h"
#include "base/test/scoped_feature_list.h"
#include "chromeos/components/phonehub/fake_phone_hub_manager.h"
#include "chromeos/constants/chromeos_features.h"
namespace ash {
using Status = chromeos::phonehub::TetherController::Status;
namespace {
class DummyEvent : public ui::Event {
public:
DummyEvent() : Event(ui::ET_UNKNOWN, base::TimeTicks(), 0) {}
};
} // namespace
class QuickActionsViewTest : public AshTestBase {
public:
QuickActionsViewTest() = default;
~QuickActionsViewTest() override = default;
// AshTestBase:
void SetUp() override {
feature_list_.InitAndEnableFeature(chromeos::features::kPhoneHub);
AshTestBase::SetUp();
quick_actions_view_ =
std::make_unique<QuickActionsView>(&phone_hub_manager_);
}
void TearDown() override {
quick_actions_view_.reset();
AshTestBase::TearDown();
}
protected:
QuickActionsView* actions_view() { return quick_actions_view_.get(); }
chromeos::phonehub::FakeTetherController* tether_controller() {
return phone_hub_manager_.fake_tether_controller();
}
chromeos::phonehub::FakeDoNotDisturbController* dnd_controller() {
return phone_hub_manager_.fake_do_not_disturb_controller();
}
chromeos::phonehub::FakeFindMyDeviceController* find_my_device_controller() {
return phone_hub_manager_.fake_find_my_device_controller();
}
private:
std::unique_ptr<QuickActionsView> quick_actions_view_;
chromeos::phonehub::FakePhoneHubManager phone_hub_manager_;
base::test::ScopedFeatureList feature_list_;
};
TEST_F(QuickActionsViewTest, QuickActionsToggle) {
// Initially, silence phone is not enabled.
EXPECT_FALSE(dnd_controller()->IsDndEnabled());
// Toggle the button will enable the feature.
actions_view()->silence_phone_->ButtonPressed(nullptr, DummyEvent());
EXPECT_TRUE(dnd_controller()->IsDndEnabled());
// Togge again to disable.
actions_view()->silence_phone_->ButtonPressed(nullptr, DummyEvent());
EXPECT_FALSE(dnd_controller()->IsDndEnabled());
}
} // namespace ash
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/phonehub/silence_phone_quick_action_controller.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/phonehub/quick_action_item.h"
#include "ui/base/l10n/l10n_util.h"
namespace ash {
SilencePhoneQuickActionController::SilencePhoneQuickActionController(
chromeos::phonehub::DoNotDisturbController* dnd_controller)
: dnd_controller_(dnd_controller) {
DCHECK(dnd_controller_);
dnd_controller_->AddObserver(this);
}
SilencePhoneQuickActionController::~SilencePhoneQuickActionController() {
dnd_controller_->RemoveObserver(this);
}
QuickActionItem* SilencePhoneQuickActionController::CreateItem() {
DCHECK(!item_);
item_ = new QuickActionItem(this, IDS_ASH_PHONE_HUB_SILENCE_PHONE_TITLE,
kSystemMenuPhoneIcon);
OnDndStateChanged();
return item_;
}
void SilencePhoneQuickActionController::OnButtonPressed(bool is_now_enabled) {
SetState(ActionState::kConnecting);
dnd_controller_->SetDoNotDisturbState(!is_now_enabled);
// TODO(leandre): Add a timer to switch back to off state after connecting
// failed.
}
void SilencePhoneQuickActionController::OnDndStateChanged() {
dnd_controller_->IsDndEnabled() ? SetState(ActionState::kOn)
: SetState(ActionState::kOff);
}
void SilencePhoneQuickActionController::SetState(ActionState state) {
bool icon_enabled;
int state_text_id;
int sub_label_text;
switch (state) {
case ActionState::kOff:
icon_enabled = false;
state_text_id = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_DISABLED_STATE_TOOLTIP;
sub_label_text = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_OFF_STATE;
break;
case ActionState::kConnecting:
icon_enabled = true;
state_text_id = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTING_STATE_TOOLTIP;
sub_label_text = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTING_STATE;
break;
case ActionState::kOn:
icon_enabled = true;
state_text_id = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_ENABLED_STATE_TOOLTIP;
sub_label_text = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_ON_STATE;
break;
}
item_->SetToggled(icon_enabled);
item_->SetSubLabel(l10n_util::GetStringUTF16(sub_label_text));
base::string16 tooltip_state =
l10n_util::GetStringFUTF16(state_text_id, item_->GetItemLabel());
item_->SetIconTooltip(
l10n_util::GetStringFUTF16(IDS_ASH_PHONE_HUB_QUICK_ACTIONS_TOGGLE_TOOLTIP,
item_->GetItemLabel(), tooltip_state));
}
} // namespace ash
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_PHONEHUB_SILENCE_PHONE_QUICK_ACTION_CONTROLLER_H_
#define ASH_SYSTEM_PHONEHUB_SILENCE_PHONE_QUICK_ACTION_CONTROLLER_H_
#include "ash/system/phonehub/quick_action_controller_base.h"
#include "chromeos/components/phonehub/do_not_disturb_controller.h"
namespace ash {
// Controller of a quick action item that toggles silence phone mode.
class SilencePhoneQuickActionController
: public QuickActionControllerBase,
public chromeos::phonehub::DoNotDisturbController::Observer {
public:
explicit SilencePhoneQuickActionController(
chromeos::phonehub::DoNotDisturbController* dnd_controller);
~SilencePhoneQuickActionController() override;
SilencePhoneQuickActionController(SilencePhoneQuickActionController&) =
delete;
SilencePhoneQuickActionController operator=(
SilencePhoneQuickActionController&) = delete;
// QuickActionControllerBase:
QuickActionItem* CreateItem() override;
void OnButtonPressed(bool is_now_enabled) override;
// chromeos::phonehub::DoNotDisturbController::Observer:
void OnDndStateChanged() override;
private:
// All the possible states that the silence phone button can be viewed. Each
// state has a corresponding icon, labels and tooltip view.
enum class ActionState { kOff, kConnecting, kOn };
// Set the item (including icon, label and tooltips) to a certain state.
void SetState(ActionState state);
chromeos::phonehub::DoNotDisturbController* dnd_controller_ = nullptr;
QuickActionItem* item_ = nullptr;
};
} // namespace ash
#endif // ASH_SYSTEM_PHONEHUB_SILENCE_PHONE_QUICK_ACTION_CONTROLLER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment