Real-time collaboration support for LiveFlow.
This module provides functions to add multi-user collaboration to any LiveFlow-powered LiveView. It handles PubSub messaging, cursor broadcasting, and optional Presence tracking.
Setup
- Call
join/4in your LiveView'smount/3to subscribe to collaboration topics. - Delegate
handle_info/2messages toCollaboration.handle_info/2. - Call
broadcast_change/3when the local user modifies the flow. - Call
broadcast_cursor/3when the local user moves their cursor.
Example
defmodule MyAppWeb.CollabFlowLive do
use MyAppWeb, :live_view
alias LiveFlow.Collaboration
alias LiveFlow.Collaboration.User
def mount(_params, _session, socket) do
user = User.new("user_123", name: "Alice")
flow = MyStore.get_flow()
socket =
socket
|> assign(flow: flow)
|> Collaboration.join("flow:room-1", user, pubsub: MyApp.PubSub)
{:ok, socket}
end
def handle_info(msg, socket) do
case Collaboration.handle_info(msg, socket) do
{:ok, socket} -> {:noreply, socket}
:ignore -> {:noreply, socket}
end
end
def handle_event("lf:node_change", %{"changes" => changes}, socket) do
flow = apply_node_changes(socket.assigns.flow, changes)
socket = Collaboration.broadcast_change(socket, {:node_changes, changes})
{:noreply, assign(socket, flow: flow)}
end
endOptions for join/4
:pubsub- (required) The PubSub module to use (e.g.,MyApp.PubSub):presence- (optional) A Phoenix.Presence module for tracking online users:presence_topic- (optional) Custom presence topic. Defaults to"#{topic}:presence"
Summary
Functions
Applies a remote change to the local flow state.
Broadcasts a flow change to all other users in the session.
Broadcasts the local user's cursor position to other users.
Broadcasts intermediate drag positions to other users.
Handles incoming PubSub and Presence messages for collaboration.
Joins a collaborative flow session.
Leaves the collaborative session.
Renders a list of online users with colored badges.
Functions
@spec apply_remote_change(LiveFlow.State.t(), tuple()) :: LiveFlow.State.t()
Applies a remote change to the local flow state.
This is a pure function — it takes a flow and a change tuple, and returns the updated flow.
@spec broadcast_change(Phoenix.LiveView.Socket.t(), tuple()) :: Phoenix.LiveView.Socket.t()
Broadcasts a flow change to all other users in the session.
The change is a tuple describing what changed. Supported change types:
{:node_changes, changes}- Node position/dimension/remove changes{:edge_add, edge}- A new edge was added{:edge_remove, id}- An edge was removed{:delete_selected, node_ids, edge_ids}- Bulk deletion{:flow_reset, flow}- The entire flow was replaced
@spec broadcast_cursor(Phoenix.LiveView.Socket.t(), number(), number()) :: Phoenix.LiveView.Socket.t()
Broadcasts the local user's cursor position to other users.
Coordinates should be in flow-space (not screen-space).
@spec broadcast_drag_move(Phoenix.LiveView.Socket.t(), list()) :: Phoenix.LiveView.Socket.t()
Broadcasts intermediate drag positions to other users.
Uses a lightweight message type that receivers handle client-side (DOM update only, no flow state change or re-render) for maximum performance during live dragging.
@spec handle_info(term(), Phoenix.LiveView.Socket.t()) :: {:ok, Phoenix.LiveView.Socket.t()} | :ignore
Handles incoming PubSub and Presence messages for collaboration.
Returns {:ok, socket} if the message was handled, or :ignore if
the message is not a collaboration message.
Delegates to your LiveView's handle_info/2:
def handle_info(msg, socket) do
case Collaboration.handle_info(msg, socket) do
{:ok, socket} -> {:noreply, socket}
:ignore -> {:noreply, socket}
end
end
@spec join( Phoenix.LiveView.Socket.t(), String.t(), LiveFlow.Collaboration.User.t(), keyword() ) :: Phoenix.LiveView.Socket.t()
Joins a collaborative flow session.
Subscribes to PubSub topics and optionally tracks Presence. Sets the following assigns on the socket:
:lf_user- TheUserstruct for the current user:lf_topic- The base collaboration topic:lf_pubsub- The PubSub module:lf_presences- Map of tracked presences (empty if Presence is not configured):lf_presence_mod- The Presence module (nil if not configured):lf_presence_topic- The presence topic
@spec leave(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
Leaves the collaborative session.
Unsubscribes from PubSub topics and untracks Presence.
Renders a list of online users with colored badges.
Attributes
:presences- Map of presences fromPresence.list/1(required):current_user- The currentUserstruct to highlight/exclude (required)
Attributes
presences(:map) (required)current_user(LiveFlow.Collaboration.User) (required)