mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 09:12:41 +01:00
Conpherence - introduce ConpherenceThreadManager
Summary: Ref T7014. Fixes T7473. This adds a class to handle thread state about what thread is loaded and what transaction we've seen last. It is deployed 100% in the durable column and only partially deployed in the regular view. Future diff(s) should clean up regular view. Note ConpherenceThreadManager API might change a bit at that time. Also includes a bonus bug fix so logged out users can't toggle this column Test Plan: tried to use durable column while logged out and nothing happened. sent messages, aphlict-received messages, added people, and changed title from both views Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T7473, T7014 Differential Revision: https://secure.phabricator.com/D12029
This commit is contained in:
parent
dd501117e8
commit
2373185e9b
8 changed files with 466 additions and 417 deletions
|
@ -11,7 +11,7 @@ return array(
|
||||||
'core.pkg.js' => '5a1c336d',
|
'core.pkg.js' => '5a1c336d',
|
||||||
'darkconsole.pkg.js' => '8ab24e01',
|
'darkconsole.pkg.js' => '8ab24e01',
|
||||||
'differential.pkg.css' => '1940be3f',
|
'differential.pkg.css' => '1940be3f',
|
||||||
'differential.pkg.js' => 'e62fe1cf',
|
'differential.pkg.js' => '53c1ccc2',
|
||||||
'diffusion.pkg.css' => '591664fa',
|
'diffusion.pkg.css' => '591664fa',
|
||||||
'diffusion.pkg.js' => 'bfc0737b',
|
'diffusion.pkg.js' => 'bfc0737b',
|
||||||
'maniphest.pkg.css' => '68d4dd3d',
|
'maniphest.pkg.css' => '68d4dd3d',
|
||||||
|
@ -351,17 +351,18 @@ return array(
|
||||||
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
|
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
|
||||||
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
||||||
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
|
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
|
||||||
'rsrc/js/application/conpherence/behavior-durable-column.js' => 'e4affa94',
|
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => 'd0742f48',
|
||||||
'rsrc/js/application/conpherence/behavior-menu.js' => '869e3445',
|
'rsrc/js/application/conpherence/behavior-durable-column.js' => '8cf41980',
|
||||||
'rsrc/js/application/conpherence/behavior-pontificate.js' => '86df5915',
|
'rsrc/js/application/conpherence/behavior-menu.js' => '6bc52765',
|
||||||
'rsrc/js/application/conpherence/behavior-widget-pane.js' => '40b1ff90',
|
'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861',
|
||||||
|
'rsrc/js/application/conpherence/behavior-widget-pane.js' => '2c1cd7f5',
|
||||||
'rsrc/js/application/countdown/timer.js' => 'e4cc26b3',
|
'rsrc/js/application/countdown/timer.js' => 'e4cc26b3',
|
||||||
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e',
|
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e',
|
||||||
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '82439934',
|
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '82439934',
|
||||||
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375',
|
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375',
|
||||||
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63',
|
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63',
|
||||||
'rsrc/js/application/differential/ChangesetViewManager.js' => '88be0133',
|
'rsrc/js/application/differential/ChangesetViewManager.js' => '88be0133',
|
||||||
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => '1b772f31',
|
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => '0286a1db',
|
||||||
'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => 'e10f8e18',
|
'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => 'e10f8e18',
|
||||||
'rsrc/js/application/differential/behavior-comment-jump.js' => '4fdb476d',
|
'rsrc/js/application/differential/behavior-comment-jump.js' => '4fdb476d',
|
||||||
'rsrc/js/application/differential/behavior-comment-preview.js' => '8e1389b5',
|
'rsrc/js/application/differential/behavior-comment-preview.js' => '8e1389b5',
|
||||||
|
@ -516,11 +517,12 @@ return array(
|
||||||
'conpherence-menu-css' => 'c6ac5299',
|
'conpherence-menu-css' => 'c6ac5299',
|
||||||
'conpherence-message-pane-css' => '5930260a',
|
'conpherence-message-pane-css' => '5930260a',
|
||||||
'conpherence-notification-css' => '04a6e10a',
|
'conpherence-notification-css' => '04a6e10a',
|
||||||
|
'conpherence-thread-manager' => 'd0742f48',
|
||||||
'conpherence-update-css' => '1099a660',
|
'conpherence-update-css' => '1099a660',
|
||||||
'conpherence-widget-pane-css' => '3d575438',
|
'conpherence-widget-pane-css' => '3d575438',
|
||||||
'differential-changeset-view-css' => '6a8b172a',
|
'differential-changeset-view-css' => '6a8b172a',
|
||||||
'differential-core-view-css' => '7ac3cabc',
|
'differential-core-view-css' => '7ac3cabc',
|
||||||
'differential-inline-comment-editor' => '1b772f31',
|
'differential-inline-comment-editor' => '0286a1db',
|
||||||
'differential-results-table-css' => '181aa9d9',
|
'differential-results-table-css' => '181aa9d9',
|
||||||
'differential-revision-add-comment-css' => 'c478bcaa',
|
'differential-revision-add-comment-css' => 'c478bcaa',
|
||||||
'differential-revision-comment-css' => '48186045',
|
'differential-revision-comment-css' => '48186045',
|
||||||
|
@ -555,9 +557,9 @@ return array(
|
||||||
'javelin-behavior-boards-dropdown' => '0ec56e1d',
|
'javelin-behavior-boards-dropdown' => '0ec56e1d',
|
||||||
'javelin-behavior-choose-control' => '6153c708',
|
'javelin-behavior-choose-control' => '6153c708',
|
||||||
'javelin-behavior-config-reorder-fields' => '14a827de',
|
'javelin-behavior-config-reorder-fields' => '14a827de',
|
||||||
'javelin-behavior-conpherence-menu' => '869e3445',
|
'javelin-behavior-conpherence-menu' => '6bc52765',
|
||||||
'javelin-behavior-conpherence-pontificate' => '86df5915',
|
'javelin-behavior-conpherence-pontificate' => '21ba5861',
|
||||||
'javelin-behavior-conpherence-widget-pane' => '40b1ff90',
|
'javelin-behavior-conpherence-widget-pane' => '2c1cd7f5',
|
||||||
'javelin-behavior-countdown-timer' => 'e4cc26b3',
|
'javelin-behavior-countdown-timer' => 'e4cc26b3',
|
||||||
'javelin-behavior-dark-console' => '08883e8b',
|
'javelin-behavior-dark-console' => '08883e8b',
|
||||||
'javelin-behavior-dashboard-async-panel' => '469c0d9e',
|
'javelin-behavior-dashboard-async-panel' => '469c0d9e',
|
||||||
|
@ -582,7 +584,7 @@ return array(
|
||||||
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
||||||
'javelin-behavior-diffusion-pull-lastmodified' => '2b228192',
|
'javelin-behavior-diffusion-pull-lastmodified' => '2b228192',
|
||||||
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
||||||
'javelin-behavior-durable-column' => 'e4affa94',
|
'javelin-behavior-durable-column' => '8cf41980',
|
||||||
'javelin-behavior-error-log' => '6882e80a',
|
'javelin-behavior-error-log' => '6882e80a',
|
||||||
'javelin-behavior-fancy-datepicker' => 'c51ae228',
|
'javelin-behavior-fancy-datepicker' => 'c51ae228',
|
||||||
'javelin-behavior-global-drag-and-drop' => '07f199d8',
|
'javelin-behavior-global-drag-and-drop' => '07f199d8',
|
||||||
|
@ -830,6 +832,14 @@ return array(
|
||||||
'unhandled-exception-css' => '37d4f9a2',
|
'unhandled-exception-css' => '37d4f9a2',
|
||||||
),
|
),
|
||||||
'requires' => array(
|
'requires' => array(
|
||||||
|
'0286a1db' => array(
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-util',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-install',
|
||||||
|
'javelin-request',
|
||||||
|
'javelin-workflow',
|
||||||
|
),
|
||||||
'029a133d' => array(
|
'029a133d' => array(
|
||||||
'aphront-dialog-view-css',
|
'aphront-dialog-view-css',
|
||||||
),
|
),
|
||||||
|
@ -931,14 +941,6 @@ return array(
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
'phabricator-keyboard-shortcut-manager',
|
'phabricator-keyboard-shortcut-manager',
|
||||||
),
|
),
|
||||||
'1b772f31' => array(
|
|
||||||
'javelin-dom',
|
|
||||||
'javelin-util',
|
|
||||||
'javelin-stratcom',
|
|
||||||
'javelin-install',
|
|
||||||
'javelin-request',
|
|
||||||
'javelin-workflow',
|
|
||||||
),
|
|
||||||
'1d298e3a' => array(
|
'1d298e3a' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
|
@ -968,6 +970,14 @@ return array(
|
||||||
'phabricator-phtize',
|
'phabricator-phtize',
|
||||||
'changeset-view-manager',
|
'changeset-view-manager',
|
||||||
),
|
),
|
||||||
|
'21ba5861' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-util',
|
||||||
|
'javelin-workflow',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'conpherence-thread-manager',
|
||||||
|
),
|
||||||
'2290aeef' => array(
|
'2290aeef' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
@ -1012,6 +1022,19 @@ return array(
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
'javelin-dom',
|
'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(
|
'2c426492' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
@ -1067,18 +1090,6 @@ return array(
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
'javelin-reactor-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(
|
42126667 => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
@ -1238,6 +1249,18 @@ return array(
|
||||||
'69adf288' => array(
|
'69adf288' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
),
|
),
|
||||||
|
'6bc52765' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-util',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-workflow',
|
||||||
|
'javelin-behavior-device',
|
||||||
|
'javelin-history',
|
||||||
|
'javelin-vector',
|
||||||
|
'phabricator-shaped-request',
|
||||||
|
'conpherence-thread-manager',
|
||||||
|
),
|
||||||
'6c2b09a2' => array(
|
'6c2b09a2' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
|
@ -1447,24 +1470,6 @@ return array(
|
||||||
'phabricator-tooltip',
|
'phabricator-tooltip',
|
||||||
'changeset-view-manager',
|
'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(
|
'87cb6b51' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
@ -1530,6 +1535,15 @@ return array(
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
),
|
),
|
||||||
|
'8cf41980' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-scrollbar',
|
||||||
|
'javelin-quicksand',
|
||||||
|
'phabricator-keyboard-shortcut',
|
||||||
|
'conpherence-thread-manager',
|
||||||
|
),
|
||||||
'8e1389b5' => array(
|
'8e1389b5' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
|
@ -1754,6 +1768,16 @@ return array(
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
'phabricator-phtize',
|
'phabricator-phtize',
|
||||||
),
|
),
|
||||||
|
'd0742f48' => array(
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-util',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-install',
|
||||||
|
'javelin-workflow',
|
||||||
|
'javelin-router',
|
||||||
|
'javelin-behavior-device',
|
||||||
|
'javelin-vector',
|
||||||
|
),
|
||||||
'd19198c8' => array(
|
'd19198c8' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
@ -1836,14 +1860,6 @@ return array(
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
'javelin-uri',
|
'javelin-uri',
|
||||||
),
|
),
|
||||||
'e4affa94' => array(
|
|
||||||
'javelin-behavior',
|
|
||||||
'javelin-dom',
|
|
||||||
'javelin-stratcom',
|
|
||||||
'javelin-scrollbar',
|
|
||||||
'javelin-quicksand',
|
|
||||||
'phabricator-keyboard-shortcut',
|
|
||||||
),
|
|
||||||
'e4cc26b3' => array(
|
'e4cc26b3' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
|
|
@ -46,7 +46,7 @@ final class ConpherenceViewController extends
|
||||||
$content = array('messages' => $messages);
|
$content = array('messages' => $messages);
|
||||||
} else {
|
} else {
|
||||||
$header = $this->buildHeaderPaneContent($conpherence);
|
$header = $this->buildHeaderPaneContent($conpherence);
|
||||||
$form = $this->renderFormContent($data['latest_transaction_id']);
|
$form = $this->renderFormContent();
|
||||||
$content = array(
|
$content = array(
|
||||||
'header' => $header,
|
'header' => $header,
|
||||||
'messages' => $messages,
|
'messages' => $messages,
|
||||||
|
@ -77,7 +77,7 @@ final class ConpherenceViewController extends
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderFormContent($latest_transaction_id) {
|
private function renderFormContent() {
|
||||||
|
|
||||||
$conpherence = $this->getConpherence();
|
$conpherence = $this->getConpherence();
|
||||||
$user = $this->getRequest()->getUser();
|
$user = $this->getRequest()->getUser();
|
||||||
|
@ -103,20 +103,6 @@ final class ConpherenceViewController extends
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->setValue(pht('Send')))
|
->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();
|
->render();
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
|
|
|
@ -82,11 +82,19 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView {
|
||||||
public function getShowDurableColumn() {
|
public function getShowDurableColumn() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
if ($request) {
|
if ($request) {
|
||||||
|
if (strncmp(
|
||||||
|
$request->getRequestURI()->getPath(),
|
||||||
|
'/conpherence',
|
||||||
|
strlen('/conpherence')) === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$viewer = $request->getUser();
|
$viewer = $request->getUser();
|
||||||
|
if ($viewer->isLoggedIn()) {
|
||||||
return PhabricatorApplication::isClassInstalledForViewer(
|
return PhabricatorApplication::isClassInstalledForViewer(
|
||||||
'PhabricatorConpherenceApplication',
|
'PhabricatorConpherenceApplication',
|
||||||
$viewer);
|
$viewer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
|
@ -6,101 +6,21 @@
|
||||||
* javelin-scrollbar
|
* javelin-scrollbar
|
||||||
* javelin-quicksand
|
* javelin-quicksand
|
||||||
* phabricator-keyboard-shortcut
|
* phabricator-keyboard-shortcut
|
||||||
|
* conpherence-thread-manager
|
||||||
*/
|
*/
|
||||||
|
|
||||||
JX.behavior('durable-column', function() {
|
JX.behavior('durable-column', function() {
|
||||||
|
|
||||||
var shouldInit = true;
|
var show = false;
|
||||||
var loadThreadID = null;
|
var loadThreadID = null;
|
||||||
var loadedThreadID = null;
|
|
||||||
var loadedThreadPHID = null;
|
|
||||||
var latestTransactionID = null;
|
|
||||||
|
|
||||||
var frame = JX.$('phabricator-standard-page');
|
var frame = JX.$('phabricator-standard-page');
|
||||||
var quick = JX.$('phabricator-standard-page-body');
|
var quick = JX.$('phabricator-standard-page-body');
|
||||||
var show = false;
|
|
||||||
|
|
||||||
|
function _getColumnContentNode() {
|
||||||
// TODO - this "upating" stuff is a copy from behavior-pontificate
|
return JX.$('conpherence-durable-column-content');
|
||||||
// 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 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() {
|
function _toggleColumn() {
|
||||||
if (window.location.pathname.indexOf('/conpherence/') === 0) {
|
if (window.location.pathname.indexOf('/conpherence/') === 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -110,7 +30,7 @@ JX.behavior('durable-column', function() {
|
||||||
var column = JX.$('conpherence-durable-column');
|
var column = JX.$('conpherence-durable-column');
|
||||||
if (show) {
|
if (show) {
|
||||||
JX.DOM.show(column);
|
JX.DOM.show(column);
|
||||||
loadThreadContent(loadThreadID);
|
threadManager.loadThreadByID(loadThreadID);
|
||||||
} else {
|
} else {
|
||||||
JX.DOM.hide(column);
|
JX.DOM.hide(column);
|
||||||
}
|
}
|
||||||
|
@ -122,10 +42,48 @@ JX.behavior('durable-column', function() {
|
||||||
.setHandler(_toggleColumn)
|
.setHandler(_toggleColumn)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
new JX.Scrollbar(JX.$('conpherence-durable-column-content'));
|
new JX.Scrollbar(_getColumnContentNode());
|
||||||
|
|
||||||
JX.Quicksand.start();
|
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(
|
JX.Stratcom.listen(
|
||||||
'click',
|
'click',
|
||||||
'conpherence-durable-column-header-action',
|
'conpherence-durable-column-header-action',
|
||||||
|
@ -139,61 +97,22 @@ JX.behavior('durable-column', function() {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'metadata':
|
case 'metadata':
|
||||||
JX.Stratcom.invoke('notification-panel-close');
|
JX.Stratcom.invoke('notification-panel-close');
|
||||||
params = {
|
threadManager.runUpdateWorkflowFromLink(
|
||||||
|
link,
|
||||||
|
{
|
||||||
action: action,
|
action: action,
|
||||||
latest_transaction_id: latestTransactionID,
|
force_ajax: true,
|
||||||
minimal_display: true,
|
stage: 'submit'
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
sync_workflow(workflow);
|
|
||||||
break;
|
break;
|
||||||
case 'add_person':
|
case 'add_person':
|
||||||
JX.Stratcom.invoke('notification-panel-close');
|
JX.Stratcom.invoke('notification-panel-close');
|
||||||
params = {
|
threadManager.runUpdateWorkflowFromLink(
|
||||||
|
link,
|
||||||
|
{
|
||||||
action: action,
|
action: action,
|
||||||
latest_transaction_id: latestTransactionID,
|
stage: 'submit'
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
sync_workflow(workflow);
|
|
||||||
break;
|
break;
|
||||||
case 'go_conpherence':
|
case 'go_conpherence':
|
||||||
JX.$U(link.href).go();
|
JX.$U(link.href).go();
|
||||||
|
@ -217,6 +136,7 @@ JX.behavior('durable-column', function() {
|
||||||
'conpherence-durable-column-body');
|
'conpherence-durable-column-body');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function _getColumnMessagesNode() {
|
function _getColumnMessagesNode() {
|
||||||
var column = JX.$('conpherence-durable-column');
|
var column = JX.$('conpherence-durable-column');
|
||||||
return JX.DOM.find(
|
return JX.DOM.find(
|
||||||
|
@ -259,65 +179,10 @@ JX.behavior('durable-column', function() {
|
||||||
JX.DOM.alterClass(column, 'loading', loading);
|
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) {
|
function _sendMessage(e) {
|
||||||
e.kill();
|
e.kill();
|
||||||
_markLoading(true);
|
|
||||||
|
|
||||||
var form = _getColumnFormNode();
|
var form = _getColumnFormNode();
|
||||||
var params = {
|
threadManager.sendMessage(form, { minimal_display: true });
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JX.Stratcom.listen(
|
JX.Stratcom.listen(
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
* javelin-history
|
* javelin-history
|
||||||
* javelin-vector
|
* javelin-vector
|
||||||
* phabricator-shaped-request
|
* phabricator-shaped-request
|
||||||
|
* conpherence-thread-manager
|
||||||
*/
|
*/
|
||||||
|
|
||||||
JX.behavior('conpherence-menu', function(config) {
|
JX.behavior('conpherence-menu', function(config) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State for displayed thread.
|
* State for displayed thread.
|
||||||
*/
|
*/
|
||||||
|
@ -22,6 +22,45 @@ JX.behavior('conpherence-menu', function(config) {
|
||||||
node: null
|
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'
|
* 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
|
* of threads or a specific 'thread'. On devices, this behavior stays in the
|
||||||
|
@ -65,9 +104,6 @@ JX.behavior('conpherence-menu', function(config) {
|
||||||
function selectThread(node, update_page_data) {
|
function selectThread(node, update_page_data) {
|
||||||
if (_thread.node) {
|
if (_thread.node) {
|
||||||
JX.DOM.alterClass(_thread.node, 'conpherence-selected', false);
|
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);
|
JX.DOM.alterClass(node, 'conpherence-selected', true);
|
||||||
|
|
|
@ -5,149 +5,16 @@
|
||||||
* javelin-util
|
* javelin-util
|
||||||
* javelin-workflow
|
* javelin-workflow
|
||||||
* javelin-stratcom
|
* javelin-stratcom
|
||||||
|
* conpherence-thread-manager
|
||||||
*/
|
*/
|
||||||
|
|
||||||
JX.behavior('conpherence-pontificate', function() {
|
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) {
|
var onsubmit = function(e) {
|
||||||
e.kill();
|
e.kill();
|
||||||
|
|
||||||
var form = e.getNode('tag:form');
|
var form = e.getNode('tag:form');
|
||||||
|
var threadManager = JX.ConpherenceThreadManager.getInstance();
|
||||||
var root = e.getNode('conpherence-layout');
|
threadManager.sendMessage(form, {});
|
||||||
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());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JX.Stratcom.listen(
|
JX.Stratcom.listen(
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
* phuix-dropdown-menu
|
* phuix-dropdown-menu
|
||||||
* phuix-action-list-view
|
* phuix-action-list-view
|
||||||
* phuix-action-view
|
* phuix-action-view
|
||||||
|
* conpherence-thread-manager
|
||||||
* @provides javelin-behavior-conpherence-widget-pane
|
* @provides javelin-behavior-conpherence-widget-pane
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -270,19 +271,18 @@ JX.behavior('conpherence-widget-pane', function(config) {
|
||||||
href = create_data.customHref;
|
href = create_data.customHref;
|
||||||
}
|
}
|
||||||
|
|
||||||
var root = JX.DOM.find(document, 'div', 'conpherence-layout');
|
var threadManager = JX.ConpherenceThreadManager.getInstance();
|
||||||
var latest_transaction_dom = JX.DOM.find(
|
var latest_transaction_id = threadManager.getLatestTransactionID();
|
||||||
root,
|
|
||||||
'input',
|
|
||||||
'latest-transaction-id');
|
|
||||||
var data = {
|
var data = {
|
||||||
latest_transaction_id : latest_transaction_dom.value,
|
latest_transaction_id : latest_transaction_id,
|
||||||
action : create_data.action
|
action : create_data.action
|
||||||
};
|
};
|
||||||
|
|
||||||
new JX.Workflow(href, data)
|
var workflow = new JX.Workflow(href, data)
|
||||||
.setHandler(function (r) {
|
.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) {
|
if (create_data.refreshFromResponse) {
|
||||||
var messages = null;
|
var messages = null;
|
||||||
try {
|
try {
|
||||||
|
@ -315,8 +315,8 @@ JX.behavior('conpherence-widget-pane', function(config) {
|
||||||
widget : widget_to_update
|
widget : widget_to_update
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.start();
|
threadManager.syncWorkflow(workflow, 'submit');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue