Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@InfiniteLee
Last active October 19, 2017 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save InfiniteLee/da41284d7e14781370f50934cbe4883b to your computer and use it in GitHub Desktop.
Save InfiniteLee/da41284d7e14781370f50934cbe4883b to your computer and use it in GitHub Desktop.
//file assets/js/chat_client.js
import {Socket, Presence} from "phoenix"
let ChatClient = {
init() {
let username = "Anonymous"
let encode = function(msg, callback) {
let builder = new flatbuffers.Builder(1024)
let body, sender, join_ref
if(msg.payload.body)
body = builder.createString(msg.payload.body)
if(msg.payload.sender)
sender = builder.createString(msg.payload.sender)
Chat.Payload.startPayload(builder)
if(body)
Chat.Payload.addBody(builder, body)
if(sender)
Chat.Payload.addSender(builder, sender)
let payload = Chat.Payload.endPayload(builder)
if(msg.join_ref)
join_ref = builder.createString(msg.join_ref)
let ref = builder.createString(msg.ref)
let topic = builder.createString(msg.topic)
let event = builder.createString(msg.event)
Chat.Message.startMessage(builder)
if(join_ref)
Chat.Message.addJoinRef(builder, join_ref)
Chat.Message.addRef(builder, ref)
Chat.Message.addTopic(builder, topic)
Chat.Message.addEvent(builder, event)
Chat.Message.addPayload(builder, payload)
let message = Chat.Message.endMessage(builder)
Chat.Message.finishMessageBuffer(builder, message)
let buf = builder.asUint8Array()
return callback(buf)
}
let decode = function(rawPayload, callback) {
let bytes = new Uint8Array(rawPayload)
let buf = new flatbuffers.ByteBuffer(bytes)
let msgBuf = Chat.Message.getRootAsMessage(buf)
let payload = msgBuf.payload()
let resp = {
join_ref: msgBuf.joinRef(),
ref: msgBuf.ref(),
topic: msgBuf.topic(),
event: msgBuf.event(),
status: msgBuf.status(),
payload: {
body: payload.body(),
sender: payload.sender(),
timestamp: payload.timestamp(),
status: payload.status(),
joins: {},
leaves: {},
state: {}
}
}
parse_presence(resp, payload, "joins")
parse_presence(resp, payload, "leaves")
parse_presence(resp, payload, "state")
return callback(resp)
}
let parse_presence = function(resp, payload, name) {
for (let i = 0; i < payload[name + "Length"](); i++) {
let payloadRoot = payload[name](i)
let respRoot = resp.payload[name]
let user = payloadRoot.user()
respRoot[user] = {metas: []}
for (let j = 0; j < payloadRoot.metasLength(); j++) {
respRoot[user].metas[j] = {
online_at: payloadRoot.metas(j).onlineAt(),
phx_ref: payloadRoot.metas(j).phxRef()
}
}
}
}
// Socket
let socket = new Socket("/socket", {
params: {
username: username,
room_id: window.room_id
},
encode: encode,
decode: decode
})
socket.connect()
socket.conn.binaryType = 'arraybuffer'
// Presence
let presences = {}
let formatTimestamp = (timestamp) => {
let date = new Date(timestamp * 1000)
return date.toLocaleTimeString()
}
let listBy = (user, {metas: metas}) => {
return {
user: user,
onlineAt: formatTimestamp(metas[0].online_at)
}
}
let userList = document.getElementById("UserList")
let render = (presences, list) => {
list['innerHTML'] = Presence.list(presences, listBy)
.map(presence => `
<li id="${list.id + ":" + presence.user}">
<b>${presence.user}</b>
<br><small>online since ${presence.onlineAt}</small>
</li>
`)
.join("")
}
// Channels
let room = socket.channel("room:lobby")
room.on("presence_state", state => {
presences = Presence.syncState(presences, state.state)
render(presences, userList)
})
room.on("presence_diff", diff => {
presences = Presence.syncDiff(presences, {joins: diff.joins, leaves: diff.leaves})
render(presences, userList)
})
room.join()
//Messages
let messageInput = document.getElementById("NewMessage")
messageInput.addEventListener("keypress", (e) => {
if (e.keyCode == 13 && messageInput.value != "") {
let message = {
body: messageInput.value,
sender: username,
}
room.push("message:new", message)
messageInput.value = ""
}
})
let messageList = document.getElementById("MessageList")
let renderMessage = (message) => {
let messageElement = document.createElement("li")
messageElement.innerHTML = `
<b>${message.sender}</b>
<i>${formatTimestamp(message.timestamp)}</i>
<p>${message.body}</p>
`
messageList.appendChild(messageElement)
messageList.scrollTop = messageList.scrollHeight;
}
room.on("message:new", message => renderMessage(message))
}
}
export default ChatClient
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment