require "rooibos"
require_relative "messages"
require_relative "tab_bar"
require_relative "counter_tab"
require_relative "color_tab"
require_relative "controls"
DEBUG_LOG = File.open("/tmp/tabbed_debug.log", "a")
def debug(msg)
DEBUG_LOG.puts("[#{Time.now}] #{msg}")
DEBUG_LOG.flush
end
module App
include Rooibos::Router
Command = Rooibos::Command
THEMES = %i[cyan green magenta yellow].freeze
Model = Data.define(:counter_tab, :color_tab, :tab_bar, :active_tab, :theme, :message_count)
Init = -> {
Ractor.make_shareable Model.new(
counter_tab: CounterTab::Init.call,
color_tab: ColorTab::Init.call,
tab_bar: TabBar::Init.call,
active_tab: :counter,
theme: :cyan,
message_count: 0
)
}
View = -> (model, tui) {
theme = model.theme
tab_bar_view = TabBar::View.call(model.tab_bar, tui, theme:)
active_tab_view = case model.active_tab
when :counter
CounterTab::View.call(model.counter_tab, tui, theme:)
when :color
ColorTab::View.call(model.color_tab, tui, theme:)
end
controls_view = Controls::View.call(model.active_tab, tui, theme:)
tui.layout(
direction: :vertical,
constraints: [
tui.constraint_length(3),
tui.constraint_fill(1),
tui.constraint_length(3),
],
children: [tab_bar_view, active_tab_view, controls_view]
)
}
route :tab_bar, to: TabBar
route :counter_tab, to: CounterTab
route :color_tab, to: ColorTab
COUNTER_ACTIVE = -> (_message, model) { model.active_tab == :counter }
COLOR_ACTIVE = -> (_message, model) { model.active_tab == :color }
action :quit, -> { Command.exit }
intercept_events :t,
-> (_, model) {
current_idx = THEMES.index(model.theme) || 0
new_theme = THEMES[(current_idx + 1) % THEMES.size]
model.with(theme: new_theme)
}
observe_instances_of ThemeChanged,
-> (message, model) { model.with(theme: message.theme) }
observe_all -> (message, model) {
debug "MSG: #{message.class} #{message.inspect[0..100]}"
new_count = model.message_count + 1
new_tab_bar = model.tab_bar.with(message_count: new_count)
[model.with(message_count: new_count, tab_bar: new_tab_bar), nil]
}
observe_instances_of TabSelected,
-> (message, model) {
new_tab = message.tab
return model if new_tab == model.active_tab
counter_model = model.counter_tab.with(active: new_tab == :counter)
color_model = model.color_tab.with(active: new_tab == :color)
model.with(
counter_tab: counter_model,
color_tab: color_model,
active_tab: new_tab
)
}
intercept_events :ctrl_c, :quit
intercept_events :q, :quit
only when: COUNTER_ACTIVE do
route_to :counter_tab do
forward_events :"1", as: :counter_1
forward_events :"2", as: :counter_2
forward_events :"3", as: :counter_3
forward_events :"4", as: :counter_4
forward_events :a, as: :panel_left
forward_events :b, as: :panel_right
forward_events :enter, as: :root_increment
end
end
only when: COLOR_ACTIVE do
route_to :color_tab do
forward_events :"1", as: :color_1
forward_events :"2", as: :color_2
forward_events :"3", as: :color_3
forward_events :"4", as: :color_4
forward_events :"5", as: :color_5
forward_events :"6", as: :color_6
forward_events :enter, as: :random_color
end
end
forward_instances_of RatatuiRuby::Event::Resize, broadcast: true
otherwise route_to: :tab_bar
Update = from_router
end