This file was deleted.

@@ -4904,8 +4904,7 @@ a.toggle-main-menu {
.convos-dialog-container header h2,
.convos-settings header h2 {
float: left;
padding-left: 0.75rem;
cursor: pointer; }
padding-left: 0.75rem; }

img.embed, .link-embedder.text-html {
max-width: 50em;
@@ -5041,28 +5040,51 @@ img.embed {
.is-sidebar {
width: 320px; } }

.convos-dialog-settings .row,
.convos-notifications .row {
margin: 0 auto;
border-bottom: 1px solid #f0f0f0; }
margin: 0 auto; }

.convos-dialog-settings .btn-floating,
.convos-notifications .btn-floating {
box-shadow: none;
vertical-align: middle;
float: right;
top: -6px; }

.convos-dialog-settings .notification:hover,
.convos-dialog-settings .participant:hover,
.convos-notifications .notification:hover,
.convos-notifications .participant:hover {
background-color: #f0f0f0; }

.convos-dialog-settings .notification h5, .convos-dialog-settings .notification .secondary-content,
.convos-dialog-settings .participant h5,
.convos-dialog-settings .participant .secondary-content,
.convos-notifications .notification h5,
.convos-notifications .notification .secondary-content,
.convos-notifications .participant h5,
.convos-notifications .participant .secondary-content {
font-size: 1rem;
line-height: 110%;
margin: 0.5rem 0 0.4rem 0; }

.convos-dialog-settings .notification,
.convos-notifications .notification {
cursor: pointer;
padding-top: 4px;
padding-bottom: 8px; }
.convos-notifications .notification:hover {
background-color: #f0f0f0; }
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0; }
.convos-dialog-settings .notification.read,
.convos-notifications .notification.read {
opacity: 0.7; }
.convos-notifications .notification h5, .convos-notifications .notification .secondary-content {
font-size: 1rem;
line-height: 110%;
margin: 0.5rem 0 0.4rem 0; }

.convos-dialog-settings .participant,
.convos-notifications .participant {
padding: 4px 0;
border-top: 1px solid #f0f0f0; }
.convos-dialog-settings .participant .secondary-content,
.convos-notifications .participant .secondary-content {
margin: 0; }

header a.notifications {
position: relative; }

Large diffs are not rendered by default.

@@ -108,6 +108,13 @@
var handler = "_sent" + action[1].toLowerCase().ucFirst();
var id;

if (action[1] == 'query') {
if (action[2]) {
Convos.settings.main = this.user.ensureDialog({connection_id: this.connection_id, dialog_id: action[2]}).href();
}
return;
}

if (!dialog) dialog = this.getDialog(action[2]); // action = ["...", "close", "#foo" ]
if (!dialog) dialog = this.user.getActiveDialog();

@@ -233,7 +240,8 @@
this.notice('Connection state changed to "' + msg);
break;
case "frozen":
this.user.ensureDialog(data).frozen = data.frozen;
case "topic":
this.user.ensureDialog(data);
break;
case "join":
case "part":
@@ -1,9 +1,10 @@
(function() {
Convos.Dialog = function(attrs) {
this.activated = 0;
this.active = false;
this.dialog_id = "";
this.frozen = "";
this.activated = 0;
this.is_private = true;
this.messages = [];
this.name = "";
this.lastRead = attrs.last_read ? Date.fromAPI(attrs.last_read) : new Date();
@@ -178,13 +179,9 @@
connection_id: this.connection_id,
dialog_id: this.dialog_id
}, function(err, xhr) {
if (err) return self.emit("error", err);

var messages = xhr.body.messages || [];
self.messages = []; // clear old messages on ws reconnect
xhr.body.messages.forEach(function(msg) {
self.addMessage(msg, {method: "push", disableNotifications: true});
});

messages.forEach(function(msg) { self.addMessage(msg, {method: "push", disableNotifications: true}) });
self.emit("join");
}
);
@@ -199,13 +196,8 @@
disableUnread: true
});
} else if (!this.messages.length) {
this.addMessage(
{
message: "You have joined " + this.name + ", but no one has said anything as long as you have been here.",
type: "notice"
},
{disableUnread: true}
);
var message = this.is_private ? "What do you want to say to " + this.name + "?" : "You have joined " + this.name + ", but no one has said anything as long as you have been here.";
this.addMessage({message: message, type: "notice"}, {disableUnread: true});
}
if (Convos.settings.notifications == "default") {
this.addMessage({type: "enable-notifications"});
@@ -215,7 +207,8 @@
proto._setParticipants = function(msg) {
this.participants = {};
msg.participants.forEach(function(p) {
this.participants[p.name] = {name: p.name, seen: new Date()};
p.seen = new Date();
this.participants[p.name] = p;
}.bind(this));
};
})();

This file was deleted.

@@ -36,6 +36,9 @@
insertIntoInput: function(e) {
var dialog = this.user.getActiveDialog();
if (dialog) dialog.emit("insertIntoInput", e.currentTarget.href.replace(/.*?#/, ""));
},
send: function(command) {
this.dialog.connection().send(command, this.dialog);
}
}
});
@@ -94,6 +94,5 @@ a.toggle-main-menu {
header h2 {
float: left;
padding-left: $gutter-width / 2;
cursor: pointer; // click to get info
}
}
@@ -78,10 +78,10 @@
}
}

.convos-dialog-settings,
.convos-notifications {
.row {
margin: 0 auto;
border-bottom: 1px solid darken($body-bg, 6%);
}

.btn-floating {
@@ -91,25 +91,33 @@
top: -6px;
}

.notification {
cursor: pointer;
padding-top: 4px;
padding-bottom: 8px;

.notification,
.participant {
&:hover {
background-color: darken($body-bg, 6%);
}

&.read {
opacity: 0.7;
}

h5, .secondary-content {
font-size: $h6-fontsize;
line-height: 110%;
margin: ($h6-fontsize / 2) 0 ($h6-fontsize / 2.5) 0;
}
}

.notification {
cursor: pointer;
padding-top: 4px;
padding-bottom: 8px;
border-bottom: 1px solid darken($body-bg, 6%);

&.read { opacity: 0.7; }
}

.participant {
padding: 4px 0;
border-top: 1px solid darken($body-bg, 6%);
.secondary-content { margin: 0; }
}
}

header a.notifications {
@@ -3,9 +3,7 @@
<header>
<convos-toggle-main-menu :user="user"></convos-toggle-main-menu>
<h2 v-tooltip="dialog.topic || 'No topic is set.'">{{user.ws.is('open') ? dialog.name || 'Convos' : 'No internet connection?'}}</h2>
<convos-header-links :toggle="true" :user="user">
<a v-dropdown.literal="settings_dropdown" v-tooltip.literal="Dialog settings"><i class="material-icons">settings</i></a>
</convos-header-links>
<convos-header-links :toggle="true" :user="user"></convos-header-links>
</header>
<main>
<component
@@ -17,12 +15,6 @@
v-for="msg in dialog.messages"></component>
</main>
<convos-input :dialog="dialog" :user="user"></convos-input>
<ul class="dropdown-content" v-el:settings_dropdown>
<li><a href="#names" @click.prevent="send('/names')">List participants</a></li>
<li><a href="#topic" @click.prevent="send('/topic')">Get topic</a></li>
<li class="divider"></li>
<li><a href="#close" @click.prevent="send('/close')">Close dialog</a></li>
</ul>
</div>
</template>
<script>
@@ -64,9 +56,6 @@ module.exports = {
if (this.atBottom || args.gotoBottom) {
window.nextTick(function() { elem.scrollTop = elem.scrollHeight; });
}
},
send: function(command) {
this.dialog.connection().send(command, this.dialog);
}
},
ready: function() {
@@ -0,0 +1,54 @@
<template>
<div class="convos-dialog-settings is-sidebar">
<header><convos-header-links :user="user"></convos-header-links></header>
<div class="content">
<div class="row">
<div class="col s12">
<h5>
<a href="#close" @click.prevent="send('/close')" v-tooltip="closeTooltip()" class="btn-floating waves-effect waves-light green" v-if="dialog"><i class="material-icons">close</i></a>
Topic
</h5>
<p>{{dialog ? dialog.topic || 'No topic is set.' : 'No active dialog.'}}</p>
</div>
</div>
<div class="row" v-if="dialog">
<div class="col s12">
<h5>Participants ({{participants.length}})</h5>
</div>
</div>
<div class="row participant" v-for="p in participants">
<div class="col s12">
<span class="secondary-content ts">
{{modes[p.mode] || p.mode}}
<a href="#info" @click.prevent="send('/whois ' + p.name)" class="waves-effect waves-light"><i class="material-icons">info</i></a>
</span>
<a href="#chat:{{p.name}}" @click.prevent="send('/query ' + p.name)">{{p.name}}</a>
</div>
</div>
</div>
</div>
</template>
<script>
module.exports = {
props: ["user"],
data: function() {
return {modes: {'@': '+o', '+': '+v'}};
},
computed: {
dialog: function() {
return this.user.getActiveDialog();
},
participants: function() {
if (!this.dialog) return [];
return Object.values(this.dialog.participants).sort(function(a, b) {
return a.name.toLowerCase() > b.name.toLowerCase();
});
}
},
methods: {
closeTooltip: function() {
return this.dialog.is_private ? 'Close conversation' : 'Part channel';
}
}
};
</script>
@@ -2,6 +2,9 @@
<div class="convos-header-links">
<slot></slot>
<template v-if="!toggle || !settings.sidebar">
<a v-sidebar.literal="#dialog-settings" v-tooltip.literal="Dialog settings" :class="activeClass('dialog-settings')">
<i class="material-icons">settings</i>
</a>
<a v-sidebar.literal="#notifications" v-tooltip.literal="Show notifications" class="notifications" :class="activeClass('notifications')">
<i class="material-icons" :class="user.unread ? 'active' : ''">{{user.unread ? "notifications_active" : "notifications_none"}}</i>
<b class="n-notifications" v-if="user.unread">{{user.unread < 100 ? user.unread : "99+"}}</b>
@@ -2,12 +2,12 @@
<div class="convos-message notice">
<a href="#chat" class="title">{{msg.from}}</a>
<div class="message">
<abbr v-tooltip="msg.name">{{msg.nick}}</abbr>
<a href="#chat:{{msg.nick}}" @click.prevent="send('/query ' + msg.nick)">{{msg.nick}}</a>
<template v-if="msg.idle_for">has been idle for {{msg.idle_for}} seconds in</template>
<template v-else="msg.idle_for">is active in</template>
<template v-for="name in channels">
{{!$index ? '' : $index + 1 == channels.length ? "and" : ", "}}
<a href="#join:{{name}}" @click.prevent="join(name)">{{name}}</a>
<a href="#join:{{name}}" @click.prevent="send('/join ' + name)">{{name}}</a>
</template>.
</div>
<span class="secondary-content ts" v-tooltip="msg.ts.toLocaleString()">{{msg.ts | timestring}}</span>
@@ -18,14 +18,6 @@ module.exports = {
props: ["dialog", "msg", "user"],
data: function() {
return {channels: Object.keys(this.msg.channels)};
},
methods: {
join: function(name) {
var connection = this.dialog.connection();
var dialog = connection.getDialogs(name);
if (dialog) return this.settings.main = dialog.href();
connection.send('/join ' + name, this.dialog);
}
}
};
</script>
@@ -182,7 +182,6 @@ sub send {
return $self->participants($target, $cb) if $cmd eq 'NAMES';
return $self->nick($message, $cb) if $cmd eq 'NICK';
return $self->_part_dialog($message || $target, $cb) if $cmd eq 'CLOSE' or $cmd eq 'PART';
return $self->_query($message, $cb) if $cmd eq 'QUERY';
return $self->_topic($target, $message, $cb) if $cmd eq 'TOPIC';
return $self->_proxy(whois => $message, $cb) if $cmd eq 'WHOIS';
return next_tick $self, $cb => 'Unknown IRC command.', undef;
@@ -307,18 +306,6 @@ sub _proxy {
$self;
}

sub _query {
my ($self, $name, $cb) = @_;

return $self->_proxy(whois => $name, $cb) if $name eq $self->_irc->nick;

my $target = $self->get_dialog($name);
return next_tick $self, $cb, '', {} if $target;

$target = $self->dialog({name => $name});
return $self->_proxy(whois => $name, $cb);
}

sub _send {
my ($self, $target, $message, $cb) = @_;
my $msg = $message;
@@ -506,6 +493,8 @@ _event irc_topic => sub {
my ($nick, $user, $host) = IRC::Utils::parse_user($msg->{prefix} || '');
my $dialog = $self->dialog({name => $msg->{params}[0], topic => $msg->{params}[1]});

$self->emit(state => topic => $dialog->TO_JSON)->save(sub { });

return $self->_notice("Topic unset by $nick") unless $dialog->topic;
return $self->_notice("$nick changed the topic to: " . $dialog->topic);
};