stats_panel.rb

Source Code

# frozen_string_literal: true

#--
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
# SPDX-License-Identifier: MIT-0
#++

require "rooibos"
require_relative "system_info"
require_relative "disk_usage"

# Composes SystemInfo and DiskUsage in a horizontal layout.
module StatsPanel
  Model = Data.define(:system_info, :disk_usage)

  Init = -> do
    system_info, = Rooibos.normalize_init(SystemInfo::Init.())
    disk_usage, = Rooibos.normalize_init(DiskUsage::Init.())
    Model.new(system_info:, disk_usage:)
  end

  View = -> (model, tui, disabled: false) do
    tui.layout(
      direction: :horizontal,
      constraints: [tui.constraint_percentage(50), tui.constraint_percentage(50)],
      children: [
        SystemInfo::View.call(model.system_info, tui, disabled:),
        DiskUsage::View.call(model.disk_usage, tui, disabled:),
      ]
    )
  end

  Update = -> (message, model) do
    case message
    # Key events forwarded from Router as semantic routed messages
    in { type: :routed, envelope: :fetch_system_info }
      new_model = model.with(system_info: model.system_info.with(loading: true))
      [new_model, SystemInfo.fetch_command]

    in { type: :routed, envelope: :fetch_disk_usage }
      new_model = model.with(disk_usage: model.disk_usage.with(loading: true))
      [new_model, DiskUsage.fetch_command]

    # Async command results forwarded from Router
    in { type: :system, envelope: :system_info }
      new_child, command = SystemInfo::Update.call(message, model.system_info)
      [model.with(system_info: new_child), command]

    in { type: :system, envelope: :disk_usage }
      new_child, command = DiskUsage::Update.call(message, model.disk_usage)
      [model.with(disk_usage: new_child), command]

    else
      [model, nil]
    end
  end
end