@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add multiple notifications and notification types

Summary:
- Allow more than one notification to be shown.
- Allow notifications to be customized with extra classes.

Test Plan: {F12776}

Reviewers: allenjohnashton, ddfisher, keebuhm, jungejason

Reviewed By: jungejason

CC: aran

Maniphest Tasks: T944

Differential Revision: https://secure.phabricator.com/D2758

+120 -38
+5 -3
src/__celerity_resource_map__.php
··· 1355 1355 ), 1356 1356 'javelin-behavior-phabricator-notification-example' => 1357 1357 array( 1358 - 'uri' => '/res/0b8fadf5/rsrc/js/application/uiexample/notification-example.js', 1358 + 'uri' => '/res/df97e4b3/rsrc/js/application/uiexample/notification-example.js', 1359 1359 'type' => 'js', 1360 1360 'requires' => 1361 1361 array( 1362 1362 0 => 'phabricator-notification', 1363 1363 1 => 'javelin-stratcom', 1364 1364 2 => 'javelin-behavior', 1365 + 3 => 'javelin-uri', 1365 1366 ), 1366 1367 'disk' => '/rsrc/js/application/uiexample/notification-example.js', 1367 1368 ), ··· 2181 2182 ), 2182 2183 'phabricator-notification' => 2183 2184 array( 2184 - 'uri' => '/res/253b3262/rsrc/js/application/core/Notification.js', 2185 + 'uri' => '/res/cacd79f1/rsrc/js/application/core/Notification.js', 2185 2186 'type' => 'js', 2186 2187 'requires' => 2187 2188 array( 2188 2189 0 => 'javelin-install', 2189 2190 1 => 'javelin-dom', 2190 2191 2 => 'javelin-stratcom', 2192 + 3 => 'javelin-util', 2191 2193 ), 2192 2194 'disk' => '/rsrc/js/application/core/Notification.js', 2193 2195 ), 2194 2196 'phabricator-notification-css' => 2195 2197 array( 2196 - 'uri' => '/res/423a14d1/rsrc/css/aphront/notification.css', 2198 + 'uri' => '/res/7452322a/rsrc/css/aphront/notification.css', 2197 2199 'type' => 'css', 2198 2200 'requires' => 2199 2201 array(
+9
webroot/rsrc/css/aphront/notification.css
··· 7 7 8 8 bottom: 24px; 9 9 left: 24px; 10 + } 11 + 12 + .jx-notification { 10 13 width: 240px; 11 14 padding: 8px 16px; 12 15 ··· 21 24 22 25 border-radius: 3px; 23 26 box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.25); 27 + margin-top: 4px; 28 + } 29 + 30 + .jx-notification-alert { 31 + background: #ffffa0; 32 + border: 1px solid #aaaa60; 24 33 }
+84 -26
webroot/rsrc/js/application/core/Notification.js
··· 2 2 * @requires javelin-install 3 3 * javelin-dom 4 4 * javelin-stratcom 5 + * javelin-util 5 6 * @provides phabricator-notification 6 7 * @javelin 7 8 */ ··· 22 23 members : { 23 24 show : function() { 24 25 var self = JX.Notification; 26 + self._show(this); 25 27 26 - self.close(); 27 - self._installListener(); 28 - self._active = this; 29 - 30 - var container = JX.$N( 28 + if (this.getDuration()) { 29 + setTimeout(JX.bind(self, self._hide, this), this.getDuration()); 30 + } 31 + }, 32 + _render : function() { 33 + return JX.$N( 31 34 'div', 32 35 { 33 - className: 'jx-notification-container', 36 + className: 'jx-notification ' + this.getClassName(), 34 37 sigil: 'jx-notification' 35 38 }, 36 39 this.getContent()); 37 - document.body.appendChild(container); 38 - 39 - self._container = container; 40 - 41 - if (this.getDuration()) { 42 - self._timeout = setTimeout(self.close, this.getDuration()); 43 - } 44 40 } 45 41 }, 46 42 47 43 properties : { 44 + 45 + /** 46 + * Optional class name(s) to add to the rendered notification. 47 + * 48 + * @param string Class name(s). 49 + */ 50 + className : null, 51 + 52 + /** 53 + * Notification content. 54 + * 55 + * @param mixed Content. 56 + */ 48 57 content : null, 49 58 50 59 /** ··· 54 63 * @param int Notification duration, in milliseconds. 55 64 */ 56 65 duration : 12000 66 + 57 67 }, 58 68 59 69 statics : { 60 70 _container : null, 61 71 _listening : false, 62 - _active : null, 72 + _active : [], 73 + _show : function(notification) { 74 + var self = JX.Notification; 75 + 76 + self._installListener(); 77 + self._active.push({ 78 + object: notification, 79 + render: notification._render() 80 + }); 81 + 82 + // Don't show more than a few notifications at once because it's silly. 83 + while (self._active.length > 5) { 84 + self._hide(self._active[0].object); 85 + } 86 + 87 + self._redraw(); 88 + }, 89 + _hide : function(notification) { 90 + var self = JX.Notification; 91 + 92 + for (var ii = 0; ii < self._active.length; ii++) { 93 + if (self._active[ii].object === notification) { 94 + notification.invoke('close'); 95 + self._active.splice(ii, 1); 96 + break; 97 + } 98 + } 99 + 100 + self._redraw(); 101 + }, 63 102 _installListener : function() { 64 103 var self = JX.Notification; 65 104 ··· 78 117 // the activate event for the active notification and dismiss it if it 79 118 // isn't handled. 80 119 81 - var activation = self._active.invoke('activate'); 82 - if (activation.getPrevented()) { 83 - return; 120 + var target = e.getNode('jx-notification'); 121 + for (var ii = 0; ii < self._active.length; ii++) { 122 + var n = self._active[ii]; 123 + if (n.render === target) { 124 + var activation = n.object.invoke('activate'); 125 + if (!activation.getPrevented()) { 126 + self._hide(n.object); 127 + } 128 + return; 129 + } 84 130 } 85 131 86 - self.close(); 87 132 }); 88 133 }, 89 - close : function() { 134 + _redraw : function() { 90 135 var self = JX.Notification; 91 136 92 - if (self._container) { 93 - JX.DOM.remove(self._container); 94 - self._container = null; 137 + if (!self._active.length) { 138 + if (self._container) { 139 + JX.DOM.remove(self._container); 140 + self._container = null; 141 + } 142 + return; 143 + } 144 + 145 + if (!self._container) { 146 + self._container = JX.$N( 147 + 'div', 148 + { 149 + className: 'jx-notification-container' 150 + }); 151 + document.body.appendChild(self._container); 152 + } 95 153 96 - self._active.invoke('close'); 97 - self._active = null; 154 + var notifications = []; 155 + for (var ii = 0; ii < self._active.length; ii++) { 156 + notifications.push(self._active[ii].render); 98 157 } 99 158 100 - self._timeout && clearTimeout(self._timeout); 101 - self._timeout = null; 159 + JX.DOM.setContent(self._container, notifications); 102 160 } 103 161 } 104 162
+22 -9
webroot/rsrc/js/application/uiexample/notification-example.js
··· 2 2 * @requires phabricator-notification 3 3 * javelin-stratcom 4 4 * javelin-behavior 5 + * javelin-uri 5 6 * @provides javelin-behavior-phabricator-notification-example 6 7 */ 7 8 ··· 12 13 function(e) { 13 14 e.kill(); 14 15 15 - var notification = new JX.Notification() 16 - .setContent('It is ' + new Date().toString()); 16 + var notification = new JX.Notification(); 17 + if (Math.random() > 0.1) { 18 + notification.setContent('It is ' + new Date().toString()); 17 19 18 - notification.listen( 19 - 'activate', 20 - function(e) { 21 - if (!confirm("Close notification?")) { 22 - e.kill(); 23 - } 24 - }); 20 + notification.listen( 21 + 'activate', 22 + function(e) { 23 + if (!confirm("Close notification?")) { 24 + e.kill(); 25 + } 26 + }); 27 + } else { 28 + notification 29 + .setContent('Alert! Click to reload!') 30 + .setDuration(0) 31 + .setClassName('jx-notification-alert'); 25 32 33 + notification.listen( 34 + 'activate', 35 + function(e) { 36 + new JX.$U().go(); 37 + }); 38 + } 26 39 notification.show() 27 40 }); 28 41