Alice
view release on metacpan or search on metacpan
- UI additions (join button, etc)
- Use Fliggy and websocket-js for Firefox
- Use noembed.com for embedded content
(tweets, video, etc.)
0.19 Tue 31 Aug 2010
- Added a dark theme
- Made preferences and connections windows
into popup divs instead of real windows
- Redis message store improvements
- Improved debug output
- Workarounds for weird android browser
quirks
- Much better mobile style
- Improved reconnect behavior
- Nick tab completion in private messages
- Use browser's timezone for timestamps
- Faster page loads
0.18 Tue 10 Aug 2010
- Shortcuts work on Linux and Windows
lib/Alice.pm view on Meta::CPAN
map {$_->[1]}
sort {$a->[0] cmp $b->[0]}
map {[($o{$_->id} || $o{$_->title} || $prefix.$_->sort_name), $_]}
$self->windows;
}
sub close_window {
my ($self, $window) = @_;
AE::log debug => "sending a request to close a tab: " . $window->title;
$self->broadcast($window->close_action);
if ($window->is_channel) {
my $irc = $self->get_irc($window->network);
my $config = $self->config->servers->{$window->network};
$config->{channels} = [grep {$_ ne $window->title} @{$config->{channels}}];
$self->config->write;
}
$self->remove_window($window->id) if $window->type ne "info";
lib/Alice.pm view on Meta::CPAN
line => $line,
);
$self->irc_command($input);
}
}
}
sub purge_disconnects {
my ($self) = @_;
AE::log debug => "removing broken streams";
$self->streams([grep {!$_->closed} @{$self->streams}]);
}
sub render {
my ($self, $template, @data) = @_;
$self->template->render_file("$template.html", $self, @data)->as_string;
}
sub is_highlight {
my ($self, $own_nick, $body) = @_;
lib/Alice/Config.pm view on Meta::CPAN
}
}
else {
say STDERR "No config found, writing a few config to ".$self->fullpath;
$self->write($loaded);
}
}
sub read_commandline_args {
my $self = shift;
my ($port, $debug, $address, $log);
GetOptions("port=i" => \$port, "debug=s" => \$debug, "log=s" => \$log, "address=s" => \$address);
$self->commandline->{port} = $port if $port and $port =~ /\d+/;
$self->commandline->{address} = $address if $address;
$AnyEvent::Log::FILTER->level($debug || "info");
if ($log) {
$AnyEvent::Log::COLLECT->attach(AnyEvent::Log::Ctx->new(
level => ($debug || "info"),
log_to_file => $log
));
}
}
sub http_port {
my $self = shift;
if ($self->commandline->{port}) {
return $self->commandline->{port};
}
lib/Alice/HTTP/Server.pm view on Meta::CPAN
$req->env->{"psgix.session.options"}{expire} = 1;
$res->redirect("/login");
}
$res->send;
}
sub setup_xhr_stream {
my ($self, $req, $res) = @_;
my $app = $self->app;
AE::log debug => "opening new stream";
$res->headers([@Alice::HTTP::Stream::XHR::headers]);
my $stream = Alice::HTTP::Stream::XHR->new(
writer => $res->writer,
start_time => $req->param('t'),
# android requires 4K updates to trigger loading event
min_bytes => $req->user_agent =~ /android/i ? 4096 : 0,
on_error => sub { $app->purge_disconnects },
);
$stream->send([$app->connect_actions]);
$app->add_stream($stream);
}
sub setup_ws_stream {
my ($self, $req, $res) = @_;
my $app = $self->app;
AE::log debug => "opening new websocket stream";
if (my $fh = $req->env->{'websocket.impl'}->handshake) {
my $stream = Alice::HTTP::Stream::WebSocket->new(
start_time => $req->param('t') || time,
fh => $fh,
on_read => sub { $app->handle_message(@_) },
on_error => sub { $app->purge_disconnects },
ws_version => $req->env->{'websocket.impl'}->version,
);
lib/Alice/HTTP/Server.pm view on Meta::CPAN
$res->notfound;
}
else {
$res->send;
}
}
sub save_tabsets {
my ($self, $req, $res) = @_;
AE::log debug => "saving tabsets";
my $tabsets = {};
for my $set ($req->param) {
next if $set eq '_';
my $wins = [$req->param($set)];
$tabsets->{$set} = $wins->[0] eq 'empty' ? [] : $wins;
}
$self->app->config->tabsets($tabsets);
$self->app->config->write;
$res->body($self->render('tabset_menu'));
$res->send;
}
sub server_config {
my ($self, $req, $res) = @_;
AE::log debug => "serving blank server config";
my $name = $req->param('name');
$name =~ s/\s+//g;
my $config = $self->render('new_server', $name);
my $listitem = $self->render('server_listitem', $name);
$res->body(to_json({config => $config, listitem => $listitem}));
$res->header("Cache-control" => "no-cache");
$res->send;
}
#
# TODO separate methods for saving prefs and server configs
#
sub save_config {
my ($self, $req, $res) = @_;
AE::log debug => "saving config";
my $new_config = {};
if ($req->param('has_servers')) {
$new_config->{servers} = {};
}
else {
$new_config->{$_} = [$req->param($_)] for qw/highlights monospace_nicks/;
}
for my $name ($req->param) {
lib/Alice/HTTP/Server.pm view on Meta::CPAN
}
$self->app->reload_config($new_config);
$self->app->send_info("config", "saved");
$res->ok;
}
sub tab_order {
my ($self, $req, $res) = @_;
AE::log debug => "updating tab order";
$self->app->tab_order([grep {defined $_} $req->param('tabs')]);
$res->ok;
}
sub auth_enabled {
my $self = shift;
$self->app->auth_enabled;
}
lib/Alice/Readme.pod view on Meta::CPAN
=head1 USAGE
Installation will add a new `alice` command to start the alice
server. When the command is run it will start the daemon and print
the URL to load in your browser.
=head2 COMMANDLINE OPTIONS
=over 4
=item -d --debug
Print out additional debug information. Useful for development or
finding out if something is wrong.
=item -p --port
This will change the port that the HTTP server listens on. The
default port is 8080.
=item -a --address
This will change the IP address that the HTTP server listens on.
lib/Alice/Role/IRCEvents.pm view on Meta::CPAN
map {
my $event = $_;
$event => sub {
my @args = @_; # we don't need the client
shift @args;
AE::log trace => "$event event for " . $irc->name;
try {
$EVENTS{$event}->($self, $irc, @args);
}
catch {
AE::log debug => "Error in $event: $_";
$self->send_info("Please report this bug! $_");
}
}
} keys %EVENTS
}
}
sub irc_event {
my ($name, $code) = @_;
share/static/alice.js view on Meta::CPAN
}.bind(this));
},
log: function () {
var win = this.activeWindow();
for (var i=0; i < arguments.length; i++) {
if (window.console && window.console.log) {
console.log(arguments[i]);
}
if (this.options.debug == "true") {
if (win) {
win.addMessage({
html: '<li class="message monospace"><div class="left">console</div><div class="msg">'+arguments[i].toString()+'</div></li>'
});
}
}
}
},
msgid: function() {
( run in 1.097 second using v1.01-cache-2.11-cpan-49f99fa48dc )