update
This commit is contained in:
123
lib/tui/helpers.rb
Normal file
123
lib/tui/helpers.rb
Normal file
@@ -0,0 +1,123 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module TUIHelpers
|
||||
# ── Layout ───────────────────────────────────────────────────────────────────
|
||||
|
||||
def content_width = term_cols - CONTENT_X - 1
|
||||
def content_height = term_rows - 4
|
||||
|
||||
# ── Theming ──────────────────────────────────────────────────────────────────
|
||||
|
||||
def themed_color(style, text)
|
||||
"#{THEME.fetch(style, THEME[:normal])}#{text}#{THEME[:reset]}"
|
||||
end
|
||||
|
||||
def format_date(iso_string)
|
||||
Time.parse(iso_string.to_s).strftime('%Y-%m-%d')
|
||||
rescue
|
||||
iso_string.to_s
|
||||
end
|
||||
|
||||
# ── Chrome ───────────────────────────────────────────────────────────────────
|
||||
|
||||
def render_chrome
|
||||
screen_fill background: :black
|
||||
panel_height = term_rows - 1
|
||||
|
||||
box x: 1, y: 1, width: LEFT_WIDTH, height: panel_height,
|
||||
style: THEME[:border], background: :black
|
||||
box x: LEFT_WIDTH + 1, y: 1, width: term_cols - LEFT_WIDTH, height: panel_height,
|
||||
title: " #{@page_title} │ #{@username} │ #{ONLINE.count} online ",
|
||||
style: THEME[:border], background: :black
|
||||
|
||||
list MENU_ITEMS.map { |item| item[0, LEFT_WIDTH - 4] },
|
||||
x: 2, y: CONTENT_Y,
|
||||
selected: @menu_selection,
|
||||
style: THEME[:normal],
|
||||
highlight: THEME[:selected]
|
||||
|
||||
bar y: term_rows,
|
||||
content: " \e[1;37;43m↑↓\e[0;30;43m Navigate \e[1;37;43mEnter\e[0;30;43m Select " \
|
||||
"\e[1;37;43mQ\e[0;30;43m Back \e[1;37;43mR\e[0;30;43m Refresh",
|
||||
style: THEME[:status]
|
||||
end
|
||||
|
||||
# ── Page renderers ────────────────────────────────────────────────────────────
|
||||
|
||||
def render_messages
|
||||
(@items[@scroll, content_height] || []).each_with_index do |message, index|
|
||||
line = "#{themed_color(:label, message.timestamp)} " \
|
||||
"#{themed_color(:bright, message.username)}: #{message.text}"
|
||||
text line[0, content_width], x: CONTENT_X, y: CONTENT_Y + index
|
||||
end
|
||||
text "#{@items.size} msg(s) ↑↓ scroll r refresh q back",
|
||||
x: CONTENT_X, y: CONTENT_Y + content_height, style: THEME[:label]
|
||||
end
|
||||
|
||||
def render_wiki_list
|
||||
list_height = content_height - 3
|
||||
visible = @items[@scroll, list_height] || []
|
||||
if visible.empty?
|
||||
text 'No items found.', x: CONTENT_X, y: CONTENT_Y, style: THEME[:normal]
|
||||
else
|
||||
list visible.map { |wiki_page| wiki_page.title[0, content_width - 2] },
|
||||
x: CONTENT_X,
|
||||
y: CONTENT_Y,
|
||||
selected: @item_selection - @scroll,
|
||||
style: THEME[:normal],
|
||||
highlight: THEME[:selected]
|
||||
if (wiki_page = @items[@item_selection])
|
||||
hint = wiki_page.description.to_s.strip[0, content_width]
|
||||
text hint, x: CONTENT_X, y: CONTENT_Y + content_height - 2, style: THEME[:normal] unless hint.empty?
|
||||
end
|
||||
end
|
||||
text '↑↓ navigate Enter read r refresh q back',
|
||||
x: CONTENT_X, y: CONTENT_Y + content_height, style: THEME[:label]
|
||||
end
|
||||
|
||||
def render_page_view
|
||||
text @page_metadata[0, content_width], x: CONTENT_X, y: CONTENT_Y, style: THEME[:label]
|
||||
(@detail[@scroll, content_height - 2] || []).each_with_index do |line, index|
|
||||
text line[0, content_width], x: CONTENT_X, y: CONTENT_Y + 2 + index, style: THEME[:normal]
|
||||
end
|
||||
text "#{@scroll + 1}/#{@detail.size} ↑↓ scroll q back",
|
||||
x: CONTENT_X, y: CONTENT_Y + content_height, style: THEME[:label]
|
||||
end
|
||||
|
||||
def render_game_card
|
||||
if @items.empty?
|
||||
text 'No games found.', x: CONTENT_X, y: CONTENT_Y, style: THEME[:normal]
|
||||
return
|
||||
end
|
||||
game = @items[@item_selection]
|
||||
links = game.external_links
|
||||
|
||||
text "#{@item_selection + 1}/#{@items.size} #{game.title}"[0, content_width],
|
||||
x: CONTENT_X, y: CONTENT_Y, style: THEME[:bright]
|
||||
text "#{game.platform} · #{game.author}"[0, content_width],
|
||||
x: CONTENT_X, y: CONTENT_Y + 1, style: THEME[:normal]
|
||||
|
||||
story_row_count = content_height - 4 - links.size
|
||||
wordwrap(game.story, content_width).first(story_row_count).each_with_index do |line, index|
|
||||
text line, x: CONTENT_X, y: CONTENT_Y + 3 + index, style: THEME[:normal]
|
||||
end
|
||||
|
||||
link_start_row = CONTENT_Y + content_height - links.size
|
||||
links.each_with_index do |link, index|
|
||||
text "#{themed_color(:label, link[:label])} #{link[:url]}"[0, content_width],
|
||||
x: CONTENT_X, y: link_start_row + index
|
||||
end
|
||||
|
||||
text '↑↓ navigate r refresh q back',
|
||||
x: CONTENT_X, y: CONTENT_Y + content_height, style: THEME[:label]
|
||||
end
|
||||
|
||||
def render_online_users
|
||||
@items.each_with_index do |username, index|
|
||||
indicator = username == @username ? themed_color(:label, ' ← you') : ''
|
||||
text themed_color(:bright, username) + indicator, x: CONTENT_X, y: CONTENT_Y + index
|
||||
end
|
||||
text "#{@items.size} user(s) online r refresh q back",
|
||||
x: CONTENT_X, y: CONTENT_Y + content_height, style: THEME[:label]
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user