537 lines
20 KiB
JavaScript
537 lines
20 KiB
JavaScript
(function() {
|
|
'use strict';
|
|
|
|
var weechat = angular.module('weechat');
|
|
|
|
weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notifications', 'bufferResume', function($rootScope, $log, models, plugins, notifications, bufferResume) {
|
|
|
|
var handleVersionInfo = function(message) {
|
|
var content = message.objects[0].content;
|
|
var version = content.value;
|
|
// Store the WeeChat version in models
|
|
// this eats things like 1.3-dev -> [1,3]
|
|
models.version = version.split(".").map(function(c) { return parseInt(c); });
|
|
};
|
|
|
|
var handleConfValue = function(message) {
|
|
var infolist = message.objects[0].content;
|
|
for (var i = 0; i < infolist.length ; i++) {
|
|
var key, val;
|
|
var item = infolist[i];
|
|
for (var j = 0; j < item.length ; j++) {
|
|
var confitem = item[j];
|
|
if (confitem.full_name) {
|
|
key = confitem.full_name;
|
|
}
|
|
if (confitem.value) {
|
|
val = confitem.value;
|
|
}
|
|
}
|
|
if (key && val) {
|
|
$log.debug('Setting wconfig "' + key + '" to value "' + val + '"');
|
|
models.wconfig[key] = val;
|
|
}
|
|
}
|
|
};
|
|
|
|
var handleBufferClosing = function(message) {
|
|
var bufferMessage = message.objects[0].content[0];
|
|
var bufferId = bufferMessage.pointers[0];
|
|
models.closeBuffer(bufferId);
|
|
};
|
|
|
|
// inject a fake buffer line for date change if needed
|
|
var injectDateChangeMessageIfNeeded = function(buffer, manually, old_date, new_date) {
|
|
if (buffer.bufferType === 1) {
|
|
// Don't add date change messages to free buffers
|
|
return;
|
|
}
|
|
old_date.setHours(0, 0, 0, 0);
|
|
new_date.setHours(0, 0, 0, 0);
|
|
// Check if the date changed
|
|
if (old_date.valueOf() !== new_date.valueOf()) {
|
|
if (manually) {
|
|
// if the message that caused this date change to be sent
|
|
// would increment buffer.lastSeen, we should increment as
|
|
// well.
|
|
++buffer.lastSeen;
|
|
}
|
|
var old_date_plus_one = old_date;
|
|
old_date_plus_one.setDate(old_date.getDate() + 1);
|
|
// it's not always true that a date with time 00:00:00
|
|
// plus one day will be time 00:00:00
|
|
old_date_plus_one.setHours(0, 0, 0, 0);
|
|
|
|
var content = "\u001943"; // this colour corresponds to chat_day_change
|
|
// Add day of the week
|
|
if ($rootScope.supports_formatting_date) {
|
|
content += new_date.toLocaleDateString(window.navigator.language,
|
|
{weekday: "long"});
|
|
} else {
|
|
// Gross code that only does English dates ew gross
|
|
var dow_to_word = [
|
|
"Sunday", "Monday", "Tuesday",
|
|
"Wednesday", "Thursday", "Friday", "Saturday"];
|
|
content += dow_to_word[new_date.getDay()];
|
|
}
|
|
// if you're testing different date formats,
|
|
// make sure to test different locales such as "en-US",
|
|
// "en-US-u-ca-persian" (which has different weekdays, year 0, and an ERA)
|
|
// "ja-JP-u-ca-persian-n-thai" (above, diff numbering, diff text)
|
|
var extra_date_format = {
|
|
day: "numeric",
|
|
month: "long"
|
|
};
|
|
if (new_date.getYear() !== old_date.getYear()) {
|
|
extra_date_format.year = "numeric";
|
|
}
|
|
content += " (";
|
|
if ($rootScope.supports_formatting_date) {
|
|
content += new_date.toLocaleDateString(window.navigator.language,
|
|
extra_date_format);
|
|
} else {
|
|
// ew ew not more gross code
|
|
var month_to_word = [
|
|
"January", "February", "March", "April",
|
|
"May", "June", "July", "August",
|
|
"September", "October", "November", "December"];
|
|
content += month_to_word[new_date.getMonth()] + " " + new_date.getDate().toString();
|
|
if (extra_date_format.year === "numeric") {
|
|
content += ", " + new_date.getFullYear().toString();
|
|
}
|
|
}
|
|
// Result should be something like
|
|
// Friday (November 27)
|
|
// or if the year is different,
|
|
// Friday (November 27, 2015)
|
|
|
|
// Comparing dates in javascript is beyond tedious
|
|
if (old_date_plus_one.valueOf() !== new_date.valueOf()) {
|
|
var date_diff = Math.round((new_date - old_date)/(24*60*60*1000)) + 1;
|
|
if (date_diff < 0) {
|
|
date_diff = -1*(date_diff);
|
|
if (date_diff === 1) {
|
|
content += ", 1 day before";
|
|
} else {
|
|
content += ", " + date_diff + " days before";
|
|
}
|
|
} else {
|
|
content += ", " + date_diff + " days later";
|
|
}
|
|
// Result: Friday (November 27, 5 days later)
|
|
}
|
|
content += ")";
|
|
|
|
var line = {
|
|
buffer: buffer.id,
|
|
date: new_date,
|
|
prefix: '\u001943\u2500',
|
|
tags_array: [],
|
|
displayed: true,
|
|
highlight: 0,
|
|
message: content
|
|
};
|
|
var new_message = new models.BufferLine(line);
|
|
buffer.addLine(new_message);
|
|
}
|
|
};
|
|
|
|
var handleLine = function(line, manually) {
|
|
var message = new models.BufferLine(line);
|
|
var buffer = models.getBuffer(message.buffer);
|
|
buffer.requestedLines++;
|
|
// Only react to line if its displayed
|
|
if (message.displayed) {
|
|
// Check for date change
|
|
if (buffer.lines.length > 0) {
|
|
var old_date = new Date(buffer.lines[buffer.lines.length - 1].date),
|
|
new_date = new Date(message.date);
|
|
injectDateChangeMessageIfNeeded(buffer, manually, old_date, new_date);
|
|
}
|
|
|
|
message = plugins.PluginManager.contentForMessage(message);
|
|
buffer.addLine(message);
|
|
|
|
if (manually) {
|
|
buffer.lastSeen++;
|
|
}
|
|
|
|
if (buffer.active && !manually) {
|
|
$rootScope.scrollWithBuffer();
|
|
}
|
|
|
|
if (!manually && (!buffer.active || !$rootScope.isWindowFocused())) {
|
|
var server = models.getServerForBuffer(buffer);
|
|
if (buffer.notify > 1 && _.contains(message.tags, 'notify_message') && !_.contains(message.tags, 'notify_none')) {
|
|
buffer.unread++;
|
|
server.unread++;
|
|
$rootScope.$emit('notificationChanged');
|
|
}
|
|
|
|
if ((buffer.notify !== 0) && (message.highlight || _.contains(message.tags, 'notify_private'))) {
|
|
buffer.notification++;
|
|
server.unread++;
|
|
notifications.createHighlight(buffer, message);
|
|
$rootScope.$emit('notificationChanged');
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var handleBufferInfo = function(message) {
|
|
var bufferInfos = message.objects[0].content;
|
|
// buffers objects
|
|
for (var i = 0; i < bufferInfos.length ; i++) {
|
|
var bufferId = bufferInfos[i].pointers[0];
|
|
var buffer = models.getBuffer(bufferId);
|
|
if (buffer !== undefined) {
|
|
// We already know this buffer
|
|
handleBufferUpdate(buffer, bufferInfos[i]);
|
|
} else {
|
|
buffer = new models.Buffer(bufferInfos[i]);
|
|
if (buffer.type === 'server') {
|
|
models.registerServer(buffer);
|
|
} else {
|
|
var server = models.getServerForBuffer(buffer);
|
|
server.unread += buffer.unread + buffer.notification;
|
|
}
|
|
models.addBuffer(buffer);
|
|
// Switch to first buffer on startup
|
|
var shouldResume = bufferResume.shouldResume(buffer);
|
|
if(shouldResume){
|
|
models.setActiveBuffer(buffer.id);
|
|
}
|
|
}
|
|
}
|
|
// If there was no buffer to autmatically load, go to the first one.
|
|
if (!bufferResume.wasAbleToResume()) {
|
|
var first = bufferInfos[0].pointers[0];
|
|
models.setActiveBuffer(first);
|
|
}
|
|
};
|
|
|
|
var handleBufferUpdate = function(buffer, message) {
|
|
if (message.pointers[0] !== buffer.id) {
|
|
// this is information about some other buffer!
|
|
return;
|
|
}
|
|
|
|
// weechat properties -- short name can be changed
|
|
buffer.shortName = message.short_name;
|
|
buffer.trimmedName = buffer.shortName.replace(/^[#&+]/, '');
|
|
buffer.title = message.title;
|
|
buffer.number = message.number;
|
|
buffer.hidden = message.hidden;
|
|
|
|
// reset unread counts, hotlist info will arrive shortly
|
|
var server = models.getServerForBuffer(buffer);
|
|
server.unread -= (buffer.unread + buffer.notification);
|
|
buffer.notification = 0;
|
|
buffer.unread = 0;
|
|
buffer.lastSeen = -1;
|
|
|
|
if (message.local_variables.type !== undefined) {
|
|
buffer.type = message.local_variables.type;
|
|
buffer.indent = (['channel', 'private'].indexOf(buffer.type) >= 0);
|
|
}
|
|
|
|
if (message.notify !== undefined) {
|
|
buffer.notify = message.notify;
|
|
}
|
|
};
|
|
|
|
var handleBufferLineAdded = function(message) {
|
|
message.objects[0].content.forEach(function(l) {
|
|
handleLine(l, false);
|
|
});
|
|
};
|
|
|
|
var handleBufferOpened = function(message) {
|
|
var bufferMessage = message.objects[0].content[0];
|
|
var buffer = new models.Buffer(bufferMessage);
|
|
if (buffer.type === 'server') {
|
|
models.registerServer(buffer);
|
|
} else {
|
|
var server = models.getServerForBuffer(buffer);
|
|
server.unread += buffer.unread + buffer.notification;
|
|
}
|
|
models.addBuffer(buffer);
|
|
};
|
|
|
|
var handleBufferTitleChanged = function(message) {
|
|
var obj = message.objects[0].content[0];
|
|
var buffer = obj.pointers[0];
|
|
var old = models.getBuffer(buffer);
|
|
old.fullName = obj.full_name;
|
|
old.title = models.parseRichText(obj.title);
|
|
old.number = obj.number;
|
|
|
|
old.rtitle = "";
|
|
for (var i = 0; i < old.title.length; ++i) {
|
|
old.rtitle += old.title[i].text;
|
|
}
|
|
};
|
|
|
|
var handleBufferRenamed = function(message) {
|
|
var obj = message.objects[0].content[0];
|
|
var buffer = obj.pointers[0];
|
|
var old = models.getBuffer(buffer);
|
|
old.fullName = obj.full_name;
|
|
old.shortName = obj.short_name;
|
|
// If it's a channel, trim away the prefix (#, &, or +). If that is empty and the buffer
|
|
// has a short name, use a space (because the prefix will be displayed separately, and we don't want
|
|
// prefix + fullname, which would happen otherwise). Else, use null so that full_name is used
|
|
old.trimmedName = obj.short_name.replace(/^[#&+]/, '') || (obj.short_name ? ' ' : null);
|
|
old.prefix = ['#', '&', '+'].indexOf(obj.short_name.charAt(0)) >= 0 ? obj.short_name.charAt(0) : '';
|
|
|
|
// After a buffer openes we get the name change event from relay protocol
|
|
// Here we check our outgoing commands that openes a buffer and switch
|
|
// to it if we find the buffer name it the list
|
|
var position = models.outgoingQueries.indexOf(old.shortName);
|
|
if (position >= 0) {
|
|
models.outgoingQueries.splice(position, 1);
|
|
models.setActiveBuffer(old.id);
|
|
}
|
|
};
|
|
|
|
var handleBufferMoved = function(message) {
|
|
var obj = message.objects[0].content[0];
|
|
var buffer = obj.pointers[0];
|
|
var old = models.getBuffer(buffer);
|
|
|
|
var old_number = old.number;
|
|
var new_number = obj.number;
|
|
|
|
_.each(models.getBuffers(), function(buffer) {
|
|
if (buffer.number > old_number && buffer.number <= new_number) {
|
|
buffer.number -= 1;
|
|
}
|
|
|
|
if (buffer.number < old_number && buffer.number >= new_number) {
|
|
buffer.number += 1;
|
|
}
|
|
});
|
|
|
|
old.number = new_number;
|
|
};
|
|
|
|
var handleBufferHidden = function(message) {
|
|
var obj = message.objects[0].content[0];
|
|
var buffer = obj.pointers[0];
|
|
var old = models.getBuffer(buffer);
|
|
old.hidden = true;
|
|
};
|
|
|
|
var handleBufferUnhidden = function(message) {
|
|
var obj = message.objects[0].content[0];
|
|
var buffer = obj.pointers[0];
|
|
var old = models.getBuffer(buffer);
|
|
old.hidden = false;
|
|
};
|
|
|
|
var handleBufferLocalvarChanged = function(message) {
|
|
var obj = message.objects[0].content[0];
|
|
var buffer = obj.pointers[0];
|
|
var old = models.getBuffer(buffer);
|
|
|
|
var localvars = obj.local_variables;
|
|
if (old !== undefined && localvars !== undefined) {
|
|
// Update indentation status
|
|
old.type = localvars.type;
|
|
old.indent = (['channel', 'private'].indexOf(localvars.type) >= 0);
|
|
// Update serverSortKey and related variables
|
|
old.plugin = localvars.plugin;
|
|
old.server = localvars.server;
|
|
old.serverSortKey = old.plugin + "." + old.server +
|
|
(old.type === "server" ? "" : ("." + old.shortName));
|
|
old.pinned = localvars.pinned === "true";
|
|
}
|
|
};
|
|
|
|
var handleBufferTypeChanged = function(message) {
|
|
var obj = message.objects[0].content[0];
|
|
var buffer = obj.pointers[0];
|
|
//var old = models.getBuffer(buffer);
|
|
// 0 = formatted (normal); 1 = free
|
|
buffer.bufferType = obj.type;
|
|
};
|
|
|
|
/*
|
|
* Handle answers to (lineinfo) messages
|
|
*
|
|
* (lineinfo) messages are specified by this client. It is request after bufinfo completes
|
|
*/
|
|
var handleLineInfo = function(message, manually) {
|
|
var lines = message.objects[0].content.reverse();
|
|
if (manually === undefined) {
|
|
manually = true;
|
|
}
|
|
lines.forEach(function(l) {
|
|
handleLine(l, manually);
|
|
});
|
|
if (message.objects[0].content.length > 0) {
|
|
// fiddle out the buffer ID and take the last line's date
|
|
var last_line =
|
|
message.objects[0].content[message.objects[0].content.length-1];
|
|
var buffer = models.getBuffer(last_line.buffer);
|
|
if (buffer.lines.length > 0) {
|
|
var last_date = new Date(buffer.lines[buffer.lines.length - 1].date);
|
|
injectDateChangeMessageIfNeeded(buffer, true, last_date, new Date());
|
|
}
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Handle answers to hotlist request
|
|
*/
|
|
var handleHotlistInfo = function(message) {
|
|
// Hotlist includes only buffers with unread counts so first we
|
|
// iterate all our buffers and resets the counts.
|
|
_.each(models.getBuffers(), function(buffer) {
|
|
buffer.unread = 0;
|
|
buffer.notification = 0;
|
|
});
|
|
_.each(models.getServers(), function(server) {
|
|
server.unread = 0;
|
|
});
|
|
if (message.objects.length > 0) {
|
|
var hotlist = message.objects[0].content;
|
|
hotlist.forEach(function(l) {
|
|
var buffer = models.getBuffer(l.buffer);
|
|
// If buffer is active in gb, but not active in WeeChat the
|
|
// hotlist in WeeChat will increase but we should ignore that
|
|
// in gb.
|
|
if (buffer.active) {
|
|
return;
|
|
}
|
|
// 1 is message
|
|
buffer.unread = l.count[1];
|
|
// 2 is private
|
|
// Use += so count[2] or count[3] doesn't overwrite each other
|
|
buffer.notification += l.count[2];
|
|
// 3 is highlight
|
|
// Use += so count[2] or count[3] doesn't overwrite each other
|
|
buffer.notification += l.count[3];
|
|
/* Since there is unread messages, we can guess
|
|
* what the last read line is and update it accordingly
|
|
*/
|
|
var unreadSum = _.reduce(l.count, function(memo, num) { return memo + num; }, 0);
|
|
buffer.lastSeen = buffer.lines.length - 1 - unreadSum;
|
|
|
|
// update server buffer. Don't incude index 0 -> not unreadSum
|
|
models.getServerForBuffer(buffer).unread += l.count[1] + l.count[2] + l.count[3];
|
|
});
|
|
}
|
|
// the unread badges in the bufferlist doesn't update if we don't do this
|
|
setTimeout(function() {
|
|
$rootScope.$apply();
|
|
$rootScope.$emit('notificationChanged');
|
|
});
|
|
};
|
|
|
|
/*
|
|
* Handle nicklist event
|
|
*
|
|
* This event can either fill or clear a nicklist. It is always a complete nicklist.
|
|
*/
|
|
var handleNicklist = function(message) {
|
|
var nicklist = message.objects[0].content;
|
|
var group = 'root';
|
|
|
|
//clear the nicklists in case we are clearing
|
|
if (nicklist.length==1)
|
|
{
|
|
models.getBuffer(nicklist[0].pointers[0]).clearNicklist();
|
|
}
|
|
|
|
//fill the nicklist
|
|
nicklist.forEach(function(n) {
|
|
var buffer = models.getBuffer(n.pointers[0]);
|
|
|
|
//buffer nicklist
|
|
if (n.group === 1) {
|
|
var g = new models.NickGroup(n);
|
|
group = g.name;
|
|
buffer.nicklist[group] = g;
|
|
} else {
|
|
var nick = new models.Nick(n);
|
|
buffer.addNick(group, nick);
|
|
}
|
|
});
|
|
|
|
//check if nicklist should be hidden or not
|
|
$rootScope.$emit('nickListChanged');
|
|
};
|
|
/*
|
|
* Handle nicklist diff event
|
|
*/
|
|
var handleNicklistDiff = function(message) {
|
|
var nicklist = message.objects[0].content;
|
|
var group;
|
|
nicklist.forEach(function(n) {
|
|
var buffer = models.getBuffer(n.pointers[0]);
|
|
var d = n._diff;
|
|
if (n.group === 1) {
|
|
group = n.name;
|
|
if (group === undefined) {
|
|
var g = new models.NickGroup(n);
|
|
buffer.nicklist[group] = g;
|
|
group = g.name;
|
|
}
|
|
} else {
|
|
var nick = new models.Nick(n);
|
|
if (d === 43) { // +
|
|
buffer.addNick(group, nick);
|
|
} else if (d === 45) { // -
|
|
buffer.delNick(group, nick);
|
|
} else if (d === 42) { // *
|
|
buffer.updateNick(group, nick);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
var eventHandlers = {
|
|
_buffer_closing: handleBufferClosing,
|
|
_buffer_line_added: handleBufferLineAdded,
|
|
_buffer_localvar_added: handleBufferLocalvarChanged,
|
|
_buffer_localvar_removed: handleBufferLocalvarChanged,
|
|
_buffer_localvar_changed: handleBufferLocalvarChanged,
|
|
_buffer_moved: handleBufferMoved,
|
|
_buffer_opened: handleBufferOpened,
|
|
_buffer_title_changed: handleBufferTitleChanged,
|
|
_buffer_type_changed: handleBufferTypeChanged,
|
|
_buffer_renamed: handleBufferRenamed,
|
|
_buffer_hidden: handleBufferHidden,
|
|
_buffer_unhidden: handleBufferUnhidden,
|
|
_nicklist: handleNicklist,
|
|
_nicklist_diff: handleNicklistDiff
|
|
};
|
|
|
|
$rootScope.$on('onMessage', function(event, message) {
|
|
if (_.has(eventHandlers, message.id)) {
|
|
eventHandlers[message.id](message);
|
|
} else {
|
|
$log.debug('Unhandled event received: ' + message.id);
|
|
}
|
|
});
|
|
|
|
var handleEvent = function(event) {
|
|
if (_.has(eventHandlers, event.id)) {
|
|
eventHandlers[event.id](event);
|
|
}
|
|
};
|
|
|
|
return {
|
|
handleVersionInfo: handleVersionInfo,
|
|
handleConfValue: handleConfValue,
|
|
handleEvent: handleEvent,
|
|
handleLineInfo: handleLineInfo,
|
|
handleHotlistInfo: handleHotlistInfo,
|
|
handleNicklist: handleNicklist,
|
|
handleBufferInfo: handleBufferInfo
|
|
};
|
|
|
|
}]);
|
|
})();
|