Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chatting functionality #9

Merged
merged 4 commits into from
Mar 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import "phoenix_html"
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".

// import socket from "./socket"
import socket from "./socket"

$(function () {
$('[data-toggle="tooltip"]').tooltip()
Expand Down
38 changes: 33 additions & 5 deletions assets/js/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,38 @@ let socket = new Socket("/socket", {params: {token: window.userToken}})

socket.connect()

// Now that you are connected, you can join channels with a topic:
let channel = socket.channel("topic:subtopic", {})
channel.join()
.receive("ok", resp => { console.log("Joined successfully", resp) })
.receive("error", resp => { console.log("Unable to join", resp) })
let channelRoomId = window.channelRoomId;

if (channelRoomId) {
// Now that you are connected, you can join channels with a topic:
let channel = socket.channel(`room:${channelRoomId}`, {})
channel.join()
.receive("ok", resp => { console.log("Joined successfully", resp) })
.receive("error", resp => { console.log("Unable to join", resp) })

channel.on(`room:${channelRoomId}:new_message`, (message) => {
console.log("message", message)
renderMessage(message)
});

document.querySelector("#new-message").addEventListener('submit', (e) => {
e.preventDefault()
let messageInput = e.target.querySelector('#message-content')

channel.push('message:add', { message: messageInput.value })

messageInput.value = ""
});
}

const renderMessage = function(message) {
let messageTemplate = `
<li class="list-group-item">
<strong>${message.user.username}</strong>:
${message.content}
</li>
`
document.querySelector("#messages").innerHTML += messageTemplate
};

export default socket
20 changes: 20 additions & 0 deletions lib/prater_web/channels/room_channel.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule PraterWeb.RoomChannel do
use PraterWeb, :channel

alias Prater.Repo
alias Prater.Auth.User

def join("room:" <> room_id, _params, socket) do
{:ok, %{channel: "room:#{room_id}"}, assign(socket, :room_id, room_id)}
end

def handle_in("message:add", %{"message" => content}, socket) do
room_id = socket.assigns[:room_id]
user = Repo.get(User, socket.assigns[:current_user_id])
message = %{content: content, user: %{username: user.username}}

broadcast!(socket, "room:#{room_id}:new_message", message)

{:reply, :ok, socket}
end
end
14 changes: 11 additions & 3 deletions lib/prater_web/channels/user_socket.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule PraterWeb.UserSocket do
use Phoenix.Socket

## Channels
# channel "room:*", PraterWeb.RoomChannel
channel "room:*", PraterWeb.RoomChannel

## Transports
transport :websocket, Phoenix.Transports.WebSocket
Expand All @@ -19,10 +19,18 @@ defmodule PraterWeb.UserSocket do
#
# See `Phoenix.Token` documentation for examples in
# performing token verification on connect.
def connect(_params, socket) do
{:ok, socket}
@max_age 24 * 60 * 60
def connect(%{"token" => token}, socket) do
case Phoenix.Token.verify(socket, "user token", token, max_age: @max_age) do
{:ok, user_id} ->
{:ok, assign(socket, :current_user_id, user_id)}
{:error, _reason} ->
:error
end
end

def connect(_params, _socket), do: :error

# Socket id's are topics that allow you to identify all sockets for a given user:
#
# def id(socket), do: "user_socket:#{socket.assigns.user_id}"
Expand Down
2 changes: 2 additions & 0 deletions lib/prater_web/plugs/set_current_user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ defmodule PraterWeb.Plugs.SetCurrentUser do

cond do
current_user = user_id && Repo.get(User, user_id) ->
token = Phoenix.Token.sign(conn, "user token", user_id)
conn
|> assign(:current_user, current_user)
|> assign(:user_signed_in?, true)
|> assign(:user_token, token)
true ->
conn
|> assign(:current_user, nil)
Expand Down
1 change: 1 addition & 0 deletions lib/prater_web/templates/layout/app.html.eex
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<script>window.userToken = "<%= assigns[:user_token] %>"</script>
<script src="<%= static_path(@conn, "/js/app.js") %>"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions lib/prater_web/templates/room/show.html.eex
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<script>window.channelRoomId = "<%= @room.id %>"</script>

<h2><%= @room.name %></h2>

<%= if Prater.Auth.Authorizer.can_manage?(@current_user, @room) do %>
Expand All @@ -8,3 +10,12 @@
<% end %>

<div><%= @room.description %></div>

<ul class="list-group mt-5" id="messages"></ul>

<form class="input-group mt-3" id="new-message">
<input type="text" class="form-control" placeholder="Message #<%= @room.name %>" id="message-content" />
<div class="input-group-append">
<button class="btn btn-outline-success" type="submit">Send</button>
</div>
</div>