Approve room invitations
We use to rely on Empathy for this but as we plan to allow users to be connected on IM without having Empathy running the Shell should do it now. https://bugzilla.gnome.org/show_bug.cgi?id=653740
This commit is contained in:
parent
c34b357051
commit
998c5f17fc
@ -190,9 +190,10 @@ NotificationDaemon.prototype = {
|
|||||||
actions, hints, timeout) {
|
actions, hints, timeout) {
|
||||||
let id;
|
let id;
|
||||||
|
|
||||||
// Filter out chat and presence notifications from Empathy, since we
|
// Filter out chat, presence and invitation notifications from Empathy, since we
|
||||||
// handle that information from telepathyClient.js
|
// handle that information from telepathyClient.js
|
||||||
if (appName == 'Empathy' && (hints['category'] == 'im.received' ||
|
if (appName == 'Empathy' && (hints['category'] == 'im.received' ||
|
||||||
|
hints['category'] == 'x-empathy.im.room-invitation' ||
|
||||||
hints['category'] == 'presence.online' ||
|
hints['category'] == 'presence.online' ||
|
||||||
hints['category'] == 'presence.offline')) {
|
hints['category'] == 'presence.offline')) {
|
||||||
// Ignore replacesId since we already sent back a
|
// Ignore replacesId since we already sent back a
|
||||||
|
@ -178,19 +178,63 @@ Client.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_displayRoomInvitation: function(conn, channel, dispatchOp, context) {
|
||||||
|
// We can only approve the rooms if we have been invited to it
|
||||||
|
let selfHandle = channel.group_get_self_handle();
|
||||||
|
if (selfHandle == 0) {
|
||||||
|
Shell.decline_dispatch_op(context, 'Not invited to the room');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let [invited, inviter, reason, msg] = channel.group_get_local_pending_info(selfHandle);
|
||||||
|
if (!invited) {
|
||||||
|
Shell.decline_dispatch_op(context, 'Not invited to the room');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request a TpContact for the inviter
|
||||||
|
Shell.get_tp_contacts(conn, [inviter],
|
||||||
|
contactFeatures,
|
||||||
|
Lang.bind(this, this._createRoomInviteSource, channel, context, dispatchOp));
|
||||||
|
|
||||||
|
context.delay();
|
||||||
|
},
|
||||||
|
|
||||||
|
_createRoomInviteSource: function(connection, contacts, failed, channel, context, dispatchOp) {
|
||||||
|
if (contacts.length < 1) {
|
||||||
|
Shell.decline_dispatch_op(context, 'Failed to get inviter');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We got the TpContact
|
||||||
|
let source = new RoomInviteSource(dispatchOp);
|
||||||
|
Main.messageTray.add(source);
|
||||||
|
|
||||||
|
let notif = new RoomInviteNotification(source, dispatchOp, channel, contacts[0]);
|
||||||
|
source.notify(notif);
|
||||||
|
context.accept();
|
||||||
|
},
|
||||||
|
|
||||||
_approveChannels: function(approver, account, conn, channels,
|
_approveChannels: function(approver, account, conn, channels,
|
||||||
dispatchOp, context) {
|
dispatchOp, context) {
|
||||||
// Approve the channels right away as we are going to handle it
|
let channel = channels[0];
|
||||||
dispatchOp.claim_with_async(this._tpClient,
|
let [targetHandle, targetHandleType] = channel.get_handle();
|
||||||
Lang.bind (this, function(dispatchOp, result) {
|
|
||||||
try {
|
|
||||||
dispatchOp.claim_with_finish(result);
|
|
||||||
this._handlingChannels(account, conn, channels);
|
|
||||||
} catch (err) {
|
|
||||||
global.logError('Failed to Claim channel: ' + err);
|
|
||||||
}}));
|
|
||||||
|
|
||||||
context.accept();
|
if (targetHandleType == Tp.HandleType.CONTACT) {
|
||||||
|
// Approve private text channels right away as we are going to handle it
|
||||||
|
dispatchOp.claim_with_async(this._tpClient,
|
||||||
|
Lang.bind(this, function(dispatchOp, result) {
|
||||||
|
try {
|
||||||
|
dispatchOp.claim_with_finish(result);
|
||||||
|
this._handlingChannels(account, conn, channels);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error('Failed to Claim channel: ' + err);
|
||||||
|
}}));
|
||||||
|
|
||||||
|
context.accept();
|
||||||
|
} else {
|
||||||
|
this._displayRoomInvitation(conn, channel, dispatchOp, context);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleChannels: function(handler, account, conn, channels,
|
_handleChannels: function(handler, account, conn, channels,
|
||||||
@ -684,3 +728,86 @@ ChatNotification.prototype = {
|
|||||||
this.source.respond(text);
|
this.source.respond(text);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function RoomInviteSource(dispatchOp) {
|
||||||
|
this._init(dispatchOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomInviteSource.prototype = {
|
||||||
|
__proto__: MessageTray.Source.prototype,
|
||||||
|
|
||||||
|
_init: function(dispatchOp) {
|
||||||
|
MessageTray.Source.prototype._init.call(this, _("Invitation"));
|
||||||
|
|
||||||
|
this._setSummaryIcon(this.createNotificationIcon());
|
||||||
|
|
||||||
|
this._dispatchOp = dispatchOp;
|
||||||
|
|
||||||
|
// Destroy the source if the channel dispatch operation is invalidated
|
||||||
|
// as we can't approve any more.
|
||||||
|
this._invalidId = dispatchOp.connect('invalidated',
|
||||||
|
Lang.bind(this, function(domain, code, msg) {
|
||||||
|
this.destroy();
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
if (this._invalidId != 0) {
|
||||||
|
this._dispatchOp.disconnect(this._invalidId);
|
||||||
|
this._invalidId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageTray.Source.prototype.destroy.call(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
createNotificationIcon: function() {
|
||||||
|
// FIXME: We don't have a 'chat room' icon (bgo #653737) use
|
||||||
|
// system-users for now as Empathy does.
|
||||||
|
return new St.Icon({ icon_name: 'system-users',
|
||||||
|
icon_type: St.IconType.FULLCOLOR,
|
||||||
|
icon_size: this.ICON_SIZE });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function RoomInviteNotification(source, dispatchOp, channel, inviter) {
|
||||||
|
this._init(source, dispatchOp, channel, inviter);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomInviteNotification.prototype = {
|
||||||
|
__proto__: MessageTray.Notification.prototype,
|
||||||
|
|
||||||
|
_init: function(source, dispatchOp, channel, inviter) {
|
||||||
|
MessageTray.Notification.prototype._init.call(this,
|
||||||
|
source,
|
||||||
|
/* translators: argument is a room name like
|
||||||
|
* room@jabber.org for example. */
|
||||||
|
_("Invitation to %s").format(channel.get_identifier()),
|
||||||
|
null,
|
||||||
|
{ customContent: true });
|
||||||
|
this.setResident(true);
|
||||||
|
|
||||||
|
/* translators: first argument is the name of a contact and the second
|
||||||
|
* one the name of a room. "Alice is inviting you to join room@jabber.org
|
||||||
|
* for example. */
|
||||||
|
this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier()));
|
||||||
|
|
||||||
|
this.addButton('decline', _("Decline"));
|
||||||
|
this.addButton('accept', _("Accept"));
|
||||||
|
|
||||||
|
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||||
|
switch (action) {
|
||||||
|
case 'decline':
|
||||||
|
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
|
||||||
|
'', function(src, result) {
|
||||||
|
src.leave_channels_finish(result)});
|
||||||
|
break;
|
||||||
|
case 'accept':
|
||||||
|
dispatchOp.handle_with_time_async('', global.get_current_time(),
|
||||||
|
function(src, result) {
|
||||||
|
src.handle_with_time_finish(result)});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.destroy();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -101,6 +101,15 @@ shell_tp_client_init (ShellTpClient *self)
|
|||||||
/* Approver */
|
/* Approver */
|
||||||
tp_base_client_add_approver_filter (TP_BASE_CLIENT (self), filter);
|
tp_base_client_add_approver_filter (TP_BASE_CLIENT (self), filter);
|
||||||
|
|
||||||
|
/* Approve room invitations. We don't handle or observe room channels so
|
||||||
|
* just register this filter for the approver. */
|
||||||
|
tp_base_client_take_approver_filter (TP_BASE_CLIENT (self), tp_asv_new (
|
||||||
|
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
|
||||||
|
TP_IFACE_CHANNEL_TYPE_TEXT,
|
||||||
|
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
|
||||||
|
TP_HANDLE_TYPE_ROOM,
|
||||||
|
NULL));
|
||||||
|
|
||||||
/* Handler */
|
/* Handler */
|
||||||
tp_base_client_add_handler_filter (TP_BASE_CLIENT (self), filter);
|
tp_base_client_add_handler_filter (TP_BASE_CLIENT (self), filter);
|
||||||
|
|
||||||
@ -371,3 +380,15 @@ shell_get_contact_events (TplLogManager *log_manager,
|
|||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
callback, NULL);
|
callback, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* gjs doesn't allow us to craft a GError so we need a C wrapper */
|
||||||
|
void
|
||||||
|
shell_decline_dispatch_op (TpAddDispatchOperationContext *context,
|
||||||
|
const gchar *message)
|
||||||
|
{
|
||||||
|
GError *error = g_error_new_literal (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
|
||||||
|
message);
|
||||||
|
|
||||||
|
tp_add_dispatch_operation_context_fail (context, error);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
@ -111,5 +111,8 @@ void shell_get_contact_events (TplLogManager *log_manager,
|
|||||||
guint num_events,
|
guint num_events,
|
||||||
GAsyncReadyCallback callback);
|
GAsyncReadyCallback callback);
|
||||||
|
|
||||||
|
void shell_decline_dispatch_op (TpAddDispatchOperationContext *context,
|
||||||
|
const gchar *message);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* __SHELL_TP_CLIENT_H__ */
|
#endif /* __SHELL_TP_CLIENT_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user