chromium/ash/assistant/ui/main_stage/assistant_zero_state_view.cc

// Copyright 2020 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/assistant/ui/main_stage/assistant_zero_state_view.h"

#include <memory>

#include "ash/assistant/model/assistant_ui_model.h"
#include "ash/assistant/ui/assistant_ui_constants.h"
#include "ash/assistant/ui/assistant_view_delegate.h"
#include "ash/assistant/ui/assistant_view_ids.h"
#include "ash/assistant/ui/main_stage/assistant_onboarding_view.h"
#include "ash/assistant/ui/main_stage/launcher_search_iph_view.h"
#include "ash/public/cpp/assistant/assistant_state.h"
#include "ash/public/cpp/assistant/controller/assistant_controller.h"
#include "ash/public/cpp/assistant/controller/assistant_ui_controller.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "base/feature_list.h"
#include "base/notreached.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/chromeos/styles/cros_styles.h"
#include "ui/color/color_provider.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"
#include "url/gurl.h"

namespace ash {

namespace {

// Appearance.
constexpr int kGreetingLabelTopMarginDip = 28;
constexpr int kOnboardingViewTopMarginDip = 48;

bool ShouldShowGreetingOrOnboarding(bool in_tablet_mode) {
  if (base::FeatureList::IsEnabled(
          feature_engagement::kIPHLauncherSearchHelpUiFeature)) {
    return !in_tablet_mode;
  }
  return true;
}

bool ShouldShowIph() {
  return base::FeatureList::IsEnabled(
      feature_engagement::kIPHLauncherSearchHelpUiFeature);
}

}  // namespace

AssistantZeroStateView::AssistantZeroStateView(AssistantViewDelegate* delegate)
    : delegate_(delegate) {
  SetID(AssistantViewID::kZeroStateView);

  InitLayout();
  UpdateLayout();

  assistant_controller_observation_.Observe(AssistantController::Get());
  AssistantUiController::Get()->GetModel()->AddObserver(this);
}

AssistantZeroStateView::~AssistantZeroStateView() {
  if (AssistantUiController::Get())
    AssistantUiController::Get()->GetModel()->RemoveObserver(this);
}

gfx::Size AssistantZeroStateView::CalculatePreferredSize(
    const views::SizeBounds& available_size) const {
  return gfx::Size(
      INT_MAX, GetLayoutManager()->GetPreferredHeightForWidth(this, INT_MAX));
}

void AssistantZeroStateView::ChildPreferredSizeChanged(views::View* child) {
  PreferredSizeChanged();
}

void AssistantZeroStateView::OnBoundsChanged(const gfx::Rect& prev_bounds) {
  if (prev_bounds.size() != bounds().size()) {
    int height = iph_view_->GetPreferredSize().height();
    auto preferred_size = gfx::Size(bounds().width(), height);
    iph_view_->SetPreferredSize(preferred_size);
  }
}

void AssistantZeroStateView::OnAssistantControllerDestroying() {
  AssistantUiController::Get()->GetModel()->RemoveObserver(this);
  DCHECK(assistant_controller_observation_.IsObservingSource(
      AssistantController::Get()));
  assistant_controller_observation_.Reset();
}

void AssistantZeroStateView::OnUiVisibilityChanged(
    AssistantVisibility new_visibility,
    AssistantVisibility old_visibility,
    std::optional<AssistantEntryPoint> entry_point,
    std::optional<AssistantExitPoint> exit_point) {
  if (new_visibility == AssistantVisibility::kClosed)
    UpdateLayout();
}

void AssistantZeroStateView::InitLayout() {
  // Layout.
  views::BoxLayout* layout =
      SetLayoutManager(std::make_unique<views::BoxLayout>(
          views::BoxLayout::Orientation::kVertical));
  layout->set_cross_axis_alignment(
      views::BoxLayout::CrossAxisAlignment::kCenter);

  // Onboarding.
  onboarding_view_ =
      AddChildView(std::make_unique<AssistantOnboardingView>(delegate_));
  onboarding_view_->SetBorder(views::CreateEmptyBorder(
      gfx::Insets::TLBR(kOnboardingViewTopMarginDip, 0, 0, 0)));

  // Greeting.
  greeting_label_ = AddChildView(std::make_unique<views::Label>());
  greeting_label_->SetID(AssistantViewID::kGreetingLabel);
  greeting_label_->SetAutoColorReadabilityEnabled(false);
  greeting_label_->SetBorder(views::CreateEmptyBorder(
      gfx::Insets::TLBR(kGreetingLabelTopMarginDip, 0, 0, 0)));
  greeting_label_->SetFontList(
      assistant::ui::GetDefaultFontList()
          .DeriveWithSizeDelta(8)
          .DeriveWithWeight(gfx::Font::Weight::MEDIUM));
  greeting_label_->SetHorizontalAlignment(
      gfx::HorizontalAlignment::ALIGN_CENTER);
  greeting_label_->SetMultiLine(true);
  greeting_label_->SetText(
      l10n_util::GetStringUTF16(IDS_ASH_ASSISTANT_PROMPT_DEFAULT));
  greeting_label_->SetBackgroundColorId(kColorAshAssistantBgPlate);
  greeting_label_->SetEnabledColorId(kColorAshAssistantTextColorPrimary);

  // Spacer.
  spacer_ = AddChildView(std::make_unique<views::View>());
  layout->SetFlexForView(spacer_, 1);

  // Launcher search IPH view:
  iph_view_ = AddChildView(std::make_unique<LauncherSearchIphView>(
      /*delegate=*/this, delegate_->IsTabletMode(),
      /*scoped_iph_session=*/nullptr,
      /*location=*/LauncherSearchIphView::UiLocation::kAssistantPage));
  iph_view_->SetID(AssistantViewID::kLauncherSearchIph);
}

void AssistantZeroStateView::UpdateLayout() {
  const bool show_greeting_or_onboarding =
      ShouldShowGreetingOrOnboarding(delegate_->IsTabletMode());
  const bool show_onboarding = delegate_->ShouldShowOnboarding();
  onboarding_view_->SetVisible(show_greeting_or_onboarding && show_onboarding);
  greeting_label_->SetVisible(show_greeting_or_onboarding && !show_onboarding);

  const bool show_iph = ShouldShowIph();
  spacer_->SetVisible(show_iph);
  iph_view_->SetVisible(show_iph);
}

void AssistantZeroStateView::RunLauncherSearchQuery(
    const std::u16string& query) {
  delegate_->OnLauncherSearchChipPressed(query);
}

void AssistantZeroStateView::OpenAssistantPage() {
  NOTREACHED();
}

BEGIN_METADATA(AssistantZeroStateView)
END_METADATA

}  // namespace ash