phoenix-liveview-counter-tutorial
phoenix-liveview-counter-tutorial copied to clipboard
initial_present needs to be run before subscribing to @presence_topic to pass the test
right now the suggested code to add on the Presence part is
defmodule CounterWeb.Counter do
use CounterWeb, :live_view
alias Counter.Count
alias Phoenix.PubSub
+ alias Counter.Presence
@topic Count.topic
+ @presence_topic "presence"
def mount(_params, _session, socket) do
PubSub.subscribe(Counter.PubSub, @topic)
+ Presence.track(self(), @presence_topic, socket.id, %{})
+ CounterWeb.Endpoint.subscribe(@presence_topic)
+
+ initial_present =
+ Presence.list(@presence_topic)
+ |> map_size
+ {:ok, assign(socket, val: Count.current(), present: initial_present) }
- {:ok, assign(socket, val: Count.current()) }
end
def handle_event("inc", _, socket) do
{:noreply, assign(socket, :val, Count.incr())}
end
def handle_event("dec", _, socket) do
{:noreply, assign(socket, :val, Count.decr())}
end
def handle_info({:count, count}, socket) do
{:noreply, assign(socket, val: count)}
end
+ def handle_info(
+ %{event: "presence_diff", payload: %{joins: joins, leaves: leaves}},
+ %{assigns: %{present: present}} = socket
+ ) do
+ new_present = present + map_size(joins) - map_size(leaves)
+
+ {:noreply, assign(socket, :present, new_present)}
+ end
def render(assigns) do
~H"""
<.live_component module={CounterComponent} id="counter" val={@val} />
+ <.live_component module={PresenceComponent} id="presence" present={@present} />
"""
end
end
where it should be
defmodule CounterWeb.Counter do
use CounterWeb, :live_view
alias Counter.Count
alias Phoenix.PubSub
+ alias Counter.Presence
@topic Count.topic
+ @presence_topic "presence"
def mount(_params, _session, socket) do
PubSub.subscribe(Counter.PubSub, @topic)
+ Presence.track(self(), @presence_topic, socket.id, %{})
+ initial_present =
+ Presence.list(@presence_topic)
+ |> map_size
+ CounterWeb.Endpoint.subscribe(@presence_topic)
+ {:ok, assign(socket, val: Count.current(), present: initial_present) }
- {:ok, assign(socket, val: Count.current()) }
end
def handle_event("inc", _, socket) do
{:noreply, assign(socket, :val, Count.incr())}
end
def handle_event("dec", _, socket) do
{:noreply, assign(socket, :val, Count.decr())}
end
def handle_info({:count, count}, socket) do
{:noreply, assign(socket, val: count)}
end
+ def handle_info(
+ %{event: "presence_diff", payload: %{joins: joins, leaves: leaves}},
+ %{assigns: %{present: present}} = socket
+ ) do
+ new_present = present + map_size(joins) - map_size(leaves)
+
+ {:noreply, assign(socket, :present, new_present)}
+ end
def render(assigns) do
~H"""
<.live_component module={CounterComponent} id="counter" val={@val} />
+ <.live_component module={PresenceComponent} id="presence" present={@present} />
"""
end
end
where initial_present is before subscribing to @presence_topic. this also referred to the actual code on the repo. if it's after, the test won't pass for handle_info/2 presence updates.