diff --git a/assets/js/app.js b/assets/js/app.js
index eb19fa5..3605b72 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -25,28 +25,34 @@ class App extends React.Component {
store.dispatch(setGameId(gameId));
- API.getGame(gameId)
- .then(response => {
- store.dispatch(setPlayer(response.data.player));
- store.dispatch(setGame(response.data));
- });
-
this.channel = Channel.gameChannel(gameId);
- this.channel.on("game_update", data => {
+ this.channel.on("game:update", data => {
+ if (data.player != undefined) {
+ store.dispatch(setPlayer(data.player));
+ };
store.dispatch(setGame(data));
});
+
+ this.channel.join()
+ .receive("error", resp => {
+ console.log("Unable to join", resp);
+ });
}
sendMove(gameId, move) {
- API.updateGame(gameId, move);
+ this.channel.push("game:move", move);
}
render() {
const { store, gameId } = this.props;
return (
-
+
);
}
}
diff --git a/assets/js/services/channel.js b/assets/js/services/channel.js
index ac8eed4..1313eeb 100644
--- a/assets/js/services/channel.js
+++ b/assets/js/services/channel.js
@@ -4,11 +4,6 @@ const Channel = {
gameChannel: (gameId) => {
const channel = socket.channel(`game:${gameId}`, {});
- channel.join()
- .receive("error", resp => {
- console.log("Unable to join", resp);
- });
-
return channel;
},
};
diff --git a/lib/chess/store/game.ex b/lib/chess/store/game.ex
index 1f62af8..2f5387d 100644
--- a/lib/chess/store/game.ex
+++ b/lib/chess/store/game.ex
@@ -32,9 +32,13 @@ defmodule Chess.Store.Game do
def change_turn("white"), do: "black"
def for_user(user) do
+ for_user_id(user.id)
+ end
+
+ def for_user_id(user_id) do
from game in Game,
- where: game.user_id == ^user.id,
- or_where: game.opponent_id == ^user.id
+ where: game.user_id == ^user_id,
+ or_where: game.opponent_id == ^user_id
end
def ordered(query) do
diff --git a/lib/chess_web/channels/game_channel.ex b/lib/chess_web/channels/game_channel.ex
index b9f7fdf..51970b1 100644
--- a/lib/chess_web/channels/game_channel.ex
+++ b/lib/chess_web/channels/game_channel.ex
@@ -1,19 +1,69 @@
defmodule ChessWeb.GameChannel do
@moduledoc false
- use Phoenix.Channel
+ use ChessWeb, :channel
+ alias Chess.Store.Game
alias Chess.Board
- def join("game:" <> _game_id, _params, socket) do
- {:ok, socket}
+ import Chess.Auth, only: [current_user: 1]
+
+ def join("game:" <> game_id, _params, socket) do
+ send(self, {:after_join, game_id})
+
+ {:ok, assign(socket, :game_id, game_id)}
end
- def update_game(game) do
+ def handle_info({:after_join, game_id}, socket) do
+ game =
+ socket.assigns.current_user_id
+ |> Game.for_user_id()
+ |> Repo.get!(game_id)
+
+ payload = %{
+ player: player(socket, game),
+ board: Board.transform(game.board),
+ turn: game.turn
+ }
+ push(socket, "game:update", payload)
+
+ {:noreply, socket}
+ end
+
+ def handle_in("game:move", move_params, socket) do
+ game =
+ socket.assigns.current_user_id
+ |> Game.for_user_id()
+ |> Repo.get!(socket.assigns.game_id)
+
+ changeset = Game.changeset(
+ game, %{
+ board: Board.move_piece(game.board, move_params),
+ turn: Game.change_turn(game.turn)
+ }
+ )
+
+ case Repo.update(changeset) do
+ {:ok, game} ->
+ send_update(game)
+
+ {:noreply, socket}
+ end
+ end
+
+ def send_update(game) do
payload = %{
board: Board.transform(game.board),
turn: game.turn
}
- ChessWeb.Endpoint.broadcast("game:#{game.id}", "game_update", payload)
+ ChessWeb.Endpoint.broadcast("game:#{game.id}", "game:update", payload)
+ end
+
+ defp player(socket, game) do
+ if game.user_id == socket.assigns.current_user_id do
+ "white"
+ else
+ "black"
+ end
end
end
diff --git a/lib/chess_web/channels/user_socket.ex b/lib/chess_web/channels/user_socket.ex
index cc9378e..d6c27ab 100644
--- a/lib/chess_web/channels/user_socket.ex
+++ b/lib/chess_web/channels/user_socket.ex
@@ -24,7 +24,7 @@ defmodule ChessWeb.UserSocket do
def connect(%{"token" => token}, socket) do
case Token.verify(socket, "game socket", token, max_age: 1_209_600) do
{:ok, user_id} ->
- {:ok, assign(socket, :current_user, user_id)}
+ {:ok, assign(socket, :current_user_id, user_id)}
{:error, _reason} ->
:error
end