Game catalog shows story and links; new_msg returns to menu on send

Game catalog: replaced emoji badges with the story field (word-wrapped)
and external links listed as label + URL. GameModel gains story and
external_links attributes.

New message: navigates back to idle immediately after a successful send
instead of sitting on the sent confirmation screen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-11 22:08:31 +02:00
parent bbeea678cf
commit a01dad96d9
2 changed files with 30 additions and 22 deletions

24
bbs.rb
View File

@@ -221,8 +221,7 @@ MAIN_TUI = BBS::TUI.define do
@status = 'Message cannot be empty.' @status = 'Message cannot be empty.'
else else
MESSAGES.append(@username, @input.strip[0...200]) MESSAGES.append(@username, @input.strip[0...200])
@status = 'Sent!' go :idle
@input = +''
end end
end end
key(:backspace) { @input.chop! unless @input.empty? } key(:backspace) { @input.chop! unless @input.empty? }
@@ -276,19 +275,24 @@ MAIN_TUI = BBS::TUI.define do
text 'No games found.', x: CONT_X, y: CONT_Y, style: THEME[:normal] text 'No games found.', x: CONT_X, y: CONT_Y, style: THEME[:normal]
else else
game = @items[@item_sel] game = @items[@item_sel]
links = game.external_links
text "#{@item_sel + 1}/#{@items.size} #{game.title}"[0, cont_w], text "#{@item_sel + 1}/#{@items.size} #{game.title}"[0, cont_w],
x: CONT_X, y: CONT_Y, style: THEME[:bright] x: CONT_X, y: CONT_Y, style: THEME[:bright]
text "#{game.platform} #{game.author}"[0, cont_w], text "#{game.platform} · #{game.author}"[0, cont_w],
x: CONT_X, y: CONT_Y + 1, style: THEME[:normal] x: CONT_X, y: CONT_Y + 1, style: THEME[:normal]
wordwrap(game.desc.to_s, cont_w).first(cont_h - 8).each_with_index do |l, i|
story_rows = cont_h - 4 - links.size
wordwrap(game.story, cont_w).first(story_rows).each_with_index do |l, i|
text l, x: CONT_X, y: CONT_Y + 3 + i, style: THEME[:normal] text l, x: CONT_X, y: CONT_Y + 3 + i, style: THEME[:normal]
end end
badges = []
badges << tc(:success, '[▶ Play]') unless game.play_path.empty? link_y = CONT_Y + cont_h - links.size
badges << tc(:label, '[⬇ Download]') unless game.download_path.empty? links.each_with_index do |lnk, i|
badges << tc(:bright, '[Source]') unless game.source_path.empty? text "#{tc(:label, lnk[:label])} #{lnk[:url]}"[0, cont_w],
badges << tc(:header, '[Docs]') unless game.docs_path.empty? x: CONT_X, y: link_y + i
text badges.join(' '), x: CONT_X, y: CONT_Y + cont_h - 3 end
text '↑↓ navigate q back', x: CONT_X, y: CONT_Y + cont_h, style: THEME[:normal] text '↑↓ navigate q back', x: CONT_X, y: CONT_Y + cont_h, style: THEME[:normal]
end end
end end

View File

@@ -1,9 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
class GameModel class GameModel
attr_reader :title, :platform, :author, :desc, attr_reader :title, :platform, :author, :desc, :story,
:play_path, :download_path, :source_path, :docs_path, :play_path, :download_path, :source_path, :docs_path,
:release_count :release_count, :external_links
def initialize(entry) def initialize(entry)
sw = entry['software'] || {} sw = entry['software'] || {}
@@ -12,10 +12,14 @@ class GameModel
@platform = sw['platform'].to_s @platform = sw['platform'].to_s
@author = sw['author'].to_s @author = sw['author'].to_s
@desc = sw['desc'].to_s @desc = sw['desc'].to_s
@story = sw['story'].to_s
@play_path = latest['htmlFolderPath'].to_s @play_path = latest['htmlFolderPath'].to_s
@download_path = latest['cartridgePath'].to_s @download_path = latest['cartridgePath'].to_s
@source_path = latest['sourcePath'].to_s @source_path = latest['sourcePath'].to_s
@docs_path = latest['docsFolderPath'].to_s @docs_path = latest['docsFolderPath'].to_s
@release_count = (entry['releases'] || []).length @release_count = (entry['releases'] || []).length
@external_links = (sw['externalLinks'] || []).filter_map do |l|
{ label: l['label'].to_s, url: l['url'].to_s } unless l['url'].to_s.empty?
end
end end
end end