if (this._container.data('count')) {
this._favico.badge(this._container.data('count'));
}
+
+ WCF.System.PushNotification.addCallback('userNotificationCount', $.proxy(this.updateUserNotificationCount, this));
},
/**
switch (data.actionName) {
case 'markAllAsConfirmed':
$('.jsNotificationItem').remove();
-
- // remove notification count
- this._favico.badge(0);
// fall through
case 'getOutstandingNotifications':
if (!data.returnValues || !data.returnValues.template) {
});
break;
}
+ },
+
+ /**
+ * @see WCF.UserPanel._updateBadge()
+ */
+ _updateBadge: function(count) {
+ this._super(count);
+
+ this._favico.badge(count);
+ },
+
+ /**
+ * Updates user notification count.
+ *
+ * @param integer count
+ */
+ updateUserNotificationCount: function(count) {
+ // close dropdown
+ WCF.Dropdown.close('userNotifications');
+
+ // revert dropdown to initial state
+ var $dropdownMenu = WCF.Dropdown.getDropdownMenu('userNotifications');
+ var $item = $dropdownMenu.find('.dropdownDivider:eq(0)');
+ $item.prevAll().remove();
+ $('<li class="jsDropdownPlaceholder"><span>' + WCF.Language.get('wcf.global.loading') + '</span></li>').insertBefore($item);
+ this._didLoad = false;
+
+ // update badge
+ this._updateBadge(count);
}
});
return;
}
- this._dropdowns[containerID].removeClass('dropdownMenu');
- this._menus[containerID].removeClass('dropdownMenu');
+ this._dropdowns[containerID].removeClass('dropdownOpen');
+ this._menus[containerID].removeClass('dropdownOpen');
},
/**
},
failure: function() { pe.stop(); },
showLoadingOverlay: false,
+ success: function(data) {
+ WCF.System.PushNotification.executeCallbacks(data);
+ },
suppressErrors: true
});
}, (seconds * 1000));
}
});
+/**
+ * System-wide handler for push notifications.
+ */
+WCF.System.PushNotification = {
+ /**
+ * list of callbacks groupped by type
+ * @var object<array>
+ */
+ _callbacks: { },
+
+ /**
+ * Adds a callback for a specific notification type.
+ *
+ * @param string type
+ * @param object callback
+ */
+ addCallback: function(type, callback) {
+ if (this._callbacks[type] === undefined) {
+ this._callbacks[type] = [ ];
+ }
+
+ this._callbacks[type].push(callback);
+ },
+
+ /**
+ * Executes all registered callbacks by type.
+ *
+ * @param object data
+ */
+ executeCallbacks: function(data) {
+ for (var $type in data.returnValues) {
+ if (this._callbacks[$type] !== undefined) {
+ for (var $i = 0; $i < this._callbacks[$type].length; $i++) {
+ this._callbacks[$type][$i](data.returnValues[$type]);
+ }
+ }
+ }
+ }
+}
+
/**
* Worker support for frontend based upon DatabaseObjectActions.
*
$('' + data.returnValues.template).prependTo($dropdownMenu);
// update badge
- var $badge = this._container.find('.badge');
- if (!$badge.length) {
- $badge = $('<span class="badge badgeInverse" />').appendTo(this._container.children('.dropdownToggle'));
- $badge.before(' ');
- }
- $badge.html(data.returnValues.totalCount);
+ this._updateBadge(data.returnValues.totalCount);
this._after($dropdownMenu);
}
$('<li><span>' + WCF.Language.get(this._noItems) + '</span></li>').prependTo($dropdownMenu);
// remove badge
+ this._updateBadge(0);
+ }
+ },
+
+ /**
+ * Updates badge count.
+ *
+ * @param integer count
+ */
+ _updateBadge: function(count) {
+ if (count) {
+ var $badge = this._container.find('.badge');
+ if (!$badge.length) {
+ $badge = $('<span class="badge badgeInverse" />').appendTo(this._container.children('.dropdownToggle'));
+ $badge.before(' ');
+ }
+ $badge.html(count);
+ }
+ else {
this._container.find('.badge').remove();
}
},
<?php
namespace wcf\data\session;
use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\event\EventHandler;
use wcf\system\session\SessionHandler;
+use wcf\system\user\notification\UserNotificationHandler;
use wcf\system\WCF;
/**
*/
protected $className = 'wcf\data\session\SessionEditor';
+ /**
+ * list of data values returned upon a keep alive request
+ * @var array<mixed>
+ */
+ public $keepAliveData = array();
+
/**
* Validates the 'keepAlive' action.
*/
}
/**
- * Updates session's last activity time to prevent it from expiring.
+ * Updates session's last activity time to prevent it from expiring. In addition this method
+ * will return updated counters for notifications and 3rd party components.
+ *
+ * @return array<mixed>
*/
public function keepAlive() {
// ignore sessions created by this request
return;
}
+ // update last activity time
SessionHandler::getInstance()->keepAlive();
+
+ // update notification counts
+ $this->keepAliveData = array(
+ 'userNotificationCount' => UserNotificationHandler::getInstance()->getNotificationCount(true)
+ );
+
+ // notify 3rd party components
+ EventHandler::getInstance()->fireAction($this, 'keepAlive');
+
+ return $this->keepAliveData;
}
}