mirror of
https://github.com/danbee/chess
synced 2025-03-04 08:39:06 +00:00
Game now works using LiveView
This commit is contained in:
parent
1e411e2e73
commit
2314dc6a19
@ -8,16 +8,13 @@
|
|||||||
width: 1.5%;
|
width: 1.5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.board__container {
|
|
||||||
grid-area: board;
|
|
||||||
}
|
|
||||||
|
|
||||||
.board {
|
.board {
|
||||||
background: $background-color;
|
background: $background-color;
|
||||||
border-collapse: unset;
|
border-collapse: unset;
|
||||||
border-radius: 2.8%;
|
border-radius: 2.8%;
|
||||||
border-spacing: 1px;
|
border-spacing: 1px;
|
||||||
color: $foreground-color;
|
color: $foreground-color;
|
||||||
|
grid-area: board;
|
||||||
height: var(--board-size);
|
height: var(--board-size);
|
||||||
padding: calc(var(--board-size) / 20);
|
padding: calc(var(--board-size) / 20);
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -61,14 +58,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
.board__body {
|
|
||||||
flex-direction: column-reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
.board__row {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.board--player-is-black {
|
.board--player-is-black {
|
||||||
@ -81,45 +70,20 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.board__body {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.board__row {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.board__body {
|
.board__body {
|
||||||
background: $background-color;
|
background: $background-color;
|
||||||
border: 0.25rem solid $foreground-color;
|
border: 0.25rem solid $foreground-color;
|
||||||
border-radius: calc(var(--board-size) / 100);
|
border-radius: calc(var(--board-size) / 100);
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-columns: repeat(8, 1fr);
|
||||||
|
grid-template-rows: repeat(8, 1fr);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 1%;
|
padding: 1%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.board__row {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
@include odd-between(1, 8) {
|
|
||||||
.square {
|
|
||||||
@include odd-between(1, 8) { @extend %square--black; }
|
|
||||||
@include even-between(1, 8) { @extend %square--white; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@include even-between(1, 8) {
|
|
||||||
.square {
|
|
||||||
@include odd-between(1, 8) { @extend %square--white; }
|
|
||||||
@include even-between(1, 8) { @extend %square--black; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.board__rank-labels {
|
.board__rank-labels {
|
||||||
display: none;
|
display: none;
|
||||||
height: 90%;
|
height: 90%;
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
defmodule Chess.Board do
|
defmodule Chess.Board do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
def search(board, %{"type" => type, "colour" => colour}) do
|
def search(board, %{"type" => type, "colour" => colour}) do
|
||||||
board
|
board
|
||||||
|> Enum.filter(fn {_index, piece} ->
|
|> Enum.filter(fn {_index, piece} ->
|
||||||
@ -17,9 +19,13 @@ defmodule Chess.Board do
|
|||||||
|> indexes_to_tuples
|
|> indexes_to_tuples
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def piece(board, {file, rank}) do
|
||||||
|
board["#{file},#{rank}"]
|
||||||
|
end
|
||||||
|
|
||||||
def move_piece(board, %{
|
def move_piece(board, %{
|
||||||
"from" => [from_file, from_rank],
|
from: {from_file, from_rank},
|
||||||
"to" => [to_file, to_rank]
|
to: {to_file, to_rank}
|
||||||
}) do
|
}) do
|
||||||
{piece, board} = Map.pop(board, to_index({from_file, from_rank}))
|
{piece, board} = Map.pop(board, to_index({from_file, from_rank}))
|
||||||
{piece_captured, board} = Map.pop(board, to_index({to_file, to_rank}))
|
{piece_captured, board} = Map.pop(board, to_index({to_file, to_rank}))
|
||||||
@ -54,15 +60,15 @@ defmodule Chess.Board do
|
|||||||
|
|
||||||
def castling_move(board, %{from: {4, rank}, to: {2, _rank}}) do
|
def castling_move(board, %{from: {4, rank}, to: {2, _rank}}) do
|
||||||
move_piece(board, %{
|
move_piece(board, %{
|
||||||
"from" => [0, rank],
|
from: {0, rank},
|
||||||
"to" => [3, rank]
|
to: {3, rank}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
def castling_move(board, %{"from" => [4, rank], "to" => [6, _rank]}) do
|
def castling_move(board, %{"from" => [4, rank], "to" => [6, _rank]}) do
|
||||||
move_piece(board, %{
|
move_piece(board, %{
|
||||||
"from" => [7, rank],
|
from: {7, rank},
|
||||||
"to" => [5, rank]
|
to: {5, rank}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,8 @@ defmodule Chess.Moves do
|
|||||||
alias Chess.Moves.Pieces.Queen
|
alias Chess.Moves.Pieces.Queen
|
||||||
alias Chess.Moves.Pieces.King
|
alias Chess.Moves.Pieces.King
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
def make_move(game, move_params) do
|
def make_move(game, move_params) do
|
||||||
params =
|
params =
|
||||||
game.board
|
game.board
|
||||||
|
|||||||
@ -39,7 +39,8 @@ defmodule ChessWeb do
|
|||||||
# Import convenience functions from controllers
|
# Import convenience functions from controllers
|
||||||
import Phoenix.Controller,
|
import Phoenix.Controller,
|
||||||
only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
|
only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
|
||||||
import Phoenix.LiveView.Helpers
|
|
||||||
|
import Phoenix.Component
|
||||||
|
|
||||||
# Use all HTML functionality (forms, tags, etc)
|
# Use all HTML functionality (forms, tags, etc)
|
||||||
use Phoenix.HTML
|
use Phoenix.HTML
|
||||||
@ -52,11 +53,10 @@ defmodule ChessWeb do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def live_view do
|
def live_view do
|
||||||
quote do
|
quote do
|
||||||
use Phoenix.LiveView,
|
use Phoenix.LiveView,
|
||||||
layout: {ChessWeb.LayoutView, "live.html"}
|
layout: {ChessWeb.LayoutView, :live}
|
||||||
|
|
||||||
unquote(view_helpers())
|
unquote(view_helpers())
|
||||||
end
|
end
|
||||||
@ -90,6 +90,7 @@ defmodule ChessWeb do
|
|||||||
def router do
|
def router do
|
||||||
quote do
|
quote do
|
||||||
use Phoenix.Router
|
use Phoenix.Router
|
||||||
|
|
||||||
import Phoenix.LiveView.Router
|
import Phoenix.LiveView.Router
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -5,7 +5,6 @@ defmodule ChessWeb.GameChannel do
|
|||||||
|
|
||||||
import ChessWeb.GameView, only: [player: 2, opponent: 2]
|
import ChessWeb.GameView, only: [player: 2, opponent: 2]
|
||||||
|
|
||||||
alias Chess.Board
|
|
||||||
alias Chess.Emails
|
alias Chess.Emails
|
||||||
alias Chess.Mailer
|
alias Chess.Mailer
|
||||||
alias Chess.MoveList
|
alias Chess.MoveList
|
||||||
@ -29,7 +28,7 @@ defmodule ChessWeb.GameChannel do
|
|||||||
opponent_id: opponent(game, socket.assigns.user_id).id,
|
opponent_id: opponent(game, socket.assigns.user_id).id,
|
||||||
player: player(game, socket.assigns.user_id),
|
player: player(game, socket.assigns.user_id),
|
||||||
opponent: opponent(game, socket.assigns.user_id).name,
|
opponent: opponent(game, socket.assigns.user_id).name,
|
||||||
board: Board.transform(game.board),
|
board: game.board,
|
||||||
turn: game.turn,
|
turn: game.turn,
|
||||||
state: game.state,
|
state: game.state,
|
||||||
moves: MoveList.transform(game.moves)
|
moves: MoveList.transform(game.moves)
|
||||||
@ -135,7 +134,7 @@ defmodule ChessWeb.GameChannel do
|
|||||||
|> Queries.game_with_moves(socket.assigns.game_id)
|
|> Queries.game_with_moves(socket.assigns.game_id)
|
||||||
|
|
||||||
payload = %{
|
payload = %{
|
||||||
board: Board.transform(game.board),
|
board: game.board,
|
||||||
turn: game.turn,
|
turn: game.turn,
|
||||||
state: game.state,
|
state: game.state,
|
||||||
moves: MoveList.transform(game.moves)
|
moves: MoveList.transform(game.moves)
|
||||||
|
|||||||
@ -4,15 +4,14 @@ defmodule ChessWeb.Endpoint do
|
|||||||
@session_options [
|
@session_options [
|
||||||
store: :cookie,
|
store: :cookie,
|
||||||
key: "_chess_key",
|
key: "_chess_key",
|
||||||
signing_salt: "9LqUhZTU"
|
signing_salt: "9LqUhZTU",
|
||||||
|
same_site: "Lax"
|
||||||
]
|
]
|
||||||
|
|
||||||
if sandbox = Application.compile_env(:chess, :sandbox) do
|
if sandbox = Application.compile_env(:chess, :sandbox) do
|
||||||
plug(Phoenix.Ecto.SQL.Sandbox, sandbox: sandbox)
|
plug(Phoenix.Ecto.SQL.Sandbox, sandbox: sandbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
socket("/socket", ChessWeb.UserSocket)
|
|
||||||
|
|
||||||
socket("/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]])
|
socket("/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]])
|
||||||
|
|
||||||
# Serve at "/" the static files from "priv/static" directory.
|
# Serve at "/" the static files from "priv/static" directory.
|
||||||
|
|||||||
@ -42,13 +42,6 @@ defmodule ChessWeb.Router do
|
|||||||
resources("/password", PasswordController, only: [:edit, :update], singleton: true)
|
resources("/password", PasswordController, only: [:edit, :update], singleton: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Other scopes may use custom stacks.
|
|
||||||
scope "/api", as: :api do
|
|
||||||
pipe_through([:api, :auth, :ensure_auth])
|
|
||||||
|
|
||||||
resources("/opponents", ChessWeb.Api.OpponentsController, only: [:index])
|
|
||||||
end
|
|
||||||
|
|
||||||
if Mix.env() == :dev do
|
if Mix.env() == :dev do
|
||||||
forward("/sent_emails", Bamboo.SentEmailViewerPlug)
|
forward("/sent_emails", Bamboo.SentEmailViewerPlug)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -21,9 +21,12 @@
|
|||||||
<div class="board__label">h</div>
|
<div class="board__label">h</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% rank_range = if white?(@user, @game), do: 7..0, else: 0..7 %>
|
||||||
|
<% file_range = if black?(@user, @game), do: 7..0, else: 0..7 %>
|
||||||
|
|
||||||
<div class="board__body">
|
<div class="board__body">
|
||||||
<%= for rank <- 0..7 do %>
|
<%= for rank <- rank_range do %>
|
||||||
<%= for file <- 0..7 do %>
|
<%= for file <- file_range do %>
|
||||||
<%= render ChessWeb.SquareView,
|
<%= render ChessWeb.SquareView,
|
||||||
"square.html",
|
"square.html",
|
||||||
rank: rank,
|
rank: rank,
|
||||||
@ -36,6 +39,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="game-state game-state--<%= @game.state %>">
|
<div class="game-state game-state--<%= @game.state %>">
|
||||||
<%= states(@game.state) %>
|
<%= state_text(@game.state) %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,10 +15,23 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<%= for {move_pair, i} <- @game.moves |>
|
||||||
|
Enum.chunk_every(2) |> Enum.with_index do %>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row" class="move-list__line-number">1.</th>
|
<th scope="row" class="move-list__line-number"><%= i + 1 %>.</th>
|
||||||
<td class="move-list__move move-list__move--white">e4</td>
|
<%= case move_pair do %>
|
||||||
|
<% [white_move, black_move] -> %>
|
||||||
|
<td class="move-list__move move-list__move--<%=
|
||||||
|
white_move.piece["colour"] %>"><%= move_text(white_move) %></td>
|
||||||
|
<td class="move-list__move move-list__move--<%=
|
||||||
|
black_move.piece["colour"] %>"><%= move_text(black_move) %></td>
|
||||||
|
<% [white_move] -> %>
|
||||||
|
<td class="move-list__move move-list__move--<%=
|
||||||
|
white_move.piece["colour"] %>"><%= move_text(white_move) %></td>
|
||||||
|
<td></td>
|
||||||
|
<% end %>
|
||||||
</tr>
|
</tr>
|
||||||
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,6 +6,15 @@ defmodule ChessWeb.GameView do
|
|||||||
import Phoenix.Component
|
import Phoenix.Component
|
||||||
import Chess.Auth, only: [current_user: 1]
|
import Chess.Auth, only: [current_user: 1]
|
||||||
|
|
||||||
|
@pieces %{
|
||||||
|
pawn: "",
|
||||||
|
knight: "N",
|
||||||
|
bishop: "B",
|
||||||
|
rook: "R",
|
||||||
|
queen: "Q",
|
||||||
|
king: "K"
|
||||||
|
}
|
||||||
|
|
||||||
def won_lost(user, game) do
|
def won_lost(user, game) do
|
||||||
if game_over?(game) && game.state == "checkmate" do
|
if game_over?(game) && game.state == "checkmate" do
|
||||||
(your_turn?(user, game) &&
|
(your_turn?(user, game) &&
|
||||||
@ -21,7 +30,7 @@ defmodule ChessWeb.GameView do
|
|||||||
def state(user, game) do
|
def state(user, game) do
|
||||||
cond do
|
cond do
|
||||||
GameState.game_over?(game) ->
|
GameState.game_over?(game) ->
|
||||||
states(game.state)
|
state_text(game.state)
|
||||||
|
|
||||||
your_turn?(user, game) ->
|
your_turn?(user, game) ->
|
||||||
gettext("Your turn")
|
gettext("Your turn")
|
||||||
@ -37,6 +46,14 @@ defmodule ChessWeb.GameView do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def white?(user, game) do
|
||||||
|
player_colour(user, game) == "white"
|
||||||
|
end
|
||||||
|
|
||||||
|
def black?(user, game) do
|
||||||
|
player_colour(user, game) == "black"
|
||||||
|
end
|
||||||
|
|
||||||
def your_turn?(user, game) do
|
def your_turn?(user, game) do
|
||||||
user
|
user
|
||||||
|> player_colour(game) == game.turn
|
|> player_colour(game) == game.turn
|
||||||
@ -47,7 +64,7 @@ defmodule ChessWeb.GameView do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def piece(board, {file, rank}) do
|
def piece(board, {file, rank}) do
|
||||||
board["#{file},#{rank}"]
|
Chess.Board.piece(board, {file, rank})
|
||||||
end
|
end
|
||||||
|
|
||||||
def files(user, game) do
|
def files(user, game) do
|
||||||
@ -79,7 +96,19 @@ defmodule ChessWeb.GameView do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def states(state) do
|
def move_text(move) do
|
||||||
|
move = Chess.Store.Move.transform(move)
|
||||||
|
|
||||||
|
piece_type = move.piece["type"] |> String.to_atom()
|
||||||
|
|
||||||
|
[
|
||||||
|
@pieces[piece_type],
|
||||||
|
move.to
|
||||||
|
]
|
||||||
|
|> Enum.join()
|
||||||
|
end
|
||||||
|
|
||||||
|
def state_text(state) do
|
||||||
Map.get(
|
Map.get(
|
||||||
%{
|
%{
|
||||||
"checkmate" => gettext("Checkmate!"),
|
"checkmate" => gettext("Checkmate!"),
|
||||||
|
|||||||
@ -3,12 +3,18 @@ defmodule ChessWeb.BoardLive do
|
|||||||
|
|
||||||
alias Chess.Store.User
|
alias Chess.Store.User
|
||||||
alias Chess.Store.Game
|
alias Chess.Store.Game
|
||||||
|
alias Chess.Store.Move
|
||||||
alias Chess.Repo
|
alias Chess.Repo
|
||||||
alias Chess.Board
|
|
||||||
alias Chess.Moves
|
alias Chess.Moves
|
||||||
|
|
||||||
|
alias ChessWeb.GameView
|
||||||
|
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
Phoenix.View.render(ChessWeb.GameView, "board.html", assigns)
|
Phoenix.View.render(GameView, "board.html", assigns)
|
||||||
end
|
end
|
||||||
|
|
||||||
def mount(_params, %{"user_id" => user_id, "game_id" => game_id}, socket) do
|
def mount(_params, %{"user_id" => user_id, "game_id" => game_id}, socket) do
|
||||||
@ -41,6 +47,7 @@ defmodule ChessWeb.BoardLive do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def handle_info(%{event: "move", payload: state}, socket) do
|
def handle_info(%{event: "move", payload: state}, socket) do
|
||||||
|
Logger.info("Handling move from board")
|
||||||
{:noreply, assign(socket, state)}
|
{:noreply, assign(socket, state)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -49,7 +56,7 @@ defmodule ChessWeb.BoardLive do
|
|||||||
board = game.board
|
board = game.board
|
||||||
user = socket.assigns[:user]
|
user = socket.assigns[:user]
|
||||||
|
|
||||||
colour = ChessWeb.GameView.player_colour(user, game)
|
colour = GameView.player_colour(user, game)
|
||||||
|
|
||||||
assigns =
|
assigns =
|
||||||
if colour == game.turn do
|
if colour == game.turn do
|
||||||
@ -66,7 +73,7 @@ defmodule ChessWeb.BoardLive do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp handle_selection(board, colour, file, rank) do
|
defp handle_selection(board, colour, file, rank) do
|
||||||
case Board.piece(board, {file, rank}) do
|
case GameView.piece(board, {file, rank}) do
|
||||||
%{"colour" => ^colour} ->
|
%{"colour" => ^colour} ->
|
||||||
[
|
[
|
||||||
{:selected, {file, rank}},
|
{:selected, {file, rank}},
|
||||||
@ -88,14 +95,21 @@ defmodule ChessWeb.BoardLive do
|
|||||||
|> Moves.make_move(%{from: selected, to: {file, rank}})
|
|> Moves.make_move(%{from: selected, to: {file, rank}})
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, %{game: game}} ->
|
{:ok, %{game: game}} ->
|
||||||
board = Board.transform(game.board)
|
game
|
||||||
|
|> Repo.preload([:user, :opponent])
|
||||||
broadcast_move(game, board)
|
|> Repo.preload(
|
||||||
|
moves:
|
||||||
|
from(
|
||||||
|
move in Move,
|
||||||
|
order_by: [asc: move.inserted_at]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|> broadcast_move(game.board)
|
||||||
|
|
||||||
[
|
[
|
||||||
{:selected, nil},
|
{:selected, nil},
|
||||||
{:available, []},
|
{:available, []},
|
||||||
{:board, board},
|
{:board, game.board},
|
||||||
{:game, game}
|
{:game, game}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3,23 +3,39 @@ defmodule ChessWeb.GameInfoLive do
|
|||||||
|
|
||||||
alias Chess.Store.User
|
alias Chess.Store.User
|
||||||
alias Chess.Store.Game
|
alias Chess.Store.Game
|
||||||
|
alias Chess.Store.Move
|
||||||
alias Chess.Repo
|
alias Chess.Repo
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
Phoenix.View.render(ChessWeb.GameView, "game_info.html", assigns)
|
Phoenix.View.render(ChessWeb.GameView, "game_info.html", assigns)
|
||||||
end
|
end
|
||||||
|
|
||||||
def mount(_params, %{"game_id" => game_id, "user_id" => user_id}, socket) do
|
def mount(_params, %{"game_id" => game_id, "user_id" => user_id}, socket) do
|
||||||
|
ChessWeb.Endpoint.subscribe("game:#{game_id}")
|
||||||
|
|
||||||
user = Repo.get!(User, user_id)
|
user = Repo.get!(User, user_id)
|
||||||
|
|
||||||
game =
|
game =
|
||||||
Game.for_user(user)
|
Game.for_user(user)
|
||||||
|> preload(:user)
|
|> preload(:user)
|
||||||
|> preload(:opponent)
|
|> preload(:opponent)
|
||||||
|
|> preload(
|
||||||
|
moves:
|
||||||
|
^from(
|
||||||
|
move in Move,
|
||||||
|
order_by: [asc: move.inserted_at]
|
||||||
|
)
|
||||||
|
)
|
||||||
|> Repo.get!(game_id)
|
|> Repo.get!(game_id)
|
||||||
|
|
||||||
{:ok, assign(socket, game: game, user: user)}
|
{:ok, assign(socket, game: game, user: user)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_info(%{event: "move", payload: state}, socket) do
|
||||||
|
{:noreply, assign(socket, state)}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user