Using session keep alive to update notification count
authorAlexander Ebert <ebert@woltlab.com>
Sun, 29 Jun 2014 10:17:13 +0000 (12:17 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 29 Jun 2014 10:17:13 +0000 (12:17 +0200)
wcfsetup/install/files/js/WCF.User.js
wcfsetup/install/files/js/WCF.js
wcfsetup/install/files/lib/data/session/SessionAction.class.php

index d855778447ace3eb5ae3c03ea261e71fbc9efc84..440210dd87cb580f787fe4279c30738e3258b443 100644 (file)
@@ -1277,6 +1277,8 @@ WCF.Notification.UserPanel = WCF.UserPanel.extend({
                if (this._container.data('count')) {
                        this._favico.badge(this._container.data('count'));
                }
+               
+               WCF.System.PushNotification.addCallback('userNotificationCount', $.proxy(this.updateUserNotificationCount, this));
        },
        
        /**
@@ -1344,9 +1346,6 @@ WCF.Notification.UserPanel = WCF.UserPanel.extend({
                switch (data.actionName) {
                        case 'markAllAsConfirmed':
                                $('.jsNotificationItem').remove();
-                               
-                               // remove notification count
-                               this._favico.badge(0);
                        // fall through
                        case 'getOutstandingNotifications':
                                if (!data.returnValues || !data.returnValues.template) {
@@ -1367,6 +1366,35 @@ WCF.Notification.UserPanel = WCF.UserPanel.extend({
                                });
                        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);
        }
 });
 
index 34afa84ab63872b80991c07c19db0675162730ba..2593ac09adc96390100bcfccbaafda3f2e133157 100755 (executable)
@@ -1245,8 +1245,8 @@ WCF.Dropdown = {
                        return;
                }
                
-               this._dropdowns[containerID].removeClass('dropdownMenu');
-               this._menus[containerID].removeClass('dropdownMenu');
+               this._dropdowns[containerID].removeClass('dropdownOpen');
+               this._menus[containerID].removeClass('dropdownOpen');
        },
        
        /**
@@ -7603,12 +7603,55 @@ WCF.System.KeepAlive = Class.extend({
                                },
                                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.
  * 
@@ -10103,12 +10146,7 @@ WCF.UserPanel = Class.extend({
                        $('' + 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);
                }
@@ -10116,6 +10154,25 @@ WCF.UserPanel = Class.extend({
                        $('<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();
                }
        },
index e848995b973724117e046acca0387c726bf12435..f4b41daddd3e51de7b07522a957c7064e8cccfe7 100644 (file)
@@ -1,7 +1,9 @@
 <?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;
 
 /**
@@ -25,6 +27,12 @@ class SessionAction extends AbstractDatabaseObjectAction {
         */
        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.
         */
@@ -33,7 +41,10 @@ class SessionAction extends AbstractDatabaseObjectAction {
        }
        
        /**
-        * 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
@@ -41,6 +52,17 @@ class SessionAction extends AbstractDatabaseObjectAction {
                        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;
        }
 }