// Copyright 2022 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_NOTIFICATION_BUILDER_H_
#define ASH_PUBLIC_CPP_SYSTEM_NOTIFICATION_BUILDER_H_
#include <memory>
#include <optional>
#include <string>
#include "ash/constants/notifier_catalogs.h"
#include "ash/public/cpp/ash_public_export.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_types.h"
#include "ui/message_center/public/cpp/notifier_id.h"
class GURL;
namespace gfx {
struct VectorIcon;
}
namespace ui::message_center {
class NotificationDelegate;
} // namespace ui::message_center
namespace ash {
// Builder class for when the `CreateSystemNotification` factory method
// doesn't provide enough flexibility. This class can be useful when you're
// emitting multiple notifications in your component but they only differ in
// very few fields like Id, message and title or when some/many arguments are
// just default constructed. The first instinct may be to create a component
// specific factory method but that may not provide enough flexibility either,
// see the second example below.
//
// Example to reduce code duplication:
// void Foo::ShowNotification1() {
// message_center::RichNotificationData optional_data;
// optional_data.buttons.push_back(message_center::ButtonInfo(
// l10n_util::GetStringUTF16(IDS_SOME_BUTTON)));
//
// CreateSystemNotificationPtr(
// message_center::NOTIFICATION_TYPE_SIMPLE,
// kNotificationId1,
// l10n_util::GetStringUTF16(
// IDS_NOTIFICATION1_TITLE),
// l10n_util::GetStringUTF16(
// IDS_NOTIFICATION1_MESSAGE),
// /*display_source=*/std::u16string(),
// /*origin_url=*/GURL(),
// message_center::NotifierId(
// message_center::NotifierType::SYSTEM_COMPONENT,
// kFoo,
// NotificationCatalogName::kFooCatalog),
// optional_data,
// base::MakeRefCounted<
// message_center::HandleNotificationClickDelegate>(
// base::BindRepeating(&OnClicked,
// some_arg)),
// kSettingsIcon,
// message_center::SystemNotificationWarningLevel::WARNING);
// }
//
// void Foo::ShowNotification2() {
// message_center::RichNotificationData optional_data;
// optional_data.buttons.push_back(message_center::ButtonInfo(
// l10n_util::GetStringUTF16(IDS_SOME_BUTTON)));
//
// CreateSystemNotificationPtr(
// message_center::NOTIFICATION_TYPE_SIMPLE,
// kNotificationId2,
// l10n_util::GetStringUTF16(
// IDS_NOTIFICATION2_TITLE),
// l10n_util::GetStringUTF16(
// IDS_NOTIFICATION2_MESSAGE),
// /*display_source=*/std::u16string(),
// /*origin_url=*/GURL(),
// message_center::NotifierId(
// message_center::NotifierType::SYSTEM_COMPONENT,
// kFoo,
// NotificationCatalogName::kFooCatalog),
// optional_data,
// base::MakeRefCounted<
// message_center::HandleNotificationClickDelegate>(
// base::BindRepeating(&OnClicked,
// other_arg)),
// kSettingsIcon,
// message_center::SystemNotificationWarningLevel::WARNING);
// }
//
// Keep the builder as member and change only the fields that differ:
// Foo::Foo() {
// message_center::RichNotificationData optional_data;
// optional_data.buttons.push_back(message_center::ButtonInfo(
// l10n_util::GetStringUTF16(IDS_SOME_BUTTON)));
//
// builder_.SetNotifierId({
// message_center::NotifierType::SYSTEM_COMPONENT,
// kFoo,
// NotificationCatalogName::kFooCatalog
// }).SetOptionalFields(optional_data)
// .SetSmallImage(kSettingsIcon)
// .SetWarningLevel(
// message_center::SystemNotificationWarningLevel::WARNING);
// }
//
// void Foo::ShowNotification1() {
// builder_.SetId(kNotificationId1).SetTitleId(IDS_NOTIFICATION1_TITLE)
// .SetMessageId(IDS_NOTIFICATION1_MESSAGE)
// .SetDelegate(
// base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
// base::BindRepeating(&OnClicked,
// some_arg)))
// .Build(false);
// }
//
// void Foo::ShowNotification2() {
// builder_.SetId(kNotificationId2).SetTitleId(IDS_NOTIFICATION2_TITLE)
// .SetMessageId(IDS_NOTIFICATION2_MESSAGE)
// .SetDelegate(
// base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
// base::BindRepeating(&OnClicked,
// other_arg)))
// .Build(false);
// }
//
// The builder can also be used when putting together the information for a
// notification and the information comes from several different branches
// depending on external factors. Instead of storing all the results in
// variables the corresponding builder methoder can be used directly.
//
// Example to reduce keeping uninitialized variables:
// void CreateNotification() {
// std::u16string message;
// if(SomeCondition()) {
// message = l10n_util::GetStringFUTF16(IDS_MESSAGE_WITH_ARGS, GetArgs());
// } else {
// message = l10n_util::GetStringUTF16(IDS_MESSAGE_NO_ARGS);
// }
//
// AddNotification(CreateSystemNotificationPtr(
// message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE,
// kNotificationId,
// l10n_util::GetStringUTF16(IDS_TITLE),
// message,
// ....
// ));
//
// Create the notification like so:
// void CreateNotification() {
// SystemNotificationBuilder builder;
// if(SomeCondition()) {
// builder.SetMessageWithArgs(IDS_MESSAGE_WITH_ARGS, GetArgs());
// } else {
// builder.SetMessageId(IDS_MESSAGE_NO_ARGS);
// }
//
// AddNotification(
// builder.SetId(kNotificationId).SetTitle(IDS_TITLE).BuildPtr(false));
// }
class ASH_PUBLIC_EXPORT SystemNotificationBuilder {
public:
SystemNotificationBuilder();
SystemNotificationBuilder(SystemNotificationBuilder&&);
SystemNotificationBuilder& operator=(SystemNotificationBuilder&&);
~SystemNotificationBuilder();
// Set the notification type.
// Default: `message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE`.
SystemNotificationBuilder& SetType(message_center::NotificationType type);
// Change the ID of the notification. This method has to be called before
// calling `Build()`/`BuildPtr()` with `id` being a non-empty value.
SystemNotificationBuilder& SetId(const std::string& id);
// Set a string title.
// Default: ""
SystemNotificationBuilder& SetTitle(const std::u16string& title);
// Provide the IDS value for the title, it will be converted to a localized
// string.
SystemNotificationBuilder& SetTitleId(const int title_id);
// Provide the IDS value for a title with replaceable arguments. The `args`
// will be used to replace placeholders in the `title_id`.
SystemNotificationBuilder& SetTitleWithArgs(
const int title_id,
const std::vector<std::u16string>& args);
// Set a string as message/body.
// Default: ""
SystemNotificationBuilder& SetMessage(const std::u16string& message);
// Provide the IDS value for the message/body, it will be converted to a
// localized string.
SystemNotificationBuilder& SetMessageId(const int message_id);
// Provide the IDS value for a message/body with replaceable arguments. The
// `args` will be used to replace placeholders in the `message_id`.
SystemNotificationBuilder& SetMessageWithArgs(
const int message_id,
const std::vector<std::u16string>& args);
// Set the display source.
// Default: ""
SystemNotificationBuilder& SetDisplaySource(
const std::u16string& display_source);
// Set the origin URL that requested the notification.
// Default: Empty, invalid URL
SystemNotificationBuilder& SetOriginUrl(const GURL& origin_url);
// Set the notifier ID.
// Default: Invalid NotifierId
SystemNotificationBuilder& SetNotifierId(
const message_center::NotifierId& notifier_id);
// Set the catalog name of the NotifierId. This will generate a NotifierId
// together with the value passed to `SetId()` when `Build()` is called.
// Even if the catalog name is set through this method, any call to
// `SetNotifierId()` will take precedence. Default: kNone
SystemNotificationBuilder& SetCatalogName(
NotificationCatalogName catalog_name);
// Set the delegate that will receive events for this notification.
// Default: nullptr
SystemNotificationBuilder& SetDelegate(
scoped_refptr<message_center::NotificationDelegate> delegate);
// Set the small image shown in the notification.
// Default: kNoneIcon
SystemNotificationBuilder& SetSmallImage(const gfx::VectorIcon& small_image);
// Set additional optional fields.
// Default: Default constructed `message_center::RichNotificationData`
SystemNotificationBuilder& SetOptionalFields(
const message_center::RichNotificationData& optional_fields);
// Returns currently set optional fields.
const message_center::RichNotificationData& GetOptionalFields();
// Set the warning level.
// Default: `message_center::SystemNotificationWarningLevel::NORMAL`
SystemNotificationBuilder& SetWarningLevel(
message_center::SystemNotificationWarningLevel warning_level);
// Create the notification from the currently stored fields.
// Unless `keep_timestamp` is true, the `timestamp` field in the
// `RichNotificationData` instance `optional_fields_` will be updated to the
// current time inside `Build()`. Keeping the previous `timestamp` is useful
// when `Build()` is used to update an existing notification.
message_center::Notification Build(bool keep_timestamp);
// Create a owning pointer of a notification from the currently stored fields.
// Unless `keep_timestamp` is true, the `timestamp` field in the
// `RichNotificationData` instance `optional_fields_` will be updated to the
// current time inside `BuildPtr()`. Keeping the previous `timestamp` is
// useful when `BuildPtr()` is used to update an existing notification.
std::unique_ptr<message_center::Notification> BuildPtr(bool keep_timestamp);
// Get a NotifierId by combining `catalog_name_` and `id_` if `notifier_id_`
// is `std::nullopt`, otherwise returns the value of `notifier_id_`.
// The `notifier_id_` should never be read directly but only through this
// method.
message_center::NotifierId GetNotifierId() const;
private:
message_center::NotificationType type_ =
message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE;
std::string id_;
std::u16string title_;
std::u16string message_;
std::u16string display_source_;
GURL origin_url_;
std::optional<message_center::NotifierId> notifier_id_;
NotificationCatalogName catalog_name_ = NotificationCatalogName::kNone;
scoped_refptr<message_center::NotificationDelegate> delegate_ = nullptr;
raw_ptr<const gfx::VectorIcon> small_image_ = &gfx::kNoneIcon;
message_center::RichNotificationData optional_fields_;
message_center::SystemNotificationWarningLevel warning_level_ =
message_center::SystemNotificationWarningLevel::NORMAL;
};
} // namespace ash
#endif // ASH_PUBLIC_CPP_SYSTEM_NOTIFICATION_BUILDER_H_