diff --git a/lib/live_beats/user_tracker.ex b/lib/live_beats/user_tracker.ex
index 2821ccf..3a2151c 100644
--- a/lib/live_beats/user_tracker.ex
+++ b/lib/live_beats/user_tracker.ex
@@ -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
diff --git a/lib/live_beats_web/live/nav.ex b/lib/live_beats_web/live/nav.ex
index 26b5d1a..82997b9 100644
--- a/lib/live_beats_web/live/nav.ex
+++ b/lib/live_beats_web/live/nav.ex
@@ -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
diff --git a/lib/live_beats_web/views/layout_view.ex b/lib/live_beats_web/views/layout_view.ex
index d0cf0f4..f44d807 100644
--- a/lib/live_beats_web/views/layout_view.ex
+++ b/lib/live_beats_web/views/layout_view.ex
@@ -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}"}
>