remove messaging.js; use notificationDaemon.js for empathy messages too
Empathy sends notifications on all the events we care about, so just use those rather than fiddling with Telepathy to get duplicate copies of them. https://bugzilla.gnome.org/show_bug.cgi?id=606331
This commit is contained in:
parent
a424bbbabf
commit
a02e6d30f7
@ -16,7 +16,6 @@ const Chrome = imports.ui.chrome;
|
|||||||
const Environment = imports.ui.environment;
|
const Environment = imports.ui.environment;
|
||||||
const ExtensionSystem = imports.ui.extensionSystem;
|
const ExtensionSystem = imports.ui.extensionSystem;
|
||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
const Messaging = imports.ui.messaging;
|
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const PlaceDisplay = imports.ui.placeDisplay;
|
const PlaceDisplay = imports.ui.placeDisplay;
|
||||||
@ -38,7 +37,6 @@ let overview = null;
|
|||||||
let runDialog = null;
|
let runDialog = null;
|
||||||
let lookingGlass = null;
|
let lookingGlass = null;
|
||||||
let wm = null;
|
let wm = null;
|
||||||
let messaging = null;
|
|
||||||
let notificationDaemon = null;
|
let notificationDaemon = null;
|
||||||
let notificationPopup = null;
|
let notificationPopup = null;
|
||||||
let messageTray = null;
|
let messageTray = null;
|
||||||
@ -120,7 +118,6 @@ function start() {
|
|||||||
panel = new Panel.Panel();
|
panel = new Panel.Panel();
|
||||||
sidebar = new Sidebar.Sidebar();
|
sidebar = new Sidebar.Sidebar();
|
||||||
wm = new WindowManager.WindowManager();
|
wm = new WindowManager.WindowManager();
|
||||||
messaging = new Messaging.Messaging();
|
|
||||||
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
||||||
notificationPopup = new MessageTray.Notification();
|
notificationPopup = new MessageTray.Notification();
|
||||||
messageTray = new MessageTray.MessageTray();
|
messageTray = new MessageTray.MessageTray();
|
||||||
|
@ -1,435 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const DBus = imports.dbus;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
|
||||||
|
|
||||||
const TELEPATHY = "org.freedesktop.Telepathy.";
|
|
||||||
const CONN = TELEPATHY + "Connection";
|
|
||||||
const CHANNEL = TELEPATHY + "Channel";
|
|
||||||
const CHANNELTEXT = CHANNEL + ".Type.Text";
|
|
||||||
const ACCOUNTMANAGER = TELEPATHY + 'AccountManager';
|
|
||||||
|
|
||||||
const ClientIface = {
|
|
||||||
name: TELEPATHY + "Client",
|
|
||||||
properties: [{ name: "Interfaces",
|
|
||||||
signature: "as",
|
|
||||||
access: "read" }]
|
|
||||||
};
|
|
||||||
|
|
||||||
const ClientObserverIface = {
|
|
||||||
name: TELEPATHY + "Client.Observer",
|
|
||||||
methods: [{ name: "ObserveChannels",
|
|
||||||
inSignature: "ooa(oa{sv})oaoa{sv}",
|
|
||||||
outSignature: "" }],
|
|
||||||
properties: [{ name: "ObserverChannelFilter",
|
|
||||||
signature: "aa{sv}",
|
|
||||||
access: "read" }]
|
|
||||||
};
|
|
||||||
|
|
||||||
const ConnectionIface = {
|
|
||||||
name: CONN,
|
|
||||||
methods: [
|
|
||||||
// This is deprecated, but the alternative requires building
|
|
||||||
// another interface object...
|
|
||||||
{ name: "ListChannels",
|
|
||||||
inSignature: "",
|
|
||||||
outSignature: "a(osuu)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'StatusChanged', inSignature: 'u' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
function Connection(path) {
|
|
||||||
this._init(path);
|
|
||||||
};
|
|
||||||
|
|
||||||
Connection.prototype = {
|
|
||||||
_init: function(path) {
|
|
||||||
DBus.session.proxifyObject(this, nameify(path), path);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(Connection.prototype, ConnectionIface);
|
|
||||||
|
|
||||||
const ConnectionAvatarsIface = {
|
|
||||||
name: CONN + '.Interface.Avatars',
|
|
||||||
methods: [
|
|
||||||
{ name: 'GetKnownAvatarTokens',
|
|
||||||
inSignature: 'au',
|
|
||||||
outSignature: 'a{us}'
|
|
||||||
},
|
|
||||||
{ name: 'RequestAvatars',
|
|
||||||
inSignature: 'au',
|
|
||||||
outSignature: ''
|
|
||||||
}
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'AvatarRetrieved',
|
|
||||||
inSignature: 'usays'
|
|
||||||
},
|
|
||||||
{ name: 'AvatarUpdated',
|
|
||||||
inSignature: 'us'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
function ConnectionAvatars(path) {
|
|
||||||
this._init(path);
|
|
||||||
};
|
|
||||||
|
|
||||||
ConnectionAvatars.prototype = {
|
|
||||||
_init: function(path) {
|
|
||||||
DBus.session.proxifyObject(this, nameify(path), path);
|
|
||||||
|
|
||||||
this.connect('AvatarUpdated', Lang.bind(this, this._avatarUpdated));
|
|
||||||
this.connect('AvatarRetrieved', Lang.bind(this, this._avatarRetrieved));
|
|
||||||
|
|
||||||
// _avatarData[handle] describes the icon for @handle: either
|
|
||||||
// the string 'default', meaning to use the default avatar, or
|
|
||||||
// an array of bytes containing, eg, PNG data.
|
|
||||||
this._avatarData = {};
|
|
||||||
|
|
||||||
// _icons[handle] is an array of the icon actors currently
|
|
||||||
// being displayed for @handle. These will be updated
|
|
||||||
// automatically if @handle's avatar changes.
|
|
||||||
this._icons = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
_avatarUpdated: function(iface, handle, token) {
|
|
||||||
if (!this._avatarData[handle]) {
|
|
||||||
// This would only happen if we get an AvatarUpdated
|
|
||||||
// signal for an avatar while there's already a
|
|
||||||
// RequestAvatars() call pending, so we don't need to do
|
|
||||||
// anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token == '') {
|
|
||||||
// Invoke the next async callback in the chain, telling
|
|
||||||
// it to use the default image.
|
|
||||||
this._avatarRetrieved(this, handle, token, 'default', null);
|
|
||||||
} else {
|
|
||||||
// In this case, @token is some sort of UUID. Telepathy
|
|
||||||
// expects us to cache avatar images to disk and use the
|
|
||||||
// tokens to figure out when we already have the right
|
|
||||||
// images cached. But we don't do that, we just
|
|
||||||
// ignore @token and request the image unconditionally.
|
|
||||||
this.RequestAvatarsRemote([handle]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_createIcon: function(iconData, size) {
|
|
||||||
let textureCache = Shell.TextureCache.get_default();
|
|
||||||
if (iconData == 'default')
|
|
||||||
return textureCache.load_icon_name('stock_person', size);
|
|
||||||
else
|
|
||||||
return textureCache.load_from_data(iconData, iconData.length, size);
|
|
||||||
},
|
|
||||||
|
|
||||||
_avatarRetrieved: function(iface, handle, token, avatarData, mimeType) {
|
|
||||||
this._avatarData[handle] = avatarData;
|
|
||||||
if (!this._icons[handle])
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < this._icons[handle].length; i++) {
|
|
||||||
let iconBox = this._icons[handle][i];
|
|
||||||
let size = iconBox.child.height;
|
|
||||||
iconBox.child = this._createIcon(avatarData, size);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
createAvatar: function(handle, size) {
|
|
||||||
let iconBox = new St.Bin({ style_class: 'avatar-box' });
|
|
||||||
|
|
||||||
if (!this._icons[handle])
|
|
||||||
this._icons[handle] = [];
|
|
||||||
this._icons[handle].push(iconBox);
|
|
||||||
|
|
||||||
iconBox.connect('destroy', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
let i = this._icons[handle].indexOf(iconBox);
|
|
||||||
if (i != -1)
|
|
||||||
this._icons[handle].splice(i, 1);
|
|
||||||
}));
|
|
||||||
|
|
||||||
let avatarData = this._avatarData[handle];
|
|
||||||
if (avatarData) {
|
|
||||||
iconBox.child = this._createIcon(avatarData, size);
|
|
||||||
return iconBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the default icon and then asynchronously load
|
|
||||||
// the real avatar.
|
|
||||||
iconBox.child = this._createIcon('default', size);
|
|
||||||
this.GetKnownAvatarTokensRemote([handle], Lang.bind(this,
|
|
||||||
function (tokens, excp) {
|
|
||||||
if (tokens && tokens[handle])
|
|
||||||
this.RequestAvatarsRemote([handle]);
|
|
||||||
else
|
|
||||||
this._avatarData[handle] = 'default';
|
|
||||||
}));
|
|
||||||
|
|
||||||
return iconBox;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(ConnectionAvatars.prototype, ConnectionAvatarsIface);
|
|
||||||
|
|
||||||
const ChannelIface = {
|
|
||||||
name: CHANNEL,
|
|
||||||
properties: [
|
|
||||||
{ name: "TargetHandle",
|
|
||||||
signature: "u",
|
|
||||||
access: "read" },
|
|
||||||
{ name: "TargetID",
|
|
||||||
signature: "s",
|
|
||||||
access: "read" }
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'Closed', inSignature: '' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
function Channel(name, path) {
|
|
||||||
this._init(name, path);
|
|
||||||
};
|
|
||||||
|
|
||||||
Channel.prototype = {
|
|
||||||
_init: function(name, path) {
|
|
||||||
DBus.session.proxifyObject(this, name, path);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(Channel.prototype, ChannelIface);
|
|
||||||
|
|
||||||
const ChannelTextIface = {
|
|
||||||
name: CHANNELTEXT,
|
|
||||||
methods: [
|
|
||||||
{ name: 'ListPendingMessages',
|
|
||||||
inSignature: 'b',
|
|
||||||
outSignature: 'a(uuuuus)'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
signals: [
|
|
||||||
{ name: 'Received', inSignature: 'uuuuus' }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
function ChannelText(name, path) {
|
|
||||||
this._init(name, path);
|
|
||||||
};
|
|
||||||
|
|
||||||
ChannelText.prototype = {
|
|
||||||
_init: function(name, path) {
|
|
||||||
DBus.session.proxifyObject(this, name, path);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(ChannelText.prototype, ChannelTextIface);
|
|
||||||
|
|
||||||
const AccountManagerIface = {
|
|
||||||
name: ACCOUNTMANAGER,
|
|
||||||
|
|
||||||
properties: [{ name: "ValidAccounts",
|
|
||||||
signature: "ao",
|
|
||||||
access: "read" }]
|
|
||||||
};
|
|
||||||
|
|
||||||
function AccountManager() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
AccountManager.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
DBus.session.proxifyObject(this,
|
|
||||||
ACCOUNTMANAGER,
|
|
||||||
pathify(ACCOUNTMANAGER));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(AccountManager.prototype, AccountManagerIface);
|
|
||||||
|
|
||||||
const AccountIface = {
|
|
||||||
name: 'org.freedesktop.Telepathy.Account',
|
|
||||||
|
|
||||||
properties: [{ name: "Connection",
|
|
||||||
signature: "o",
|
|
||||||
access: "read" }]
|
|
||||||
};
|
|
||||||
|
|
||||||
function Account(name, path) {
|
|
||||||
this._init(name, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Account.prototype = {
|
|
||||||
_init: function(name, path) {
|
|
||||||
DBus.session.proxifyObject(this, name, path);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.proxifyPrototype(Account.prototype, AccountIface);
|
|
||||||
|
|
||||||
let nameify = function(path) {
|
|
||||||
return path.substr(1).replace('/', '.', 'g');
|
|
||||||
};
|
|
||||||
|
|
||||||
let pathify = function(name) {
|
|
||||||
return '/' + name.replace('.', '/', 'g');
|
|
||||||
};
|
|
||||||
|
|
||||||
function Messaging() {
|
|
||||||
this._init();
|
|
||||||
};
|
|
||||||
|
|
||||||
Messaging.prototype = {
|
|
||||||
_init : function() {
|
|
||||||
let name = TELEPATHY + "Client.GnomeShell";
|
|
||||||
DBus.session.exportObject(pathify(name), this);
|
|
||||||
DBus.session.acquire_name(name, DBus.SINGLE_INSTANCE,
|
|
||||||
function(name){log("Acquired name " + name);},
|
|
||||||
function(name){log("Lost name " + name);});
|
|
||||||
|
|
||||||
this._conns = {};
|
|
||||||
this._channels = {};
|
|
||||||
|
|
||||||
// Acquire existing connections. (This wouldn't really be
|
|
||||||
// needed if gnome-shell was only being started at the start
|
|
||||||
// of a session, but it's very useful for making things
|
|
||||||
// continue to work after restarting the shell.)
|
|
||||||
let accountManager = new AccountManager();
|
|
||||||
accountManager.GetRemote('ValidAccounts', Lang.bind(this, this._gotValidAccounts));
|
|
||||||
},
|
|
||||||
|
|
||||||
_gotValidAccounts: function(accounts, excp) {
|
|
||||||
if (!accounts)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < accounts.length; i++) {
|
|
||||||
let account = new Account(ACCOUNTMANAGER, accounts[i]);
|
|
||||||
account.GetRemote('Connection', Lang.bind(this,
|
|
||||||
function (conn_path, excp) {
|
|
||||||
if (!conn_path || conn_path == '/')
|
|
||||||
return;
|
|
||||||
|
|
||||||
let conn = new Connection(conn_path);
|
|
||||||
conn.ListChannelsRemote(Lang.bind(this,
|
|
||||||
function(channels, excp) {
|
|
||||||
if (!channels) {
|
|
||||||
log('no channels on ' + conn.getPath() + ': ' + excp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (let i = 0; i < channels.length; i++) {
|
|
||||||
let [path, channel_type, handle_type, handle] = channels[i];
|
|
||||||
if (channel_type != CHANNELTEXT)
|
|
||||||
continue;
|
|
||||||
if (this._channels[path])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let connName = nameify(conn.getPath());
|
|
||||||
let channel = new Channel(connName, path);
|
|
||||||
channel.GetAllRemote(Lang.bind(this,
|
|
||||||
function(props, excp) {
|
|
||||||
this._addChannel(conn, path,
|
|
||||||
props['TargetHandle'],
|
|
||||||
props['TargetID']);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
get Interfaces() {
|
|
||||||
return [TELEPATHY + "Client.Observer"];
|
|
||||||
},
|
|
||||||
|
|
||||||
get ObserverChannelFilter() {
|
|
||||||
return [
|
|
||||||
{ 'org.freedesktop.Telepathy.Channel.ChannelType': CHANNELTEXT }
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
ObserveChannels: function(account, conn_path, channels,
|
|
||||||
dispatch_operation, requests_satisfied,
|
|
||||||
observer_info) {
|
|
||||||
let conn = new Connection(conn_path);
|
|
||||||
let conn_name = nameify(conn_path);
|
|
||||||
for (let i = 0; i < channels.length; i++) {
|
|
||||||
let channelPath = channels[i][0];
|
|
||||||
let props = channels[i][1];
|
|
||||||
let targetHandle = props[CHANNEL + '.TargetHandle'];
|
|
||||||
let targetId = props[CHANNEL + '.TargetID'];
|
|
||||||
this._addChannel(conn, channelPath, targetHandle, targetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [true];
|
|
||||||
},
|
|
||||||
|
|
||||||
_addChannel: function(conn, channelPath, targetHandle, targetId) {
|
|
||||||
this._channels[channelPath] = new Source(conn, channelPath, targetHandle, targetId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DBus.conformExport(Messaging.prototype, ClientIface);
|
|
||||||
DBus.conformExport(Messaging.prototype, ClientObserverIface);
|
|
||||||
|
|
||||||
function Source(conn, channelPath, channel_props, targetId) {
|
|
||||||
this._init(conn, channelPath, channel_props, targetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Source.prototype = {
|
|
||||||
__proto__: MessageTray.Source.prototype,
|
|
||||||
|
|
||||||
_init: function(conn, channelPath, targetHandle, targetId) {
|
|
||||||
MessageTray.Source.prototype._init.call(this, targetId);
|
|
||||||
|
|
||||||
let connName = nameify(conn.getPath());
|
|
||||||
this._channel = new Channel(connName, channelPath);
|
|
||||||
this._closedId = this._channel.connect('Closed', Lang.bind(this, this._channelClosed));
|
|
||||||
|
|
||||||
this._targetHandle = targetHandle;
|
|
||||||
this._targetId = targetId;
|
|
||||||
log('channel for ' + this._targetId + ' channelPath ' + channelPath);
|
|
||||||
|
|
||||||
this._avatars = new ConnectionAvatars(conn.getPath());
|
|
||||||
|
|
||||||
this._channelText = new ChannelText(connName, channelPath);
|
|
||||||
this._receivedId = this._channelText.connect('Received', Lang.bind(this, this._receivedMessage));
|
|
||||||
|
|
||||||
this._channelText.ListPendingMessagesRemote(false, Lang.bind(this, this._gotPendingMessages));
|
|
||||||
},
|
|
||||||
|
|
||||||
createIcon: function(size) {
|
|
||||||
return this._avatars.createAvatar(this._targetHandle, size);
|
|
||||||
},
|
|
||||||
|
|
||||||
_gotPendingMessages: function(msgs, excp) {
|
|
||||||
if (!msgs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < msgs.length; i++)
|
|
||||||
this._receivedMessage.apply(this, [this._channel].concat(msgs[i]));
|
|
||||||
},
|
|
||||||
|
|
||||||
_channelClosed: function() {
|
|
||||||
log('Channel closed ' + this._targetId);
|
|
||||||
this._channel.disconnect(this._closedId);
|
|
||||||
this._channelText.disconnect(this._receivedId);
|
|
||||||
this.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
_receivedMessage: function(channel, id, timestamp, sender,
|
|
||||||
type, flags, text) {
|
|
||||||
log('Received: id ' + id + ', time ' + timestamp + ', sender ' + sender + ', type ' + type + ', flags ' + flags + ': ' + text);
|
|
||||||
if (!Main.messageTray.contains(this))
|
|
||||||
Main.messageTray.add(this);
|
|
||||||
this.notify(text);
|
|
||||||
}
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user