ranch-talk/lib/ranch_talk/socket_message_displayer.ex

102 lines
2.5 KiB
Elixir

defmodule RanchTalk.SocketMessageDisplayer do
use Kino.JS
use Kino.JS.Live
@spec new() :: Kino.JS.Live.t()
def new() do
Kino.JS.Live.new(__MODULE__, [])
end
@impl true
def init(messages, ctx) do
{:ok, assign(ctx, messages: messages)}
end
@impl true
def handle_info({:form_message, %{data: data}}, ctx) do
data = Map.put(data, :date, DateTime.utc_now())
broadcast_event(ctx, "add_message", data)
new_messages = [data | ctx.assigns.messages]
{:noreply, assign(ctx, messages: new_messages)}
end
@impl true
def handle_cast({:subscribe_to_form, form}, ctx) do
subscribe_to_form(form)
{:noreply, ctx}
end
@impl true
def handle_connect(ctx) do
IO.inspect(ctx)
# subscribe_to_form(ctx.assigns.form)
{:ok, ctx.assigns, ctx}
end
defp subscribe_to_form(form) do
Kino.Control.subscribe(form, :form_message)
end
asset "main.js" do
"""
var cache = [
'',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' '
]
function leftPad(str, len, ch) {
str = str + ''
len = len - str.length
if (len <= 0) return str
if (!ch && ch !== 0) ch = ' '
ch = ch + ''
if (ch === ' ' && len < 10) return cache[len] + str
var pad = ''
while (true) {
if (len & 1) pad += ch
len >>= 1
if (len) ch += ch
else break
}
return pad + str
}
function dateStr(date) {
console.log("before str", date)
const hours = leftPad(date.getHours().toString(), 2, '0')
const minutes = leftPad(date.getMinutes().toString(), 2, '0')
const seconds = leftPad(date.getSeconds().toString(), 2, '0')
return `${hours}:${minutes}:${seconds}`
}
export function init(ctx, state) {
const header = document.createElement("h1")
header.textContent = "Received Messages:"
ctx.root.appendChild(header)
const messages = document.createElement("ul")
messages.style.fontFamily = 'IosevkaLyte, monospace'
messages.style.fontSize = '16px'
ctx.root.appendChild(messages)
ctx.handleEvent("add_message", ({name, message, date}) => {
console.log("Raw Date", date)
const messageDate = new Date(date)
console.log("Message Date", messageDate)
const messageEl = document.createElement("li")
messageEl.textContent = `${dateStr(messageDate)} ${name}: ${message}`
messages.appendChild(messageEl)
})
}
"""
end
end