56 lines
1.9 KiB
Ruby
56 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module UI
|
|
module Windows
|
|
module_function
|
|
|
|
def chat(app, services:)
|
|
cols = app.cols
|
|
rows = app.rows
|
|
w = cols - 8
|
|
h = rows - 6
|
|
window = BBS::Window.new(title: ' Live Chat ')
|
|
window.layout(5, 3, w, h)
|
|
window.theme = app.theme
|
|
|
|
history = BBS::Widgets::ScrollView.new(lines: services[:chat].history.map { |l| format_line(l) })
|
|
history.layout(window.bounds.x + 2, window.bounds.y + 1, w - 4, h - 5)
|
|
window.add(history)
|
|
history.scroll = [history.lines.size - history.bounds.height, 0].max
|
|
|
|
input = BBS::Widgets::TextInput.new(placeholder: 'Type a message and press Enter…')
|
|
input.layout(window.bounds.x + 2, window.bounds.y + h - 3, w - 14, 1)
|
|
input.on_submit = lambda do |value, _|
|
|
next if value.strip.empty?
|
|
services[:chat].broadcast(app.context[:username] || 'Anonymous', value.strip)
|
|
input.value = ''
|
|
:handled
|
|
end
|
|
window.add(input)
|
|
|
|
close = BBS::Widgets::Button.new(label: '&Close',
|
|
on_click: ->(_) { app.close_window(window) })
|
|
close.layout(window.bounds.x + w - 11, window.bounds.y + h - 3, 9, 1)
|
|
window.add(close)
|
|
|
|
# Stash a poll lambda on the window so the app tick can pull updates
|
|
window.instance_variable_set(:@chat_poll, lambda do
|
|
new_lines = services[:chat].drain(app.session_id).map { |l| format_line(l) }
|
|
unless new_lines.empty?
|
|
history.lines = (history.lines + new_lines).last(500)
|
|
history.scroll = [history.lines.size - history.bounds.height, 0].max
|
|
end
|
|
end)
|
|
|
|
window.reset_focus
|
|
window.focus_manager.focus(input)
|
|
app.open_window(window)
|
|
window
|
|
end
|
|
|
|
def format_line(line)
|
|
" \e[2;37m#{line.timestamp}\e[0m \e[1;33m#{line.username}\e[0m: #{line.text}"
|
|
end
|
|
end
|
|
end
|