Skip to content

Commit

Permalink
Add ability to join user lobby from their profile page (#209)
Browse files Browse the repository at this point in the history
* fix: make_lobby not creating lobby properly in tests

* feat: add join button to user overview page
This will tell the current user's client to the selected user's lobby. If the user is not in a lobby, or the current user's client is not connected, a flash message will be rendered with the error reason.

* feat: do not render join button when user is not in a lobby

* fix: respect server rules for joining

* chore: formatter
  • Loading branch information
darcymiranda authored Jun 3, 2024
1 parent d3ba30b commit 82eace8
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 3 deletions.
5 changes: 3 additions & 2 deletions lib/teiserver/libs/test_lib.ex
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,10 @@ defmodule Teiserver.TeiserverTestLib do
}
}
|> Map.merge(params)
|> Teiserver.Lobby.create_lobby()
|> Teiserver.Lobby.add_lobby()

lobby_pid = LobbyLib.start_lobby_server(lobby)
{lobby.id, lobby_pid}
lobby.id
end

@spec make_clan_membership(Integer.t(), Integer.t(), Map.t()) ::
Expand Down
75 changes: 75 additions & 0 deletions lib/teiserver_web/live/account/profile/overview.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
defmodule TeiserverWeb.Account.ProfileLive.Overview do
@moduledoc false

use TeiserverWeb, :live_view

alias Phoenix.PubSub
alias Teiserver.Account
alias Teiserver.Lobby

@impl true
def mount(%{"userid" => userid_str}, _session, socket) do
Expand All @@ -16,12 +20,19 @@ defmodule TeiserverWeb.Account.ProfileLive.Overview do
|> redirect(to: ~p"/")

true ->
:ok =
PubSub.subscribe(
Teiserver.PubSub,
"teiserver_client_messages:#{userid}"
)

socket
|> assign(:tab, nil)
|> assign(:site_menu_active, "teiserver_account")
|> assign(:view_colour, Teiserver.Account.UserLib.colours())
|> assign(:user, user)
|> assign(:role_data, Account.RoleLib.role_data())
|> assign(:client, Account.get_client_by_id(userid))
|> get_relationships_and_permissions
end

Expand All @@ -48,6 +59,30 @@ defmodule TeiserverWeb.Account.ProfileLive.Overview do
|> assign(:page_title, "#{user.name} - Achievements")
end

def handle_info(%{channel: "teiserver_client_messages:" <> _, event: :connected}, socket) do
user_id = socket.assigns.user.id

socket = assign(socket, :client, Account.get_client_by_id(user_id))

{:noreply, socket}
end

def handle_info(%{channel: "teiserver_client_messages:" <> _, event: :disconnected}, socket) do
{:noreply, assign(socket, :client, nil)}
end

def handle_info(%{channel: "teiserver_client_messages:" <> _, event: :client_updated}, socket) do
user_id = socket.assigns.user.id

socket = assign(socket, :client, Account.get_client_by_id(user_id))

{:noreply, socket}
end

def handle_info(%{channel: "teiserver_client_messages:" <> _}, socket) do
{:noreply, socket}
end

@impl true
def handle_event(
"follow-user",
Expand Down Expand Up @@ -250,6 +285,46 @@ defmodule TeiserverWeb.Account.ProfileLive.Overview do
|> assign(:profile_permissions, [])
end

def handle_event("join", _params, %{assigns: assigns} = socket) do
user_id = assigns.user.id
current_user_id = assigns.current_user.id
lobby_id = assigns.client.lobby_id

with :ok <- client_connected(current_user_id),
:ok <- server_allows_join(lobby_id, current_user_id),
:ok <- join_lobby(lobby_id, current_user_id) do
{:noreply, put_flash(socket, :success, "Lobby joined")}
else
{:error, reason} ->
{:noreply, put_flash(socket, :warning, reason)}
end
end

defp client_connected(user_id) do
client = Account.get_client_by_id(user_id)

if not is_nil(client) do
:ok
else
{:error, "Client is not connected"}
end
end

defp server_allows_join(lobby_id, user_id) do
case Lobby.server_allows_join?(user_id, lobby_id) do
true -> :ok
{:failure, reason} -> {:error, reason}
end
end

defp join_lobby(lobby_id, user_id) do
if :ok == Lobby.force_add_user_to_lobby(user_id, lobby_id) do
:ok
else
{:error, "Failed to join lobby"}
end
end

def get_relationships_and_permissions(
%{assigns: %{current_user: current_user, user: user}} = socket
)
Expand Down
4 changes: 4 additions & 0 deletions lib/teiserver_web/live/account/profile/overview.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@
</.link>
<% end %>

<span :if={not is_nil(@client[:lobby_id])} phx-click="join" class="btn btn-outline-info mx-1">
Join
</span>

<.link
:if={allow?(@current_user, "Moderator")}
navigate={~p"/teiserver/admin/user/#{@user.id}"}
Expand Down
2 changes: 1 addition & 1 deletion test/teiserver/lobby/commands/explain_command_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule Teiserver.Lobby.Commands.ExplainCommandTest do
Coordinator.start_coordinator()

user = TeiserverTestLib.new_user()
{lobby_id, _lobby_pid} = TeiserverTestLib.make_lobby()
lobby_id = TeiserverTestLib.make_lobby()
chat_listener = PubsubListener.new_listener(["teiserver_lobby_chat:#{lobby_id}"])
client_listener = PubsubListener.new_listener(["teiserver_client_messages:#{user.id}"])

Expand Down
85 changes: 85 additions & 0 deletions test/teiserver_web/live/account/profile/overview_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
defmodule TeiserverWeb.Live.Account.Profile.OverviewTest do
use TeiserverWeb.ConnCase, async: false
import Phoenix.LiveViewTest

alias Central.Helpers.GeneralTestLib
alias Teiserver.{Battle, TeiserverTestLib, Client}

setup do
{:ok, data} =
TeiserverTestLib.player_permissions()
|> GeneralTestLib.conn_setup()
|> TeiserverTestLib.conn_setup()

profile_user = GeneralTestLib.make_user()
login_user(profile_user)

%{conn: data[:conn], user: data[:user], profile_user: profile_user}
end

describe "join lobby" do
test "clicking join joins the client to the user's lobby", %{
conn: conn,
user: user,
profile_user: profile_user
} do
login_user(user)

lobby_id = TeiserverTestLib.make_lobby()

Battle.force_add_user_to_lobby(profile_user.id, lobby_id)

{:ok, view, _html} = live(conn, "/profile/#{profile_user.id}")

view
|> element("span[phx-click=join]")
|> render_click()

assert user.id in Battle.get_lobby_member_list(lobby_id)
end

test "only renders join button when user to join is in a lobby", %{
conn: conn,
profile_user: profile_user
} do
lobby_id = TeiserverTestLib.make_lobby()

{:ok, view, _html} = live(conn, "/profile/#{profile_user.id}")

refute view
|> element("span[phx-click=join]")
|> has_element?()

Battle.force_add_user_to_lobby(profile_user.id, lobby_id)

assert view
|> element("span[phx-click=join]")
|> has_element?()
end

test "renders error flash when client is not connected", %{
conn: conn,
profile_user: profile_user
} do
# Skip client login

lobby_id = TeiserverTestLib.make_lobby()

Battle.force_add_user_to_lobby(profile_user.id, lobby_id)

{:ok, view, _html} = live(conn, "/profile/#{profile_user.id}")

view
|> element("span[phx-click=join]")
|> render_click()

assert render(view) =~ "Client is not connected"
end
end

defp login_user(user) do
user
|> Map.merge(%{rank: 1, print_client_messages: false, print_server_messages: false})
|> Client.login(:spring, "127.0.0.1")
end
end

0 comments on commit 82eace8

Please sign in to comment.