Issho.Live (Issho v0.2.0)

Copy Markdown View Source

A LiveView in a room: the same session as a browser's channel or an agent's process, in the LiveView's own process. Presence, awareness, the room's documents and the policy work the same; the room's events reach the LiveView's components with send_update/2, or the LiveView itself.

live_session :default, on_mount: [Issho.Live] do

# In a LiveView or one of its components, once connected:
{:ok, _session} = Issho.Live.join(MyApp.Issho, current_user, "board:42")
{:ok, snapshot} = Issho.Live.open("board:42", "board:42", notify: {MyComponent, "board"})

A component named in notify gets update/2 with an :issho assign for each event, {event, key, payload}:

  • {"tx", document_id, accepted_transaction}: a transaction accepted in a document it opened;
  • {"aware", room, frame}: the others' awareness;
  • {"presence_diff", room, diff}: people who came and went;
  • {"bye", room, reason}: the session ended (revoked, refused).

notify: :self sends them to the LiveView as {Issho.Live, event, key, payload} messages instead.

Grants: rooms the browser joins

A component whose browser half joins the room itself (a text editor, which applies its own changes in the browser) needs a grant: a short token for the room, signed by the LiveView for the actor it authenticated. grant/4 signs it and remembers it, and the hook renews it when the browser asks (the "issho:grant" event, with the room), after asking the policy again, so that a person whose access went away gets no new grant. One grant serves every component of the page in that room.

grant = Issho.Live.grant(MyApp.Issho, current_user, "notebook:7", can: :write)

The components of a LiveView share one session per room: joining a room the LiveView is in already gives the same session.

Join only in a connected LiveView (connected?(socket)): the static render has no process that lasts.

Summary

Functions

Sets this session's awareness state (nil clears it).

This session's own awareness state (an empty map for none).

A grant for the browser to join the room as the actor: %{"room", "token", "can", "self", "socket", "max_channels"}, for a component's browser half. The LiveView renews it when the browser asks. Options: :can (:write or :read), :claims, :on_behalf_of, :socket (the Issho socket's path, "/issho/socket") and :max_channels (that socket's :max_channels_per_transport, 100).

Joins a room as an actor, from this LiveView, or gives the session the LiveView already has there. Options: :can (:write), :claims, :on_behalf_of.

Merges keys into this session's awareness state: for the components of a LiveView that share its session in a room, each setting its own keys (a grid its place, another component its own key).

Opens a document of the room. Options: :notify, a component ({module, id}) or :self, for its transactions and the room's events; and :spec, what the document is if this opens it first (see Issho.Documents.open/4).

The people of the room now: Phoenix.Presence's list, by actor key.

The document's current snapshot, from its authority.

The session id of this LiveView in the room, or nil.

The awareness states of the room's sessions, from every node: %{session_id => %{"key" => actor_key, "state" => state}}, for a component that draws the others itself.

Sends the room's events to a component, or the LiveView, without opening a document.

Commits to an open document: a list of operations (on the document's latest revision) or a whole transaction.

Types

target()

@type target() :: {module(), term()} | :self

Functions

aware(room, state)

@spec aware(String.t(), map() | nil) :: :ok | {:error, term()}

Sets this session's awareness state (nil clears it).

awareness(room)

@spec awareness(String.t()) :: map()

This session's own awareness state (an empty map for none).

grant(instance, actor, room, opts \\ [])

@spec grant(atom(), Issho.Actor.t(), String.t(), keyword()) :: map()

A grant for the browser to join the room as the actor: %{"room", "token", "can", "self", "socket", "max_channels"}, for a component's browser half. The LiveView renews it when the browser asks. Options: :can (:write or :read), :claims, :on_behalf_of, :socket (the Issho socket's path, "/issho/socket") and :max_channels (that socket's :max_channels_per_transport, 100).

join(instance, actor, room, opts \\ [])

@spec join(atom(), Issho.Actor.t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, term()}

Joins a room as an actor, from this LiveView, or gives the session the LiveView already has there. Options: :can (:write), :claims, :on_behalf_of.

merge(room, changes)

@spec merge(String.t(), map()) :: :ok | {:error, term()}

Merges keys into this session's awareness state: for the components of a LiveView that share its session in a room, each setting its own keys (a grid its place, another component its own key).

open(room, document_id, opts \\ [])

@spec open(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}

Opens a document of the room. Options: :notify, a component ({module, id}) or :self, for its transactions and the room's events; and :spec, what the document is if this opens it first (see Issho.Documents.open/4).

people(room)

@spec people(String.t()) :: map()

The people of the room now: Phoenix.Presence's list, by actor key.

read(room, document_id)

@spec read(String.t(), String.t()) :: {:ok, map()} | {:error, term()}

The document's current snapshot, from its authority.

session_id(room)

@spec session_id(String.t()) :: String.t() | nil

The session id of this LiveView in the room, or nil.

states(room)

@spec states(String.t()) :: map()

The awareness states of the room's sessions, from every node: %{session_id => %{"key" => actor_key, "state" => state}}, for a component that draws the others itself.

subscribe(key, target)

@spec subscribe(String.t(), target()) :: true

Sends the room's events to a component, or the LiveView, without opening a document.

transact(room, document_id, ops)

@spec transact(String.t(), String.t(), [term()] | map()) ::
  {:ok, map()} | {:error, term()}

Commits to an open document: a list of operations (on the document's latest revision) or a whole transaction.