mirror of
https://github.com/danbee/chess
synced 2025-03-04 08:39:06 +00:00
73 lines
1.8 KiB
Elixir
73 lines
1.8 KiB
Elixir
defmodule ChessWeb.GameInfoLive do
|
|
use Phoenix.LiveView
|
|
|
|
alias Chess.Store.User
|
|
alias Chess.Store.Game
|
|
alias Chess.Store.Move
|
|
alias Chess.Repo
|
|
alias ChessWeb.Presence
|
|
|
|
import Ecto.Query
|
|
|
|
require Logger
|
|
|
|
def render(assigns) do
|
|
Phoenix.View.render(ChessWeb.GameView, "game_info.html", assigns)
|
|
end
|
|
|
|
def mount(_params, %{"game_id" => game_id, "user_id" => user_id}, socket) do
|
|
topic = "game:#{game_id}"
|
|
|
|
ChessWeb.Endpoint.subscribe(topic)
|
|
|
|
user = Repo.get!(User, user_id)
|
|
|
|
game =
|
|
Game.for_user(user)
|
|
|> preload(:user)
|
|
|> preload(:opponent)
|
|
|> preload(
|
|
moves:
|
|
^from(
|
|
move in Move,
|
|
order_by: [asc: move.inserted_at]
|
|
)
|
|
)
|
|
|> Repo.get!(game_id)
|
|
|
|
Presence.track(self(), topic, :user, %{id: user_id})
|
|
|
|
{:ok, assign(socket, game: game, user: user, presence: presence_list(topic))}
|
|
end
|
|
|
|
def handle_info(%{event: "move", payload: state}, socket) do
|
|
{:noreply, assign(socket, state)}
|
|
end
|
|
|
|
def handle_info(
|
|
%{event: "presence_diff", payload: %{joins: joins, leaves: leaves}},
|
|
socket
|
|
) do
|
|
{:noreply, socket |> handle_joins(joins) |> handle_leaves(leaves)}
|
|
end
|
|
|
|
defp presence_list(topic) do
|
|
Presence.list(topic)
|
|
|> Map.get("user")
|
|
|> Map.get(:metas)
|
|
|> Map.new(fn meta -> {meta.id, meta} end)
|
|
end
|
|
|
|
defp handle_joins(socket, joins) do
|
|
Enum.reduce(joins, socket, fn {"user", %{metas: [meta | _]}}, socket ->
|
|
assign(socket, :presence, Map.put(socket.assigns.presence, meta.id, meta))
|
|
end)
|
|
end
|
|
|
|
defp handle_leaves(socket, leaves) do
|
|
Enum.reduce(leaves, socket, fn {"user", %{metas: [meta | _]}}, socket ->
|
|
assign(socket, :presence, Map.delete(socket.assigns.presence, meta.id))
|
|
end)
|
|
end
|
|
end
|