#ifndef ASH_SYSTEM_PHONEHUB_PHONE_HUB_TRAY_H_
#define ASH_SYSTEM_PHONEHUB_PHONE_HUB_TRAY_H_
#include "ash/ash_export.h"
#include "ash/session/session_controller_impl.h"
#include "ash/system/phonehub/onboarding_view.h"
#include "ash/system/phonehub/phone_hub_content_view.h"
#include "ash/system/phonehub/phone_hub_ui_controller.h"
#include "ash/system/phonehub/phone_status_view.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/tray_background_view.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chromeos/ash/components/phonehub/app_stream_manager.h"
#include "chromeos/ash/components/phonehub/icon_decoder.h"
#include "chromeos/ash/components/phonehub/phone_hub_manager.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/display/manager/display_manager_observer.h"
#include "ui/events/event.h"
#include "ui/menus/simple_menu_model.h"
#include "ui/views/controls/button/image_button.h"
namespace views {
class ImageButton;
}
namespace ash {
class EcheIconLoadingIndicatorView;
class OnboardingNudgeController;
class PhoneHubContentView;
class TrayBubbleWrapper;
class SessionControllerImpl;
namespace phonehub {
namespace proto {
class AppStreamUpdate;
}
class PhoneHubManager;
}
class ASH_EXPORT PhoneHubTray : public TrayBackgroundView,
public OnboardingView::Delegate,
public PhoneStatusView::Delegate,
public PhoneHubUiController::Observer,
public ui::SimpleMenuModel::Delegate,
public SessionObserver,
public display::DisplayManagerObserver,
public phonehub::AppStreamManager::Observer {
METADATA_HEADER(PhoneHubTray, TrayBackgroundView)
public:
explicit PhoneHubTray(Shelf* shelf);
PhoneHubTray(const PhoneHubTray&) = delete;
PhoneHubTray& operator=(const PhoneHubTray&) = delete;
~PhoneHubTray() override;
void SetPhoneHubManager(phonehub::PhoneHubManager* phone_hub_manager);
void ClickedOutsideBubble(const ui::LocatedEvent& event) override;
void UpdateTrayItemColor(bool is_active) override;
void HandleLocaleChange() override;
void HideBubbleWithView(const TrayBubbleView* bubble_view) override;
void AnchorUpdated() override;
void Initialize() override;
void CloseBubbleInternal() override;
void ShowBubble() override;
std::unique_ptr<ui::SimpleMenuModel> CreateContextMenuModel() override;
TrayBubbleView* GetBubbleView() override;
views::Widget* GetBubbleWidget() const override;
bool CanOpenConnectedDeviceSettings() override;
void OpenConnectedDevicesSettings() override;
void HideStatusHeaderView() override;
bool IsPhoneHubIconClickedWhenNudgeVisible() override;
void OnDidApplyDisplayChanges() override;
void OnAppStreamUpdate(
const phonehub::proto::AppStreamUpdate app_stream_update) override;
void OnIconsDecoded(
std::string visible_name,
std::unique_ptr<std::vector<phonehub::IconDecoder::DecodingData>>
decoding_data_list);
views::ImageButton* eche_icon_view() { return eche_icon_; }
EcheIconLoadingIndicatorView* eche_loading_indicator() {
return eche_loading_indicator_;
}
void SetEcheIconActivationCallback(base::RepeatingCallback<void()> callback);
views::View* content_view_for_testing() { return content_view_; }
PhoneHubUiController* ui_controller() { return ui_controller_.get(); }
OnboardingNudgeController* onboarding_nudge_controller_for_testing() {
return onboarding_nudge_controller_.get();
}
protected:
void OnVisibilityAnimationFinished(bool should_log_visible_pod_count,
bool aborted) override;
private:
FRIEND_TEST_ALL_PREFIXES(PhoneHubTrayTest, EcheIconActivatesCallback);
FRIEND_TEST_ALL_PREFIXES(PhoneHubTrayTest, SafeAccessToHeaderView);
FRIEND_TEST_ALL_PREFIXES(PhoneHubTrayTest, TrayPressedMetrics);
FRIEND_TEST_ALL_PREFIXES(PhoneHubTrayTest, AccessibleNames);
static constexpr base::TimeDelta kMultiDeviceSetupNotificationTimeLimit =
base::Minutes(5);
std::u16string GetAccessibleNameForBubble() override;
bool ShouldEnableExtraKeyboardAccessibility() override;
void HideBubble(const TrayBubbleView* bubble_view) override;
void OnPhoneHubUiStateChanged() override;
void OnSessionStateChanged(session_manager::SessionState state) override;
void OnActiveUserSessionChanged(const AccountId& account_id) override;
void ExecuteCommand(int command_id, int event_flags) override;
void UpdateVisibility();
void UpdateHeaderVisibility();
void TemporarilyDisableAnimation();
void EcheIconActivated(const ui::Event& event);
void PhoneHubIconActivated(const ui::Event& event);
views::View* GetPhoneStatusView();
bool IsInsideUnlockWindow();
bool is_icon_clicked_when_setup_notification_visible_ = false;
bool is_icon_clicked_when_nudge_visible_ = false;
raw_ptr<views::ImageButton> icon_;
raw_ptr<views::ImageButton> eche_icon_ = nullptr;
raw_ptr<EcheIconLoadingIndicatorView> eche_loading_indicator_ = nullptr;
base::RepeatingCallback<void()> eche_icon_callback_ = base::DoNothing();
std::unique_ptr<PhoneHubUiController> ui_controller_;
std::unique_ptr<OnboardingNudgeController> onboarding_nudge_controller_;
std::unique_ptr<TrayBubbleWrapper> bubble_;
raw_ptr<views::View> phone_status_view_dont_use_ = nullptr;
raw_ptr<PhoneHubContentView, DanglingUntriaged> content_view_ = nullptr;
raw_ptr<phonehub::PhoneHubManager> phone_hub_manager_ = nullptr;
base::Time last_unlocked_timestamp_;
base::ScopedObservation<PhoneHubUiController, PhoneHubUiController::Observer>
observed_phone_hub_ui_controller_{this};
base::ScopedObservation<SessionControllerImpl, SessionObserver>
observed_session_{this};
base::WeakPtrFactory<PhoneHubTray> weak_factory_{this};
};
}
#endif