Live

Renders a real-time summary of the most recent events.

Users need to see the immediate result of their actions without digging through a log. Identifying the specific details of the last key press or mouse move at a glance is difficult.

This component displays a table showing the latest event of each type with its timestamp and description.

Use it to provide instant feedback for user interactions.

Examples

live_view = View::Live.new
live_view.call(state, tui, frame, area)

Source Code

# frozen_string_literal: true

# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

require_relative "../view"

# Renders a real-time summary of the most recent events.
#
# Users need to see the immediate result of their actions without digging through a log.
# Identifying the specific details of the last key press or mouse move at a glance is difficult.
#
# This component displays a table showing the latest event of each type with its timestamp and description.
#
# Use it to provide instant feedback for user interactions.
#
# === Examples
#
#   live_view = View::Live.new
#   live_view.call(state, tui, frame, area)
class View::Live
  # Renders the live event table to the given area.
  #
  # [state] ViewState containing event data and styles.
  # [tui] RatatuiRuby instance.
  # [frame] RatatuiRuby::Frame being rendered.
  # [area] RatatuiRuby::Rect defining the widget's bounds.
  #
  # === Example
  #
  #   live_view.call(state, tui, frame, area)
  def call(state, tui, frame, area)
    rows = []

    rows << tui.text_line(spans: [
      tui.text_span(content: "Type".ljust(9), style: tui.style(fg: :gray, modifiers: [:bold])),
      tui.text_span(content: "Time".ljust(10), style: tui.style(fg: :gray, modifiers: [:bold])),
      tui.text_span(content: "Description", style: tui.style(fg: :gray, modifiers: [:bold])),
    ])

    (AppAllEvents::EVENT_TYPES - [:none]).each do |type|
      event_data = state.events.live_event(type)

      class_str = type.to_s.capitalize
      time_str = event_data ? event_data[:time].strftime("%H:%M:%S") : "—"
      desc_str = event_data ? event_data[:description] : "—"

      is_lit = state.events.lit?(type)
      row_style = is_lit ? tui.style(fg: :black, bg: :green) : nil

      rows << tui.text_line(spans: [
        tui.text_span(content: class_str.ljust(9), style: row_style || tui.style(fg: :cyan)),
        tui.text_span(content: time_str.ljust(10), style: row_style || tui.style(fg: :white)),
        tui.text_span(content: desc_str, style: row_style),
      ])
    end

    widget = tui.paragraph(
      text: rows,
      scroll: [0, 0],
      block: tui.block(
        title: "Live Display",
        borders: [:all],
        border_style: tui.style(fg: state.border_color)
      )
    )
    frame.render_widget(widget, area)
  end
end