chromium/components/global_media_controls/public/views/media_item_ui_detailed_view.cc

// 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.

#include "components/global_media_controls/public/views/media_item_ui_detailed_view.h"

#include <memory>

#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "components/global_media_controls/media_view_utils.h"
#include "components/global_media_controls/public/views/media_action_button.h"
#include "components/global_media_controls/public/views/media_progress_view.h"
#include "components/media_message_center/media_notification_container.h"
#include "components/media_message_center/media_notification_item.h"
#include "components/media_message_center/media_notification_util.h"
#include "components/media_message_center/vector_icons/vector_icons.h"
#include "components/strings/grit/components_strings.h"
#include "media/base/media_switches.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/background.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/view_utils.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "components/global_media_controls/public/views/chapter_item_view.h"
#include "components/vector_icons/vector_icons.h"
#endif

namespace global_media_controls {

MediaSessionAction;

namespace {

constexpr gfx::Insets kBackgroundInsets =;
constexpr gfx::Insets kMainRowInsets =;
constexpr gfx::Insets kMediaInfoInsets =;
constexpr gfx::Insets kSourceRowInsets =;
constexpr gfx::Insets kControlsColumnInsets =;
constexpr gfx::Insets kDeviceSelectorSeparatorInsets =;
constexpr gfx::Insets kDeviceSelectorSeparatorLineInsets =;

constexpr int kBackgroundCornerRadius =;
constexpr int kSourceTextLineHeight =;
constexpr int kTextLineHeight =;
constexpr int kFontSize =;
constexpr int kMediaInfoSeparator =;
constexpr int kControlsColumnSeparator =;
constexpr int kChevronIconSize =;
constexpr int kMediaActionButtonIconSize =;

constexpr float kFocusRingHaloInset =;

constexpr gfx::Size kArtworkSize =;
constexpr gfx::Size kPlayPauseButtonSize =;
constexpr gfx::Size kControlsButtonSize =;

constexpr char kMediaDisplayPageHistogram[] =;

#if BUILDFLAG(IS_CHROMEOS_ASH)
constexpr int kProgressRowHeight = 20;
constexpr gfx::Insets kButtonRowInsets = gfx::Insets::TLBR(0, 8, 0, 0);
constexpr char16_t kTimestampDelimiter[] = u" / ";
const gfx::FontList kTimestampFont({"Google Sans"},
                                   gfx::Font::NORMAL,
                                   13,
                                   gfx::Font::Weight::MEDIUM);
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

class MediaLabelButton : public views::Button {};

BEGIN_METADATA()

}  // namespace

MediaItemUIDetailedView::MediaItemUIDetailedView(
    media_message_center::MediaNotificationContainer* container,
    base::WeakPtr<media_message_center::MediaNotificationItem> item,
    std::unique_ptr<MediaItemUIFooter> footer_view,
    std::unique_ptr<MediaItemUIDeviceSelector> device_selector_view,
    std::unique_ptr<views::View> dismiss_button,
    media_message_center::MediaColorTheme theme,
    MediaDisplayPage media_display_page)
    :{}

MediaItemUIDetailedView::~MediaItemUIDetailedView() {}

///////////////////////////////////////////////////////////////////////////////
// MediaNotificationView implementations:

void MediaItemUIDetailedView::UpdateWithMediaSessionInfo(
    const media_session::mojom::MediaSessionInfoPtr& session_info) {}

void MediaItemUIDetailedView::UpdateWithMediaMetadata(
    const media_session::MediaMetadata& metadata) {}

void MediaItemUIDetailedView::UpdateWithMediaActions(
    const base::flat_set<media_session::mojom::MediaSessionAction>& actions) {}

void MediaItemUIDetailedView::UpdateWithMediaPosition(
    const media_session::MediaPosition& position) {}

void MediaItemUIDetailedView::UpdateWithMediaArtwork(
    const gfx::ImageSkia& image) {}

void MediaItemUIDetailedView::UpdateWithChapterArtwork(
    int index,
    const gfx::ImageSkia& image) {}

void MediaItemUIDetailedView::UpdateDeviceSelectorAvailability(
    bool has_devices) {}

///////////////////////////////////////////////////////////////////////////////
// views::View implementations:

void MediaItemUIDetailedView::AddedToWidget() {}

bool MediaItemUIDetailedView::OnKeyPressed(const ui::KeyEvent& event) {}

///////////////////////////////////////////////////////////////////////////////
// MediaItemUIDetailedView implementations:

void MediaItemUIDetailedView::MediaLabelPressed(MediaLabelButton* button) {}

MediaActionButton* MediaItemUIDetailedView::CreateMediaActionButton(
    views::View* parent,
    int button_id,
    const gfx::VectorIcon& vector_icon,
    int tooltip_text_id) {}

void MediaItemUIDetailedView::UpdateActionButtonsVisibility() {}

void MediaItemUIDetailedView::MediaActionButtonPressed(views::Button* button) {}

void MediaItemUIDetailedView::OnPlaybackStateChangeForProgressDrag(
    PlaybackStateChangeForDragging change) {}

void MediaItemUIDetailedView::SeekTo(double seek_progress) {}

void MediaItemUIDetailedView::SeekToTimestamp(
    const base::TimeDelta time) const {}

void MediaItemUIDetailedView::StartCastingButtonPressed() {}

void MediaItemUIDetailedView::UpdateCastingState() {}

void MediaItemUIDetailedView::UpdateChapterListViewWithMetadata(
    const media_session::MediaMetadata& metadata) {}

views::View* MediaItemUIDetailedView::CreateControlsRow() {}

void MediaItemUIDetailedView::OnProgressViewUpdateProgress(
    base::TimeDelta current_timestamp) {}

// Helper functions for testing:
views::ImageView* MediaItemUIDetailedView::GetArtworkViewForTesting() {}

views::Label* MediaItemUIDetailedView::GetSourceLabelForTesting() {}

views::Label* MediaItemUIDetailedView::GetTitleLabelForTesting() {}

views::Label* MediaItemUIDetailedView::GetArtistLabelForTesting() {}

views::ImageView* MediaItemUIDetailedView::GetChevronIconForTesting() {}

views::Button* MediaItemUIDetailedView::GetActionButtonForTesting(
    media_session::mojom::MediaSessionAction action) {}

MediaProgressView* MediaItemUIDetailedView::GetProgressViewForTesting() {}

media_session::MediaPosition MediaItemUIDetailedView::GetPositionForTesting() {}

views::Button* MediaItemUIDetailedView::GetStartCastingButtonForTesting() {}

MediaItemUIFooter* MediaItemUIDetailedView::GetFooterForTesting() {}

MediaItemUIDeviceSelector*
MediaItemUIDetailedView::GetDeviceSelectorForTesting() {}

views::View* MediaItemUIDetailedView::GetDeviceSelectorSeparatorForTesting() {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
views::Button* MediaItemUIDetailedView::GetChapterListButtonForTesting() {
  return chapter_list_button_;
}

views::View* MediaItemUIDetailedView::GetChapterListViewForTesting() {
  return chapter_list_view_;
}

views::Label* MediaItemUIDetailedView::GetCurrentTimestampViewForTesting() {
  return current_timestamp_view_;
}

views::Label* MediaItemUIDetailedView::GetTotalDurationViewForTesting() {
  return total_duration_view_;
}

base::flat_map<int, ChapterItemView*>
MediaItemUIDetailedView::GetChaptersForTesting() {
  return chapters_;
}

void MediaItemUIDetailedView::ToggleChapterListView() {
  if (!base::FeatureList::IsEnabled(media::kBackgroundListening)) {
    return;
  }

  if (!chapter_list_view_) {
    return;
  }

  const bool is_showing_chapters = chapter_list_view_->GetVisible();

  if (chapters_.empty()) {
    if (chapter_list_button_->GetVisible()) {
      chapter_list_button_->SetVisible(false);
    }

    if (is_showing_chapters) {
      chapter_list_view_->SetVisible(false);
    }
    return;
  }

  // TODO(b/327505486): Update tooltips.
  if (is_showing_chapters) {
    // Hide the ink drop color if user clicks the button to hide devices.
    views::InkDrop::Get(chapter_list_button_)->GetInkDrop()->SnapToHidden();
  } else {
    // Use the ink drop color as the button background if user clicks the
    // button to show devices.
    views::InkDrop::Get(chapter_list_button_)->GetInkDrop()->SnapToActivated();

    // Hide the `device_selector_view_` if it's shown.
    if (device_selector_view_ &&
        device_selector_view_->IsDeviceSelectorExpanded()) {
      device_selector_view_->HideDevices();
      UpdateCastingState();
    }
  }

  chapter_list_view_->SetVisible(!is_showing_chapters);
  container_->OnListViewSizeChanged();
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

BEGIN_METADATA()

}  // namespace global_media_controls