Move presence tracking to player

This commit is contained in:
Chris McCord 2022-01-12 12:27:30 -05:00
parent a30e311645
commit 924da28b6b
5 changed files with 67 additions and 69 deletions

View file

@ -83,9 +83,9 @@ defmodule Phoenix.Presence.Client do
defp untrack_pid(state, pid, topic, key) do defp untrack_pid(state, pid, topic, key) do
if Map.has_key?(state.topics, topic) do if Map.has_key?(state.topics, topic) do
state.presence_mod.untrack(pid, topic, key) state.presence_mod.untrack(pid, topic, key)
else
state
end end
state
end end
defp merge_diff(state, topic, %{leaves: leaves, joins: joins}) do defp merge_diff(state, topic, %{leaves: leaves, joins: joins}) do

View file

@ -4,6 +4,31 @@ defmodule LiveBeats.PresenceClient do
@presence LiveBeatsWeb.Presence @presence LiveBeatsWeb.Presence
@pubsub LiveBeats.PubSub @pubsub LiveBeats.PubSub
alias LiveBeats.MediaLibrary
def track(%MediaLibrary.Profile{} = profile, current_user_id) do
Phoenix.Presence.Client.track(
"proxy:" <> topic(profile),
current_user_id,
%{}
)
end
def untrack(%MediaLibrary.Profile{} = profile, current_user_id) do
Phoenix.Presence.Client.untrack(
"proxy:" <> topic(profile),
current_user_id
)
end
def subscribe(%MediaLibrary.Profile{} = profile) do
Phoenix.PubSub.subscribe(@pubsub, topic(profile))
end
def list(%MediaLibrary.Profile{} = profile) do
list("proxy:" <> topic(profile))
end
def list(topic) do def list(topic) do
@presence.list(topic) @presence.list(topic)
end end
@ -16,42 +41,21 @@ defmodule LiveBeats.PresenceClient do
@impl Phoenix.Presence.Client @impl Phoenix.Presence.Client
def handle_join(topic, _key, presence, state) do def handle_join(topic, _key, presence, state) do
active_users_topic = local_broadcast(topic, {__MODULE__, %{user_joined: presence}})
topic
|> profile_identifier()
|> active_users_topic()
Phoenix.PubSub.local_broadcast(
@pubsub,
active_users_topic,
{__MODULE__, %{user_joined: presence}}
)
{:ok, state} {:ok, state}
end end
@impl Phoenix.Presence.Client @impl Phoenix.Presence.Client
def handle_leave(topic, _key, presence, state) do def handle_leave(topic, _key, presence, state) do
active_users_topic = local_broadcast(topic, {__MODULE__, %{user_left: presence}})
topic
|> profile_identifier()
|> active_users_topic()
Phoenix.PubSub.local_broadcast(
@pubsub,
active_users_topic,
{__MODULE__, %{user_left: presence}}
)
{:ok, state} {:ok, state}
end end
defp active_users_topic(user_id) do defp topic(%MediaLibrary.Profile{} = profile) do
"active_users:#{user_id}" "active_profiles:#{profile.user_id}"
end end
defp profile_identifier(topic) do defp local_broadcast("proxy:" <> topic, payload) do
"active_profile:" <> identifier = topic Phoenix.PubSub.local_broadcast(@pubsub, topic, payload)
identifier
end end
end end

View file

@ -11,15 +11,30 @@ defmodule LiveBeatsWeb.Presence do
import Phoenix.LiveView.Helpers import Phoenix.LiveView.Helpers
import LiveBeatsWeb.LiveHelpers import LiveBeatsWeb.LiveHelpers
@pubsub LiveBeats.PubSub
alias LiveBeats.Accounts alias LiveBeats.{Accounts, MediaLibrary}
def subscribe(%MediaLibrary.Profile{} = profile) do
LiveBeats.PresenceClient.subscribe(profile)
end
def fetch(_topic, presences) do
users =
presences
|> Map.keys()
|> Accounts.get_users_map()
|> Enum.into(%{})
for {key, %{metas: metas}} <- presences, into: %{} do
{key, %{metas: metas, user: users[String.to_integer(key)]}}
end
end
def listening_now(assigns) do def listening_now(assigns) do
~H""" ~H"""
<!-- users --> <!-- users -->
<div class="px-4 mt-6 sm:px-6 lg:px-8"> <div class="px-4 mt-6 sm:px-6 lg:px-8">
<h2 class="text-gray-500 text-xs font-medium uppercase tracking-wide">Here now</h2> <h2 class="text-gray-500 text-xs font-medium uppercase tracking-wide">Listening now</h2>
<ul <ul
id="listening-now" id="listening-now"
phx-update="prepend" phx-update="prepend"
@ -41,24 +56,4 @@ defmodule LiveBeatsWeb.Presence do
</div> </div>
""" """
end end
def fetch(_topic, presences) do
users =
presences
|> Map.keys()
|> Accounts.get_users_map()
|> Enum.into(%{})
for {key, %{metas: metas}} <- presences, into: %{} do
{key, %{metas: metas, user: users[String.to_integer(key)]}}
end
end
def subscribe(user_id) do
Phoenix.PubSub.subscribe(@pubsub, topic(user_id))
end
defp topic(profile) do
"active_users:#{profile.user_id}"
end
end end

View file

@ -142,16 +142,22 @@ defmodule LiveBeatsWeb.PlayerLive do
defp switch_profile(socket, nil) do defp switch_profile(socket, nil) do
current_user = Accounts.update_active_profile(socket.assigns.current_user, nil) current_user = Accounts.update_active_profile(socket.assigns.current_user, nil)
if profile = connected?(socket) and socket.assigns.profile do
LiveBeats.PresenceClient.untrack(profile, current_user.id)
end
socket socket
|> assign(current_user: current_user) |> assign(current_user: current_user)
|> assign_profile(nil) |> assign_profile(nil)
end end
defp switch_profile(socket, profile_user_id) do defp switch_profile(socket, profile_user_id) do
%{current_user: current_user} = socket.assigns
profile = get_profile(profile_user_id) profile = get_profile(profile_user_id)
if profile && connected?(socket) do if profile && connected?(socket) do
current_user = Accounts.update_active_profile(socket.assigns.current_user, profile.user_id) current_user = Accounts.update_active_profile(current_user, profile.user_id)
LiveBeats.PresenceClient.track(profile, current_user.id)
send(self(), :play_current) send(self(), :play_current)
socket socket
@ -258,8 +264,6 @@ defmodule LiveBeatsWeb.PlayerLive do
def handle_info({MediaLibrary, _}, socket), do: {:noreply, socket} def handle_info({MediaLibrary, _}, socket), do: {:noreply, socket}
def handle_info(%{event: "presence_diff"}, socket), do: {:noreply, socket}
defp play_song(socket, %Song{} = song, elapsed) do defp play_song(socket, %Song{} = song, elapsed) do
socket socket
|> push_play(song, elapsed) |> push_play(song, elapsed)

View file

@ -88,12 +88,6 @@ defmodule LiveBeatsWeb.ProfileLive do
MediaLibrary.subscribe_to_profile(profile) MediaLibrary.subscribe_to_profile(profile)
Accounts.subscribe(current_user.id) Accounts.subscribe(current_user.id)
LiveBeatsWeb.Presence.subscribe(profile) LiveBeatsWeb.Presence.subscribe(profile)
Phoenix.Presence.Client.track(
topic(profile.user_id),
current_user.id,
%{}
)
end end
active_song_id = active_song_id =
@ -259,13 +253,16 @@ defmodule LiveBeatsWeb.ProfileLive do
end end
defp assign_presences(socket) do defp assign_presences(socket) do
if profile = socket.assigns.profile do
presences = presences =
socket.assigns.profile.user_id profile
|> topic()
|> LiveBeats.PresenceClient.list() |> LiveBeats.PresenceClient.list()
|> Enum.map(fn {_key, meta} -> meta.user end) |> Enum.map(fn {_key, meta} -> meta.user end)
assign(socket, presences: presences) assign(socket, presences: presences)
else
assign(socket, presences: [])
end
end end
defp url_text(nil), do: "" defp url_text(nil), do: ""
@ -274,6 +271,4 @@ defmodule LiveBeatsWeb.ProfileLive do
uri = URI.parse(url_str) uri = URI.parse(url_str)
uri.host <> uri.path uri.host <> uri.path
end end
defp topic(user_id) when is_integer(user_id), do: "active_profile:#{user_id}"
end end