//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