chromium/chromeos/ash/components/phonehub/notification.h

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

#ifndef CHROMEOS_ASH_COMPONENTS_PHONEHUB_NOTIFICATION_H_
#define CHROMEOS_ASH_COMPONENTS_PHONEHUB_NOTIFICATION_H_

#include <stdint.h>

#include <optional>
#include <ostream>
#include <string>
#include <unordered_map>

#include "base/containers/flat_map.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chromeos/ash/components/phonehub/proto/phonehub_api.pb.h"
#include "ui/gfx/image/image.h"

// Serves the same purpose as a forward declare to avoid an extra include.
typedef uint32_t SkColor;

namespace ash::phonehub {

// A notification generated on the phone, whose contents are transferred to
// Chrome OS via a Phone Hub connection. Notifications in Phone Hub support
// inline reply and images.
class Notification {
 public:
  // Describes the app which generates a notification.
  struct AppMetadata {
    AppMetadata(const std::u16string& visible_app_name,
                const std::string& package_name,
                const gfx::Image& color_icon,
                const std::optional<gfx::Image>& monochrome_icon_mask,
                const std::optional<SkColor> icon_color,
                bool icon_is_monochrome,
                int64_t user_id,
                proto::AppStreamabilityStatus app_streamability_status =
                    proto::AppStreamabilityStatus::STREAMABLE);
    ~AppMetadata();
    AppMetadata(const AppMetadata& other);
    AppMetadata& operator=(const AppMetadata& other);

    bool operator==(const AppMetadata& other) const;
    bool operator!=(const AppMetadata& other) const;

    static AppMetadata FromValue(const base::Value::Dict& value);
    base::Value::Dict ToValue() const;

    std::u16string visible_app_name;
    std::string package_name;
    // The |color_icon| is the icon with it's original color whereas the
    // |monochrome_icon| is the icon with a monochrome or system theme mask.
    gfx::Image color_icon;
    std::optional<gfx::Image> monochrome_icon_mask;
    // Color for a monochrome icon. Leave empty to use the system theme default.
    std::optional<SkColor> icon_color;
    // Whether the icon image is just a mask used to generate a monochrome icon.
    bool icon_is_monochrome;
    int64_t user_id;
    proto::AppStreamabilityStatus app_streamability_status;
  };

  // Interaction behavior for integration with other features.
  enum class InteractionBehavior {
    // Default value. No interactions available.
    kNone,

    // Notification can be opened.
    kOpenable,
  };

  // Interaction behavior for integration with other features.
  enum class ActionType {
    // Default value. No interactions available.
    kNone,

    // User can click the reply button for the conversation type notification.
    kInlineReply,

    // User can click answer button for the incoming call notification.
    kAnswer,

    // User can click decline button for the incoming call notification.
    kDecline,

    // User can click hang up button for the ongoing call notification.
    kHangup,
  };

  enum class Category {
    // Default value..
    kNone,

    // User can click the reply button for the conversation type notification.
    kConversation,

    // The incoming call notification with answer and decline action buttons.
    // User can click the answer button to open the App streaming window to
    // answer the call and click the decline button to decline call directly.
    kIncomingCall,

    // The ongoing call notification with a hangup action button. User can
    // click on the body of notification to open the App streaming window to
    // resume the call.
    kOngoingCall,

    // The Screening call notification with a screening call action button.
    kScreenCall,
  };

  // Notification importance; for more details, see
  // https://developer.android.com/reference/android/app/NotificationManager.
  enum class Importance {
    // Older versions of Android do not specify an importance level.
    kUnspecified,

    // Does not show in the Android notification shade.
    kNone,

    // Shows in the Android notification shade, below the fold.
    kMin,

    // Shows in the Android notification shade and potentially status bar, but
    // is not audibly intrusive.
    kLow,

    // Shows in the Android notification shade and status bar and makes noise,
    // but does not visually intrude.
    kDefault,

    // Shows in the Android notification shade and status bar, makes noise, and
    // "peeks" down onto the screen when received.
    kHigh
  };

  // Note: A notification should include at least one of |title|,
  // |text_content|, and |shared_image| so that it can be rendered in the UI.
  Notification(
      int64_t id,
      const AppMetadata& app_metadata,
      const base::Time& timestamp,
      Importance importance,
      Notification::Category category,
      const base::flat_map<Notification::ActionType, int64_t>& action_id_map,
      InteractionBehavior interaction_behavior,
      const std::optional<std::u16string>& title = std::nullopt,
      const std::optional<std::u16string>& text_content = std::nullopt,
      const std::optional<gfx::Image>& shared_image = std::nullopt,
      const std::optional<gfx::Image>& contact_image = std::nullopt);
  Notification(const Notification& other);
  ~Notification();

  bool operator<(const Notification& other) const;
  bool operator==(const Notification& other) const;
  bool operator!=(const Notification& other) const;

  int64_t id() const { return id_; }
  const AppMetadata& app_metadata() const { return app_metadata_; }
  base::Time timestamp() const { return timestamp_; }
  Importance importance() const { return importance_; }
  Notification::Category category() const { return category_; }
  base::flat_map<Notification::ActionType, int64_t> action_id_map() const {
    return action_id_map_;
  }
  InteractionBehavior interaction_behavior() const {
    return interaction_behavior_;
  }
  const std::optional<std::u16string>& title() const { return title_; }
  const std::optional<std::u16string>& text_content() const {
    return text_content_;
  }
  const std::optional<gfx::Image>& shared_image() const {
    return shared_image_;
  }
  const std::optional<gfx::Image>& contact_image() const {
    return contact_image_;
  }

 private:
  int64_t id_;
  AppMetadata app_metadata_;
  base::Time timestamp_;
  Importance importance_;
  Notification::Category category_;
  base::flat_map<Notification::ActionType, int64_t> action_id_map_;
  InteractionBehavior interaction_behavior_;
  std::optional<std::u16string> title_;
  std::optional<std::u16string> text_content_;
  std::optional<gfx::Image> shared_image_;
  std::optional<gfx::Image> contact_image_;
};

std::ostream& operator<<(std::ostream& stream,
                         const Notification::AppMetadata& app_metadata);
std::ostream& operator<<(std::ostream& stream,
                         Notification::Importance importance);
std::ostream& operator<<(std::ostream& stream,
                         const Notification& notification);
std::ostream& operator<<(std::ostream& stream,
                         const Notification::InteractionBehavior behavior);
std::ostream& operator<<(std::ostream& stream,
                         const Notification::Category category);

}  // namespace ash::phonehub

#endif  // CHROMEOS_ASH_COMPONENTS_PHONEHUB_NOTIFICATION_H_