# `PhiaUi.Collab.CollabPresence`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/collab/collab_presence.ex#L1)

Phoenix.Presence wrapper for collaborative editing sessions.

Provides standardized user presence tracking with cursor positions,
typing indicators, and idle detection. Compatible with the
`presence_avatars` and `connection_status` PhiaUI components.

## Setup

Configure the PubSub name in your config:

    config :phia_ui, :collab_pubsub, MyApp.PubSub

Add `PhiaUi.Collab.Supervisor` to your supervision tree — it starts
the required `Registry` and `DynamicSupervisor`. This Presence module
must also be started in your supervision tree (it runs its own tracker):

    children = [
      PhiaUi.Collab.Supervisor,
      PhiaUi.Collab.CollabPresence
    ]

## Topic Convention

Use `"collab:room:<room_id>"` as the presence topic to match the
channel topic convention used by `PhiaUi.Editor.CollabChannel`.

## User Metadata

Each tracked user carries standardized metadata:

  - `:name` — display name (default `"Anonymous"`)
  - `:color` — hex color for cursor/avatar (default `"#6366F1"`)
  - `:avatar_url` — optional avatar image URL
  - `:cursor` — `%{x: number, y: number}` or nil
  - `:typing` — boolean typing indicator
  - `:idle_since` — UTC datetime when user became idle, or nil
  - `:joined_at` — UTC datetime when user was first tracked

# `user_meta`

```elixir
@type user_meta() :: %{
  name: String.t(),
  color: String.t(),
  avatar_url: String.t() | nil,
  cursor: map() | nil,
  typing: boolean(),
  idle_since: DateTime.t() | nil,
  joined_at: DateTime.t()
}
```

# `child_spec`

# `fetch`

# `fetchers_pids`

# `get_by_key`

# `list`

# `mark_idle`

```elixir
@spec mark_idle(String.t(), String.t()) :: {:ok, binary()} | {:error, term()}
```

Mark a user as idle.

Sets `idle_since` to the current UTC time and clears the typing flag.

# `online_users`

```elixir
@spec online_users(String.t()) :: [map()]
```

Returns a formatted list of online users compatible with the `presence_avatars` component.

Each user map contains: `:id`, `:name`, `:color`, `:avatar_url`, `:status`, `:cursor`, `:typing`.
The `:status` field is `"online"` or `"idle"` based on the `idle_since` metadata.

# `track`

# `track`

# `track_user`

```elixir
@spec track_user(String.t(), String.t(), map()) :: {:ok, binary()} | {:error, term()}
```

Track a user in a collaboration room.

Normalizes the provided metadata into the standard presence schema.
Missing fields receive sensible defaults.

## Parameters
  - `topic` — the presence topic (e.g., `"collab:room:doc-123"`)
  - `user_id` — unique user identifier (string)
  - `meta` — user metadata map; recognized keys: `:name`, `:color`, `:avatar_url`

## Examples

    iex> CollabPresence.track_user("collab:room:doc-1", "user-42", %{name: "Alice", color: "#EF4444"})
    {:ok, _ref}

# `typing_users`

```elixir
@spec typing_users(String.t()) :: [map()]
```

Returns only users who are currently typing.

# `untrack`

# `untrack`

# `update`

# `update`

# `update_cursor`

```elixir
@spec update_cursor(String.t(), String.t(), map()) ::
  {:ok, binary()} | {:error, term()}
```

Update the cursor position for a tracked user.

Also clears the idle state, since cursor movement implies activity.

## Parameters
  - `topic` — the presence topic
  - `user_id` — the user whose cursor moved
  - `cursor` — a map with position data (e.g., `%{x: 120, y: 340}`)

# `update_typing`

```elixir
@spec update_typing(String.t(), String.t(), boolean()) ::
  {:ok, binary()} | {:error, term()}
```

Set or clear the typing indicator for a user.

## Parameters
  - `topic` — the presence topic
  - `user_id` — the user who started or stopped typing
  - `typing?` — `true` when typing, `false` when stopped

# `user_count`

```elixir
@spec user_count(String.t()) :: non_neg_integer()
```

Returns the count of distinct online users in the topic.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
