Chat

Allows current site visitors to chat with each other
1234 ~111.71.38.43 2 days ago
1234 ~111.71.38.43 2 days ago
1234 ~111.71.38.43 2 days ago
1234 ~111.71.38.43 2 days ago
~111.71.38.43 2 days ago
1234 ~111.71.38.43 2 days ago
1234 ~111.71.38.43 2 days ago
1234 ~111.71.38.43 2 days ago
ghjkmgh ~85.73.221.22 2 days ago
sdfsdf ~94.114.2.75 1 day ago
~152.115.175.214 1 day ago
wtwetqwet ~152.115.175.214 1 day ago
4321 ~83.45.206.197 1 day ago
test ~186.54.64.120 1 day ago
asd ~186.54.64.120 1 day ago
we ~186.54.64.120 1 day ago
hello ~97.120.7.238 1 day ago
Fhfj ~37.160.231.176 1 day ago
sdlkj ~24.161.55.135 about 23 hours ago
asdads ~79.148.59.47 about 7 hours ago
ffsdfsd ~178.237.230.137 about 6 hours ago
ddsfs ~197.210.52.103 about 4 hours ago
1234 ~111.71.38.43 2 days ago
1234 ~111.71.38.43 2 days ago
~111.71.38.43 2 days ago
sdlkjlskdf ~24.161.55.135 about 23 hours ago
hi ~45.228.139.110 about 5 hours ago
hi ~157.45.178.56 2 days ago
hi ~157.45.178.56 2 days ago
hi ~157.45.178.56 2 days ago
hi ~157.45.178.56 2 days ago
hi ~157.45.178.56 2 days ago
hi ~157.45.178.56 2 days ago
Test comment ~60.60.250.161 2 days ago
test ~157.45.162.93 1 day ago
sdfgadfg ~24.161.55.135 about 23 hours ago

Code (117 LOC)

ERB (41 LOC)
app/views/chats/_demo.html.erb (16 LOC)
<ul class="nav nav-tabs">
<li class="nav-item">
<a data-toggle="tab" data-reflex="click->ChatReflex#set_color" href="#red" class="nav-link <%= "active" if active_chat?(:red) %>">Red Chat</a>
</li>
<li class="nav-item">
<a data-toggle="tab" data-reflex="click->ChatReflex#set_color" href="#yellow" class="nav-link <%= "active" if active_chat?(:yellow) %>">Yellow Chat</a>
</li>
<li class="nav-item">
<a data-toggle="tab" data-reflex="click->ChatReflex#set_color" href="#blue" class="nav-link <%= "active" if active_chat?(:blue) %>">Blue Chat</a>
</li>
</ul>
<div class="tab-content">
<%= render "color", color: "red" %>
<%= render "color", color: "yellow" %>
<%= render "color", color: "blue" %>
</div>
app/views/chats/_color.html.erb (25 LOC)
<div id="<%= color %>" data-color="<%= color %>"
data-controller="chat" data-action="chats:added@document->chat#reload cable-ready:after-morph@document->chat#scroll"
class="<%= css "tab-pane bg-white p-4 border border-top-0", "show active": active_chat?(color) %>">
<div data-target="chat.list" class="bg-light border rounded mb-2 p-3" style="height:400px; max-width:800px; overflow-y:scroll;">
<% @chats.select { |chat| chat[:color] == color }.each do |chat| %>
<% if chat_author? chat %>
<div class="<%= chat_css color %> rounded-lg border my-2 p-1 px-2 text-right w-75 float-right">
<%= chat[:message] %>
<small class="opacity-30 d-block">~me <%= distance_of_time_in_words_to_now Time.parse(chat[:created_at]) %> ago</small>
</div>
<% else %>
<div class="bg-light rounded-lg border my-2 p-1 px-2 text-left w-75 float-left">
<%= chat[:message] %>
<small class="opacity-30 d-block">~<%= chat[:author] %> <%= distance_of_time_in_words_to_now Time.parse(chat[:created_at]) %> ago</small>
</div>
<% end %>
<% end %>
</div>
<form style="max-width:800px;">
<div class="form-group">
<textarea data-target="chat.input" class="form-control border <%= chat_border_css color %>" rows="3" placeholder="Type your message..."></textarea>
</div>
<button data-action="click->chat#post" type="submit" class="btn btn-primary btn-lg">Submit</button>
</form>
</div>
JavaScript (48 LOC)
app/javascript/controllers/chat_controller.js (41 LOC)
import Rails from '@rails/ujs'
import { debounce } from 'lodash-es'
import ApplicationController from './application_controller'
let lastMessageId
const reload = controller => {
controller.stimulate('ChatReflex#reload')
}
const debouncedReload = debounce(reload, 100)
export default class extends ApplicationController {
static targets = ['list', 'input']
connect () {
super.connect()
this.scroll(100)
}
post (event) {
Rails.stopEverything(event)
lastMessageId = Math.random()
this.stimulate(
'ChatReflex#post',
this.element.dataset.color,
this.inputTarget.value,
lastMessageId
)
}
afterPost () {
this.inputTarget.value = ''
this.inputTarget.focus()
this.scroll(1)
}
scroll (delay = 10) {
const lists = document.querySelectorAll('[data-target="chat.list"]')
setTimeout(() => {
lists.forEach(e => (e.scrollTop = e.scrollHeight))
}, delay)
}
reload (event) {
const { messageId } = event.detail
if (messageId === lastMessageId) return
debouncedReload(this)
}
}
app/javascript/channels/chat_channel.js (7 LOC)
import consumer from './consumer'
import CableReady from 'cable_ready'
consumer.subscriptions.create('ChatChannel', {
received (data) {
if (data.cableReady) CableReady.perform(data.operations)
}
})
Ruby (28 LOC)
app/controllers/chats_controller.rb (6 LOC)
class ChatsController < ApplicationController
def show
session[:chat_color] ||= "red"
@chats ||= Rails.cache.read(:chats) || []
end
end
app/reflexes/chat_reflex.rb (22 LOC)
class ChatReflex < ApplicationReflex
include CableReady::Broadcaster
def post(color, message, message_id)
@chats = Rails.cache.read(:chats) || []
@chats.shift while @chats.size > 1000
@chats << {
id: message_id,
color: color,
author: request.remote_ip,
message: message,
created_at: Time.current.iso8601,
}
Rails.cache.write :chats, @chats
cable_ready["chat"].dispatch_event name: "chats:added", detail: {message_id: message_id}
cable_ready.broadcast
end
def set_color
session[:chat_color] = element[:href].delete("#")
end
def reload
end
end