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' => '63e782fb', - 'core.pkg.js' => '44aac665', + 'core.pkg.js' => '3a917cb1', 'darkconsole.pkg.js' => '8ab24e01', 'differential.pkg.css' => '8af45893', 'differential.pkg.js' => 'dad3622f', @@ -200,6 +200,7 @@ 'rsrc/externals/javelin/lib/Router.js' => '29274e2b', 'rsrc/externals/javelin/lib/URI.js' => '6eff08aa', 'rsrc/externals/javelin/lib/Vector.js' => 'cc1bd0b0', + 'rsrc/externals/javelin/lib/Websocket.js' => '466df727', 'rsrc/externals/javelin/lib/Workflow.js' => 'd149e002', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b', @@ -341,7 +342,7 @@ 'rsrc/image/texture/table_header_hover.png' => '038ec3b9', 'rsrc/image/texture/table_header_tall.png' => 'd56b434f', 'rsrc/js/application/aphlict/Aphlict.js' => '4a07e8e3', - 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'f6bc26f0', + 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '57e1587c', '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', @@ -536,7 +537,7 @@ 'inline-comment-summary-css' => '8cfd34e8', 'javelin-aphlict' => '4a07e8e3', 'javelin-behavior' => '61cbc29a', - 'javelin-behavior-aphlict-dropdown' => 'f6bc26f0', + 'javelin-behavior-aphlict-dropdown' => '57e1587c', 'javelin-behavior-aphlict-listen' => 'a826c925', 'javelin-behavior-aphlict-status' => '58f7803f', 'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884', @@ -685,6 +686,7 @@ 'javelin-view-interpreter' => '0c33c1a0', 'javelin-view-renderer' => '6c2b09a2', 'javelin-view-visitor' => 'efe49472', + 'javelin-websocket' => '466df727', 'javelin-workflow' => 'd149e002', 'lightbox-attachment-css' => '7acac05d', 'maniphest-batch-editor' => '8f380ebc', @@ -1075,6 +1077,9 @@ 'javelin-behavior', 'javelin-dom', ), + '466df727' => array( + 'javelin-install', + ), '469c0d9e' => array( 'javelin-behavior', 'javelin-dom', @@ -1150,6 +1155,17 @@ 'javelin-vector', 'javelin-dom', ), + '57e1587c' => array( + 'javelin-behavior', + 'javelin-request', + 'javelin-stratcom', + 'javelin-vector', + 'javelin-dom', + 'javelin-uri', + 'javelin-behavior-device', + 'javelin-websocket', + 'phabricator-title', + ), '58f7803f' => array( 'javelin-behavior', 'javelin-aphlict', @@ -1885,16 +1901,6 @@ 'javelin-util', 'javelin-reactor', ), - 'f6bc26f0' => array( - 'javelin-behavior', - 'javelin-request', - 'javelin-stratcom', - 'javelin-vector', - 'javelin-dom', - 'javelin-uri', - 'javelin-behavior-device', - 'phabricator-title', - ), 'f7379f45' => array( 'javelin-behavior', 'javelin-dom', diff --git a/webroot/rsrc/externals/javelin/lib/Websocket.js b/webroot/rsrc/externals/javelin/lib/Websocket.js new file mode 100644 --- /dev/null +++ b/webroot/rsrc/externals/javelin/lib/Websocket.js @@ -0,0 +1,102 @@ +/** + * @requires javelin-install + * @provides javelin-websocket + * @javelin + */ + +JX.install('WebSocket', { + construct: function(uri) { + this.setURI(uri); + }, + + properties: { + URI: null, + openHandler: null, + messageHandler: null, + closeHandler: null + }, + + members: { + _socket: null, + _isOpen: false, + _isReconnect: false, + _shouldClose: false, + _delay: 2000, + + isAvailable: function() { + return !!window.WebSocket; + }, + + open: function() { + if (!this.isAvailable()) { + return; + } + + this._init(); + }, + + send: function(message) { + if (this._isOpen) { + this._socket.send(message); + } + }, + + close: function() { + if (!$this._isOpen) { + return; + } + this._shouldClose = true; + this._socket.close(); + }, + + _init: function() { + this._shouldClose = false; + + this._socket = new WebSocket(this.getURI()); + this._socket.onopen = JX.bind(this, this._onopen); + this._socket.onmessage = JX.bind(this, this._onmessage); + this._socket.onclose = JX.bind(this, this._onclose); + }, + + _onopen: function(e) { + this._isOpen = true; + this._delay = 1000; + + var handler = this.getOpenHandler(); + if (handler) { + handler(); + } + }, + + _onmessage: function(e) { + var data = e.data; + + var handler = this.getMessageHandler(); + if (handler) { + handler(data); + } + }, + + _onclose: function(e) { + this._isOpen = false; + + var done = false; + + var handler = this.getCloseHandler(); + if (handler) { + done = handler(); + } + + if (!done && !this._shouldClose) { + setTimeout(JX.bind(this, this._reconnect), this._delay); + } + }, + + _reconnect: function() { + this._delay = this._delay * 2; + this._isReconnect = true; + this._init(); + } + + } +}); 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 @@ -7,6 +7,7 @@ * javelin-dom * javelin-uri * javelin-behavior-device + * javelin-websocket * phabricator-title */ @@ -14,6 +15,29 @@ // Track the current globally visible menu. statics.visible = statics.visible || null; + if (!statics.socket) { + statics.socket = new JX.WebSocket( + 'ws://local.phacility.com:9000/', + 'chat'); + + statics.socket.setOpenHandler(function() { + JX.log('connected'); + }); + + statics.socket.setMessageHandler(function(m) { + JX.log('>>> websocket >>> ' + m); + }); + + statics.socket.setCloseHandler(function() { + JX.log('bye'); + }); + + statics.socket.open(); + + window.xsock = statics.socket; + } + + var dropdown = JX.$(config.dropdownID); var bubble = JX.$(config.bubbleID); var icon = JX.DOM.scry(bubble, 'span', 'menu-icon')[0]; @@ -166,4 +190,5 @@ dirty = true; refresh(); }); + });