Hi guys,
I’m building a small app where I would like to have a page with listed users who are currently online across the app, no matter which page they are on at the moment.
I created a LiveView to track users and the page where the list of users is showing, but if new users sign in or sign out, the list is not being updated and I get the following message in terminal:
[debug] send_update failed because component MyAppWeb.PagesLive.OnlineUsersComponent with ID "online-users" does not exist or it has been removed
app.html.heex - I added LiveView inside app.html.heex
<div>
<%= live_render(@socket, MyAppWeb.OMyAppnlineUsersLive, id: "online-users", sticky: true) %>
<main>
<%= @inner_content %>
</main>
</div>
OnlineUsersLive LiveView
defmodule MyAppWeb.OnlineUsersLive do
use MyAppWeb, :live_view
alias MyAppWeb.Presence
alias MyApp.{Accounts, Profiles}
alias MyAppWeb.PagesLive.OnlineUsersComponent
@impl true
def render(assigns) do
~H"""
<div class=""></div>
"""
end
@impl true
def mount(_params, %{"user_token" => user_token} = _session, socket) do
current_user = Accounts.get_user_by_session_token(user_token)
profile = Profiles.get_profile!(current_user.id)
if connected?(socket) do
{:ok, _} = Presence.track_user(self(), current_user, profile)
Phoenix.PubSub.subscribe(MyApp.PubSub, "online_users")
end
{:ok,
socket
|> assign(:current_user, current_user),
layout: false
}
end
def mount(_params, _session, socket) do
if connected?(socket) do
Phoenix.PubSub.subscribe(MyApp.PubSub, "online_users")
end
{:ok,
socket
|> assign(:current_user, nil),
layout: false
}
end
@impl true
def handle_info(%{event: "presence_diff"}, socket) do
send_update(OnlineUsersComponent, id: "online-users")
{:noreply, socket}
end
end
presence.ex
defmodule MyAppWeb.Presence do
use Phoenix.Presence, otp_app: :myapp, pubsub_server: MyApp.PubSub
alias __MODULE__
def track_user(pid, user, profile) do
Presence.track(
pid,
"online_users",
user.id,
%{
username: profile.username,
name: profile.name,
}
)
end
end
Online Users Component
defmodule MyAppWeb.PagesLive.OnlineUsersComponent do
use MyAppWeb, :live_component
alias MyAppWeb.Presence
@impl true
def render(assigns) do
~H"""
<div id={@id}>
Online Users
<%= for {user_id, %{metas: [data]}} <- @online_users do %>
<%= user_id %>
<%= data.username %>
<% end %>
</div>
"""
end
@impl true
def update(assigns, socket) do
{:ok,
socket
|> assign(assigns)
|> assign(:online_users, Presence.list("online_users"))
}
end
end
browse.ex page where signed in users are listed
<div>
Browse Users
<.live_component
module={MyAppWeb.PagesLive.OnlineUsersComponent}
id="online-users"
/>
</div>
Can anyone help?