telepathyClient: Add messages from TelepathyLogger

This allows users to see chat history from other contacts with
the inline message tray replies.

https://bugzilla.gnome.org/show_bug.cgi?id=643377
This commit is contained in:
Jasper St. Pierre 2011-03-07 17:10:53 -05:00
parent 525da01a62
commit 5a269db9d5

View File

@ -7,6 +7,7 @@ const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const Tpl = imports.gi.TelepathyLogger;
const Tp = imports.gi.TelepathyGLib; const Tp = imports.gi.TelepathyGLib;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
@ -22,6 +23,9 @@ const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
const SCROLLBACK_RECENT_LENGTH = 20; const SCROLLBACK_RECENT_LENGTH = 20;
const SCROLLBACK_IDLE_LENGTH = 5; const SCROLLBACK_IDLE_LENGTH = 5;
// See Source._displayPendingMessages
const SCROLLBACK_HISTORY_LINES = 10;
const NotificationDirection = { const NotificationDirection = {
SENT: 'chat-sent', SENT: 'chat-sent',
RECEIVED: 'chat-received' RECEIVED: 'chat-received'
@ -36,6 +40,31 @@ let contactFeatures = [Tp.ContactFeature.ALIAS,
// lets us see messages even if they belong to another app (eg, // lets us see messages even if they belong to another app (eg,
// Empathy). // Empathy).
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text();
return {
messageType: tpMessage.get_message_type(),
text: text,
sender: tpMessage.sender.alias,
timestamp: tpMessage.get_received_timestamp(),
direction: direction
};
}
function makeMessageFromTplEvent(event) {
let sent = event.get_sender().get_entity_type() == Tpl.EntityType.SELF;
let direction = sent ? NotificationDirection.SENT : NotificationDirection.RECEIVED;
return {
messageType: event.get_message_type(),
text: event.get_message(),
sender: event.get_sender().get_alias(),
timestamp: event.get_timestamp(),
direction: direction
};
}
function Client() { function Client() {
this._init(); this._init();
}; };
@ -160,7 +189,7 @@ Source.prototype = {
Main.messageTray.add(this); Main.messageTray.add(this);
this.pushNotification(this._notification); this.pushNotification(this._notification);
this._displayPendingMessages(); this._getLogMessages();
}, },
_updateAlias: function() { _updateAlias: function() {
@ -203,13 +232,50 @@ Source.prototype = {
req.ensure_channel_async('', null, null); req.ensure_channel_async('', null, null);
}, },
_displayPendingMessages: function() { _getLogMessages: function() {
let msgs = this._channel.get_pending_messages(); let logManager = Tpl.LogManager.dup_singleton();
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
Shell.get_contact_events(logManager,
this._account, entity,
SCROLLBACK_HISTORY_LINES,
Lang.bind(this, this._displayPendingMessages));
},
for (let i = 0; i < msgs.length; i++) { _displayPendingMessages: function(logManager, result) {
let msg = msgs[i]; let [success, events] = logManager.get_filtered_events_finish(result);
this._messageReceived(this._channel, msg);
let logMessages = events.map(makeMessageFromTplEvent);
for (let i = 0; i < logMessages.length; i++) {
this._notification.appendMessage(logMessages[i], true);
} }
let pendingMessages = this._channel.get_pending_messages();
let hasPendingMessage = false;
for (let i = 0; i < pendingMessages.length; i++) {
let message = makeMessageFromTpMessage(pendingMessages[i], NotificationDirection.RECEIVED);
// Skip any pending messages that are in the logs.
let inLog = false;
for (let j = 0; j < logMessages.length; j++) {
let logMessage = logMessages[j];
if (logMessage.timestamp == message.timestamp && logMessage.text == message.body) {
inLog = true;
}
}
if (inLog)
continue;
this._notification.appendMessage(message, true);
hasPendingMessage = true;
}
// Only show the timestamp if we have at least one message.
if (hasPendingMessage || logMessages.length > 0)
this._notification.appendTimestamp();
if (hasPendingMessage)
this.notify();
}, },
_channelClosed: function() { _channelClosed: function() {
@ -225,14 +291,16 @@ Source.prototype = {
}, },
_messageReceived: function(channel, message) { _messageReceived: function(channel, message) {
this._notification.appendMessage(message, NotificationDirection.RECEIVED); message = makeMessageFromTpMessage(message, NotificationDirection.RECEIVED);
this._notification.appendMessage(message);
this.notify(); this.notify();
}, },
// This is called for both messages we send from // This is called for both messages we send from
// our client and other clients as well. // our client and other clients as well.
_messageSent: function(channel, message, flags, token) { _messageSent: function(channel, message, flags, token) {
this._notification.appendMessage(message, NotificationDirection.SENT); message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
}, },
notify: function() { notify: function() {
@ -320,25 +388,34 @@ Notification.prototype = {
this._timestampTimeoutId = 0; this._timestampTimeoutId = 0;
}, },
appendMessage: function(message, direction) { /**
let type = message.get_message_type(); * appendMessage:
let [text, flags] = message.to_text(); * @message: An object with the properties:
let timestamp = message.get_received_timestamp(); * text: the body of the message,
* messageType: a #Tp.ChannelTextMessageType,
* sender: the name of the sender,
* timestamp: the time the message was sent
* direction: a #NotificationDirection
*
* @noTimestamp: Whether to add a timestamp. If %true, no timestamp
* will be added, regardless of the difference since the
* last timestamp
*/
appendMessage: function(message, noTimestamp) {
let messageBody = GLib.markup_escape_text(message.text, -1);
let styles = [message.direction];
let messageBody = GLib.markup_escape_text(text, -1); if (message.messageType == Tp.ChannelTextMessageType.ACTION) {
let styles = [direction]; let senderAlias = GLib.markup_escape_text(message.sender, -1);
if (type == Tp.ChannelTextMessageType.ACTION) {
let senderAlias = GLib.markup_escape_text(message.sender.alias, -1);
messageBody = '<i>%s</i> %s'.format(senderAlias, messageBody); messageBody = '<i>%s</i> %s'.format(senderAlias, messageBody);
styles.push('chat-action'); styles.push('chat-action');
} }
this.update(this.source.title, messageBody, { customContent: true, bannerMarkup: true }); this.update(this.source.title, messageBody, { customContent: true, bannerMarkup: true });
this._append(messageBody, styles, timestamp); this._append(messageBody, styles, message.timestamp, noTimestamp);
}, },
_append: function(text, styles, timestamp) { _append: function(text, styles, timestamp, noTimestamp) {
let currentTime = (Date.now() / 1000); let currentTime = (Date.now() / 1000);
if (!timestamp) if (!timestamp)
timestamp = currentTime; timestamp = currentTime;
@ -356,14 +433,16 @@ Notification.prototype = {
this._history.unshift({ actor: body, time: timestamp, realMessage: true }); this._history.unshift({ actor: body, time: timestamp, realMessage: true });
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) if (!noTimestamp) {
this._appendTimestamp(); if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME)
else this.appendTimestamp();
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME else
// from the timestamp of the message. // Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
this._timestampTimeoutId = Mainloop.timeout_add_seconds( // from the timestamp of the message.
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp), this._timestampTimeoutId = Mainloop.timeout_add_seconds(
Lang.bind(this, this._appendTimestamp)); SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
Lang.bind(this, this.appendTimestamp));
}
if (this._history.length > 1) { if (this._history.length > 1) {
// Keep the scrollback from growing too long. If the most // Keep the scrollback from growing too long. If the most
@ -384,7 +463,7 @@ Notification.prototype = {
} }
}, },
_appendTimestamp: function() { appendTimestamp: function() {
let lastMessageTime = this._history[0].time; let lastMessageTime = this._history[0].time;
let lastMessageDate = new Date(lastMessageTime * 1000); let lastMessageDate = new Date(lastMessageTime * 1000);