diff --git a/lib/teiserver/libs/test_lib.ex b/lib/teiserver/libs/test_lib.ex index e424def22..c75eb2f78 100644 --- a/lib/teiserver/libs/test_lib.ex +++ b/lib/teiserver/libs/test_lib.ex @@ -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()) :: diff --git a/lib/teiserver_web/live/account/profile/overview.ex b/lib/teiserver_web/live/account/profile/overview.ex index 7d7156e70..9b850ab4d 100644 --- a/lib/teiserver_web/live/account/profile/overview.ex +++ b/lib/teiserver_web/live/account/profile/overview.ex @@ -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 @@ -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 @@ -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", @@ -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 ) diff --git a/lib/teiserver_web/live/account/profile/overview.html.heex b/lib/teiserver_web/live/account/profile/overview.html.heex index 1c9e55c3c..d91923d39 100644 --- a/lib/teiserver_web/live/account/profile/overview.html.heex +++ b/lib/teiserver_web/live/account/profile/overview.html.heex @@ -190,6 +190,10 @@ <% end %> + + Join + + <.link :if={allow?(@current_user, "Moderator")} navigate={~p"/teiserver/admin/user/#{@user.id}"} diff --git a/test/teiserver/lobby/commands/explain_command_test.exs b/test/teiserver/lobby/commands/explain_command_test.exs index c24c7fffa..00b9bf473 100644 --- a/test/teiserver/lobby/commands/explain_command_test.exs +++ b/test/teiserver/lobby/commands/explain_command_test.exs @@ -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}"]) diff --git a/test/teiserver_web/live/account/profile/overview_test.exs b/test/teiserver_web/live/account/profile/overview_test.exs new file mode 100644 index 000000000..907c45b5d --- /dev/null +++ b/test/teiserver_web/live/account/profile/overview_test.exs @@ -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