171 lines
5.7 KiB
Ruby
171 lines
5.7 KiB
Ruby
module MeowClient
|
|
class UI
|
|
def initialize(program)
|
|
@program = program
|
|
@profiles = ProfileRepository.new(program)
|
|
end
|
|
|
|
def main
|
|
loop do
|
|
action, profile = connection_manager
|
|
case action
|
|
when :connect
|
|
connect(profile)
|
|
when :new
|
|
edit_profile(nil)
|
|
when :edit
|
|
edit_profile(profile)
|
|
when :delete
|
|
delete_profile(profile)
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def connection_manager
|
|
profiles = @profiles.all
|
|
labels = profiles.map do |profile|
|
|
security = profile.tls ? _("TLS") : _("plain")
|
|
_("%{name}, %{host}, port %{port}, %{security}") % {
|
|
:name => profile.name,
|
|
:host => profile.host,
|
|
:port => profile.port,
|
|
:security => security
|
|
}
|
|
end
|
|
list = ListBox.new(
|
|
labels,
|
|
:header => _("Connections"),
|
|
:empty_label => _("No connection profiles. Choose New to create one.")
|
|
)
|
|
connect_button = Button.new(_("Connect"))
|
|
new_button = Button.new(_("New"))
|
|
edit_button = Button.new(_("Edit"))
|
|
delete_button = Button.new(_("Delete"))
|
|
exit_button = Button.new(_("Exit"))
|
|
form = Form.new([list, connect_button, new_button, edit_button, delete_button, exit_button], :quiet => true)
|
|
form.accept_button = connect_button
|
|
form.cancel_button = exit_button
|
|
result = nil
|
|
|
|
choose = proc do |action|
|
|
if profiles.empty? && [:connect, :edit, :delete].include?(action)
|
|
alert(_("Create a connection profile first."))
|
|
else
|
|
result = [action, profiles[list.index]]
|
|
form.resume
|
|
end
|
|
end
|
|
connect_button.on(:press) { choose.call(:connect) }
|
|
new_button.on(:press) do
|
|
result = [:new, nil]
|
|
form.resume
|
|
end
|
|
edit_button.on(:press) { choose.call(:edit) }
|
|
delete_button.on(:press) { choose.call(:delete) }
|
|
exit_button.on(:press) do
|
|
result = [:exit, nil]
|
|
form.resume
|
|
end
|
|
form.wait
|
|
result || [:exit, nil]
|
|
end
|
|
|
|
def edit_profile(existing)
|
|
profile = existing || @profiles.build
|
|
name = EditBox.new(_("Profile name"), :text => profile.name)
|
|
host = EditBox.new(_("Server host"), :text => profile.host)
|
|
port = EditBox.new(_("Port"), :type => EditBox::Flags::Numbers, :text => profile.port.to_s)
|
|
tls = CheckBox.new(_("Use TLS"), :checked => profile.tls)
|
|
auto_read = CheckBox.new(_("Read incoming text automatically"), :checked => profile.auto_read)
|
|
encoding_names = ProfileRepository::ENCODINGS.keys
|
|
encoding_index = [ProfileRepository::ENCODINGS.values.index(profile.encoding) || 0, 0].max
|
|
encoding = ChoiceListBox.new(
|
|
[[_("Character encoding"), encoding_names, encoding_index]],
|
|
:header => _("Connection options")
|
|
)
|
|
save = Button.new(_("Save"))
|
|
cancel = Button.new(_("Cancel"))
|
|
form = Form.new([name, host, port, tls, auto_read, encoding, save, cancel], :quiet => true)
|
|
form.accept_button = save
|
|
form.cancel_button = cancel
|
|
saved = false
|
|
|
|
save.on(:press) do
|
|
candidate = @profiles.build(
|
|
:id => profile.id,
|
|
:name => name.text,
|
|
:host => host.text,
|
|
:port => port.text,
|
|
:tls => tls.checked,
|
|
:encoding => ProfileRepository::ENCODINGS[encoding_names[encoding.value(0)]],
|
|
:auto_read => auto_read.checked
|
|
)
|
|
errors = @profiles.validate(candidate)
|
|
if errors.empty?
|
|
@profiles.save(candidate)
|
|
saved = true
|
|
form.resume
|
|
else
|
|
alert(errors.join("\n"))
|
|
end
|
|
end
|
|
cancel.on(:press) { form.resume }
|
|
form.wait
|
|
speak(_("Connection profile saved.")) if saved
|
|
rescue Exception => error
|
|
Log.error("Meow profile editor failed: #{error.class}: #{error.message}") if defined?(Log)
|
|
alert(_("Could not save the connection profile: %{message}") % {:message => error.message})
|
|
end
|
|
|
|
def delete_profile(profile)
|
|
return if profile == nil
|
|
return unless confirm(_("Delete connection %{name}?") % {:name => profile.name})
|
|
@profiles.delete(profile.id)
|
|
speak(_("Connection profile deleted."))
|
|
rescue Exception => error
|
|
alert(_("Could not delete the connection profile: %{message}") % {:message => error.message})
|
|
end
|
|
|
|
def connect(profile)
|
|
transport = begin
|
|
EltenAPI::Tasks.run(
|
|
:title => _("Connecting to %{name}") % {:name => profile.name},
|
|
:timeout => 20
|
|
) do |_progress, token|
|
|
token.raise_if_cancelled!
|
|
Transport.connect(profile)
|
|
end
|
|
rescue EltenAPI::Tasks::Cancelled
|
|
speak(_("Connection cancelled."))
|
|
return
|
|
rescue EltenAPI::Tasks::TimedOut
|
|
alert(_("The connection attempt timed out."))
|
|
return
|
|
rescue SocketError, SystemCallError, IOError, OpenSSL::SSL::SSLError, EltenAPI::TLS::Error => error
|
|
alert(_("Could not connect: %{message}") % {:message => error.message})
|
|
return
|
|
rescue Exception => error
|
|
Log.error("Meow connection failed: #{error.class}: #{error.message}") if defined?(Log)
|
|
alert(_("Could not connect: %{message}") % {:message => error.message})
|
|
return
|
|
end
|
|
|
|
@program.manage(transport)
|
|
begin
|
|
Session.new(@program, profile, transport).run
|
|
rescue Exception => error
|
|
Log.error("Meow session failed: #{error.class}: #{error.message}") if defined?(Log)
|
|
alert(_("The session closed because of an error: %{message}") % {:message => error.message})
|
|
ensure
|
|
transport.close
|
|
@program.release(transport, :close => false)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|