send leaves and joines separated

This commit is contained in:
Berenice Medel 2022-01-27 16:25:21 -06:00
parent 6c3eacf66f
commit 979469d23e
3 changed files with 46 additions and 22 deletions

View file

@ -29,7 +29,12 @@ defmodule LiveBeats.UserTracker do
@impl true
def init(_opts) do
{:ok, schedule_updates(%{})}
{:ok,
schedule_updates(%{
active_users: %{},
user_leaves: [],
user_joins: []
})}
end
@impl true
@ -49,8 +54,14 @@ defmodule LiveBeats.UserTracker do
@impl true
def handle_info(:send_updates, state) do
broadcast_updates(state)
{:noreply, schedule_updates(state)}
leaves = state.user_leaves -- state.user_joins
joins = state.user_joins -- state.user_leaves
broadcast_updates(leaves, joins)
# cleaning joins and leaves for each interval
new_state = %{state | user_leaves: [], user_joins: []}
{:noreply, schedule_updates(new_state)}
end
defp schedule_updates(state) do
@ -58,17 +69,23 @@ defmodule LiveBeats.UserTracker do
state
end
defp handle_join(state, presence) do
if Map.has_key?(state, presence.user.id) do
defp handle_join(state, %{user: user}) do
if Map.has_key?(state.active_users, user.id) do
state
else
Map.put_new(state, presence.user.id, presence.user)
updated_active_users = Map.put_new(state.active_users, user.id, user)
updated_user_joins = [user | state.user_joins]
%{state | active_users: updated_active_users, user_joins: updated_user_joins}
end
end
defp handle_leave(state, presence) do
if Map.has_key?(state, presence.user.id) and presence.metas == [] do
Map.delete(state, presence.user.id)
defp handle_leave(state, %{user: user, metas: metas}) do
if Map.has_key?(state.active_users, user.id) and metas == [] do
updated_active_users = Map.delete(state.active_users, user.id)
updated_user_leaves = [user | state.user_leaves]
%{state | active_users: updated_active_users, user_leaves: updated_user_leaves}
else
state
end
@ -78,15 +95,15 @@ defmodule LiveBeats.UserTracker do
"active_users"
end
defp broadcast_updates(state) do
defp broadcast_updates(leaves, joins) do
Phoenix.PubSub.local_broadcast(
@pubsub,
topic(),
{LiveBeats.UserTracker, %{active_users: list_users(state)}}
{LiveBeats.UserTracker, %{user_leaves: leaves, user_joins: joins}}
)
end
defp list_users(state) do
Enum.map(state, fn {_key, value} -> value end)
Enum.map(state.active_users, fn {_key, value} -> value end)
end
end

View file

@ -8,19 +8,13 @@ defmodule LiveBeatsWeb.Nav do
UserTracker.subscribe()
end
socket =
socket
|> assign(:active_users, UserTracker.list_active_users())
|> assign(:region, System.get_env("FLY_REGION"))
|> attach_hook(:active_tab, :handle_params, &handle_active_tab_params/3)
|> attach_hook(:ping, :handle_event, &handle_event/3)
|> attach_hook(:actie_users, :handle_info, fn
{LiveBeats.UserTracker, %{active_users: users}}, socket ->
{:halt, assign(socket, :active_users, users)}
_params, socket ->
{:cont, socket}
end)
|> attach_hook(:active_users, :handle_info, &handle_info/2)
{:cont, socket}
end
@ -49,6 +43,19 @@ defmodule LiveBeatsWeb.Nav do
defp handle_event(_, _, socket), do: {:cont, socket}
defp handle_info({UserTracker, %{user_leaves: leaves, user_joins: joins}}, socket) do
updated_socket =
Enum.reduce(leaves, socket, fn user, socket ->
socket
|> push_event("remove-el", %{id: "mobile-active-users-container-#{user.id}"})
|> push_event("remove-el", %{id: "desktop-active-users-container-#{user.id}"})
end)
{:halt, update(updated_socket, :active_users, &(joins ++ &1))}
end
defp handle_info(_params, socket), do: {:cont, socket}
defp current_user_profile_username(socket) do
if user = socket.assigns.current_user do
user.username

View file

@ -17,13 +17,13 @@ defmodule LiveBeatsWeb.LayoutView do
class="mt-1 space-y-1"
role="group"
aria-labelledby={@id}
id="listening-now"
id={"#{@id}-container"}
phx-update="prepend"
>
<%= for user <- @users do %>
<.link navigate={profile_path(user)}
class="group flex items-center px-3 py-2 text-base leading-5 font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50"
id={"active-user#{user.id}"}
id={"#{@id}-#{user.id}"}
>
<span class="w-2.5 h-2.5 mr-4 bg-indigo-500 rounded-full" aria-hidden="true"></span>
<span class="truncate">