123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- // Copyright 2021 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 COMPONENTS_USER_EDUCATION_COMMON_FEATURE_PROMO_SPECIFICATION_H_
- #define COMPONENTS_USER_EDUCATION_COMMON_FEATURE_PROMO_SPECIFICATION_H_
- #include <string>
- #include <vector>
- #include "base/callback_forward.h"
- #include "base/memory/raw_ptr.h"
- #include "components/user_education/common/help_bubble_params.h"
- #include "components/user_education/common/tutorial_identifier.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/abseil-cpp/absl/types/variant.h"
- #include "ui/base/accelerators/accelerator.h"
- #include "ui/base/interaction/element_identifier.h"
- #include "ui/base/interaction/element_tracker.h"
- namespace base {
- struct Feature;
- }
- namespace gfx {
- struct VectorIcon;
- }
- namespace user_education {
- class FeaturePromoHandle;
- // Specifies the parameters for a feature promo and its associated bubble.
- class FeaturePromoSpecification {
- public:
- // The body text (specified by |bubble_body_string_id|) can have parameters
- // that can be specified situationally. When specifying these parameters,
- // use a |StringReplacements| object.
- using StringReplacements = std::vector<std::u16string>;
- // Optional method that filters a set of potential `elements` to choose and
- // return the anchor element, or null if none of the inputs is appropriate.
- // This method can return an element different from the input list, or null
- // if no valid element is found (this will cause the IPH not to run).
- using AnchorElementFilter = base::RepeatingCallback<ui::TrackedElement*(
- const ui::ElementTracker::ElementList& elements)>;
- // The callback type when creating a custom action IPH. The parameters are
- // `context`, which provides the context of the window in which the promo was
- // shown, and `promo_handle`, which holds the promo open until it is
- // destroyed.
- //
- // Typically, if you are taking an additional sequence of actions in response
- // to the custom callback, you will want to move `promo_handle` into longer-
- // term storage until that sequence is complete, to prevent additional IPH or
- // similar promos from being able to trigger in the interim. If you do not
- // care, simply let `promo_handle` expire at the end of the callback.
- using CustomActionCallback =
- base::RepeatingCallback<void(ui::ElementContext context,
- FeaturePromoHandle promo_handle)>;
- // Describes the type of promo. Used to configure defaults for the promo's
- // bubble.
- enum class PromoType {
- // Uninitialized/invalid specification.
- kUnspecifiied,
- // A toast-style promo.
- kToast,
- // A snooze-style promo.
- kSnooze,
- // A tutorial promo.
- kTutorial,
- // A promo where one button is replaced by a custom action.
- kCustomAction,
- // A simple promo that acts like a toast but without the required
- // accessibility data.
- kLegacy,
- };
- // Represents a command or command accelerator. Can be valueless (falsy) if
- // neither a command ID nor an explicit accelerator is specified.
- class AcceleratorInfo {
- public:
- // You can assign either an int (command ID) or a ui::Accelerator to an
- // AcceleratorInfo object.
- using ValueType = absl::variant<int, ui::Accelerator>;
- AcceleratorInfo();
- AcceleratorInfo(const AcceleratorInfo& other);
- ~AcceleratorInfo();
- explicit AcceleratorInfo(ValueType value);
- AcceleratorInfo& operator=(ValueType value);
- AcceleratorInfo& operator=(const AcceleratorInfo& other);
- explicit operator bool() const;
- bool operator!() const { return !static_cast<bool>(*this); }
- ui::Accelerator GetAccelerator(
- const ui::AcceleratorProvider* provider) const;
- private:
- ValueType value_;
- };
- struct DemoPageInfo {
- std::string display_title;
- std::string display_description;
- base::RepeatingClosure setup_for_feature_promo_callback;
- explicit DemoPageInfo(
- std::string display_title_ = std::string(),
- std::string display_description_ = std::string(),
- base::RepeatingClosure setup_for_feature_promo_callback_ =
- base::DoNothing());
- ~DemoPageInfo();
- DemoPageInfo(const DemoPageInfo& other);
- DemoPageInfo& operator=(const DemoPageInfo& other);
- };
- FeaturePromoSpecification();
- FeaturePromoSpecification(FeaturePromoSpecification&& other);
- ~FeaturePromoSpecification();
- FeaturePromoSpecification& operator=(FeaturePromoSpecification&& other);
- // Specifies a standard toast promo.
- // Because toasts are transient, they expect a separate screen reader prompt.
- // It is recommended that the prompt include an
- static FeaturePromoSpecification CreateForToastPromo(
- const base::Feature& feature,
- ui::ElementIdentifier anchor_element_id,
- int body_text_string_id,
- int accessible_text_string_id,
- AcceleratorInfo accessible_accelerator);
- // Specifies a promo with snooze buttons.
- static FeaturePromoSpecification CreateForSnoozePromo(
- const base::Feature& feature,
- ui::ElementIdentifier anchor_element_id,
- int body_text_string_id);
- // Specifies a promo that launches a tutorial.
- static FeaturePromoSpecification CreateForTutorialPromo(
- const base::Feature& feature,
- ui::ElementIdentifier anchor_element_id,
- int body_text_string_id,
- TutorialIdentifier tutorial_id);
- // Specifies a promo that triggers a custom action.
- static FeaturePromoSpecification CreateForCustomAction(
- const base::Feature& feature,
- ui::ElementIdentifier anchor_element_id,
- int body_text_string_id,
- int custom_action_string_id,
- CustomActionCallback custom_action_callback);
- // Specifies a text-only promo without additional accessibility information.
- // Deprecated. Only included for backwards compatibility with existing
- // promos. This is the only case in which |feature| can be null, and if it is
- // the result can only be used for a critical promo.
- static FeaturePromoSpecification CreateForLegacyPromo(
- const base::Feature* feature,
- ui::ElementIdentifier anchor_element_id,
- int body_text_string_id);
- // Set the optional bubble title. This text appears above the body text in a
- // slightly larger font.
- FeaturePromoSpecification& SetBubbleTitleText(int title_text_string_id);
- // Set the optional bubble icon. This is displayed next to the title or body
- // text.
- FeaturePromoSpecification& SetBubbleIcon(const gfx::VectorIcon* bubble_icon);
- // Set the bubble arrow. Default is top-left.
- FeaturePromoSpecification& SetBubbleArrow(HelpBubbleArrow bubble_arrow);
- // Set the anchor element filter.
- FeaturePromoSpecification& SetAnchorElementFilter(
- AnchorElementFilter anchor_element_filter);
- // Set whether we should look for the anchor element in any context.
- // Default is false. Since usually we only want to create the bubble in the
- // currently active window, this is only really useful for cases where there
- // is a floating window, WebContents, or tab-modal dialog that can become
- // detached from the current active window and therefore requires its own
- // unique context.
- FeaturePromoSpecification& SetInAnyContext(bool in_any_context);
- // Get the anchor element based on `anchor_element_id`,
- // `anchor_element_filter`, and `context`.
- ui::TrackedElement* GetAnchorElement(ui::ElementContext context) const;
- const base::Feature* feature() const { return feature_; }
- PromoType promo_type() const { return promo_type_; }
- ui::ElementIdentifier anchor_element_id() const { return anchor_element_id_; }
- const AnchorElementFilter& anchor_element_filter() const {
- return anchor_element_filter_;
- }
- bool in_any_context() const { return in_any_context_; }
- int bubble_body_string_id() const { return bubble_body_string_id_; }
- const std::u16string& bubble_title_text() const { return bubble_title_text_; }
- const gfx::VectorIcon* bubble_icon() const { return bubble_icon_; }
- HelpBubbleArrow bubble_arrow() const { return bubble_arrow_; }
- int screen_reader_string_id() const { return screen_reader_string_id_; }
- const AcceleratorInfo& screen_reader_accelerator() const {
- return screen_reader_accelerator_;
- }
- const DemoPageInfo& demo_page_info() const { return demo_page_info_; }
- FeaturePromoSpecification& SetDemoPageInfo(DemoPageInfo demo_page_info);
- const TutorialIdentifier& tutorial_id() const { return tutorial_id_; }
- const std::u16string custom_action_caption() const {
- return custom_action_caption_;
- }
- // Sets whether the custom action button is the default button on the help
- // bubble (default is false). It is an error to call this method for a promo
- // not created with CreateForCustomAction().
- FeaturePromoSpecification& SetCustomActionIsDefault(
- bool custom_action_is_default);
- bool custom_action_is_default() const { return custom_action_is_default_; }
- // Used to claim the callback when creating the bubble.
- CustomActionCallback custom_action_callback() const {
- return custom_action_callback_;
- }
- private:
- static constexpr HelpBubbleArrow kDefaultBubbleArrow =
- HelpBubbleArrow::kTopRight;
- FeaturePromoSpecification(const base::Feature* feature,
- PromoType promo_type,
- ui::ElementIdentifier anchor_element_id,
- int bubble_body_string_id);
- raw_ptr<const base::Feature> feature_ = nullptr;
- // The type of promo. A promo with type kUnspecified is not valid.
- PromoType promo_type_ = PromoType::kUnspecifiied;
- // The element identifier of the element to attach the promo to.
- ui::ElementIdentifier anchor_element_id_;
- // Whether we are allowed to search for the anchor element in any context.
- bool in_any_context_ = false;
- // The filter to use if there is more than one matching element, or
- // additional processing is needed (default is to always use the first
- // matching element).
- AnchorElementFilter anchor_element_filter_;
- // Text to be displayed in the promo bubble body. Should not be zero for
- // valid bubbles. We keep the string ID around because we can specify format
- // parameters when we actually create the bubble.
- int bubble_body_string_id_ = 0;
- // Optional text that is displayed at the top of the bubble, in a slightly
- // more prominent font.
- std::u16string bubble_title_text_;
- // Optional icon that is displayed next to bubble text.
- raw_ptr<const gfx::VectorIcon> bubble_icon_ = nullptr;
- // Optional arrow pointing to the promo'd element. Defaults to top left.
- HelpBubbleArrow bubble_arrow_ = kDefaultBubbleArrow;
- // Optional screen reader announcement that replaces bubble text when the
- // bubble is first announced.
- int screen_reader_string_id_ = 0;
- // Accelerator that is used to fill in a parametric field in
- // screen_reader_string_id_.
- AcceleratorInfo screen_reader_accelerator_;
- // Information to be displayed on the demo page
- DemoPageInfo demo_page_info_;
- // Tutorial identifier if the user decides to view a tutorial.
- TutorialIdentifier tutorial_id_;
- // Custom action button text.
- std::u16string custom_action_caption_;
- // Custom action button action.
- CustomActionCallback custom_action_callback_;
- // Whether the custom action is the default button.
- bool custom_action_is_default_ = false;
- };
- } // namespace user_education
- #endif // COMPONENTS_USER_EDUCATION_COMMON_FEATURE_PROMO_SPECIFICATION_H_
|