Skip to main content

lib/omni/ui/notification.ex

defmodule Omni.UI.Notification do
  @moduledoc """
  A single notification shown in the Omni.UI toaster.

  Built via `Omni.UI.notify/2` or `Omni.UI.notify/3`. The id is generated on
  construction and used by the stream + FIFO-cap bookkeeping.
  """

  @typedoc "Notification severity."
  @type level :: :info | :success | :warning | :error

  @typedoc "A notification struct with id, level, message, and auto-dismiss timeout."
  @type t :: %__MODULE__{
          id: integer(),
          level: level(),
          message: String.t(),
          timeout: non_neg_integer()
        }

  @default_timeout 20_000

  @enforce_keys [:id, :level, :message, :timeout]
  defstruct [:id, :level, :message, :timeout]

  @doc """
  Builds a notification.

  ## Options

    * `:timeout` — ms until auto-dismiss (default `#{@default_timeout}`).
  """
  @spec new(level(), String.t(), keyword()) :: t()
  def new(level, message, opts \\ [])
      when level in [:info, :success, :warning, :error] and is_binary(message) do
    %__MODULE__{
      id: System.unique_integer([:positive]),
      level: level,
      message: message,
      timeout: Keyword.get(opts, :timeout, @default_timeout)
    }
  end
end