diff --git a/assets/js/app.js b/assets/js/app.js
index 476cdc1..18adfa1 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -183,7 +183,7 @@ Hooks.Ping = {
this.handleEvent("pong", () => {
let rtt = Date.now() - this.nowMs
this.el.innerText = `ping: ${rtt}ms`
- this.timer = setTimeout(() => this.ping(rtt), 1000)
+ this.timer = setTimeout(() => this.ping(rtt), 100)
})
this.ping(null)
},
diff --git a/lib/live_beats_web/channels/presence.ex b/lib/live_beats_web/channels/presence.ex
index d86e9b2..1510917 100644
--- a/lib/live_beats_web/channels/presence.ex
+++ b/lib/live_beats_web/channels/presence.ex
@@ -13,6 +13,7 @@ defmodule LiveBeatsWeb.Presence do
import LiveBeatsWeb.LiveHelpers
alias LiveBeats.{Accounts, MediaLibrary}
+ alias LiveBeatsWeb.Presence.BadgeComponent
def subscribe(%MediaLibrary.Profile{} = profile) do
LiveBeats.PresenceClient.subscribe(profile)
@@ -29,57 +30,79 @@ defmodule LiveBeatsWeb.Presence do
{key, %{metas: metas, user: users[String.to_integer(key)]}}
end
end
-end
-defmodule LiveBeatsWeb.Presence.BadgeListComponent do
- use LiveBeatsWeb, :live_component
+ def listening_now(assigns) do
+ import Phoenix.LiveView
+ count = Enum.count(assigns.presence_ids)
+
+ assigns =
+ assigns
+ |> assign(:count, count)
+ |> assign_new(:total_count, fn -> count end)
- def render(assigns) do
~H"""
- <%= user.username %>
- <%= if ping do %>
- ping: <%= ping %>ms
- <%= if region do %><% end %>
- <% end %>
-
+ presence_ids={@presence_ids}
+ total_count={@presences_count}
+ />
<%= for song <- if(@owns_profile?, do: @songs, else: []), id = "delete-modal-#{song.id}" do %>
@@ -115,7 +111,7 @@ defmodule LiveBeatsWeb.ProfileLive do
|> list_songs()
|> assign_presences()
- {:ok, socket, temporary_assigns: [songs: [], presences: []]}
+ {:ok, socket, temporary_assigns: [songs: [], presences: %{}]}
end
def handle_params(params, _url, socket) do
@@ -152,15 +148,14 @@ defmodule LiveBeatsWeb.ProfileLive do
end
def handle_info({LiveBeats.PresenceClient, %{user_joined: presence}}, socket) do
- %{user: user} = presence
- {:noreply, update(socket, :presences, &[user | &1])}
+ {:noreply, assign_presence(socket, presence)}
end
def handle_info({LiveBeats.PresenceClient, %{user_left: presence}}, socket) do
%{user: user} = presence
if presence.metas == [] do
- {:noreply, push_event(socket, "remove-el", %{id: "presence-#{user.id}"})}
+ {:noreply, remove_presence(socket, user)}
else
{:noreply, socket}
end
@@ -191,8 +186,9 @@ defmodule LiveBeatsWeb.ProfileLive do
def handle_info({MediaLibrary, {:ping, ping}}, socket) do
%{user: user, rtt: rtt, region: region} = ping
- send_update(Presence.BadgeListComponent,
- id: :presence_badges,
+
+ send_update(Presence.BadgeComponent,
+ id: user.id,
action: {:ping, %{user: user, ping: rtt, region: region}}
)
@@ -276,18 +272,43 @@ defmodule LiveBeatsWeb.ProfileLive do
end
defp assign_presences(socket) do
- if profile = socket.assigns.profile do
- presences =
- profile
- |> LiveBeats.PresenceClient.list()
- |> Enum.map(fn {_key, meta} -> meta.user end)
+ socket = assign(socket, presences_count: 0, presences: %{}, presence_ids: %{})
- assign(socket, presences: presences)
+ if profile = connected?(socket) && socket.assigns.profile do
+ profile
+ |> LiveBeats.PresenceClient.list()
+ |> Enum.reduce(socket, fn {_, presence}, acc -> assign_presence(acc, presence) end)
else
- assign(socket, presences: [])
+ socket
end
end
+ defp assign_presence(socket, presence) do
+ %{user: user} = presence
+ %{presence_ids: presence_ids} = socket.assigns
+
+ cond do
+ Map.has_key?(presence_ids, user.id) ->
+ socket
+
+ Enum.count(presence_ids) < @max_presences ->
+ socket
+ |> update(:presences, &Map.put(&1, user.id, user))
+ |> update(:presence_ids, &Map.put(&1, user.id, System.system_time()))
+ |> update(:presences_count, &(&1 + 1))
+
+ true ->
+ update(socket, :presences_count, &(&1 + 1))
+ end
+ end
+
+ defp remove_presence(socket, user) do
+ socket
+ |> update(:presences, &Map.delete(&1, user.id))
+ |> update(:presence_ids, &Map.delete(&1, user.id))
+ |> update(:presences_count, &(&1 - 1))
+ end
+
defp url_text(nil), do: ""
defp url_text(url_str) do