13
13
const History = imports.misc.history;
14
14
const Main = imports.ui.main;
15
15
const MessageTray = imports.ui.messageTray;
16
const NotificationDaemon = imports.ui.notificationDaemon;
16
17
const Params = imports.misc.params;
17
18
const PopupMenu = imports.ui.popupMenu;
385
386
/* Display notification to ask user to accept/reject request */
386
let source = this._ensureSubscriptionSource();
387
let source = this._ensureAppSource();
388
389
let notif = new SubscriptionRequestNotification(source, contact);
389
390
source.notify(notif);
392
_ensureSubscriptionSource: function() {
393
if (this._subscriptionSource == null) {
394
this._subscriptionSource = new MessageTray.Source(_("Subscription request"),
395
'gtk-dialog-question');
396
Main.messageTray.add(this._subscriptionSource);
397
this._subscriptionSource.connect('destroy', Lang.bind(this, function () {
398
this._subscriptionSource = null;
402
return this._subscriptionSource;
405
393
_accountConnectionStatusNotifyCb: function(account) {
406
394
let connectionError = account.connection_error;
417
405
/* Display notification that account failed to connect */
418
let source = this._ensureAccountSource();
406
let source = this._ensureAppSource();
420
408
notif = new AccountNotification(source, account, connectionError);
421
409
this._accountNotifications[account.get_object_path()] = notif;
425
413
source.notify(notif);
428
_ensureAccountSource: function() {
429
if (this._accountSource == null) {
430
this._accountSource = new MessageTray.Source(_("Connection error"),
432
Main.messageTray.add(this._accountSource);
433
this._accountSource.connect('destroy', Lang.bind(this, function () {
434
this._accountSource = null;
416
_ensureAppSource: function() {
417
if (this._appSource == null) {
418
this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
419
this._appSource.policy = new NotificationDaemon.NotificationApplicationPolicy('empathy');
421
Main.messageTray.add(this._appSource);
422
this._appSource.connect('destroy', Lang.bind(this, function () {
423
this._appSource = null;
438
return this._accountSource;
427
return this._appSource;
493
482
item.connect('activate', Lang.bind(this, function() {
494
483
this.setMuted(!this.isMuted);
495
this.emit('done-displaying-content');
484
this.emit('done-displaying-content', false);
497
486
rightClickMenu.add(item.actor);
498
487
return rightClickMenu;
490
_createPolicy: function() {
491
return new NotificationDaemon.NotificationApplicationPolicy('empathy');
501
494
_updateAlias: function() {
502
495
let oldAlias = this.title;
503
496
let newAlias = this._contact.get_alias();
509
502
this._notification.appendAliasChange(oldAlias, newAlias);
512
createIcon: function(size) {
513
this._iconBox = new St.Bin({ style_class: 'avatar-box' });
514
this._iconBox._size = size;
515
let textureCache = St.TextureCache.get_default();
505
getIcon: function() {
516
506
let file = this._contact.get_avatar_file();
519
let uri = file.get_uri();
520
this._iconBox.child = textureCache.load_uri_async(uri, this._iconBox._size, this._iconBox._size);
508
return new Gio.FileIcon({ file: file });
522
this._iconBox.child = new St.Icon({ icon_name: 'avatar-default',
523
icon_size: this._iconBox._size });
510
return new Gio.ThemedIcon({ name: 'avatar-default' });
526
return this._iconBox;
529
createSecondaryIcon: function() {
530
let iconBox = new St.Bin();
531
iconBox.child = new St.Icon({ style_class: 'secondary-icon' });
514
getSecondaryIcon: function() {
532
516
let presenceType = this._contact.get_presence_type();
534
518
switch (presenceType) {
535
519
case Tp.ConnectionPresenceType.AVAILABLE:
536
iconBox.child.icon_name = 'user-available';
520
iconName = 'user-available';
538
522
case Tp.ConnectionPresenceType.BUSY:
539
iconBox.child.icon_name = 'user-busy';
523
iconName = 'user-busy';
541
525
case Tp.ConnectionPresenceType.OFFLINE:
542
iconBox.child.icon_name = 'user-offline';
526
iconName = 'user-offline';
544
528
case Tp.ConnectionPresenceType.HIDDEN:
545
iconBox.child.icon_name = 'user-invisible';
529
iconName = 'user-invisible';
547
531
case Tp.ConnectionPresenceType.AWAY:
548
iconBox.child.icon_name = 'user-away';
532
iconName = 'user-away';
550
534
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
551
iconBox.child.icon_name = 'user-idle';
535
iconName = 'user-idle';
554
iconBox.child.icon_name = 'user-offline';
538
iconName = 'user-offline';
540
return new Gio.ThemedIcon({ name: iconName });
559
543
_updateAvatarIcon: function() {
736
724
title = GLib.markup_escape_text(this.title, -1);
738
this._notification.update(this._notification.title, null, { customContent: true, secondaryIcon: this.createSecondaryIcon() });
726
this._notification.update(this._notification.title, null, { customContent: true, secondaryGIcon: this.getSecondaryIcon() });
741
729
msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>';
753
741
_ackMessages: function() {
754
742
// Don't clear our messages here, tp-glib will send a
755
743
// 'pending-message-removed' for each one.
756
this._channel.ack_all_pending_messages_async(Lang.bind(this, function(src, result) {
757
this._channel.ack_all_pending_messages_finish(result);}));
744
this._channel.ack_all_pending_messages_async(null);
763
750
Extends: MessageTray.Notification,
765
752
_init: function(source) {
766
this.parent(source, source.title, null, { customContent: true, secondaryIcon: source.createSecondaryIcon() });
753
this.parent(source, source.title, null, { customContent: true, secondaryGIcon: source.getSecondaryIcon() });
767
754
this.setResident(true);
769
756
this._responseEntry = new St.Entry({ style_class: 'chat-response',
788
775
// force a scroll to the bottom if things change while we were at the
790
777
this._oldMaxScrollValue = this._scrollArea.vscroll.adjustment.value;
778
this._scrollArea.add_style_class_name('chat-notification-scrollview');
791
779
this._scrollArea.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
792
780
if (adjustment.value == this._oldMaxScrollValue)
793
781
this.scrollTo(St.Side.BOTTOM);
934
// Show only the hour if date is on today
936
format = "<b>%H:%M</b>";
938
// Show the word "Yesterday" and time if date is on yesterday
940
/* Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/
941
// xgettext:no-c-format
942
format = _("<b>Yesterday</b>, <b>%H:%M</b>");
946
944
// Show a week day and time if date is in the last week
947
if (daysAgo < 1 || (daysAgo < 7 && now.getDay() != date.getDay())) {
948
/* Translators: this is a time format string followed by a date.
949
If applicable, replace %X with a strftime format valid for your
950
locale, without seconds. */
945
else if (daysAgo < 7) {
946
/* Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/
951
947
// xgettext:no-c-format
952
format = _("Sent at <b>%X</b> on <b>%A</b>");
948
format = _("<b>%A</b>, <b>%H:%M</b>");
954
950
} else if (date.getYear() == now.getYear()) {
955
/* Translators: this is a time format in the style of "Wednesday, May 25",
956
shown when you get a chat message in the same year. */
951
/* Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/
957
952
// xgettext:no-c-format
958
format = _("Sent on <b>%A</b>, <b>%B %d</b>");
953
format = _("<b>%B</b> <b>%d</b>, <b>%H:%M</b>");
960
/* Translators: this is a time format in the style of "Wednesday, May 25, 2012",
961
shown when you get a chat message in a different year. */
955
/* Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/
962
956
// xgettext:no-c-format
963
format = _("Sent on <b>%A</b>, <b>%B %d</b>, %Y");
957
format = _("<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> ");
966
960
return date.toLocaleFormat(format);
973
967
let timeLabel = this._append({ body: this._formatTimestamp(lastMessageDate),
975
969
styles: ['chat-meta-message'],
976
childProps: { expand: true, x_fill: false,
977
x_align: St.Align.END },
970
childProps: { expand: true, x_fill: false },
978
971
noTimestamp: true,
979
972
timestamp: lastMessageTime });
1138
1134
this.parent(source, title, null, { customContent: true });
1139
1135
this.setResident(true);
1141
this.addButton('reject', _("Reject"));
1137
this.addButton('reject', _("Decline"));
1142
1138
/* translators: this is a button label (verb), not a noun */
1143
1139
this.addButton('answer', _("Answer"));
1355
1351
this.parent(source,
1356
1352
/* translators: argument is the account name, like
1357
1353
* name@jabber.org for example. */
1358
_("Connection to %s failed").format(account.get_display_name()),
1359
null, { customContent: true });
1361
this._label = new St.Label();
1362
this.addActor(this._label);
1363
this._updateMessage(connectionError);
1354
_("Unable to connect to %s").format(account.get_display_name()),
1355
this._getMessage(connectionError));
1365
1357
this._account = account;
1367
this.addButton('reconnect', _("Reconnect"));
1368
this.addButton('edit', _("Edit account"));
1359
this.addButton('view', _("View account"));
1370
1361
this.connect('action-invoked', Lang.bind(this, function(self, action) {
1371
1362
switch (action) {
1373
// If it fails again, a new notification should pop up with the
1375
account.reconnect_async(null);
1378
let cmd = '/usr/bin/empathy-accounts'
1379
+ ' --select-account=%s'
1380
.format(account.get_path_suffix());
1364
let cmd = 'empathy-accounts --select-account=' +
1365
account.get_path_suffix();
1381
1366
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
1382
1367
app_info.launch([], global.create_app_launch_context());
1400
1385
if (status == Tp.ConnectionStatus.CONNECTED) {
1401
1386
this.destroy();
1402
1387
} else if (status == Tp.ConnectionStatus.DISCONNECTED) {
1403
this._updateMessage(account.connection_error);
1388
this.update(this.title, this._getMessage(account.connection_error));
1408
_updateMessage: function(connectionError) {
1393
_getMessage: function(connectionError) {
1410
1395
if (connectionError in _connectionErrorMessages) {
1411
1396
message = _connectionErrorMessages[connectionError];
1413
1398
message = _("Unknown reason");
1415
this._label.set_text(message);
1418
1403
destroy: function() {