From 463faafe71bae460c49bc1c179b28156992b08ef Mon Sep 17 00:00:00 2001 From: Berenice Medel Date: Thu, 9 Dec 2021 01:29:00 -0600 Subject: [PATCH] Implement handle_leave and handle_join in presence_client - The profile Liveview is subscribed to active_users topic - user_joined and user_left events are sent - Users are added and removed from presences assign --- lib/live_beats/accounts.ex | 4 +++ lib/live_beats/presence/presence_client.ex | 31 +++++++++++++++---- lib/live_beats_web/channels/presence.ex | 9 ++++++ lib/live_beats_web/live/profile_live.ex | 35 ++++++++++++++-------- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/lib/live_beats/accounts.ex b/lib/live_beats/accounts.ex index 9b3070e..7ec1f1a 100644 --- a/lib/live_beats/accounts.ex +++ b/lib/live_beats/accounts.ex @@ -21,6 +21,10 @@ defmodule LiveBeats.Accounts do Repo.all(from u in User, limit: ^Keyword.fetch!(opts, :limit)) end + def list_users_by_ids(user_ids) when is_list(user_ids) do + Repo.all(from u in User, where: u.id in ^user_ids) + end + def lists_users_by_active_profile(id, opts) do Repo.all( from u in User, where: u.active_profile_user_id == ^id, limit: ^Keyword.fetch!(opts, :limit) diff --git a/lib/live_beats/presence/presence_client.ex b/lib/live_beats/presence/presence_client.ex index 0c5cefc..fed70ad 100644 --- a/lib/live_beats/presence/presence_client.ex +++ b/lib/live_beats/presence/presence_client.ex @@ -1,7 +1,8 @@ defmodule LiveBeats.PresenceClient do @behaviour Phoenix.Presence.Client - @presence LiveBeats.Presence + @presence LiveBeatsWeb.Presence + @pubsub LiveBeats.PubSub def start_link(opts) do Phoenix.Presence.Client.start_link(presence: @presence, client: __MODULE__) @@ -16,13 +17,33 @@ defmodule LiveBeats.PresenceClient do {:ok, %{}} end - def handle_join(key, presence, state) do - # can local pubsub to LVs about new join + def handle_join(topic, key, meta, state) do + active_users_topic = + topic + |> profile_identifier() + |> active_users_topic() + + Phoenix.PubSub.broadcast!(@pubsub, active_users_topic, {__MODULE__, %{user_joined: key}}) + {:ok, state} end - def handle_leave(key, presence, state) do - # can local pubsub to LVs about new leave + def handle_leave(topic, key, presence, state) do + active_users_topic = + topic + |> profile_identifier() + |> active_users_topic() + + Phoenix.PubSub.broadcast!(@pubsub, active_users_topic, {__MODULE__, %{user_left: key}}) {:ok, state} end + + defp active_users_topic(user_id) do + "active_users:#{user_id}" + end + + defp profile_identifier(topic) do + "active_profile:" <> identifier = topic + identifier + end end diff --git a/lib/live_beats_web/channels/presence.ex b/lib/live_beats_web/channels/presence.ex index 9378943..adfd407 100644 --- a/lib/live_beats_web/channels/presence.ex +++ b/lib/live_beats_web/channels/presence.ex @@ -10,6 +10,7 @@ defmodule LiveBeatsWeb.Presence do import Phoenix.LiveView.Helpers import LiveBeatsWeb.LiveHelpers + @pubsub LiveBeats.PubSub def listening_now(assigns) do ~H""" @@ -31,4 +32,12 @@ defmodule LiveBeatsWeb.Presence do """ 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 diff --git a/lib/live_beats_web/live/profile_live.ex b/lib/live_beats_web/live/profile_live.ex index c206b36..b9ff901 100644 --- a/lib/live_beats_web/live/profile_live.ex +++ b/lib/live_beats_web/live/profile_live.ex @@ -87,6 +87,7 @@ defmodule LiveBeatsWeb.ProfileLive do if connected?(socket) do MediaLibrary.subscribe_to_profile(profile) Accounts.subscribe(current_user.id) + LiveBeatsWeb.Presence.subscribe(profile) Phoenix.Presence.Client.track(topic(profile.user_id), current_user.id, %{} @@ -146,6 +147,22 @@ defmodule LiveBeatsWeb.ProfileLive do {:noreply, socket} end + def handle_info({LiveBeats.PresenceClient, %{user_joined: user_id}}, socket) do + new_user = Accounts.get_user!(user_id) + updated_presences = + if new_user in socket.assigns.presences do + socket.assigns.presences + else + [new_user | socket.assigns.presences] + end + {:noreply, assign(socket, :presences, updated_presences)} + end + + def handle_info({LiveBeats.PresenceClient, %{user_left: user_id}}, socket) do + updated_presences = socket.assign.presences |> Enum.reject(fn user -> user.id == user_id end) + {:noreply, assign(socket, :presences, updated_presences)} + end + def handle_info({Accounts, %Accounts.Events.ActiveProfileChanged{} = event}, socket) do {:noreply, assign(socket, active_profile_id: event.new_profile_user_id)} end @@ -173,14 +190,6 @@ defmodule LiveBeatsWeb.ProfileLive do def handle_info({Accounts, _}, socket), do: {:noreply, socket} - def handle_info( - %{event: "presence_diff", payload: %{joins: _joins, leaves: _leaves}}, - %{assigns: %{presences: _users}} = socket - ) do - - {:noreply, assign_presences(socket)} - end - defp stop_song(socket, song_id) do SongRowComponent.send_status(song_id, :stopped) @@ -256,11 +265,11 @@ defmodule LiveBeatsWeb.ProfileLive do defp assign_presences(socket) do presences = socket.assigns.profile.user_id |> topic() - |> Presence.list() - |> Enum.map(fn {_user_id, user_data} -> - user_data[:metas] - |> List.first() + |> LiveBeats.PresenceClient.list() + |> Enum.map(fn {user_id, _user_data} -> + user_id end) + |> Accounts.list_users_by_ids() assign(socket, presences: presences) end @@ -272,5 +281,5 @@ defmodule LiveBeatsWeb.ProfileLive do uri.host <> uri.path end - defp topic(user_id) when is_integer(user_id), do: "profile:#{user_id}" + defp topic(user_id) when is_integer(user_id), do: "active_profile:#{user_id}" end