# `MishkaCmsBuilder.Presence`
[🔗](https://github.com/mishka-group/mishka_cms_builder/blob/v0.0.1-alpha.2/lib/mishka_cms_builder/presence.ex#L5)

Who else is in this editing session — real `Phoenix.Presence` on the session's own PubSub topic.

The prototype drew three hardcoded avatars (JD, AB, CD). That is worse than showing none: it tells
an author their colleagues are watching when nobody is, and it hides the one case that actually
matters — two people editing the same page, where the editor is last-write-wins at the op level.

Tracking costs nothing here because the topic already exists: both LiveViews of a session are
subscribed to it for document updates, so presence rides along.

# `child_spec`

# `display_name`

```elixir
@spec display_name(map() | nil) :: String.t()
```

A display name for a review byline: the local part of the address, `"Someone"` with no user.

Accounts carry no separate name field, so the address is what there is. The domain is dropped
because a comment thread reads better as "ada.love" than as a full address.

# `editors`

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

Everyone currently in the session, one entry per person however many tabs they have open.

# `fetch`

# `fetchers_pids`

# `get_by_key`

# `initials`

```elixir
@spec initials(map()) :: String.t()
```

Two letters for an avatar chip, from the local part of an email: `"ada.love@x.com"` gives `"AL"`.

An address is an `Ash.CiString`, not a binary, so it is stringified rather than guarded on —
guarding on `is_binary/1` silently produced "?" for every real user.

# `join`

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

Announces a user as editing `token`. Safe to call with no user — an anonymous mount tracks nothing.

The entry carries the user's id, initials and whether it is a master, never its email.

# `list`

# `name`

```elixir
@spec name(map() | nil, map() | nil) :: String.t()
```

Who `user` is to `viewer`: their address when `viewer` may see it, "Master" for a master when not,
"Unknown" for anyone else — what `MishkaCmsBuilderWeb.Templates.ReviewComments` writes on a note by
them, so a person's avatar and their notes are named alike.

# `others`

```elixir
@spec others(String.t(), map() | nil) :: [map()]
```

Everyone except `user` — the avatars worth showing, since your own presence is not news.

A master's avatar reads the first letter of `MishkaCmsCore.Accounts.Helper.label(:master)`, "M",
unless `user` is a master too.

Each entry also carries `:name`, who it is as `user` may call them — the same answer a review note's
byline gives (`name/2`): the address of somebody `user` may see, "Master" for a master a site user
may not. Two people with one set of initials are told apart by it. It is read from the accounts,
in one read for the whole session, because the entry itself carries no address.

# `track`

# `track`

# `untrack`

# `untrack`

# `update`

# `update`

---

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