diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -352,9 +352,9 @@ '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/ConpherenceThreadManager.js' => 'efef202b', - 'rsrc/js/application/conpherence/behavior-durable-column.js' => '016fa2e9', - 'rsrc/js/application/conpherence/behavior-menu.js' => 'e476c952', + 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '4edea023', + 'rsrc/js/application/conpherence/behavior-durable-column.js' => '581d8699', + 'rsrc/js/application/conpherence/behavior-menu.js' => 'c4151295', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861', 'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3', 'rsrc/js/application/conpherence/behavior-widget-pane.js' => '2c1cd7f5', @@ -518,7 +518,7 @@ 'conpherence-menu-css' => 'c6ac5299', 'conpherence-message-pane-css' => '5930260a', 'conpherence-notification-css' => '04a6e10a', - 'conpherence-thread-manager' => 'efef202b', + 'conpherence-thread-manager' => '4edea023', 'conpherence-update-css' => '1099a660', 'conpherence-widget-pane-css' => '3d575438', 'differential-changeset-view-css' => '6a8b172a', @@ -558,7 +558,7 @@ 'javelin-behavior-boards-dropdown' => '0ec56e1d', 'javelin-behavior-choose-control' => '6153c708', 'javelin-behavior-config-reorder-fields' => '14a827de', - 'javelin-behavior-conpherence-menu' => 'e476c952', + 'javelin-behavior-conpherence-menu' => 'c4151295', 'javelin-behavior-conpherence-pontificate' => '21ba5861', 'javelin-behavior-conpherence-widget-pane' => '2c1cd7f5', 'javelin-behavior-countdown-timer' => 'e4cc26b3', @@ -585,7 +585,7 @@ 'javelin-behavior-diffusion-locate-file' => '6d3e1947', 'javelin-behavior-diffusion-pull-lastmodified' => '2b228192', 'javelin-behavior-doorkeeper-tag' => 'e5822781', - 'javelin-behavior-durable-column' => '016fa2e9', + 'javelin-behavior-durable-column' => '581d8699', 'javelin-behavior-error-log' => '6882e80a', 'javelin-behavior-fancy-datepicker' => 'c51ae228', 'javelin-behavior-global-drag-and-drop' => '07f199d8', @@ -834,15 +834,6 @@ 'unhandled-exception-css' => '37d4f9a2', ), 'requires' => array( - '016fa2e9' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-scrollbar', - 'javelin-quicksand', - 'phabricator-keyboard-shortcut', - 'conpherence-thread-manager', - ), '0286a1db' => array( 'javelin-dom', 'javelin-util', @@ -1171,6 +1162,16 @@ 'javelin-stratcom', 'javelin-request', ), + '4edea023' => array( + 'javelin-dom', + 'javelin-util', + 'javelin-stratcom', + 'javelin-install', + 'javelin-workflow', + 'javelin-router', + 'javelin-behavior-device', + 'javelin-vector', + ), '4fdb476d' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1203,6 +1204,15 @@ 'javelin-vector', 'javelin-dom', ), + '581d8699' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-scrollbar', + 'javelin-quicksand', + 'phabricator-keyboard-shortcut', + 'conpherence-thread-manager', + ), '59b251eb' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1747,6 +1757,18 @@ 'javelin-dom', 'javelin-vector', ), + 'c4151295' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-util', + 'javelin-stratcom', + 'javelin-workflow', + 'javelin-behavior-device', + 'javelin-history', + 'javelin-vector', + 'phabricator-shaped-request', + 'conpherence-thread-manager', + ), 'c51ae228' => array( 'javelin-behavior', 'javelin-util', @@ -1850,18 +1872,6 @@ 'javelin-dom', 'javelin-uri', ), - 'e476c952' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-util', - 'javelin-stratcom', - 'javelin-workflow', - 'javelin-behavior-device', - 'javelin-history', - 'javelin-vector', - 'phabricator-shaped-request', - 'conpherence-thread-manager', - ), 'e4cc26b3' => array( 'javelin-behavior', 'javelin-dom', @@ -1909,16 +1919,6 @@ 'javelin-install', 'javelin-util', ), - 'efef202b' => array( - 'javelin-dom', - 'javelin-util', - 'javelin-stratcom', - 'javelin-install', - 'javelin-workflow', - 'javelin-router', - 'javelin-behavior-device', - 'javelin-vector', - ), 'f24f3253' => array( 'javelin-behavior', 'javelin-dom', diff --git a/src/applications/conpherence/controller/ConpherenceColumnViewController.php b/src/applications/conpherence/controller/ConpherenceColumnViewController.php --- a/src/applications/conpherence/controller/ConpherenceColumnViewController.php +++ b/src/applications/conpherence/controller/ConpherenceColumnViewController.php @@ -67,7 +67,12 @@ $participant->markUpToDate($conpherence, $latest_transaction); unset($write_guard); + $draft = PhabricatorDraft::newFromUserAndKey( + $user, + $conpherence->getPHID()); + $durable_column + ->setDraft($draft) ->setSelectedConpherence($conpherence) ->setConpherences($latest_conpherences); $conpherence_id = $conpherence->getID(); diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php --- a/src/applications/conpherence/controller/ConpherenceUpdateController.php +++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php @@ -52,7 +52,35 @@ $conpherence->getPHID()); $draft->setDraft($request->getStr('text')); $draft->replaceOrDelete(); - return new AphrontAjaxResponse(); + $draft_comment = id(new ConpherenceTransactionComment()) + ->makeEphemeral() + ->setContent($draft->getDraft()) + ->setAuthorPHID($user->getPHID()) + ->setConpherencePHID($conpherence->getPHID()); + $engine = id(new PhabricatorMarkupEngine()) + ->setViewer($user) + ->addObject( + $draft_comment, + PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT); + $engine->process(); + $draft_xaction = id(new ConpherenceTransaction()) + ->makeEphemeral() + ->setAuthorPHID($user->getPHID()) + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) + ->attachComment($draft_comment); + $minimal_display = $request->getExists('minimal_display'); + $user_handle = $this->loadViewerHandles(array($user->getPHID())); + $draft_xaction_view = id(new ConpherenceTransactionView()) + ->setUser($user) + ->setMarkupEngine($engine) + ->setConpherenceTransaction($draft_xaction) + ->setShowImages(!$minimal_display) + ->setShowContentSource(!$minimal_display) + ->setHandles($user_handle); + return id(new AphrontAjaxResponse()) + ->setContent(array( + 'threadID' => $conpherence->getID(), + 'content' => $draft_xaction_view->render(),)); case ConpherenceUpdateActions::MESSAGE: $message = $request->getStr('text'); $xactions = $editor->generateTransactionsFromText( diff --git a/src/applications/conpherence/view/ConpherenceDurableColumnView.php b/src/applications/conpherence/view/ConpherenceDurableColumnView.php --- a/src/applications/conpherence/view/ConpherenceDurableColumnView.php +++ b/src/applications/conpherence/view/ConpherenceDurableColumnView.php @@ -2,7 +2,8 @@ final class ConpherenceDurableColumnView extends AphrontTagView { - private $conpherences; + private $conpherences = array(); + private $draft; private $selectedConpherence; private $transactions; private $visible; @@ -17,6 +18,15 @@ return $this->conpherences; } + public function setDraft(PhabricatorDraft $draft) { + $this->draft = $draft; + return $this; + } + + public function getDraft() { + return $this->draft; + } + public function setSelectedConpherence( ConpherenceThread $conpherence = null) { $this->selectedConpherence = $conpherence; @@ -343,6 +353,12 @@ return null; } + $draft = $this->getDraft(); + $draft_value = null; + if ($draft) { + $draft_value = $draft->getDraft(); + } + $textarea = javelin_tag( 'textarea', array( @@ -350,7 +366,8 @@ 'class' => 'conpherence-durable-column-textarea', 'sigil' => 'conpherence-durable-column-textarea', 'placeholder' => pht('Send a message...'), - )); + ), + $draft_value); $id = $conpherence->getID(); return phabricator_form( $this->getUser(), diff --git a/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js b/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js --- a/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js +++ b/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js @@ -28,6 +28,7 @@ _latestTransactionID: null, _updating: null, _minimalDisplay: false, + _renderedDrafts: null, _willLoadThreadCallback: JX.bag, _didLoadThreadCallback: JX.bag, _didUpdateThreadCallback: JX.bag, @@ -165,6 +166,7 @@ this._updateThread(); })); + this._renderedDrafts = {}; }, _updateThread: function() { @@ -252,6 +254,37 @@ this._didSendMessageCallback(r); })); this.syncWorkflow(workflow, 'finally'); + }, + + _storeRenderedDraft: function(r) { + this._renderedDrafts[r.threadID] = r.content; + }, + + getRenderedDraft: function () { + var threadID = this._loadedThreadID; + if (this._renderedDrafts[threadID]) { + return this._renderedDrafts[threadID]; + } + return null; + }, + + handleDraftKeydown: function(e) { + var form = e.getNode('tag:form'); + var data = e.getNodeData('tag:form'); + + if (!data.preview) { + var uri = '/conpherence/update/' + this._loadedThreadID + '/'; + data.preview = new JX.PhabricatorShapedRequest( + uri, + JX.bind(this, this._storeRenderedDraft), + JX.bind(this, function () { + var data = JX.DOM.convertFormToDictionary(form); + data.action = 'draft'; + data = this._getParams(data); + return data; + })); + } + data.preview.trigger(); } }, 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 @@ -96,18 +96,29 @@ scrollbar.scrollTo(messages.scrollHeight); }); threadManager.setWillSendMessageCallback(function() { - _markLoading(true); + var draft = threadManager.getRenderedDraft(); + var textarea = _getColumnTextareaNode(); + textarea.value = ''; + if (draft) { + var draftObj = JX.$N( + 'div', + { sigil: 'draft-message' }, + JX.$H(draft)); + var messages = _getColumnMessagesNode(); + JX.DOM.appendContent(messages, draftObj); + scrollbar.scrollTo(messages.scrollHeight); + } }); threadManager.setDidSendMessageCallback(function(r) { var messages = _getColumnMessagesNode(); + var draftObj = null; + try { + draftObj = JX.DOM.find(messages, 'div', 'draft-message'); + JX.DOM.remove(draftObj); + } catch (e) { + } JX.DOM.appendContent(messages, JX.$H(r.transactions)); scrollbar.scrollTo(messages.scrollHeight); - - var textarea = _getColumnTextareaNode(); - textarea.value = ''; - - _markLoading(false); - _focusColumnTextareaNode(); }); threadManager.setWillUpdateWorkflowCallback(function() { @@ -203,9 +214,9 @@ function _getColumnTextareaNode() { var column = JX.$('conpherence-durable-column'); return JX.DOM.find( - column, - 'textarea', - 'conpherence-durable-column-textarea'); + column, + 'textarea', + 'conpherence-durable-column-textarea'); } function _focusColumnTextareaNode() { @@ -221,7 +232,12 @@ function _sendMessage(e) { e.kill(); var form = _getColumnFormNode(); - threadManager.sendMessage(form, { minimal_display: true }); + threadManager.sendMessage( + form, + { + text: _getColumnTextareaNode().value, + minimal_display: true + }); } JX.Stratcom.listen( @@ -234,6 +250,13 @@ 'conpherence-message-form', _sendMessage); + JX.Stratcom.listen( + ['keydown'], + 'conpherence-durable-column-textarea', + function (e) { + threadManager.handleDraftKeydown(e); + }); + if (config.visible) { _toggleColumn(false); } 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 @@ -564,28 +564,11 @@ handleThreadScrollers ); - var onkeydownDraft = function (e) { - var form = e.getNode('tag:form'); - var data = e.getNodeData('tag:form'); - - if (!data.preview) { - var uri = config.baseURI + 'update/' + _thread.selected + '/'; - data.preview = new JX.PhabricatorShapedRequest( - uri, - JX.bag, - function () { - var data = JX.DOM.convertFormToDictionary(form); - data.action = 'draft'; - return data; - }); - } - - data.preview.trigger(); - }; - JX.Stratcom.listen( ['keydown'], 'conpherence-pontificate', - onkeydownDraft); + function (e) { + threadManager.handleDraftKeydown(e); + }); });