1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153

ash / public / cpp / system / anchored_nudge_data.h [blame]

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

#ifndef ASH_PUBLIC_CPP_SYSTEM_ANCHORED_NUDGE_DATA_H_
#define ASH_PUBLIC_CPP_SYSTEM_ANCHORED_NUDGE_DATA_H_

#include <optional>
#include <string>

#include "ash/constants/notifier_catalogs.h"
#include "ash/public/cpp/ash_public_export.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/time/time.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/view_tracker.h"

namespace views {
class View;
class Widget;
}  // namespace views

namespace ash {

// Refer to `anchored_nudge_manager_impl.cc` to see the duration values.
// TODO(b/297619385): Move constants to a new constants file.
enum class NudgeDuration {
  // Default duration that is used for nudges that expire.
  kDefaultDuration = 0,

  // Used for nudges with a button or a body text that has
  // `AnchoredNudgeManagerImpl::kLongBodyTextLength` or more characters.
  kMediumDuration = 1,

  // Used for nudges that are meant to persist until user interacts with them.
  kLongDuration = 2,

  kMaxValue = kLongDuration
};

using HoverChangedCallback = base::RepeatingCallback<void(bool is_hovered)>;
using NudgeClickCallback = base::RepeatingCallback<void()>;
using NudgeDismissCallback = base::RepeatingCallback<void()>;

// Describes the contents of a System Nudge (AnchoredNudge), which is a notifier
// that informs users about something that might enhance their experience. See
// the "Educational Nudges" section in go/notifier-framework for example usages.
// Nudges may anchor to any `views::View` on screen and will follow it to set
// its bounds. Nudges with no `anchor_view` will show in the default location.
// Nudges `anchored_to_shelf` will set their arrow based on the shelf alignment.
// TODO(b/285988235): `AnchoredNudge` will replace the existing `SystemNudge`
// and take over its name.
struct ASH_PUBLIC_EXPORT AnchoredNudgeData {
  AnchoredNudgeData(const std::string& id,
                    NudgeCatalogName catalog_name,
                    const std::u16string& body_text,
                    views::View* anchor_view = nullptr);
  AnchoredNudgeData(AnchoredNudgeData&& other);
  AnchoredNudgeData& operator=(AnchoredNudgeData&& other);
  ~AnchoredNudgeData();

  views::View* GetAnchorView() const { return anchor_view_tracker_->view(); }
  bool is_anchored() const { return is_anchored_; }

  // Sets the anchor view, observes it with a view tracker to assign a nullptr
  // in case the view is deleted, and sets the `is_anchored_` member variable.
  void SetAnchorView(views::View* anchor_view);

  // Required system nudge elements.
  std::string id;
  NudgeCatalogName catalog_name;
  std::u16string body_text;

  // Optional system nudge view elements. If not empty, a leading image, nudge
  // title, or keyboard shortcut view will be created and the background will
  // use customized colors.
  ui::ImageModel image_model;
  std::u16string title_text;
  std::vector<ui::KeyboardCode> keyboard_codes;
  std::optional<ui::ColorId> background_color_id;
  std::optional<ui::ColorId> image_background_color_id;

  // Callback for close button pressed.
  base::RepeatingClosure close_button_callback;

  // Optional system nudge buttons. If the text is not empty, the respective
  // button will be created. Pressing the button will execute its callback, if
  // any, followed by the nudge being closed. `secondary_button_text` should
  // only be set if `primary_button_text` has also been set.
  // TODO(b/285023559): Add a `ChainedCancelCallback` class instead of a
  // `RepeatingClosure` so we don't have to manually modify the provided
  // callbacks in the manager.
  std::u16string primary_button_text;
  base::RepeatingClosure primary_button_callback = base::DoNothing();

  std::u16string secondary_button_text;
  base::RepeatingClosure secondary_button_callback = base::DoNothing();

  // Used to set the nudge's placement in relation to the anchor view, if any.
  views::BubbleBorder::Arrow arrow = views::BubbleBorder::BOTTOM_RIGHT;

  // Nudges can set a default, medium or long duration for nudges that persist.
  // Refer to `anchored_nudge_manager_impl.cc` to see the duration values.
  // TODO(b/297619385): Move constants to a new constants file.
  NudgeDuration duration = NudgeDuration::kDefaultDuration;

  // If true, `arrow` will be set based on the current shelf alignment, and the
  // nudge will listen to shelf alignment changes to readjust its `arrow`.
  // It will maintain the shelf visible while a nudge is being shown.
  bool anchored_to_shelf = false;

  // Whether the image will be set to the same size as its container view. This
  // is required for lottie images, which need their size to be set directly.
  bool fill_image_size = false;

  // Highlight anchor button by default.
  bool highlight_anchor_button = true;

  // If true, set the `anchor_view` as parent.
  bool set_anchor_view_as_parent = false;

  // If false, the ChromeVox will not announce `body_text`.
  bool announce_chromevox = true;

  // If not null, the nudge will anchor inside the `anchor_widget`, which is a
  // `views::Widget`. Used together with the `views::BubbleBorder::Arrow`, but
  // currently only support anchoring to the bottom corners of the
  // `anchor_widget`. NOTE: This is a new type of anchoring, which is different
  // than the `anchor_view`. At most only one of them can be set.
  raw_ptr<views::Widget> anchor_widget = nullptr;

  // Nudge action custom callbacks.
  HoverChangedCallback hover_changed_callback;
  NudgeClickCallback click_callback;
  NudgeDismissCallback dismiss_callback;

 private:
  // True if an anchor view is provided when constructing the nudge data object
  // or through the `SetAnchorView` function.
  bool is_anchored_ = false;

  // View tracker that caches a pointer to the anchor view and sets it to
  // nullptr in case the view was deleted.
  std::unique_ptr<views::ViewTracker> anchor_view_tracker_;
};

}  // namespace ash

#endif  // ASH_PUBLIC_CPP_SYSTEM_ANCHORED_NUDGE_DATA_H_