Move code to reducer
This commit is contained in:
parent
ba622dde1c
commit
b5d71df782
|
@ -23,6 +23,9 @@ Metrics/LineLength:
|
|||
Metrics/MethodLength:
|
||||
Enabled: false
|
||||
|
||||
Metrics/ModuleLength:
|
||||
Enabled: false
|
||||
|
||||
Metrics/ParameterLists:
|
||||
Enabled: false
|
||||
|
||||
|
|
|
@ -3,6 +3,25 @@
|
|||
require 'obredux'
|
||||
|
||||
require 'actions/load_friends'
|
||||
require 'actions/friend_request'
|
||||
require 'actions/friend_message'
|
||||
require 'actions/change_friend_name'
|
||||
require 'actions/change_friend_status'
|
||||
require 'actions/change_friend_status_message'
|
||||
require 'actions/new_message_enter'
|
||||
require 'actions/new_message_putc'
|
||||
|
||||
module Actions
|
||||
class WindowLeft < Obredux::Action; end
|
||||
class WindowRight < Obredux::Action; end
|
||||
|
||||
class MenuUp < Obredux::Action; end
|
||||
class MenuDown < Obredux::Action; end
|
||||
|
||||
class NewMessageLeft < Obredux::Action; end
|
||||
class NewMessageRight < Obredux::Action; end
|
||||
class NewMessageHome < Obredux::Action; end
|
||||
class NewMessageEnd < Obredux::Action; end
|
||||
class NewMessageBackspace < Obredux::Action; end
|
||||
class NewMessageDelete < Obredux::Action; end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Actions
|
||||
class ChangeFriendName < Obredux::Action
|
||||
attr_reader :friend, :new_name
|
||||
|
||||
def initialize(friend, new_name)
|
||||
self.friend = friend
|
||||
self.new_name = new_name
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def friend=(value)
|
||||
raise TypeError, "expected friend to be a #{Tox::Friend}" unless value.is_a? Tox::Friend
|
||||
@friend = value
|
||||
end
|
||||
|
||||
def new_name=(value)
|
||||
raise TypeError, "expected name to be a #{String}" unless value.is_a? String
|
||||
@new_name = value.frozen? ? value : value.dup.freeze
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Actions
|
||||
class ChangeFriendStatus < Obredux::Action
|
||||
attr_reader :friend, :new_status
|
||||
|
||||
def initialize(friend, new_status)
|
||||
self.friend = friend
|
||||
self.new_status = new_status
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def friend=(value)
|
||||
raise TypeError, "expected friend to be a #{Tox::Friend}" unless value.is_a? Tox::Friend
|
||||
@friend = value
|
||||
end
|
||||
|
||||
def new_status=(value)
|
||||
raise TypeError, "expected status to be a #{Symbol}" unless value.is_a? Symbol
|
||||
@new_status = value.frozen? ? value : value.dup.freeze
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Actions
|
||||
class ChangeFriendStatusMessage < Obredux::Action
|
||||
attr_reader :friend, :new_status_message
|
||||
|
||||
def initialize(friend, new_status_message)
|
||||
self.friend = friend
|
||||
self.new_status_message = new_status_message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def friend=(value)
|
||||
raise TypeError, "expected friend to be a #{Tox::Friend}" unless value.is_a? Tox::Friend
|
||||
@friend = value
|
||||
end
|
||||
|
||||
def new_status_message=(value)
|
||||
raise TypeError, "expected status message to be a #{String}" unless value.is_a? String
|
||||
@new_status_message = value.frozen? ? value : value.dup.freeze
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Actions
|
||||
class FriendMessage < Obredux::Action
|
||||
attr_reader :friend, :text
|
||||
|
||||
def initialize(friend, text)
|
||||
self.friend = friend
|
||||
self.text = text
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def friend=(value)
|
||||
raise TypeError, "expected friend to be a #{Tox::Friend}" unless value.is_a? Tox::Friend
|
||||
@friend = value
|
||||
end
|
||||
|
||||
def text=(value)
|
||||
raise TypeError, "expected text to be a #{String}" unless value.is_a? String
|
||||
@text = value.frozen? ? value : value.dup.freeze
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Actions
|
||||
class FriendRequest < Obredux::Action
|
||||
attr_reader :tox_client, :public_key
|
||||
|
||||
def initialize(tox_client, public_key)
|
||||
self.tox_client = tox_client
|
||||
self.public_key = public_key
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tox_client=(value)
|
||||
raise TypeError, "expected Tox client to be a #{Tox::Client}" unless value.is_a? Tox::Client
|
||||
@tox_client = value
|
||||
end
|
||||
|
||||
def public_key=(value)
|
||||
raise TypeError, "expected public key to be a #{Tox::PublicKey}" unless value.is_a? Tox::PublicKey
|
||||
@public_key = value
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Actions
|
||||
class NewMessageEnter < Obredux::Action
|
||||
attr_reader :tox_client
|
||||
|
||||
def initialize(tox_client)
|
||||
self.tox_client = tox_client
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tox_client=(value)
|
||||
raise TypeError, "expected Tox client to be a #{Tox::Client}" unless value.is_a? Tox::Client
|
||||
@tox_client = value
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Actions
|
||||
class NewMessagePutc < Obredux::Action
|
||||
attr_reader :char
|
||||
|
||||
def initialize(char)
|
||||
self.char = char
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def char=(value)
|
||||
raise TypeError, "expected char to be a #{String}" unless value.is_a? String
|
||||
raise ArguentError, 'expected char to have length 1' unless value.length == 1
|
||||
@char = value.frozen? ? value : value.dup.freeze
|
||||
end
|
||||
end
|
||||
end
|
372
lib/main.rb
372
lib/main.rb
|
@ -27,6 +27,13 @@ class Main
|
|||
|
||||
private
|
||||
|
||||
def store
|
||||
return @store if @store
|
||||
@store = Obredux::Store.new Reducer
|
||||
@store.state = initial_state
|
||||
@store
|
||||
end
|
||||
|
||||
def call
|
||||
tox_options = Tox::Options.new
|
||||
tox_options.savedata = File.binread SAVEDATA_FILENAME if File.exist? SAVEDATA_FILENAME
|
||||
|
@ -57,79 +64,32 @@ private
|
|||
|
||||
def on_iteration
|
||||
@screen.poll
|
||||
@screen.props = state
|
||||
@screen.props = store.state
|
||||
@screen.draw
|
||||
end
|
||||
|
||||
def on_friends_load(friends)
|
||||
@state = Reducer.call state, Actions::LoadFriends.new(friends)
|
||||
store.dispatch Actions::LoadFriends.new friends
|
||||
end
|
||||
|
||||
def on_friend_request(public_key, _text)
|
||||
friend = @tox_client.friend_add_norequest public_key
|
||||
|
||||
@state = state.merge(
|
||||
active_friend_index: state[:active_friend_index] || state[:friends].count,
|
||||
|
||||
friends: state[:friends].merge(
|
||||
friend.number => {
|
||||
public_key: friend.public_key.to_hex.freeze,
|
||||
name: friend.name.freeze,
|
||||
status: friend.status,
|
||||
status_message: friend.status_message.freeze,
|
||||
history: [].freeze,
|
||||
new_message: {
|
||||
text: '',
|
||||
cursor_pos: 0,
|
||||
}.freeze,
|
||||
}.freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::FriendRequest.new @tox_client, public_key
|
||||
end
|
||||
|
||||
def on_friend_message(friend, text)
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend.number => state[:friends][friend.number].merge(
|
||||
history: (state[:friends][friend.number][:history] + [
|
||||
out: false,
|
||||
time: Time.now.utc.freeze,
|
||||
name: friend.name.freeze,
|
||||
text: text.freeze,
|
||||
]).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::FriendMessage.new friend, text
|
||||
end
|
||||
|
||||
def on_friend_name_change(friend, name)
|
||||
@state = @state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend.number => state[:friends][friend.number].merge(
|
||||
name: name.freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::ChangeFriendName.new friend, name
|
||||
end
|
||||
|
||||
def on_friend_status_message_change(friend, status_message)
|
||||
@state = @state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend.number => state[:friends][friend.number].merge(
|
||||
status_message: status_message.freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::ChangeFriendStatusMessage.new friend, status_message
|
||||
end
|
||||
|
||||
def on_friend_status_change(friend, status)
|
||||
@state = @state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend.number => state[:friends][friend.number].merge(
|
||||
status: status,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::ChangeFriendStatus.new friend, status
|
||||
end
|
||||
|
||||
####################
|
||||
|
@ -137,335 +97,59 @@ private
|
|||
####################
|
||||
|
||||
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
|
||||
store.dispatch Actions::WindowLeft.new
|
||||
end
|
||||
|
||||
def on_window_right
|
||||
@state = state.merge(
|
||||
focus: :chat,
|
||||
|
||||
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
|
||||
store.dispatch Actions::WindowRight.new
|
||||
end
|
||||
|
||||
def on_menu_up
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
active_friend_index = state[:active_friend_index] + 1
|
||||
top = state[:sidebar][:menu][:top]
|
||||
|
||||
if active_friend_index.negative?
|
||||
active_friend_index = state[:friends].count - 1
|
||||
elsif active_friend_index >= state[:friends].count
|
||||
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 = state.merge(
|
||||
active_friend_index: active_friend_index,
|
||||
|
||||
sidebar: state[:sidebar].merge(
|
||||
menu: state[:sidebar][:menu].merge(
|
||||
top: top,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::MenuUp.new
|
||||
end
|
||||
|
||||
def on_menu_down
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
active_friend_index = state[:active_friend_index] + 1
|
||||
top = state[:sidebar][:menu][:top]
|
||||
|
||||
if active_friend_index.negative?
|
||||
active_friend_index = state[:friends].count - 1
|
||||
elsif active_friend_index >= state[:friends].count
|
||||
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 = state.merge(
|
||||
active_friend_index: active_friend_index,
|
||||
|
||||
sidebar: state[:sidebar].merge(
|
||||
menu: state[:sidebar][:menu].merge(
|
||||
top: top,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::MenuDown.new
|
||||
end
|
||||
|
||||
def on_new_message_enter
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
text = state[:friends][friend_number][:new_message][:text].strip.freeze
|
||||
|
||||
return if text.empty?
|
||||
|
||||
error = false
|
||||
|
||||
begin
|
||||
@tox_client.friend(friend_number).send_message text
|
||||
rescue
|
||||
error = true
|
||||
end
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => state[:friends][friend_number].merge(
|
||||
new_message: state[:friends][friend_number][:new_message].merge(
|
||||
text: '',
|
||||
cursor_pos: 0,
|
||||
),
|
||||
|
||||
history: (state[:friends][friend_number][:history] + [
|
||||
error: error,
|
||||
out: true,
|
||||
received: false,
|
||||
time: Time.now.utc.freeze,
|
||||
name: @tox_client.name.freeze,
|
||||
text: text,
|
||||
]).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessageEnter.new @tox_client
|
||||
end
|
||||
|
||||
def on_new_message_putc(char)
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
text = "#{text[0...cursor_pos]}#{char}#{text[cursor_pos..-1]}"
|
||||
cursor_pos += 1
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
text: text,
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessagePutc.new char
|
||||
end
|
||||
|
||||
def on_new_message_left
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
cursor_pos -= 1
|
||||
|
||||
cursor_pos = 0 if cursor_pos.negative?
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessageLeft.new
|
||||
end
|
||||
|
||||
def on_new_message_right
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
cursor_pos += 1
|
||||
|
||||
cursor_pos = text.length if cursor_pos > text.length
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessageRight.new
|
||||
end
|
||||
|
||||
def on_new_message_home
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: 0,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessageHome.new
|
||||
end
|
||||
|
||||
def on_new_message_end
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: new_message[:text].length,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessageEnd.new
|
||||
end
|
||||
|
||||
def on_new_message_backspace
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
return unless cursor_pos.positive?
|
||||
|
||||
text = "#{text[0...(cursor_pos - 1)]}#{text[cursor_pos..-1]}"
|
||||
cursor_pos -= 1
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
text: text,
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessageBackspace.new
|
||||
end
|
||||
|
||||
def on_new_message_delete
|
||||
return if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
return if cursor_pos > text.length
|
||||
|
||||
text = "#{text[0...cursor_pos]}#{text[(cursor_pos + 1)..-1]}"
|
||||
|
||||
@state = state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
text: text,
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
store.dispatch Actions::NewMessageDelete.new
|
||||
end
|
||||
|
||||
#########
|
||||
# State #
|
||||
#########
|
||||
|
||||
def state
|
||||
@state ||= {
|
||||
def initial_state
|
||||
store.state ||= {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: Curses.stdscr.maxx,
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Obredux
|
||||
UNDEFINED = Object.new.freeze
|
||||
|
||||
class Action; end
|
||||
|
||||
class Init < Action; end
|
||||
|
||||
class Store
|
||||
attr_reader :reducer, :state
|
||||
|
||||
attr_writer :state
|
||||
|
||||
def initialize(reducer)
|
||||
@reducer = reducer
|
||||
# @state = reducer.call UNDEFINED, Init.new
|
||||
end
|
||||
|
||||
def dispatch(action)
|
||||
@state = reducer.call state, action
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
357
lib/reducer.rb
357
lib/reducer.rb
|
@ -21,6 +21,363 @@ module Reducer
|
|||
]
|
||||
end.to_h.freeze,
|
||||
).freeze
|
||||
when Actions::FriendRequest
|
||||
friend = action.tox_client.friend_add_norequest action.public_key
|
||||
|
||||
state.merge(
|
||||
active_friend_index: state[:active_friend_index] || state[:friends].count,
|
||||
|
||||
friends: state[:friends].merge(
|
||||
friend.number => {
|
||||
public_key: friend.public_key.to_hex.freeze,
|
||||
name: friend.name.freeze,
|
||||
status: friend.status,
|
||||
status_message: friend.status_message.freeze,
|
||||
history: [].freeze,
|
||||
new_message: {
|
||||
text: '',
|
||||
cursor_pos: 0,
|
||||
}.freeze,
|
||||
}.freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::FriendMessage
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
action.friend.number => state[:friends][action.friend.number].merge(
|
||||
history: (state[:friends][action.friend.number][:history] + [
|
||||
out: false,
|
||||
time: Time.now.utc.freeze,
|
||||
name: action.friend.name.freeze,
|
||||
text: action.text.freeze,
|
||||
]).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::ChangeFriendName
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
action.friend.number => state[:friends][action.friend.number].merge(
|
||||
name: action.new_name.freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::ChangeFriendStatusMessage
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
action.friend.number => state[:friends][action.friend.number].merge(
|
||||
status_message: action.new_status_message.freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::ChangeFriendStatus
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
action.friend.number => state[:friends][action.friend.number].merge(
|
||||
status: action.new_status,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::WindowLeft
|
||||
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
|
||||
when Actions::WindowRight
|
||||
state.merge(
|
||||
focus: :chat,
|
||||
|
||||
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
|
||||
when Actions::MenuUp
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
active_friend_index = state[:active_friend_index] + 1
|
||||
top = state[:sidebar][:menu][:top]
|
||||
|
||||
if active_friend_index.negative?
|
||||
active_friend_index = state[:friends].count - 1
|
||||
elsif active_friend_index >= state[:friends].count
|
||||
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(
|
||||
active_friend_index: active_friend_index,
|
||||
|
||||
sidebar: state[:sidebar].merge(
|
||||
menu: state[:sidebar][:menu].merge(
|
||||
top: top,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::MenuDown
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
active_friend_index = state[:active_friend_index] + 1
|
||||
top = state[:sidebar][:menu][:top]
|
||||
|
||||
if active_friend_index.negative?
|
||||
active_friend_index = state[:friends].count - 1
|
||||
elsif active_friend_index >= state[:friends].count
|
||||
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(
|
||||
active_friend_index: active_friend_index,
|
||||
|
||||
sidebar: state[:sidebar].merge(
|
||||
menu: state[:sidebar][:menu].merge(
|
||||
top: top,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessageEnter
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
text = state[:friends][friend_number][:new_message][:text].strip.freeze
|
||||
|
||||
return state if text.empty?
|
||||
|
||||
error = false
|
||||
|
||||
begin
|
||||
action.tox_client.friend(friend_number).send_message text
|
||||
rescue
|
||||
error = true
|
||||
end
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => state[:friends][friend_number].merge(
|
||||
new_message: state[:friends][friend_number][:new_message].merge(
|
||||
text: '',
|
||||
cursor_pos: 0,
|
||||
),
|
||||
|
||||
history: (state[:friends][friend_number][:history] + [
|
||||
error: error,
|
||||
out: true,
|
||||
received: false,
|
||||
time: Time.now.utc.freeze,
|
||||
name: action.tox_client.name.freeze,
|
||||
text: text,
|
||||
]).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessagePutc
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
text = "#{text[0...cursor_pos]}#{action.char}#{text[cursor_pos..-1]}"
|
||||
cursor_pos += 1
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
text: text,
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessageLeft
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
cursor_pos -= 1
|
||||
|
||||
cursor_pos = 0 if cursor_pos.negative?
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessageRight
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
cursor_pos += 1
|
||||
|
||||
cursor_pos = text.length if cursor_pos > text.length
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessageHome
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: 0,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessageEnd
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
cursor_pos: new_message[:text].length,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessageBackspace
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
return state unless cursor_pos.positive?
|
||||
|
||||
text = "#{text[0...(cursor_pos - 1)]}#{text[cursor_pos..-1]}"
|
||||
cursor_pos -= 1
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
text: text,
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
when Actions::NewMessageDelete
|
||||
return state if state[:active_friend_index].nil?
|
||||
|
||||
friend_number = state[:friends].keys[state[:active_friend_index]]
|
||||
|
||||
return state if friend_number.nil?
|
||||
|
||||
friend = state[:friends][friend_number]
|
||||
new_message = friend[:new_message]
|
||||
|
||||
text = new_message[:text]
|
||||
cursor_pos = new_message[:cursor_pos]
|
||||
|
||||
return state if cursor_pos > text.length
|
||||
|
||||
text = "#{text[0...cursor_pos]}#{text[(cursor_pos + 1)..-1]}"
|
||||
|
||||
state.merge(
|
||||
friends: state[:friends].merge(
|
||||
friend_number => friend.merge(
|
||||
new_message: new_message.merge(
|
||||
text: text,
|
||||
cursor_pos: cursor_pos,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze,
|
||||
).freeze
|
||||
else
|
||||
state
|
||||
end
|
||||
|
|
|
@ -45,7 +45,7 @@ module Widgets
|
|||
def render_public_key
|
||||
setpos 0, 1
|
||||
addstr PUBLIC_KEY_LABEL
|
||||
addstr props[:public_key].ljustetc props[:width] - PUBLIC_KEY_LABEL.length
|
||||
addstr props[:public_key].ljustetc props[:width] - PUBLIC_KEY_LABEL.length if props[:public_key]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Reference in New Issue