Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15408484
D9700.id23293.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
16 KB
Referenced Files
None
Subscribers
None
D9700.id23293.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -7,8 +7,8 @@
return array(
'names' =>
array(
- 'core.pkg.css' => '22e4fc33',
- 'core.pkg.js' => 'f5ba2408',
+ 'core.pkg.css' => 'f9c94804',
+ 'core.pkg.js' => '8c184823',
'darkconsole.pkg.js' => 'df001cab',
'differential.pkg.css' => '4a93db37',
'differential.pkg.js' => 'd1443567',
@@ -37,7 +37,7 @@
'rsrc/css/aphront/typeahead.css' => 'a989b5b3',
'rsrc/css/application/auth/auth.css' => '1e655982',
'rsrc/css/application/base/main-menu-view.css' => 'aceca0e9',
- 'rsrc/css/application/base/notification-menu.css' => 'cbff1b94',
+ 'rsrc/css/application/base/notification-menu.css' => '8ae4a008',
'rsrc/css/application/base/phabricator-application-launch-view.css' => '8b7e271d',
'rsrc/css/application/base/standard-page-view.css' => '517cdfb1',
'rsrc/css/application/chatlog/chatlog.css' => '852140ff',
@@ -346,9 +346,10 @@
'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' => 'da12704d',
- 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '862ea0fe',
+ 'rsrc/js/application/aphlict/Aphlict.js' => '4a07e8e3',
+ 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'f51afce0',
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'a826c925',
+ 'rsrc/js/application/aphlict/behavior-aphlict-status.js' => '58f7803f',
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
'rsrc/js/application/conpherence/behavior-menu.js' => 'f0a41b9f',
@@ -490,7 +491,7 @@
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4',
'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca',
- 'rsrc/swf/aphlict.swf' => 'ef64606d',
+ 'rsrc/swf/aphlict.swf' => 'e5a24c72',
),
'symbols' =>
array(
@@ -539,10 +540,11 @@
'herald-rule-editor' => '6c9e6fb8',
'herald-test-css' => '778b008e',
'inline-comment-summary-css' => '8cfd34e8',
- 'javelin-aphlict' => 'da12704d',
+ 'javelin-aphlict' => '4a07e8e3',
'javelin-behavior' => '8a3ed18b',
- 'javelin-behavior-aphlict-dropdown' => '862ea0fe',
+ 'javelin-behavior-aphlict-dropdown' => 'f51afce0',
'javelin-behavior-aphlict-listen' => 'a826c925',
+ 'javelin-behavior-aphlict-status' => '58f7803f',
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
'javelin-behavior-aphront-crop' => 'fa0f4fc2',
'javelin-behavior-aphront-drag-and-drop-textarea' => '92eb531d',
@@ -725,7 +727,7 @@
'phabricator-nav-view-css' => '9283c2df',
'phabricator-notification' => '0c6946e7',
'phabricator-notification-css' => 'ef2c9b34',
- 'phabricator-notification-menu-css' => 'cbff1b94',
+ 'phabricator-notification-menu-css' => '8ae4a008',
'phabricator-object-selector-css' => '029a133d',
'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => '41ed7994',
@@ -1190,6 +1192,11 @@
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
+ '4a07e8e3' =>
+ array(
+ 0 => 'javelin-install',
+ 1 => 'javelin-util',
+ ),
'4d94d9c3' =>
array(
0 => 'javelin-behavior',
@@ -1235,6 +1242,13 @@
2 => 'javelin-vector',
3 => 'javelin-dom',
),
+ '58f7803f' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-aphlict',
+ 2 => 'phabricator-phtize',
+ 3 => 'javelin-dom',
+ ),
'59b251eb' =>
array(
0 => 'javelin-behavior',
@@ -1477,16 +1491,6 @@
3 => 'javelin-workflow',
4 => 'javelin-stratcom',
),
- '862ea0fe' =>
- array(
- 0 => 'javelin-behavior',
- 1 => 'javelin-request',
- 2 => 'javelin-stratcom',
- 3 => 'javelin-vector',
- 4 => 'javelin-dom',
- 5 => 'javelin-uri',
- 6 => 'javelin-behavior-device',
- ),
'880fa5ac' =>
array(
0 => 'javelin-behavior',
@@ -1921,11 +1925,6 @@
1 => 'javelin-util',
2 => 'javelin-stratcom',
),
- 'da12704d' =>
- array(
- 0 => 'javelin-install',
- 1 => 'javelin-util',
- ),
'dd7e8ef5' =>
array(
0 => 'javelin-behavior',
@@ -2038,6 +2037,16 @@
5 => 'phuix-action-view',
6 => 'javelin-workflow',
),
+ 'f51afce0' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-request',
+ 2 => 'javelin-stratcom',
+ 3 => 'javelin-vector',
+ 4 => 'javelin-dom',
+ 5 => 'javelin-uri',
+ 6 => 'javelin-behavior-device',
+ ),
'f588412e' =>
array(
0 => 'javelin-behavior',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1803,6 +1803,7 @@
'PhabricatorNotificationPanelController' => 'applications/notification/controller/PhabricatorNotificationPanelController.php',
'PhabricatorNotificationQuery' => 'applications/notification/PhabricatorNotificationQuery.php',
'PhabricatorNotificationStatusController' => 'applications/notification/controller/PhabricatorNotificationStatusController.php',
+ 'PhabricatorNotificationStatusView' => 'applications/notification/view/PhabricatorNotificationStatusView.php',
'PhabricatorNotificationTestController' => 'applications/notification/controller/PhabricatorNotificationTestController.php',
'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php',
'PhabricatorOAuthClientAuthorizationQuery' => 'applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php',
@@ -4631,6 +4632,7 @@
'PhabricatorNotificationPanelController' => 'PhabricatorNotificationController',
'PhabricatorNotificationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorNotificationStatusController' => 'PhabricatorNotificationController',
+ 'PhabricatorNotificationStatusView' => 'AphrontTagView',
'PhabricatorNotificationTestController' => 'PhabricatorNotificationController',
'PhabricatorOAuthClientAuthorization' =>
array(
diff --git a/src/applications/notification/controller/PhabricatorNotificationPanelController.php b/src/applications/notification/controller/PhabricatorNotificationPanelController.php
--- a/src/applications/notification/controller/PhabricatorNotificationPanelController.php
+++ b/src/applications/notification/controller/PhabricatorNotificationPanelController.php
@@ -25,16 +25,31 @@
pht('You have no notifications.'));
}
+ $notifications_link = phutil_tag(
+ 'a',
+ array(
+ 'href' => '/notification/',
+ ),
+ pht('Notifications'));
+
+ $connection_status = new PhabricatorNotificationStatusView();
+
+ $header = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'phabricator-notification-header',
+ ),
+ array(
+ $connection_status,
+ $notifications_link,
+ ));
+
$content = hsprintf(
- '<div class="phabricator-notification-header">%s %s</div>'.
'%s'.
- '<div class="phabricator-notification-view-all">%s</div>',
- phutil_tag(
- 'a',
- array(
- 'href' => '/notification/',
- ),
- pht('Notifications')),
+ '%s'.
+ '<div class="phabricator-notification-view-all">%s %s %s</div>',
+ $header,
+ $content,
javelin_tag(
'a',
array(
@@ -43,7 +58,7 @@
'class' => 'phabricator-notification-clear-all'
),
pht('Mark All Read')),
- $content,
+ " \xC2\xB7 ",
phutil_tag(
'a',
array(
diff --git a/src/applications/notification/view/PhabricatorNotificationStatusView.php b/src/applications/notification/view/PhabricatorNotificationStatusView.php
new file mode 100644
--- /dev/null
+++ b/src/applications/notification/view/PhabricatorNotificationStatusView.php
@@ -0,0 +1,34 @@
+<?php
+
+final class PhabricatorNotificationStatusView extends AphrontTagView {
+
+ protected function getTagAttributes() {
+ if (!$this->getID()) {
+ $this->setID(celerity_generate_unique_node_id());
+ }
+
+ Javelin::initBehavior(
+ 'aphlict-status',
+ array(
+ 'nodeID' => $this->getID(),
+ 'pht' => array(
+ 'setup' => pht('Setting Up Client'),
+ 'start' => pht('Starting Client'),
+ 'ready' => pht('Ready to Connect'),
+ 'connecting' => pht('Connecting...'),
+ 'connected' => pht('Connected'),
+ 'error' => pht('Connection Error'),
+ 'client' => pht('Connected Locally'),
+
+ 'error.flash.xdomain' => pht(
+ 'Unable to connect to Flash Policy Server. Check that the '.
+ 'notification server is running and port 843 is not firewalled.'),
+ ),
+ ));
+
+ return array(
+ 'class' => 'aphlict-connection-status',
+ );
+ }
+
+}
diff --git a/support/aphlict/client/src/Aphlict.as b/support/aphlict/client/src/Aphlict.as
--- a/support/aphlict/client/src/Aphlict.as
+++ b/support/aphlict/client/src/Aphlict.as
@@ -42,10 +42,6 @@
this.externalInvoke('log', message);
}
- final protected function setStatus(status:String):void {
- this.externalInvoke('status', {type: status});
- }
-
}
}
diff --git a/support/aphlict/client/src/AphlictClient.as b/support/aphlict/client/src/AphlictClient.as
--- a/support/aphlict/client/src/AphlictClient.as
+++ b/support/aphlict/client/src/AphlictClient.as
@@ -41,6 +41,7 @@
UncaughtErrorEvent.UNCAUGHT_ERROR,
this.uncaughtErrorHandler);
+ ExternalInterface.marshallExceptions = true;
ExternalInterface.addCallback('connect', this.externalConnect);
this.setStatus('ready');
@@ -150,6 +151,10 @@
this.externalInvoke('receive', msg);
}
+ public function setStatus(status:String, code:String = null):void {
+ this.externalInvoke('status', {type: status, code: code});
+ }
+
}
}
diff --git a/support/aphlict/client/src/AphlictMaster.as b/support/aphlict/client/src/AphlictMaster.as
--- a/support/aphlict/client/src/AphlictMaster.as
+++ b/support/aphlict/client/src/AphlictMaster.as
@@ -48,6 +48,9 @@
private var socket:Socket;
private var readBuffer:ByteArray;
+ private var status:String;
+ private var statusCode:String;
+
public function AphlictMaster(server:String, port:Number) {
super();
@@ -75,6 +78,8 @@
if (!this.clients[client]) {
this.log('Registering client: ' + client);
this.clients[client] = new Date().getTime();
+
+ this.send.send(client, 'setStatus', this.status, this.statusCode);
}
}
@@ -106,6 +111,8 @@
}
private function connectToServer():void {
+ this.setStatusOnClients('connecting');
+
var socket:Socket = new Socket();
socket.addEventListener(Event.CONNECT, didConnectSocket);
@@ -124,7 +131,7 @@
}
private function didConnectSocket(event:Event):void {
- this.externalInvoke('connected');
+ this.setStatusOnClients('connected');
// Send subscriptions
var phids = new Array();
@@ -146,7 +153,15 @@
}
private function didSecurityErrorSocket(event:SecurityErrorEvent):void {
- this.externalInvoke('error', event.text);
+ var text = event.text;
+
+ // This is really gross but there doesn't seem to be anything else
+ // on the object which gives us an error code.
+ if (text.match(/^Error #2048/)) {
+ this.setStatusOnClients('error', 'error.flash.xdomain');
+ }
+
+ this.error(text);
}
public function subscribe(client:String, phids:Array):void {
@@ -280,6 +295,18 @@
}
}
+ private function setStatusOnClients(
+ status:String,
+ code:String = null):void {
+
+ this.status = status;
+ this.statusCode = code;
+
+ for (var client:String in this.clients) {
+ this.send.send(client, 'setStatus', status, code);
+ }
+ }
+
}
}
diff --git a/webroot/rsrc/css/application/base/notification-menu.css b/webroot/rsrc/css/application/base/notification-menu.css
--- a/webroot/rsrc/css/application/base/notification-menu.css
+++ b/webroot/rsrc/css/application/base/notification-menu.css
@@ -97,3 +97,17 @@
padding: 8px;
font-size: 12px;
}
+
+.phabricator-notification-menu .aphlict-connection-status {
+ float: right;
+ font-weight: normal;
+ color: {$lightgreytext};
+}
+
+.aphlict-connection-status .aphlict-connection-status-connected {
+ color: {$green};
+}
+
+.aphlict-connection-status .aphlict-connection-status-error {
+ color: {$red};
+}
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
@@ -28,7 +28,7 @@
construct: function(id, server, port, subscriptions) {
if (__DEV__) {
if (JX.Aphlict._instance) {
- JX.$E('Aphlict object is a singleton!');
+ JX.$E('Aphlict object is a singleton.');
}
}
@@ -36,17 +36,24 @@
this._server = server;
this._port = port;
this._subscriptions = subscriptions;
+ this._setStatus('setup');
JX.Aphlict._instance = this;
},
+ events: ['didChangeStatus'],
+
members: {
_id: null,
_server: null,
_port: null,
_subscriptions: null,
+ _status: null,
+ _statusCode: null,
start: function(node, uri) {
+ this._setStatus('start');
+
// NOTE: This is grotesque, but seems to work everywhere.
node.innerHTML =
'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000">' +
@@ -72,6 +79,20 @@
this._server,
this._port,
this._subscriptions);
+ },
+
+ getStatus: function() {
+ return this._status;
+ },
+
+ getStatusCode: function() {
+ return this._statusCode;
+ },
+
+ _setStatus: function(status, code) {
+ this._status = status;
+ this._statusCode = code || null;
+ this.invoke('didChangeStatus');
}
},
@@ -98,6 +119,7 @@
}
if (type == 'status') {
+ client._setStatus(message.type, message.code);
switch (message.type) {
case 'ready':
client._didStartFlash();
diff --git a/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js b/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js
--- a/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js
+++ b/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js
@@ -73,6 +73,12 @@
return;
}
+ if (!e.getNode('notification')) {
+ // User clicked somewhere in the dead area of the menu, like the header
+ // or footer.
+ return;
+ }
+
// If the user clicked a notification (but missed a link) and it has a
// primary URI, go there.
var href = e.getNodeData('notification').href;
diff --git a/webroot/rsrc/js/application/aphlict/behavior-aphlict-status.js b/webroot/rsrc/js/application/aphlict/behavior-aphlict-status.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/aphlict/behavior-aphlict-status.js
@@ -0,0 +1,47 @@
+/**
+ * @provides javelin-behavior-aphlict-status
+ * @requires javelin-behavior
+ * javelin-aphlict
+ * phabricator-phtize
+ * javelin-dom
+ * @javelin
+ */
+
+JX.behavior('aphlict-status', function(config) {
+ var pht = JX.phtize(config.pht);
+
+ function update() {
+ var client = JX.Aphlict.getInstance();
+ if (!client) {
+ return;
+ }
+
+ var node;
+ try {
+ node = JX.$(config.nodeID);
+ } catch (ignored) {
+ return;
+ }
+
+ var tip = null;
+ var status = client.getStatus();
+
+ if (status == 'error') {
+ tip = pht(client.getStatusCode());
+ }
+
+ var status_node = JX.$N(
+ 'span',
+ {
+ className: 'aphlict-connection-status-' + status,
+ sigil: tip ? 'has-tooltip' : null,
+ meta: tip ? {tip: tip, align: 'S', size: 300} : {}
+ },
+ pht(status));
+
+ JX.DOM.setContent(node, status_node);
+ }
+
+ JX.Aphlict.listen('didChangeStatus', update);
+ update();
+});
diff --git a/webroot/rsrc/swf/aphlict.swf b/webroot/rsrc/swf/aphlict.swf
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 19, 11:28 PM (5 d, 11 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7226604
Default Alt Text
D9700.id23293.diff (16 KB)
Attached To
Mode
D9700: Show Aphlict connection status in notification menu
Attached
Detach File
Event Timeline
Log In to Comment