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/reducer.rb

428 lines
11 KiB
Ruby
Raw Normal View History

2017-07-27 20:33:32 -04:00
# frozen_string_literal: true
2017-07-27 23:42:52 -04:00
require 'reducers/data'
class Reducer < Obredux::Reducer
2017-07-27 23:51:44 -04:00
combine data: Reducers::Data
class << self
attr_reader :screen_width, :screen_height
def screen_width=(value)
raise TypeError, "expected screen width to be an #{Integer}" unless value.is_a? Integer
raise ArgumentError, 'expected screen width to be greater than or equal to zero' unless value >= 0
@screen_width = value
end
def screen_height=(value)
raise TypeError, "expected screen height to be an #{Integer}" unless value.is_a? Integer
raise ArgumentError, 'expected screen height to be greater than or equal to zero' unless value >= 0
@screen_height = value
end
end
private
2017-07-27 22:27:42 -04:00
def initial_state
2017-07-27 21:55:30 -04:00
{
x: 0,
y: 0,
width: self.class.screen_width,
height: self.class.screen_height,
2017-07-27 21:55:30 -04:00
focus: :sidebar,
focused: true,
sidebar: {
x: 0,
y: 0,
width: Widgets::Logo::WIDTH,
height: self.class.screen_height,
2017-07-27 21:55:30 -04:00
focus: :menu,
focused: true,
logo: {
x: 0,
y: 0,
width: Widgets::Logo::WIDTH,
height: Widgets::Logo::HEIGHT,
}.freeze,
menu: {
x: 0,
y: Widgets::Logo::HEIGHT,
width: Widgets::Logo::WIDTH,
height: self.class.screen_height - Widgets::Logo::HEIGHT,
2017-07-27 21:55:30 -04:00
focused: true,
active: 0,
top: 0,
}.freeze,
}.freeze,
chat: {
x: Widgets::Logo::WIDTH + 1,
y: 0,
width: self.class.screen_width - Widgets::Logo::WIDTH - 1,
height: self.class.screen_height,
2017-07-27 21:55:30 -04:00
focus: :new_message,
focused: false,
info: {
x: Widgets::Logo::WIDTH + 1,
y: 0,
width: self.class.screen_width - Widgets::Logo::WIDTH - 1,
2017-07-27 21:55:30 -04:00
height: 2,
focused: false,
}.freeze,
new_message: {
x: Widgets::Logo::WIDTH + 1,
y: self.class.screen_height - 1,
width: self.class.screen_width - Widgets::Logo::WIDTH - 1,
2017-07-27 21:55:30 -04:00
height: 1,
focused: false,
}.freeze,
history: {
x: Widgets::Logo::WIDTH + 1,
y: 3,
width: self.class.screen_width - Widgets::Logo::WIDTH - 1,
height: self.class.screen_height - 5,
2017-07-27 21:55:30 -04:00
focused: true,
}.freeze,
}.freeze,
}.freeze
end
def reduce
2017-07-27 20:33:32 -04:00
case action
2017-07-27 21:47:18 -04:00
when Actions::WindowLeft
2017-07-27 22:27:42 -04:00
window_left
2017-07-27 22:17:41 -04:00
when Actions::WindowRight
2017-07-27 22:27:42 -04:00
window_right
2017-07-27 22:17:41 -04:00
when Actions::MenuUp
2017-07-27 22:27:42 -04:00
menu_up
2017-07-27 22:17:41 -04:00
when Actions::MenuDown
2017-07-27 22:27:42 -04:00
menu_down
2017-07-27 22:17:41 -04:00
when Actions::NewMessagePutc
2017-07-27 22:27:42 -04:00
new_message_putc
2017-07-27 22:17:41 -04:00
when Actions::NewMessageLeft
2017-07-27 22:27:42 -04:00
new_message_left
2017-07-27 22:17:41 -04:00
when Actions::NewMessageRight
2017-07-27 22:27:42 -04:00
new_message_right
2017-07-27 22:17:41 -04:00
when Actions::NewMessageHome
2017-07-27 22:27:42 -04:00
new_message_home
2017-07-27 22:17:41 -04:00
when Actions::NewMessageEnd
2017-07-27 22:27:42 -04:00
new_message_end
2017-07-27 22:17:41 -04:00
when Actions::NewMessageBackspace
2017-07-27 22:27:42 -04:00
new_message_backspace
2017-07-27 22:17:41 -04:00
when Actions::NewMessageDelete
2017-07-27 22:27:42 -04:00
new_message_delete
2017-07-27 22:17:41 -04:00
else
state
end
end
2017-07-27 21:47:18 -04:00
2017-07-27 22:27:42 -04:00
def window_left
2017-07-27 22:17:41 -04:00
state.merge(
focus: :sidebar,
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
sidebar: state[:sidebar].merge(
focused: true,
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
logo: state[:sidebar][:logo].merge(focused: state[:sidebar][:focus] == :logo).freeze,
menu: state[:sidebar][:menu].merge(focused: state[:sidebar][:focus] == :menu).freeze,
).freeze,
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
chat: state[:chat].merge(
focused: false,
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
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
2017-07-27 21:47:18 -04:00
2017-07-27 22:27:42 -04:00
def window_right
2017-07-27 22:17:41 -04:00
state.merge(
focus: :chat,
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
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-27 22:27:42 -04:00
def menu_up
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 22:17:41 -04:00
2017-07-27 23:13:05 -04:00
active_friend_index = state[:data][:active_friend_index] + 1
2017-07-27 22:17:41 -04:00
top = state[:sidebar][:menu][:top]
if active_friend_index.negative?
2017-07-27 23:13:05 -04:00
active_friend_index = state[:data][:friends].count - 1
elsif active_friend_index >= state[:data][:friends].count
2017-07-27 22:17:41 -04:00
active_friend_index = 0
end
if active_friend_index < top
top = active_friend_index
elsif active_friend_index >= top + state[:height]
top = active_friend_index - state[:height] + 1
end
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
active_friend_index: active_friend_index,
).freeze,
2017-07-27 22:17:41 -04:00
sidebar: state[:sidebar].merge(
menu: state[:sidebar][:menu].merge(
top: top,
2017-07-27 21:47:18 -04:00
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 22:27:42 -04:00
def menu_down
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
active_friend_index = state[:data][:active_friend_index] + 1
2017-07-27 22:17:41 -04:00
top = state[:sidebar][:menu][:top]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
if active_friend_index.negative?
2017-07-27 23:13:05 -04:00
active_friend_index = state[:data][:friends].count - 1
elsif active_friend_index >= state[:data][:friends].count
2017-07-27 22:17:41 -04:00
active_friend_index = 0
end
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
if active_friend_index < top
top = active_friend_index
elsif active_friend_index >= top + state[:height]
top = active_friend_index - state[:height] + 1
end
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
active_friend_index: active_friend_index,
).freeze,
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
sidebar: state[:sidebar].merge(
menu: state[:sidebar][:menu].merge(
top: top,
2017-07-27 21:47:18 -04:00
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 21:47:18 -04:00
2017-07-27 22:27:42 -04:00
def new_message_putc
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend_number = state[:data][:friends].keys[state[:data][:active_friend_index]]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if friend_number.nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend = state[:data][:friends][friend_number]
2017-07-27 22:17:41 -04:00
new_message = friend[:new_message]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
text = new_message[:text]
cursor_pos = new_message[:cursor_pos]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
text = "#{text[0...cursor_pos]}#{action.char}#{text[cursor_pos..-1]}"
cursor_pos += 1
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
friends: state[:data][:friends].merge(
friend_number => friend.merge(
new_message: new_message.merge(
text: text,
cursor_pos: cursor_pos,
).freeze,
2017-07-27 21:47:18 -04:00
).freeze,
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 22:27:42 -04:00
def new_message_left
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend_number = state[:data][:friends].keys[state[:data][:active_friend_index]]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if friend_number.nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend = state[:data][:friends][friend_number]
2017-07-27 22:17:41 -04:00
new_message = friend[:new_message]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
cursor_pos = new_message[:cursor_pos]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
cursor_pos -= 1
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
cursor_pos = 0 if cursor_pos.negative?
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
friends: state[:data][:friends].merge(
friend_number => friend.merge(
new_message: new_message.merge(
cursor_pos: cursor_pos,
).freeze,
2017-07-27 21:47:18 -04:00
).freeze,
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 22:27:42 -04:00
def new_message_right
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend_number = state[:data][:friends].keys[state[:data][:active_friend_index]]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if friend_number.nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend = state[:data][:friends][friend_number]
2017-07-27 22:17:41 -04:00
new_message = friend[:new_message]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
text = new_message[:text]
cursor_pos = new_message[:cursor_pos]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
cursor_pos += 1
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
cursor_pos = text.length if cursor_pos > text.length
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
friends: state[:data][:friends].merge(
friend_number => friend.merge(
new_message: new_message.merge(
cursor_pos: cursor_pos,
).freeze,
2017-07-27 21:47:18 -04:00
).freeze,
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 22:27:42 -04:00
def new_message_home
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend_number = state[:data][:friends].keys[state[:data][:active_friend_index]]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if friend_number.nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend = state[:data][:friends][friend_number]
2017-07-27 22:17:41 -04:00
new_message = friend[:new_message]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
friends: state[:data][:friends].merge(
friend_number => friend.merge(
new_message: new_message.merge(
cursor_pos: 0,
).freeze,
2017-07-27 21:47:18 -04:00
).freeze,
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 22:27:42 -04:00
def new_message_end
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend_number = state[:data][:friends].keys[state[:data][:active_friend_index]]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if friend_number.nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend = state[:data][:friends][friend_number]
2017-07-27 22:17:41 -04:00
new_message = friend[:new_message]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
friends: state[:data][:friends].merge(
friend_number => friend.merge(
new_message: new_message.merge(
cursor_pos: new_message[:text].length,
).freeze,
2017-07-27 21:47:18 -04:00
).freeze,
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 22:27:42 -04:00
def new_message_backspace
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend_number = state[:data][:friends].keys[state[:data][:active_friend_index]]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if friend_number.nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend = state[:data][:friends][friend_number]
2017-07-27 22:17:41 -04:00
new_message = friend[:new_message]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
text = new_message[:text]
cursor_pos = new_message[:cursor_pos]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state unless cursor_pos.positive?
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
text = "#{text[0...(cursor_pos - 1)]}#{text[cursor_pos..-1]}"
cursor_pos -= 1
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
friends: state[:data][:friends].merge(
friend_number => friend.merge(
new_message: new_message.merge(
text: text,
cursor_pos: cursor_pos,
).freeze,
2017-07-27 21:47:18 -04:00
).freeze,
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
end
2017-07-27 22:27:42 -04:00
def new_message_delete
2017-07-27 23:13:05 -04:00
return state if state[:data][:active_friend_index].nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend_number = state[:data][:friends].keys[state[:data][:active_friend_index]]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if friend_number.nil?
2017-07-27 21:47:18 -04:00
2017-07-27 23:13:05 -04:00
friend = state[:data][:friends][friend_number]
2017-07-27 22:17:41 -04:00
new_message = friend[:new_message]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
text = new_message[:text]
cursor_pos = new_message[:cursor_pos]
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
return state if cursor_pos > text.length
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
text = "#{text[0...cursor_pos]}#{text[(cursor_pos + 1)..-1]}"
2017-07-27 21:47:18 -04:00
2017-07-27 22:17:41 -04:00
state.merge(
2017-07-27 23:13:05 -04:00
data: state[:data].merge(
friends: state[:data][:friends].merge(
friend_number => friend.merge(
new_message: new_message.merge(
text: text,
cursor_pos: cursor_pos,
).freeze,
2017-07-27 21:47:18 -04:00
).freeze,
).freeze,
2017-07-27 22:17:41 -04:00
).freeze,
).freeze
2017-07-27 20:33:32 -04:00
end
end