From dd91732df338258a165c412c4b4f77c9afb9b159 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 23 Jun 2014 15:19:34 -0700 Subject: [PATCH] Make JX.Aphlict a real singleton with a more sensible initialization order Summary: Ref T5373. The control flow between `aphlict-listener` and `JX.Aphlict` is pretty weird right now, where the listener (which is the highest-level component) has intimate knowledge of how to put the SWF on the page. Instead: - Make `JX.Aphlict` a real singleton. - Instantiate it sooner. - Have it handle the flash setup handshake. Test Plan: Loaded page in debug mode, saw normal flow take place. Reviewers: joshuaspence Reviewed By: joshuaspence Subscribers: epriestley Maniphest Tasks: T5373 Differential Revision: https://secure.phabricator.com/D9699 --- resources/celerity/map.php | 61 ++++++------- support/aphlict/client/src/Aphlict.as | 4 + support/aphlict/client/src/AphlictClient.as | 9 +- .../rsrc/js/application/aphlict/Aphlict.js | 80 +++++++++++++----- .../aphlict/behavior-aphlict-listen.js | 35 +++----- webroot/rsrc/swf/aphlict.swf | Bin 6258 -> 6268 bytes 6 files changed, 105 insertions(+), 84 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 784054df15..92f84c54ee 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => '22e4fc33', - 'core.pkg.js' => '941224f2', + 'core.pkg.js' => 'f5ba2408', 'darkconsole.pkg.js' => 'df001cab', 'differential.pkg.css' => '4a93db37', 'differential.pkg.js' => 'd1443567', @@ -346,9 +346,9 @@ return array( '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' => '08be8878', + 'rsrc/js/application/aphlict/Aphlict.js' => 'da12704d', 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '862ea0fe', - 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'bdb2032d', + 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'a826c925', '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 +490,7 @@ return array( 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', - 'rsrc/swf/aphlict.swf' => '14d5aa2e', + 'rsrc/swf/aphlict.swf' => 'ef64606d', ), 'symbols' => array( @@ -539,10 +539,10 @@ return array( 'herald-rule-editor' => '6c9e6fb8', 'herald-test-css' => '778b008e', 'inline-comment-summary-css' => '8cfd34e8', - 'javelin-aphlict' => '08be8878', + 'javelin-aphlict' => 'da12704d', 'javelin-behavior' => '8a3ed18b', 'javelin-behavior-aphlict-dropdown' => '862ea0fe', - 'javelin-behavior-aphlict-listen' => 'bdb2032d', + 'javelin-behavior-aphlict-listen' => 'a826c925', 'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884', 'javelin-behavior-aphront-crop' => 'fa0f4fc2', 'javelin-behavior-aphront-drag-and-drop-textarea' => '92eb531d', @@ -878,11 +878,6 @@ return array( 3 => 'javelin-vector', 4 => 'javelin-stratcom', ), - '08be8878' => - array( - 0 => 'javelin-install', - 1 => 'javelin-util', - ), '08e56a4e' => array( 0 => 'javelin-install', @@ -1279,6 +1274,13 @@ return array( 1 => 'javelin-stratcom', 2 => 'javelin-dom', ), + '62e18640' => + array( + 0 => 'javelin-install', + 1 => 'javelin-util', + 2 => 'javelin-dom', + 3 => 'javelin-typeahead-normalizer', + ), '6453c869' => array( 0 => 'javelin-install', @@ -1357,13 +1359,6 @@ return array( 0 => 'javelin-behavior', 1 => 'javelin-dom', ), - '62e18640' => - array( - 0 => 'javelin-install', - 1 => 'javelin-util', - 2 => 'javelin-dom', - 3 => 'javelin-typeahead-normalizer', - ), '76b9fc3e' => array( 0 => 'javelin-behavior', @@ -1642,6 +1637,19 @@ return array( 1 => 'javelin-stratcom', 2 => 'javelin-dom', ), + 'a826c925' => + array( + 0 => 'javelin-behavior', + 1 => 'javelin-aphlict', + 2 => 'javelin-stratcom', + 3 => 'javelin-request', + 4 => 'javelin-uri', + 5 => 'javelin-dom', + 6 => 'javelin-json', + 7 => 'javelin-router', + 8 => 'javelin-util', + 9 => 'phabricator-notification', + ), 'a82a7769' => array( 0 => 'javelin-behavior', @@ -1794,18 +1802,6 @@ return array( 2 => 'javelin-util', 3 => 'javelin-request', ), - 'bdb2032d' => - array( - 0 => 'javelin-behavior', - 1 => 'javelin-aphlict', - 2 => 'javelin-stratcom', - 3 => 'javelin-request', - 4 => 'javelin-uri', - 5 => 'javelin-dom', - 6 => 'javelin-json', - 7 => 'javelin-router', - 8 => 'phabricator-notification', - ), 'bdb3e4d0' => array( 0 => 'javelin-behavior', @@ -1925,6 +1921,11 @@ return array( 1 => 'javelin-util', 2 => 'javelin-stratcom', ), + 'da12704d' => + array( + 0 => 'javelin-install', + 1 => 'javelin-util', + ), 'dd7e8ef5' => array( 0 => 'javelin-behavior', diff --git a/support/aphlict/client/src/Aphlict.as b/support/aphlict/client/src/Aphlict.as index 55c48aab13..872129b94f 100644 --- a/support/aphlict/client/src/Aphlict.as +++ b/support/aphlict/client/src/Aphlict.as @@ -42,6 +42,10 @@ package { 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 index dfbb390231..181a31f623 100644 --- a/support/aphlict/client/src/AphlictClient.as +++ b/support/aphlict/client/src/AphlictClient.as @@ -42,11 +42,8 @@ package { this.uncaughtErrorHandler); ExternalInterface.addCallback('connect', this.externalConnect); - ExternalInterface.call( - 'JX.Stratcom.invoke', - 'aphlict-component-ready', - null, - {}); + + this.setStatus('ready'); } private function uncaughtErrorHandler(event:UncaughtErrorEvent):void { @@ -58,8 +55,6 @@ package { port:Number, subscriptions:Array):void { - this.externalInvoke('connect'); - this.remoteServer = server; this.remotePort = port; this.subscriptions = subscriptions; diff --git a/webroot/rsrc/js/application/aphlict/Aphlict.js b/webroot/rsrc/js/application/aphlict/Aphlict.js index 22f4e14ade..9e11bf640c 100644 --- a/webroot/rsrc/js/application/aphlict/Aphlict.js +++ b/webroot/rsrc/js/application/aphlict/Aphlict.js @@ -25,51 +25,87 @@ */ JX.install('Aphlict', { - construct : function(id, server, port, subscriptions) { + construct: function(id, server, port, subscriptions) { if (__DEV__) { if (JX.Aphlict._instance) { - JX.$E('Aphlict object is sort of a singleton..!'); + JX.$E('Aphlict object is a singleton!'); } } - JX.Aphlict._instance = this; - + this._id = id; this._server = server; this._port = port; this._subscriptions = subscriptions; - // Flash puts its "objects" into global scope in an inconsistent way, - // because it was written in like 1816 when globals were awesome and IE4 - // didn't support other scopes since global scope is the best anyway. - var container = document[id] || window[id]; - - this._flashContainer = container; + JX.Aphlict._instance = this; }, - members : { - _server : null, - _port : null, - _subscriptions : null, - start : function() { + members: { + _id: null, + _server: null, + _port: null, + _subscriptions: null, + + start: function(node, uri) { + // NOTE: This is grotesque, but seems to work everywhere. + node.innerHTML = + '' + + '' + + '' + + '' + + '' + + '' + + ''; + }, + + _didStartFlash: function() { + var id = this._id; + + // Flash puts its "objects" into global scope in an inconsistent way, + // because it was written in like 1816 when globals were awesome and IE4 + // didn't support other scopes since global scope is the best anyway. + var container = document[id] || window[id]; + + this._flashContainer = container; this._flashContainer.connect( this._server, this._port, this._subscriptions); } + }, - properties : { - handler : null + properties: { + handler: null }, - statics : { - _instance : null, - didReceiveEvent : function(type, message) { - if (!JX.Aphlict._instance) { + statics: { + _instance: null, + + getInstance: function() { + var self = JX.Aphlict; + if (!self._instance) { + return null; + } + return self._instance; + }, + + didReceiveEvent: function(type, message) { + var client = JX.Aphlict.getInstance(); + if (!client) { return; } - var handler = JX.Aphlict._instance.getHandler(); + if (type == 'status') { + switch (message.type) { + case 'ready': + client._didStartFlash(); + break; + } + } + + var handler = client.getHandler(); if (handler) { handler(type, message); } diff --git a/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js b/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js index 04cd66d378..d34b90a95f 100644 --- a/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js +++ b/webroot/rsrc/js/application/aphlict/behavior-aphlict-listen.js @@ -16,18 +16,6 @@ JX.behavior('aphlict-listen', function(config) { var showing_reload = false; - function onready() { - var client = new JX.Aphlict( - config.id, - config.server, - config.port, - config.subscriptions); - - client - .setHandler(onaphlictmessage) - .start(); - } - JX.Stratcom.listen('aphlict-receive-message', null, function(e) { var message = e.getData(); @@ -61,6 +49,8 @@ JX.behavior('aphlict-listen', function(config) { default: case 'error': + case 'log': + case 'status': if (config.debug) { var details = message ? JX.JSON.stringify(message) : ''; JX.log('(Aphlict) [' + type + '] ' + details); @@ -98,19 +88,14 @@ JX.behavior('aphlict-listen', function(config) { } } + var client = new JX.Aphlict( + config.id, + config.server, + config.port, + config.subscriptions); - // Wait for the element to load, and don't do anything if it never loads. - // If we just go crazy and start making calls to it before it loads, its - // interfaces won't be registered yet. - JX.Stratcom.listen('aphlict-component-ready', null, onready); + client + .setHandler(onaphlictmessage) + .start(JX.$(config.containerID), config.swfURI); - // Add Flash object to page - JX.$(config.containerID).innerHTML = - '' + - '' + - '' + - '' + - '' + - ''; //Evan sanctioned }); diff --git a/webroot/rsrc/swf/aphlict.swf b/webroot/rsrc/swf/aphlict.swf index b314f019e0c1f5df39e1dc3676118ac0adcf41ca..a6ea7083217f6226e2a0b6fff5797a8dc2da8df2 100644 GIT binary patch literal 6268 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