phollyer / elm-phoenix-websocket / Phoenix.Presence

This module can be used to receive Presence messages from your Channels from anywhere in your Elm program without needing to add anything to your Model. That is all it does and all it is intended to do.


type alias Presence =
{ id : String
, metas : List Json.Decode.Value
, user : Json.Decode.Value
, presence : Json.Decode.Value 
}

A type alias representing a Presence on a Channel.

-- MyAppWeb.MyChannel.ex

def handle_info(:after_join, socket) do
  {:ok, _} = Presence.track(socket, socket.assigns.user_id, %{
    online_at: System.os_time(:millisecond)
  })

  push(socket, "presence_state", Presence.list(socket))

  {:noreply, socket}
end

-- MyAppWeb.Presence.ex

defmodule MyAppWeb.Presence do
  use Phoenix.Presence,
    otp_app: :my_app,
    pubsub_server: MyApp.PubSub

  def fetch(_topic, presences) do
    query =
      from u in User,
      where: u.id in ^Map.keys(presences),
      select: {u.id, u}

    users = query |> Repo.all() |> Enum.into(%{})

    for {key, %{metas: metas}} <- presences, into: %{} do
      {key, %{metas: metas, user: users[key]}}
    end
  end
end


type alias PresenceDiff =
{ joins : List Presence
, leaves : List Presence 
}

A type alias representing the joins and leaves on the Channel as they happen.


type alias Topic =
String

A type alias representing the Channel topic id. For example "topic:subTopic".


type InternalError
    = DecoderError String
    | InvalidMessage Topic String

An InternalError should never happen, but if it does, it is because the JS is out of sync with this package.

If you ever receive this message, please raise an issue.


type Msg
    = Join Topic Presence
    | Leave Topic Presence
    | State Topic (List Presence)
    | Diff Topic PresenceDiff
    | InternalError InternalError

All of the Presence messages that can come from the Channel.

If you are using more than one Channel, then you can pattern match on Topic to determine which Channel the Msg relates to.


type alias PortIn msg =
({ topic : Topic
, msg : String
, payload : Json.Encode.Value } -> msg) -> Platform.Sub.Sub ms
)

A type alias representing the port function required to receive a Msg from Phoenix Presence.

You will find this port function in the Port module.

subscriptions : (Msg -> msg) -> PortIn msg -> Platform.Sub.Sub msg

Subscribe to receive incoming Presence Msgs.

import Phoenix.Presence as Presence
import Ports.Phoenix as Port

type Msg
  = PresenceMsg Presence.Msg
  | ...


subscriptions : Model -> Sub Msg
subscriptions _ =
    Presence.subscriptions
        PresenceMsg
        Port.presenceReceiver