Creating our chat channel

To start implementing chat in our application, we'll need to start building out the chat channel and setting up all of the framework code necessary for us to support the new channel. We'll need to start by adding the new channel to lib/vocial_web/channels/user_socket.ex:

channel "chat:*", VocialWeb.ChatChannel

We don't actually have a Chat Channel module yet, so that will be the next file that we will have to start building up. In the same directory, we'll create a chat_channel.ex file and start it off with a simple channel skeleton:

defmodule VocialWeb.ChatChannel do
use VocialWeb, :channel

def join("chat:lobby", _payload, socket) do
{:ok, socket}
end
end

We'll also have to refactor our JavaScript in the socket.js file since we had originally written that to be very specific to the live polls work. We'll create a new file in assets/js called poll.js, and move all of the poll-specific code there:

// Push the vote up to the server
const pushVote = (el, channel) => {
channel
.push("vote", { option_id: el.getAttribute("data-option-id") })
.receive("ok", res => console.log("You Voted!"))
.receive("error", res => console.log("Failed to vote:", res));
};

// When we join the channel, do this
const onJoin = (res, channel) => {
document.querySelectorAll(".vote-button-manual").forEach(el => {
el.addEventListener("click", event => {
event.preventDefault();
pushVote(el, channel);
});
});
console.log("Joined channel:", res);
};

const connect = socket => {
// Only connect to the socket if the polls channel actually exists!
const enableLivePolls = document.getElementById("enable-polls-channel");
if (!enableLivePolls) {
return;
}

// Pull the Poll Id to find the right topic from the data attribute
const pollId = enableLivePolls.getAttribute("data-poll-id");
// Get the stored remote IP for a user
const remoteIp = document
.getElementsByName("remote_ip")[0]
.getAttribute("content");
// Create a channel to handle joining/sending/receiving
const channel = socket.channel("polls:" + pollId, { remote_ip: remoteIp });

// Next, join the topic on the channel!
channel
.join()
.receive("ok", res => onJoin(res, channel))
.receive("error", res => console.log("Failed to join channel:", res));

document.getElementById("polls-ping").addEventListener("click", () => {
channel
.push("ping")
.receive("ok", res => console.log("Received PING response:", res.message))
.receive("error", res => console.log("Error sending PING:", res));
});

channel.on("pong", payload => {
console.log("The server has been PONG'd and all is well:", payload);
});

channel.on("new_vote", ({ option_id, votes }) => {
document.getElementById("vote-count-" + option_id).innerHTML = votes;
});
};

export default { connect };

We'll also refactor our socket.js file to be more minimal:

// Import Phoenix's Socket Library
import { Socket } from "phoenix";

// Next, create a new Phoenix Socket to reuse
const socket = new Socket("/socket");

// Connect to the socket itself
socket.connect();

// Finally, export the socket to be imported in app.js
export default socket;

Finally, we'll need to modify our app.js file to use this new code:

// Import the default Phoenix HTML libraries
import "phoenix_html";

// Import the User Socket code to enable websockets
import socket from "./socket";

// Import the polls channel code to enable live polling
import LivePolls from "./poll";
LivePolls.connect(socket);

We need to do this all because our poll code needs to be properly separated out from our chat code, and the socket itself needs to be more reusable than it is currently. We are also now ready to start building up our chat code, so let's create another new file in that same directory called chat.js, which we'll give a similar structure to our live polls code. We'll start off explicitly targeting the chat lobby but we'll eventually move into being able to support either version of chat:

// Import Phoenix's Socket Library
import { Socket } from "phoenix";

// Utility functions

// When we join the channel, do this
const onJoin = (res, channel) => {
console.log("Joined channel:", res);
};

// Next, create a new Phoenix Socket to reuse
const socket = new Socket("/socket");

// Connect to the socket itself
socket.connect();

const connect = (socket) => {
// Only connect to the socket if the chat channel actually exists!
const enableLiveChat = document.getElementById("enable-chat-channel");
if (!enableLiveChat) {
return;
}
// Create a channel to handle joining/sending/receiving
const channel = socket.channel("chat:lobby");

// Next, join the topic on the channel!
channel
.join()
.receive("ok", res => onJoin(res, channel))
.receive("error", res => console.log("Failed to join channel:", res));
};

// Finally, export the socket to be imported in app.js
export default { connect };

Finally, we'll hop back over to app.js and import/enable this code as well:

// // Import the Chat Socket code to enable chat
import LiveChat from "./chat";
LiveChat.connect(socket);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset