Page MenuHomePhabricator

D12029.id28953.diff
No OneTemporary

D12029.id28953.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -351,10 +351,11 @@
'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',
- 'rsrc/js/application/conpherence/behavior-durable-column.js' => 'e4affa94',
- 'rsrc/js/application/conpherence/behavior-menu.js' => '869e3445',
- 'rsrc/js/application/conpherence/behavior-pontificate.js' => '86df5915',
- 'rsrc/js/application/conpherence/behavior-widget-pane.js' => '40b1ff90',
+ 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => 'b4de855a',
+ 'rsrc/js/application/conpherence/behavior-durable-column.js' => '76179b8c',
+ 'rsrc/js/application/conpherence/behavior-menu.js' => '8e0bd999',
+ 'rsrc/js/application/conpherence/behavior-pontificate.js' => '072db76a',
+ 'rsrc/js/application/conpherence/behavior-widget-pane.js' => '2c1cd7f5',
'rsrc/js/application/countdown/timer.js' => 'e4cc26b3',
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e',
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '82439934',
@@ -516,6 +517,7 @@
'conpherence-menu-css' => 'c6ac5299',
'conpherence-message-pane-css' => '5930260a',
'conpherence-notification-css' => '04a6e10a',
+ 'conpherence-thread-manager' => 'b4de855a',
'conpherence-update-css' => '1099a660',
'conpherence-widget-pane-css' => '3d575438',
'differential-changeset-view-css' => '6a8b172a',
@@ -555,9 +557,9 @@
'javelin-behavior-boards-dropdown' => '0ec56e1d',
'javelin-behavior-choose-control' => '6153c708',
'javelin-behavior-config-reorder-fields' => '14a827de',
- 'javelin-behavior-conpherence-menu' => '869e3445',
- 'javelin-behavior-conpherence-pontificate' => '86df5915',
- 'javelin-behavior-conpherence-widget-pane' => '40b1ff90',
+ 'javelin-behavior-conpherence-menu' => '8e0bd999',
+ 'javelin-behavior-conpherence-pontificate' => '072db76a',
+ 'javelin-behavior-conpherence-widget-pane' => '2c1cd7f5',
'javelin-behavior-countdown-timer' => 'e4cc26b3',
'javelin-behavior-dark-console' => '08883e8b',
'javelin-behavior-dashboard-async-panel' => '469c0d9e',
@@ -582,7 +584,7 @@
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
'javelin-behavior-diffusion-pull-lastmodified' => '2b228192',
'javelin-behavior-doorkeeper-tag' => 'e5822781',
- 'javelin-behavior-durable-column' => 'e4affa94',
+ 'javelin-behavior-durable-column' => '76179b8c',
'javelin-behavior-error-log' => '6882e80a',
'javelin-behavior-fancy-datepicker' => 'c51ae228',
'javelin-behavior-global-drag-and-drop' => '07f199d8',
@@ -850,6 +852,14 @@
'javelin-stratcom',
'javelin-workflow',
),
+ '072db76a' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-workflow',
+ 'javelin-stratcom',
+ 'conpherence-thread-manager',
+ ),
'07f199d8' => array(
'javelin-behavior',
'javelin-dom',
@@ -1004,6 +1014,19 @@
'javelin-stratcom',
'javelin-dom',
),
+ '2c1cd7f5' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-stratcom',
+ 'javelin-workflow',
+ 'javelin-util',
+ 'phabricator-notification',
+ 'javelin-behavior-device',
+ 'phuix-dropdown-menu',
+ 'phuix-action-list-view',
+ 'phuix-action-view',
+ 'conpherence-thread-manager',
+ ),
'2c426492' => array(
'javelin-behavior',
'javelin-dom',
@@ -1059,18 +1082,6 @@
'javelin-dom',
'javelin-reactor-dom',
),
- '40b1ff90' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-stratcom',
- 'javelin-workflow',
- 'javelin-util',
- 'phabricator-notification',
- 'javelin-behavior-device',
- 'phuix-dropdown-menu',
- 'phuix-action-list-view',
- 'phuix-action-view',
- ),
42126667 => array(
'javelin-behavior',
'javelin-dom',
@@ -1329,6 +1340,15 @@
'javelin-vector',
'javelin-dom',
),
+ '76179b8c' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-stratcom',
+ 'javelin-scrollbar',
+ 'javelin-quicksand',
+ 'phabricator-keyboard-shortcut',
+ 'conpherence-thread-manager',
+ ),
'7644823e' => array(
'javelin-dom',
'javelin-util',
@@ -1455,24 +1475,6 @@
'phabricator-tooltip',
'changeset-view-manager',
),
- '869e3445' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-util',
- 'javelin-stratcom',
- 'javelin-workflow',
- 'javelin-behavior-device',
- 'javelin-history',
- 'javelin-vector',
- 'phabricator-shaped-request',
- ),
- '86df5915' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-util',
- 'javelin-workflow',
- 'javelin-stratcom',
- ),
'87cb6b51' => array(
'javelin-behavior',
'javelin-dom',
@@ -1528,6 +1530,18 @@
'javelin-stratcom',
'javelin-behavior',
),
+ '8e0bd999' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-stratcom',
+ 'javelin-workflow',
+ 'javelin-behavior-device',
+ 'javelin-history',
+ 'javelin-vector',
+ 'phabricator-shaped-request',
+ 'conpherence-thread-manager',
+ ),
'8ef9ab58' => array(
'javelin-behavior',
'javelin-dom',
@@ -1684,6 +1698,16 @@
'javelin-typeahead-preloaded-source',
'javelin-util',
),
+ 'b4de855a' => array(
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-stratcom',
+ 'javelin-install',
+ 'javelin-workflow',
+ 'javelin-router',
+ 'javelin-behavior-device',
+ 'javelin-vector',
+ ),
'b5c256b8' => array(
'javelin-install',
'javelin-dom',
@@ -1836,14 +1860,6 @@
'javelin-dom',
'javelin-uri',
),
- 'e4affa94' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-stratcom',
- 'javelin-scrollbar',
- 'javelin-quicksand',
- 'phabricator-keyboard-shortcut',
- ),
'e4cc26b3' => array(
'javelin-behavior',
'javelin-dom',
diff --git a/src/applications/conpherence/controller/ConpherenceViewController.php b/src/applications/conpherence/controller/ConpherenceViewController.php
--- a/src/applications/conpherence/controller/ConpherenceViewController.php
+++ b/src/applications/conpherence/controller/ConpherenceViewController.php
@@ -46,7 +46,7 @@
$content = array('messages' => $messages);
} else {
$header = $this->buildHeaderPaneContent($conpherence);
- $form = $this->renderFormContent($data['latest_transaction_id']);
+ $form = $this->renderFormContent();
$content = array(
'header' => $header,
'messages' => $messages,
@@ -77,7 +77,7 @@
));
}
- private function renderFormContent($latest_transaction_id) {
+ private function renderFormContent() {
$conpherence = $this->getConpherence();
$user = $this->getRequest()->getUser();
@@ -103,20 +103,6 @@
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Send')))
- ->appendChild(
- javelin_tag(
- 'input',
- array(
- 'type' => 'hidden',
- 'name' => 'latest_transaction_id',
- 'value' => $latest_transaction_id,
- 'sigil' => 'latest-transaction-id',
- 'meta' => array(
- 'threadPHID' => $conpherence->getPHID(),
- 'threadID' => $conpherence->getID(),
- ),
- ),
- ''))
->render();
return $form;
diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php
--- a/src/view/page/PhabricatorStandardPageView.php
+++ b/src/view/page/PhabricatorStandardPageView.php
@@ -82,10 +82,18 @@
public function getShowDurableColumn() {
$request = $this->getRequest();
if ($request) {
+ if (strncmp(
+ $request->getRequestURI()->getPath(),
+ '/conpherence',
+ strlen('/conpherence')) === 0) {
+ return false;
+ }
$viewer = $request->getUser();
- return PhabricatorApplication::isClassInstalledForViewer(
- 'PhabricatorConpherenceApplication',
+ if ($viewer->isLoggedIn()) {
+ return PhabricatorApplication::isClassInstalledForViewer(
+ 'PhabricatorConpherenceApplication',
$viewer);
+ }
}
return false;
}
diff --git a/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js b/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js
@@ -0,0 +1,271 @@
+/**
+ * @provides conpherence-thread-manager
+ * @requires javelin-dom
+ * javelin-util
+ * javelin-stratcom
+ * javelin-install
+ * javelin-workflow
+ * javelin-router
+ * javelin-behavior-device
+ * javelin-vector
+ */
+JX.install('ConpherenceThreadManager', {
+
+ construct : function() {
+ if (__DEV__) {
+ if (JX.ConpherenceThreadManager._instance) {
+ JX.$E('ConpherenceThreadManager object is a singleton.');
+ }
+ }
+ JX.ConpherenceThreadManager._instance = this;
+ return this;
+ },
+
+ members: {
+ _loadThreadURI: null,
+ _loadedThreadID: null,
+ _loadedThreadPHID: null,
+ _latestTransactionID: null,
+ _updating: null,
+ _minimalDisplay: false,
+ _getMessagesNodeFunction: JX.bag,
+ _getTitleNodeFunction: JX.bag,
+ _willLoadThreadCallback: JX.bag,
+ _didLoadThreadCallback: JX.bag,
+ _willSendMessageCallback: JX.bag,
+ _didSendMessageCallback: JX.bag,
+
+ setLoadThreadURI: function(uri) {
+ this._loadThreadURI = uri;
+ return this;
+ },
+
+ getLoadThreadURI: function() {
+ return this._loadThreadURI;
+ },
+
+ isThreadLoaded: function() {
+ return Boolean(this._loadedThreadID);
+ },
+
+ isThreadIDLoaded: function(thread_id) {
+ return this._loadedThreadID == thread_id;
+ },
+
+ getLoadedThreadID: function() {
+ return this._loadedThreadID;
+ },
+
+ getLoadedThreadPHID: function() {
+ return this._loadedThreadPHID;
+ },
+
+ getLatestTransactionID: function() {
+ return this._latestTransactionID;
+ },
+
+ setLatestTransactionID: function(id) {
+ this._latestTransactionID = id;
+ return this;
+ },
+
+ setMessagesNodeFunction: function(callback) {
+ this._getMessagesNodeFunction = callback;
+ return this;
+ },
+
+ _getMessagesNode: function() {
+ return this._getMessagesNodeFunction();
+ },
+
+ setTitleNodeFunction: function(callback) {
+ this._getTitleNodeFunction = callback;
+ return this;
+ },
+
+ _getTitleNode: function() {
+ return this._getTitleNodeFunction();
+ },
+
+ setMinimalDisplay: function(bool) {
+ this._minimalDisplay = bool;
+ return this;
+ },
+
+ setWillLoadThreadCallback: function(callback) {
+ this._willLoadThreadCallback = callback;
+ return this;
+ },
+
+ setDidLoadThreadCallback: function(callback) {
+ this._didLoadThreadCallback = callback;
+ return this;
+ },
+
+ setWillSendMessageCallback: function(callback) {
+ this._willSendMessageCallback = callback;
+ return this;
+ },
+
+ setDidSendMessageCallback: function(callback) {
+ this._didSendMessageCallback = callback;
+ return this;
+ },
+
+ _getParams: function(base_params) {
+ if (this._minimalDisplay) {
+ base_params.minimal_display = true;
+ }
+ if (this._latestTransactionID) {
+ base_params.latest_transaction_id = this._latestTransactionID;
+ }
+ return base_params;
+ },
+ start: function() {
+ JX.Stratcom.listen(
+ 'aphlict-server-message',
+ null,
+ JX.bind(this, function(e) {
+ var message = e.getData();
+
+ if (message.type != 'message') {
+ // Not a message event.
+ return;
+ }
+
+ if (message.threadPHID != this._loadedThreadPHID) {
+ // Message event for some thread other than the visible one.
+ return;
+ }
+
+ if (message.messageID <= this._latestTransactionID) {
+ // Message event for something we already know about.
+ return;
+ }
+
+ // If we're currently updating, wait for the update to complete.
+ // If this notification tells us about a message which is newer than
+ // the newest one we know to exist, keep track of it so we can
+ // update once the in-flight update finishes.
+ if (this._updating &&
+ this._updating.threadPHID == this._loadedThreadPHID) {
+ if (message.messageID > this._updating.knownID) {
+ this._updating.knownID = message.messageID;
+ return;
+ }
+ }
+
+ this._updateThread();
+ }));
+ },
+
+ _updateThread: function() {
+ var params = this._getParams({
+ action: 'load',
+ });
+
+ var uri = '/conpherence/update/' + this._loadedThreadID + '/';
+
+ var workflow = new JX.Workflow(uri)
+ .setData(params)
+ .setHandler(JX.bind(this, function(r) {
+ this._latestTransactionID = r.latest_transaction_id;
+
+ var messages = this._getMessagesNode();
+ JX.DOM.appendContent(messages, JX.$H(r.transactions));
+ messages.scrollTop = messages.scrollHeight;
+ }));
+
+ this.syncWorkflow(workflow, 'finally');
+ },
+
+ syncWorkflow: function(workflow, stage) {
+ this._updating = {
+ threadPHID: this._loadedThreadPHID,
+ knownID: this._latestTransactionID
+ };
+ workflow.listen(stage, JX.bind(this, function() {
+ // TODO - do we need to handle if we switch threads somehow?
+ var need_sync = (this._updating.knownID > this._latestTransactionID);
+ this._updating = null;
+ if (need_sync) {
+ this._updateThread();
+ }
+ }));
+ workflow.start();
+ },
+
+ runUpdateWorkflowFromLink: function(link, params) {
+ params = this._getParams(params);
+
+ var workflow = new JX.Workflow.newFromLink(link)
+ .setData(params)
+ .setHandler(JX.bind(this, function(r) {
+ this._latestTransactionID = r.latest_transaction_id;
+
+ var messages = this._getMessagesNode();
+ JX.DOM.appendContent(messages, JX.$H(r.transactions));
+ messages.scrollTop = messages.scrollHeight;
+
+ JX.DOM.setContent(this._getTitleNode(), r.conpherence_title);
+ }));
+ this.syncWorkflow(workflow, params.stage);
+ },
+
+ loadThreadByID: function(thread_id) {
+ if (this.isThreadLoaded() &&
+ this.isThreadIDLoaded(thread_id)) {
+ return;
+ }
+
+ this._willLoadThreadCallback();
+
+ var params = {};
+ // We pick a thread from the server if not specified
+ if (thread_id) {
+ params.id = thread_id;
+ }
+ params = this._getParams(params);
+
+ var handler = JX.bind(this, function(r) {
+ this._loadedThreadID = r.threadID;
+ this._loadedThreadPHID = r.threadPHID;
+ this._loadThreadID = r.threadID;
+ this._latestTransactionID = r.latestTransactionID;
+
+ this._didLoadThreadCallback(r);
+ });
+
+ // should this be sync'd too?
+ new JX.Workflow(this.getLoadThreadURI())
+ .setData(params)
+ .setHandler(handler)
+ .start();
+ },
+
+ sendMessage: function(form, params) {
+ params = this._getParams(params);
+
+ this._willSendMessageCallback();
+ var workflow = JX.Workflow.newFromForm(form, params)
+ .setHandler(JX.bind(this, function(r) {
+ this._latestTransactionID = r.latest_transaction_id;
+ this._didSendMessageCallback(r);
+ }));
+ this.syncWorkflow(workflow, 'finally');
+ }
+ },
+
+ statics: {
+ _instance: null,
+
+ getInstance: function() {
+ var self = JX.ConpherenceThreadManager;
+ if (!self._instance) {
+ return null;
+ }
+ return self._instance;
+ }
+ }
+
+});
diff --git a/webroot/rsrc/js/application/conpherence/behavior-durable-column.js b/webroot/rsrc/js/application/conpherence/behavior-durable-column.js
--- a/webroot/rsrc/js/application/conpherence/behavior-durable-column.js
+++ b/webroot/rsrc/js/application/conpherence/behavior-durable-column.js
@@ -6,100 +6,20 @@
* javelin-scrollbar
* javelin-quicksand
* phabricator-keyboard-shortcut
+ * conpherence-thread-manager
*/
JX.behavior('durable-column', function() {
- var shouldInit = true;
+ var show = false;
var loadThreadID = null;
- var loadedThreadID = null;
- var loadedThreadPHID = null;
- var latestTransactionID = null;
var frame = JX.$('phabricator-standard-page');
var quick = JX.$('phabricator-standard-page-body');
- var show = false;
-
-
- // TODO - this "upating" stuff is a copy from behavior-pontificate
- // TODO: This isn't very clean. When you submit a message, you may get a
- // notification about it back before you get the rendered message back. To
- // prevent this, we keep track of whether we're currently updating the
- // thread. If we are, we hold further updates until the response comes
- // back.
-
- // After the response returns, we'll do another update if we know about
- // a transaction newer than the one we got back from the server.
- var updating = null;
- // Copy continues with slight modifications for how we store data now
- JX.Stratcom.listen('aphlict-server-message', null, function(e) {
- var message = e.getData();
-
- if (message.type != 'message') {
- // Not a message event.
- return;
- }
- if (message.threadPHID != loadedThreadPHID) {
- // Message event for some thread other than the visible one.
- return;
- }
-
- if (message.messageID <= latestTransactionID) {
- // Message event for something we already know about.
- return;
- }
-
- // If we're currently updating, wait for the update to complete.
- // If this notification tells us about a message which is newer than the
- // newest one we know to exist, keep track of it so we can update once
- // the in-flight update finishes.
- if (updating && updating.threadPHID == loadedThreadPHID) {
- if (message.messageID > updating.knownID) {
- updating.knownID = message.messageID;
- return;
- }
- }
-
- update_thread();
- });
- function update_thread() {
- var params = {
- action: 'load',
- latest_transaction_id: latestTransactionID,
- minimal_display: true
- };
-
- var uri = '/conpherence/update/' + loadedThreadID + '/';
-
- var workflow = new JX.Workflow(uri)
- .setData(params)
- .setHandler(function(r) {
- var messages = _getColumnMessagesNode();
- JX.DOM.appendContent(messages, JX.$H(r.transactions));
- messages.scrollTop = messages.scrollHeight;
-
- latestTransactionID = r.latest_transaction_id;
- });
-
- sync_workflow(workflow);
+ function _getColumnContentNode() {
+ return JX.$('conpherence-durable-column-content');
}
- function sync_workflow(workflow) {
- updating = {
- threadPHID: loadedThreadPHID,
- knownID: latestTransactionID
- };
- workflow.listen('finally', function() {
- var need_sync = (updating && updating.knownID > latestTransactionID);
- updating = null;
- if (need_sync) {
- update_thread();
- }
- });
- workflow.start();
- }
- // end copy / hack of stuff with big ole TODO on it
-
function _toggleColumn() {
if (window.location.pathname.indexOf('/conpherence/') === 0) {
@@ -110,7 +30,7 @@
var column = JX.$('conpherence-durable-column');
if (show) {
JX.DOM.show(column);
- loadThreadContent(loadThreadID);
+ threadManager.loadThreadByID(loadThreadID);
} else {
JX.DOM.hide(column);
}
@@ -122,10 +42,48 @@
.setHandler(_toggleColumn)
.register();
- new JX.Scrollbar(JX.$('conpherence-durable-column-content'));
+ new JX.Scrollbar(_getColumnContentNode());
JX.Quicksand.start();
+ /* Conpherence Thread Manager configuration - lots of display
+ * callbacks.
+ */
+ var threadManager = new JX.ConpherenceThreadManager();
+ threadManager.setMinimalDisplay(true);
+ threadManager.setMessagesNodeFunction(_getColumnMessagesNode);
+ threadManager.setTitleNodeFunction(_getColumnTitleNode);
+ threadManager.setLoadThreadURI('/conpherence/columnview/');
+ threadManager.setWillLoadThreadCallback(function () {
+ _markLoading(true);
+ });
+ threadManager.setDidLoadThreadCallback(function (r) {
+ var column = _getColumnNode();
+ var new_column = JX.$H(r.content);
+ JX.DOM.replace(column, new_column);
+ JX.DOM.show(_getColumnNode());
+ new JX.Scrollbar(_getColumnContentNode());
+ _markLoading(false);
+ loadThreadID = threadManager.getLoadedThreadID();
+ });
+ threadManager.setWillSendMessageCallback(function () {
+ _markLoading(true);
+ });
+ threadManager.setDidSendMessageCallback(function (r) {
+ var messages = _getColumnMessagesNode();
+ JX.DOM.appendContent(messages, JX.$H(r.transactions));
+ var content = _getColumnContentNode();
+ content.scrollTop = content.scrollHeight;
+
+ var textarea = _getColumnTextareaNode();
+ textarea.value = '';
+
+ _markLoading(false);
+
+ _focusColumnTextareaNode();
+ });
+ threadManager.start();
+
JX.Stratcom.listen(
'click',
'conpherence-durable-column-header-action',
@@ -139,61 +97,22 @@
switch (action) {
case 'metadata':
JX.Stratcom.invoke('notification-panel-close');
- params = {
- action: action,
- latest_transaction_id: latestTransactionID,
- minimal_display: true,
- force_ajax: true
- };
- var workflow = new JX.Workflow.newFromLink(link)
- .setData(params)
- .setHandler(function(r) {
- var messages = _getColumnMessagesNode();
- JX.DOM.appendContent(messages, JX.$H(r.transactions));
- messages.scrollTop = messages.scrollHeight;
-
- var title = _getColumnTitleNode();
- JX.DOM.setContent(title, r.conpherence_title);
-
- latestTransactionID = r.latest_transaction_id;
- // since this is a two step workflow, and the "finally" method
- // gets called on the first form load, restore "updating" if
- // necessary
- if (updating === null) {
- updating = {
- threadPHID: loadedThreadPHID,
- knownID: latestTransactionID
- };
- }
+ threadManager.runUpdateWorkflowFromLink(
+ link,
+ {
+ action: action,
+ force_ajax: true,
+ stage: 'submit'
});
- sync_workflow(workflow);
break;
case 'add_person':
JX.Stratcom.invoke('notification-panel-close');
- params = {
- action: action,
- latest_transaction_id: latestTransactionID,
- minimal_display: true
- };
- var workflow = new JX.Workflow.newFromLink(link)
- .setData(params)
- .setHandler(function(r) {
- var messages = _getColumnMessagesNode();
- JX.DOM.appendContent(messages, JX.$H(r.transactions));
- messages.scrollTop = messages.scrollHeight;
-
- latestTransactionID = r.latest_transaction_id;
- // since this is a two step workflow, and the "finally" method
- // gets called on the first form load, restore "updating" if
- // necessary
- if (updating === null) {
- updating = {
- threadPHID: loadedThreadPHID,
- knownID: latestTransactionID
- };
- }
+ threadManager.runUpdateWorkflowFromLink(
+ link,
+ {
+ action: action,
+ stage: 'submit'
});
- sync_workflow(workflow);
break;
case 'go_conpherence':
JX.$U(link.href).go();
@@ -217,6 +136,7 @@
'conpherence-durable-column-body');
}
+
function _getColumnMessagesNode() {
var column = JX.$('conpherence-durable-column');
return JX.DOM.find(
@@ -259,65 +179,10 @@
JX.DOM.alterClass(column, 'loading', loading);
}
- function loadThreadContent(thread_id) {
- // loaded this thread already
- if (loadedThreadID !== null && loadedThreadID == thread_id) {
- return;
- }
- _markLoading(true);
-
- var uri = '/conpherence/columnview/';
- var params = null;
- // We can pick a thread from the server the first time
- if (shouldInit) {
- shouldInit = false;
- } else {
- params = { id : thread_id };
- }
- var handler = function(r) {
- var column = _getColumnNode();
- var new_column = JX.$H(r.content);
- loadedThreadID = r.threadID;
- loadedThreadPHID = r.threadPHID;
- loadThreadID = r.threadID;
- latestTransactionID = r.latestTransactionID;
- JX.DOM.replace(column, new_column);
- JX.DOM.show(_getColumnNode());
- new JX.Scrollbar(JX.$('conpherence-durable-column-content'));
- _markLoading(false);
- };
-
- new JX.Workflow(uri)
- .setData(params)
- .setHandler(handler)
- .start();
- }
-
function _sendMessage(e) {
e.kill();
- _markLoading(true);
-
var form = _getColumnFormNode();
- var params = {
- latest_transaction_id : latestTransactionID,
- minimal_display : true
- };
- var workflow = JX.Workflow.newFromForm(form, params)
- .setHandler(function(r) {
- var messages = _getColumnMessagesNode();
- JX.DOM.appendContent(messages, JX.$H(r.transactions));
- messages.scrollTop = messages.scrollHeight;
-
- var textarea = _getColumnTextareaNode();
- textarea.value = '';
-
- latestTransactionID = r.latest_transaction_id;
-
- _markLoading(false);
-
- _focusColumnTextareaNode();
- });
- sync_workflow(workflow);
+ threadManager.sendMessage(form, { minimal_display: true });
}
JX.Stratcom.listen(
diff --git a/webroot/rsrc/js/application/conpherence/behavior-menu.js b/webroot/rsrc/js/application/conpherence/behavior-menu.js
--- a/webroot/rsrc/js/application/conpherence/behavior-menu.js
+++ b/webroot/rsrc/js/application/conpherence/behavior-menu.js
@@ -9,10 +9,10 @@
* javelin-history
* javelin-vector
* phabricator-shaped-request
+ * conpherence-thread-manager
*/
JX.behavior('conpherence-menu', function(config) {
-
/**
* State for displayed thread.
*/
@@ -22,6 +22,45 @@
node: null
};
+ // TODO - move more logic into the ThreadManager
+ var threadManager = new JX.ConpherenceThreadManager();
+ threadManager.setMessagesNodeFunction(function () {
+ return JX.DOM.find(document, 'div', 'conpherence-messages');
+ });
+ threadManager.setWillSendMessageCallback(function () {
+ var root = JX.DOM.find(document, 'div', 'conpherence-layout');
+ var form_root = JX.DOM.find(root, 'div', 'conpherence-form');
+ markThreadLoading(true);
+ JX.DOM.alterClass(form_root, 'loading', true);
+ });
+ threadManager.setDidSendMessageCallback(function (r) {
+ var root = JX.DOM.find(document, 'div', 'conpherence-layout');
+ var form_root = JX.DOM.find(root, 'div', 'conpherence-form');
+ var messages_root = JX.DOM.find(root, 'div', 'conpherence-message-pane');
+ var messages = JX.DOM.find(messages_root, 'div', 'conpherence-messages');
+ var fileWidget = null;
+ try {
+ fileWidget = JX.DOM.find(root, 'div', 'widgets-files');
+ } catch (ex) {
+ // Ignore; maybe no files widget
+ }
+ JX.DOM.appendContent(messages, JX.$H(r.transactions));
+ messages.scrollTop = messages.scrollHeight;
+
+ if (fileWidget) {
+ JX.DOM.setContent(
+ fileWidget,
+ JX.$H(r.file_widget)
+ );
+ }
+ var textarea = JX.DOM.find(form_root, 'textarea');
+ textarea.value = '';
+ markThreadLoading(false);
+
+ setTimeout(function() { JX.DOM.focus(textarea); }, 100);
+ });
+ threadManager.start();
+
/**
* Current role of this behavior. The two possible roles are to show a 'list'
* of threads or a specific 'thread'. On devices, this behavior stays in the
@@ -65,9 +104,6 @@
function selectThread(node, update_page_data) {
if (_thread.node) {
JX.DOM.alterClass(_thread.node, 'conpherence-selected', false);
- // keep the unread-count hidden still. big TODO once we ajax in updates
- // to threads to make this work right and move threads between read /
- // unread
}
JX.DOM.alterClass(node, 'conpherence-selected', true);
diff --git a/webroot/rsrc/js/application/conpherence/behavior-pontificate.js b/webroot/rsrc/js/application/conpherence/behavior-pontificate.js
--- a/webroot/rsrc/js/application/conpherence/behavior-pontificate.js
+++ b/webroot/rsrc/js/application/conpherence/behavior-pontificate.js
@@ -5,149 +5,16 @@
* javelin-util
* javelin-workflow
* javelin-stratcom
+ * conpherence-thread-manager
*/
JX.behavior('conpherence-pontificate', function() {
- // TODO: This isn't very clean. When you submit a message, you may get a
- // notification about it back before you get the rendered message back. To
- // prevent this, we keep track of whether we're currently updating the
- // thread. If we are, we hold further updates until the response comes
- // back.
-
- // After the response returns, we'll do another update if we know about
- // a transaction newer than the one we got back from the server.
- var updating = null;
-
- function get_thread_data() {
- // TODO: This is really, really gross.
- var infonode = JX.DOM.find(document, 'input', 'latest-transaction-id');
- var data = JX.Stratcom.getData(infonode);
- data.latestID = infonode.value;
- return data;
- }
-
- function update_latest_transaction_id(id) {
- // TODO: Continued grossness from above.
- var infonode = JX.DOM.find(document, 'input', 'latest-transaction-id');
- infonode.value = id;
- }
-
- JX.Stratcom.listen('aphlict-server-message', null, function(e) {
- var message = e.getData();
-
- if (message.type != 'message') {
- // Not a message event.
- return;
- }
-
- var data = get_thread_data();
-
- if (message.threadPHID != data.threadPHID) {
- // Message event for some thread other than the visible one.
- return;
- }
-
- if (message.messageID <= data.latestID) {
- // Message event for something we already know about.
- return;
- }
-
- // If we're currently updating, wait for the update to complete.
- // If this notification tells us about a message which is newer than the
- // newest one we know to exist, keep track of it so we can update once
- // the in-flight update finishes.
- if (updating && updating.threadPHID == data.threadPHID) {
- if (message.messageID > updating.knownID) {
- updating.knownID = message.messageID;
- return;
- }
- }
-
- update_thread(data);
- });
-
- function update_thread(data) {
- var params = {
- action: 'load',
- latest_transaction_id: data.latestID
- };
-
- var uri = '/conpherence/update/' + data.threadID + '/';
-
- var workflow = new JX.Workflow(uri)
- .setData(params)
- .setHandler(function(r) {
- var messages = JX.DOM.find(document, 'div', 'conpherence-messages');
- JX.DOM.appendContent(messages, JX.$H(r.transactions));
- messages.scrollTop = messages.scrollHeight;
-
- update_latest_transaction_id(r.latest_transaction_id);
- });
-
- sync_workflow(workflow, data);
- }
-
- function sync_workflow(workflow, data) {
- updating = {
- threadPHID: data.threadPHID,
- knownID: data.latestID
- };
-
- workflow.listen('finally', function() {
- var new_data = get_thread_data();
- var need_sync = (updating.knownID > new_data.latestID);
-
- updating = null;
-
- if (need_sync) {
- update_thread(new_data);
- }
- });
-
- workflow.start();
- }
-
var onsubmit = function(e) {
e.kill();
-
var form = e.getNode('tag:form');
-
- var root = e.getNode('conpherence-layout');
- var messages_root = JX.DOM.find(root, 'div', 'conpherence-message-pane');
- var form_root = JX.DOM.find(root, 'div', 'conpherence-form');
- var messages = JX.DOM.find(messages_root, 'div', 'conpherence-messages');
- var fileWidget = null;
- try {
- fileWidget = JX.DOM.find(root, 'div', 'widgets-files');
- } catch (ex) {
- // Ignore; maybe no files widget
- }
- JX.DOM.alterClass(form_root, 'loading', true);
-
- var workflow = JX.Workflow.newFromForm(form)
- .setHandler(JX.bind(this, function(r) {
- JX.DOM.appendContent(messages, JX.$H(r.transactions));
- messages.scrollTop = messages.scrollHeight;
-
- if (fileWidget) {
- JX.DOM.setContent(
- fileWidget,
- JX.$H(r.file_widget)
- );
- }
-
- update_latest_transaction_id(r.latest_transaction_id);
-
- var textarea = JX.DOM.find(form, 'textarea');
- textarea.value = '';
-
- JX.DOM.alterClass(form_root, 'loading', false);
-
- setTimeout(function() { JX.DOM.focus(textarea); }, 100);
- }));
-
- sync_workflow(workflow, get_thread_data());
+ var threadManager = JX.ConpherenceThreadManager.getInstance();
+ threadManager.sendMessage(form, {});
};
JX.Stratcom.listen(
diff --git a/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js b/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js
--- a/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js
+++ b/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js
@@ -9,6 +9,7 @@
* phuix-dropdown-menu
* phuix-action-list-view
* phuix-action-view
+ * conpherence-thread-manager
* @provides javelin-behavior-conpherence-widget-pane
*/
@@ -270,19 +271,18 @@
href = create_data.customHref;
}
- var root = JX.DOM.find(document, 'div', 'conpherence-layout');
- var latest_transaction_dom = JX.DOM.find(
- root,
- 'input',
- 'latest-transaction-id');
+ var threadManager = JX.ConpherenceThreadManager.getInstance();
+ var latest_transaction_id = threadManager.getLatestTransactionID();
var data = {
- latest_transaction_id : latest_transaction_dom.value,
+ latest_transaction_id : latest_transaction_id,
action : create_data.action
};
- new JX.Workflow(href, data)
+ var workflow = new JX.Workflow(href, data)
.setHandler(function (r) {
- latest_transaction_dom.value = r.latest_transaction_id;
+ var threadManager = JX.ConpherenceThreadManager.getInstance();
+ threadManager.setLatestTransactionID(r.latest_transaction_id);
+ var root = JX.DOM.find(document, 'div', 'conpherence-layout');
if (create_data.refreshFromResponse) {
var messages = null;
try {
@@ -315,8 +315,8 @@
widget : widget_to_update
});
}
- })
- .start();
+ });
+ threadManager.syncWorkflow(workflow, 'submit');
}
);

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 6, 5:31 AM (1 w, 5 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/py/kf/h7oh4g6mowg3pmui
Default Alt Text
D12029.id28953.diff (35 KB)

Event Timeline