Archived
1
0
Fork 0
This repository has been archived on 2023-03-27. You can view files and clone it, but cannot push or open issues or pull requests.
cli-old/lib/main.rb

249 lines
5.5 KiB
Ruby
Raw Normal View History

2017-07-21 02:48:04 -04:00
# frozen_string_literal: true
require 'thread'
2017-07-21 11:23:43 -04:00
require 'faker'
2017-07-24 08:48:22 -04:00
require 'screen'
2017-07-21 10:00:01 -04:00
2017-07-21 02:48:04 -04:00
class Main
def self.inherited(_base)
raise "#{self} is final"
end
def self.mutex
(@mutex ||= Mutex.new).tap { freeze }
end
def initialize
raise "#{self.class} is singleton" unless self.class.mutex.try_lock
call
end
private
def call
before_loop
loop do
before_iteration
sleep
after_iteration
end
after_loop
end
def sleep
super 0.01
end
def before_loop
2017-07-24 08:48:22 -04:00
@screen = Screen.new
2017-07-22 05:46:15 -04:00
Style.default = Style.new
2017-07-21 02:48:04 -04:00
end
def after_loop
2017-07-24 08:48:22 -04:00
@screen.close
2017-07-21 02:48:04 -04:00
end
2017-07-21 07:41:05 -04:00
def before_iteration
2017-07-24 18:38:23 -04:00
@screen.props = state
2017-07-24 08:48:22 -04:00
@screen.render
2017-07-21 07:41:05 -04:00
end
2017-07-21 02:48:04 -04:00
def after_iteration
2017-07-24 08:48:22 -04:00
@screen.poll
2017-07-21 08:03:53 -04:00
end
2017-07-24 18:38:23 -04:00
def state
@state ||= {
2017-07-25 09:46:31 -04:00
x: 0,
y: 0,
width: Curses.stdscr.maxx,
height: Curses.stdscr.maxy,
2017-07-24 18:38:23 -04:00
focus: :sidebar,
2017-07-25 09:46:31 -04:00
focused: true,
2017-07-25 12:22:38 -04:00
on_window_left: method(:on_window_left),
on_window_right: method(:on_window_right),
2017-07-25 12:22:38 -04:00
on_menu_up: method(:on_menu_up),
on_menu_down: method(:on_menu_down),
2017-07-24 18:38:23 -04:00
sidebar: {
2017-07-25 09:46:31 -04:00
x: 0,
y: 0,
width: Widgets::Logo::WIDTH,
height: Curses.stdscr.maxy,
2017-07-24 18:38:23 -04:00
focus: :menu,
2017-07-25 09:46:31 -04:00
focused: true,
2017-07-25 10:29:01 -04:00
logo: {
2017-07-25 09:46:31 -04:00
x: 0,
y: 0,
width: Widgets::Logo::WIDTH,
2017-07-25 10:29:01 -04:00
height: Widgets::Logo::HEIGHT,
}.freeze,
menu: {
x: 0,
y: Widgets::Logo::HEIGHT,
width: Widgets::Logo::WIDTH,
2017-07-25 09:46:31 -04:00
height: Curses.stdscr.maxy - Widgets::Logo::HEIGHT,
2017-07-24 18:38:23 -04:00
focused: true,
2017-07-25 09:46:31 -04:00
2017-07-24 18:38:23 -04:00
active: 0,
top: 0,
items: 1.upto(Curses.stdscr.maxy).map do
{
name: Faker::Name.name,
online: [false, true].sample,
}
end,
}.freeze,
}.freeze,
2017-07-25 09:46:31 -04:00
2017-07-24 18:38:23 -04:00
chat: {
2017-07-25 10:29:01 -04:00
x: Widgets::Logo::WIDTH,
2017-07-25 09:46:31 -04:00
y: 0,
width: Curses.stdscr.maxx - Widgets::Logo::WIDTH,
height: Curses.stdscr.maxy,
2017-07-24 18:38:23 -04:00
focus: :new_message,
2017-07-25 09:46:31 -04:00
focused: false,
2017-07-24 18:38:23 -04:00
info: {
2017-07-25 10:29:01 -04:00
x: Widgets::Logo::WIDTH,
2017-07-25 09:46:31 -04:00
y: 0,
width: Curses.stdscr.maxx - Widgets::Logo::WIDTH,
height: 2,
focused: false,
2017-07-24 18:38:23 -04:00
name: Faker::Name.name,
public_key: SecureRandom.hex(32),
}.freeze,
2017-07-25 09:46:31 -04:00
2017-07-24 18:38:23 -04:00
new_message: {
2017-07-25 10:29:01 -04:00
x: Widgets::Logo::WIDTH,
y: Curses.stdscr.maxy - 1,
2017-07-25 09:46:31 -04:00
width: Curses.stdscr.maxx - Widgets::Logo::WIDTH,
2017-07-25 10:29:01 -04:00
height: 1,
2017-07-25 09:46:31 -04:00
focused: false,
2017-07-24 18:38:23 -04:00
text: '',
cursor_pos: 0,
}.freeze,
2017-07-25 09:46:31 -04:00
2017-07-24 18:38:23 -04:00
history: {
2017-07-25 10:29:01 -04:00
x: Widgets::Logo::WIDTH,
y: 2,
2017-07-25 09:46:31 -04:00
width: Curses.stdscr.maxx - Widgets::Logo::WIDTH,
2017-07-25 10:29:01 -04:00
height: Curses.stdscr.maxy - 3,
2017-07-25 09:46:31 -04:00
focused: true,
2017-07-24 18:38:23 -04:00
messages: 1.upto(100).map do
{
out: rand <= 0.2,
time: Faker::Time.forward,
name: Faker::Name.name,
text: Faker::Lorem.sentence,
}
end,
}.freeze,
}.freeze,
}.freeze
end
def on_window_left
@state = state.merge(
focus: :sidebar,
sidebar: state[:sidebar].merge(
focused: true,
logo: state[:sidebar][:logo].merge(focused: state[:sidebar][:focus] == :logo).freeze,
menu: state[:sidebar][:menu].merge(focused: state[:sidebar][:focus] == :menu).freeze,
).freeze,
chat: state[:chat].merge(
focused: false,
info: state[:chat][:info].merge(focused: false).freeze,
new_message: state[:chat][:new_message].merge(focused: false).freeze,
history: state[:chat][:history].merge(focused: false).freeze,
).freeze,
).freeze
end
def on_window_right
@state = state.merge(
focus: :sidebar,
sidebar: state[:sidebar].merge(
focused: true,
logo: state[:sidebar][:logo].merge(focused: false).freeze,
menu: state[:sidebar][:menu].merge(focused: false).freeze,
).freeze,
chat: state[:chat].merge(
focused: false,
info: state[:chat][:info].merge(focused: state[:chat][:focus] == :info).freeze,
new_message: state[:chat][:new_message].merge(focused: state[:chat][:focus] == :new_message).freeze,
history: state[:chat][:history].merge(focused: state[:chat][:focus] == :history).freeze,
).freeze,
).freeze
end
2017-07-25 12:22:38 -04:00
def on_menu_up
active = state[:sidebar][:menu][:active]
top = state[:sidebar][:menu][:top]
items = state[:sidebar][:menu][:items]
height = state[:sidebar][:menu][:height]
active -= 1
active = items.count - 1 if active.negative?
if active < top
top = active
elsif active >= top + height
top = active - height + 1
end
@state = state.merge(
sidebar: state[:sidebar].merge(
menu: state[:sidebar][:menu].merge(
active: active,
top: top,
).freeze,
).freeze,
).freeze
end
def on_menu_down
active = state[:sidebar][:menu][:active]
top = state[:sidebar][:menu][:top]
items = state[:sidebar][:menu][:items]
height = state[:sidebar][:menu][:height]
active += 1
active = 0 if active >= items.count
if active < top
top = active
elsif active >= top + height
top = active - height + 1
end
@state = state.merge(
sidebar: state[:sidebar].merge(
menu: state[:sidebar][:menu].merge(
active: active,
top: top,
).freeze,
).freeze,
).freeze
end
end