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}"} >