Page MenuHomePhabricator

D11360.id27378.diff
No OneTemporary

D11360.id27378.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -8,7 +8,7 @@
return array(
'names' => array(
'core.pkg.css' => '8d1c0f87',
- 'core.pkg.js' => 'b6a9c22a',
+ 'core.pkg.js' => 'f68622ac',
'darkconsole.pkg.js' => '8ab24e01',
'differential.pkg.css' => '8af45893',
'differential.pkg.js' => 'dad3622f',
@@ -342,9 +342,9 @@
'rsrc/image/texture/table_header.png' => '5c433037',
'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
'rsrc/image/texture/table_header_tall.png' => 'd56b434f',
- 'rsrc/js/application/aphlict/Aphlict.js' => 'b300dac3',
+ 'rsrc/js/application/aphlict/Aphlict.js' => 'bd5ef34c',
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '335470d7',
- 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => '62998733',
+ 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'cb695c97',
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
@@ -535,10 +535,10 @@
'herald-rule-editor' => '335fd41f',
'herald-test-css' => '778b008e',
'inline-comment-summary-css' => '8cfd34e8',
- 'javelin-aphlict' => 'b300dac3',
+ 'javelin-aphlict' => 'bd5ef34c',
'javelin-behavior' => '61cbc29a',
'javelin-behavior-aphlict-dropdown' => '335470d7',
- 'javelin-behavior-aphlict-listen' => '62998733',
+ 'javelin-behavior-aphlict-listen' => 'cb695c97',
'javelin-behavior-aphlict-status' => 'ea681761',
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
'javelin-behavior-aphront-crop' => 'fa0f4fc2',
@@ -1212,18 +1212,6 @@
'javelin-magical-init',
'javelin-util',
),
- 62998733 => array(
- 'javelin-behavior',
- 'javelin-aphlict',
- 'javelin-stratcom',
- 'javelin-request',
- 'javelin-uri',
- 'javelin-dom',
- 'javelin-json',
- 'javelin-router',
- 'javelin-util',
- 'phabricator-notification',
- ),
'6453c869' => array(
'javelin-install',
'javelin-dom',
@@ -1581,13 +1569,6 @@
'javelin-dom',
'phortune-credit-card-form',
),
- 'b300dac3' => array(
- 'javelin-install',
- 'javelin-util',
- 'javelin-websocket',
- 'javelin-leader',
- 'javelin-json',
- ),
'b3a4b884' => array(
'javelin-behavior',
'phabricator-prefab',
@@ -1623,6 +1604,13 @@
'javelin-vector',
'javelin-stratcom',
),
+ 'bd5ef34c' => array(
+ 'javelin-install',
+ 'javelin-util',
+ 'javelin-websocket',
+ 'javelin-leader',
+ 'javelin-json',
+ ),
'bdaf4d04' => array(
'javelin-behavior',
'javelin-dom',
@@ -1682,6 +1670,19 @@
'javelin-stratcom',
'phabricator-phtize',
),
+ 'cb695c97' => array(
+ 'javelin-behavior',
+ 'javelin-aphlict',
+ 'javelin-stratcom',
+ 'javelin-request',
+ 'javelin-uri',
+ 'javelin-dom',
+ 'javelin-json',
+ 'javelin-router',
+ 'javelin-util',
+ 'javelin-leader',
+ 'phabricator-notification',
+ ),
'cc1bd0b0' => array(
'javelin-install',
'javelin-event',
diff --git a/webroot/rsrc/js/application/aphlict/Aphlict.js b/webroot/rsrc/js/application/aphlict/Aphlict.js
--- a/webroot/rsrc/js/application/aphlict/Aphlict.js
+++ b/webroot/rsrc/js/application/aphlict/Aphlict.js
@@ -41,6 +41,12 @@
_subscriptions: null,
_status: null,
+ /**
+ * Starts the Aphlict client.
+ *
+ * This tab will attempt to become the leader tab. The leader tab will be
+ * responsible for sending and receiving messages from the Aphlict server.
+ */
start: function() {
JX.Leader.listen('onBecomeLeader', JX.bind(this, this._lead));
JX.Leader.listen('onReceiveBroadcast', JX.bind(this, this._receive));
@@ -62,6 +68,12 @@
{type: 'aphlict.subscribe', data: this._subscriptions});
},
+ /**
+ * Communicate with the Aphlict server.
+ *
+ * This function will be executed by the leader tab and will setup the
+ * necessary callbacks for communicating with the Aphlict server.
+ */
_lead: function() {
this._socket = new JX.WebSocket(this._uri);
this._socket.setOpenHandler(JX.bind(this, this._open));
@@ -84,29 +96,41 @@
JX.Leader.broadcast(null, {type: 'aphlict.status', data: status});
},
+ /**
+ * Receive a message from the Aphlict server.
+ *
+ * This callback is used by the leader tab to handle messages from the
+ * Aphlict server. When a message is received from the server it is then
+ * broadcast to all other tabs.
+ */
_message: function(raw) {
var message = JX.JSON.parse(raw);
JX.Leader.broadcast(null, {type: 'aphlict.server', data: message});
},
+ /**
+ * Receive a message from the leader.
+ *
+ * When the leader receives a message from the Aphlict server, it will be
+ * broadcast to all tabs.
+ */
_receive: function(message, is_leader) {
+ var handler = this.getHandler();
+
switch (message.type) {
case 'aphlict.status':
this._setStatus(message.data);
break;
-
case 'aphlict.getstatus':
if (is_leader) {
this._broadcastStatus(this.getStatus());
}
break;
-
case 'aphlict.getsubscribers':
JX.Leader.broadcast(
null,
{type: 'aphlict.subscribe', data: this._subscriptions});
break;
-
case 'aphlict.subscribe':
if (is_leader) {
this._write({
@@ -115,19 +139,26 @@
});
}
break;
-
case 'aphlict.server':
- var handler = this.getHandler();
handler && handler(message.data);
break;
+ default:
+ handler && handler(message, is_leader);
+ break;
}
},
+ /**
+ * Set a human-readable status string.
+ */
_setStatus: function(status) {
this._status = status;
this.invoke('didChangeStatus');
},
+ /**
+ * Send a message to the Aphlict server by writing to the socket.
+ */
_write: function(message) {
this._socket.send(JX.JSON.stringify(message));
}
diff --git a/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js b/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js
--- a/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js
+++ b/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js
@@ -9,22 +9,47 @@
* javelin-json
* javelin-router
* javelin-util
+ * javelin-leader
* phabricator-notification
*/
JX.behavior('aphlict-listen', function(config) {
+
var showing_reload = false;
- JX.Stratcom.listen('aphlict-receive-message', null, function(e) {
+ JX.Stratcom.listen('aphlict-server-message', null, function(e) {
var message = e.getData();
if (message.type != 'notification') {
return;
}
+ JX.Leader.callIfLeader(function() {
+ requestNotification(message);
+ });
+ });
+
+ // Respond to a notification from the Aphlict notification server. We send
+ // a request to Phabricator to get notification details.
+ function onAphlictMessage(message) {
+ switch (message.type) {
+ case 'aphlict.server':
+ JX.Stratcom.invoke('aphlict-server-message', null, message);
+ break;
+
+ case 'notification.individual':
+ JX.Stratcom.invoke('aphlict-notification-message');
+ break;
+ }
+ }
+
+ // Request the individual notification. This function is only called by the
+ // leader tab, which then broadcasts the notification content back to all
+ // other tabs.
+ function requestNotification(message) {
var request = new JX.Request(
- '/notification/individual/',
- onNotification);
+ '/notification/individual/',
+ receiveNotification);
var routable = request
.addData({key: message.key})
@@ -35,30 +60,32 @@
.setPriority(250);
JX.Router.getInstance().queue(routable);
- });
-
- // Respond to a notification from the Aphlict notification server. We send
- // a request to Phabricator to get notification details.
- function onAphlictMessage(message) {
- JX.Stratcom.invoke('aphlict-receive-message', null, message);
}
- // Respond to a response from Phabricator about a specific notification.
- function onNotification(response) {
+ // Receive the individual notification and broadcast it to all other tabs.
+ function receiveNotification(response) {
if (!response.pertinent) {
return;
}
+ JX.Leader.broadcast(null, {
+ type: 'notification.individual',
+ data: response
+ });
+ }
+
+ // Respond to a response from Phabricator about a specific notification.
+ JX.Stratcom.listen('aphlict-notification-message', null, function(e) {
JX.Stratcom.invoke('notification-panel-update', null, {});
// Show the notification itself.
new JX.Notification()
- .setContent(JX.$H(response.content))
+ .setContent(JX.$H(e.content))
.show();
- // If the notification affected an object on this page, show a
- // permanent reload notification if we aren't already.
- if ((response.primaryObjectPHID in config.pageObjects) && !showing_reload) {
+ // If the notification affected an object on this page, show a permanent
+ // reload notification if we aren't already.
+ if ((e.primaryObjectPHID in config.pageObjects) && !showing_reload) {
var reload = new JX.Notification()
.setContent('Page updated, click to reload.')
.alterClassName('jx-notification-alert', true)
@@ -68,7 +95,7 @@
showing_reload = true;
}
- }
+ });
var client = new JX.Aphlict(
config.websocketURI,

File Metadata

Mime Type
text/plain
Expires
Sat, May 11, 6:58 AM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6285031
Default Alt Text
D11360.id27378.diff (9 KB)

Event Timeline