@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add a quote action to Differential and Maniphest

Summary:
Ref T4119. This is ugly for now, but technically works.

The comment area and transaction log don't realy know about each other, so for the moment the linking is a bit manual. Differential/Maniphest are special cases anyway.

Test Plan: {F149992}

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T4119

Differential Revision: https://secure.phabricator.com/D8957

+187 -2
+2
src/__phutil_library_map__.php
··· 1164 1164 'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php', 1165 1165 'PhabricatorApplicationTransactionCommentHistoryController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php', 1166 1166 'PhabricatorApplicationTransactionCommentQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php', 1167 + 'PhabricatorApplicationTransactionCommentQuoteController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentQuoteController.php', 1167 1168 'PhabricatorApplicationTransactionCommentRemoveController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentRemoveController.php', 1168 1169 'PhabricatorApplicationTransactionCommentView' => 'applications/transactions/view/PhabricatorApplicationTransactionCommentView.php', 1169 1170 'PhabricatorApplicationTransactionController' => 'applications/transactions/controller/PhabricatorApplicationTransactionController.php', ··· 3936 3937 'PhabricatorApplicationTransactionCommentEditor' => 'PhabricatorEditor', 3937 3938 'PhabricatorApplicationTransactionCommentHistoryController' => 'PhabricatorApplicationTransactionController', 3938 3939 'PhabricatorApplicationTransactionCommentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 3940 + 'PhabricatorApplicationTransactionCommentQuoteController' => 'PhabricatorApplicationTransactionController', 3939 3941 'PhabricatorApplicationTransactionCommentRemoveController' => 'PhabricatorApplicationTransactionController', 3940 3942 'PhabricatorApplicationTransactionCommentView' => 'AphrontView', 3941 3943 'PhabricatorApplicationTransactionController' => 'PhabricatorController',
+6 -2
src/applications/differential/controller/DifferentialRevisionViewController.php
··· 256 256 $target, 257 257 $all_changesets); 258 258 259 + if (!$viewer_is_anonymous) { 260 + $comment_view->setQuoteRef('D'.$revision->getID()); 261 + $comment_view->setQuoteTargetID('comment-content'); 262 + } 263 + 259 264 $wrap_id = celerity_generate_unique_node_id(); 260 265 $comment_view = phutil_tag( 261 266 'div', ··· 373 378 $comment_form->setErrorView($review_warnings_panel); 374 379 } 375 380 376 - // TODO: Restore the ability for fields to add accept warnings. 377 - 378 381 $comment_form->setActions($this->getRevisionCommentActions($revision)); 379 382 $action_uri = $this->getApplicationURI( 380 383 'comment/save/'.$revision->getID().'/'); ··· 415 418 $changeset_view, 416 419 )); 417 420 if ($comment_form) { 421 + 418 422 $page_pane->appendChild($comment_form); 419 423 } else { 420 424 // TODO: For now, just use this to get "Login to Comment".
+2
src/applications/maniphest/controller/ManiphestTaskDetailController.php
··· 377 377 ->setFlush(true) 378 378 ->setHeaderText($comment_header) 379 379 ->appendChild($comment_form); 380 + $timeline->setQuoteTargetID('transaction-comments'); 381 + $timeline->setQuoteRef($object_name); 380 382 } 381 383 382 384 $object_box = id(new PHUIObjectBoxView())
+2
src/applications/transactions/application/PhabricatorApplicationTransactions.php
··· 19 19 => 'PhabricatorApplicationTransactionCommentRemoveController', 20 20 'history/(?<phid>[^/]+)/' 21 21 => 'PhabricatorApplicationTransactionCommentHistoryController', 22 + 'quote/(?<phid>[^/]+)/' 23 + => 'PhabricatorApplicationTransactionCommentQuoteController', 22 24 'detail/(?<phid>[^/]+)/' 23 25 => 'PhabricatorApplicationTransactionDetailController', 24 26 '(?P<value>old|new)/(?<phid>[^/]+)/'
+67
src/applications/transactions/controller/PhabricatorApplicationTransactionCommentQuoteController.php
··· 1 + <?php 2 + 3 + final class PhabricatorApplicationTransactionCommentQuoteController 4 + extends PhabricatorApplicationTransactionController { 5 + 6 + private $phid; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->phid = $data['phid']; 10 + } 11 + 12 + public function processRequest() { 13 + $request = $this->getRequest(); 14 + $viewer = $request->getUser(); 15 + 16 + $xaction = id(new PhabricatorObjectQuery()) 17 + ->withPHIDs(array($this->phid)) 18 + ->setViewer($viewer) 19 + ->executeOne(); 20 + if (!$xaction) { 21 + return new Aphront404Response(); 22 + } 23 + 24 + if (!$xaction->getComment()) { 25 + return new Aphront404Response(); 26 + } 27 + 28 + if ($xaction->getComment()->getIsRemoved()) { 29 + return new Aphront400Response(); 30 + } 31 + 32 + if (!$xaction->hasComment()) { 33 + return new Aphront404Response(); 34 + } 35 + 36 + $content = $xaction->getComment()->getContent(); 37 + $content = phutil_split_lines($content, true); 38 + foreach ($content as $key => $line) { 39 + if (strlen($line) && ($line[0] != '>')) { 40 + $content[$key] = '> '.$line; 41 + } else { 42 + $content[$key] = '>'.$line; 43 + } 44 + } 45 + $content = implode('', $content); 46 + 47 + $author = id(new PhabricatorHandleQuery()) 48 + ->setViewer($viewer) 49 + ->withPHIDs(array($xaction->getComment()->getAuthorPHID())) 50 + ->executeOne(); 51 + 52 + $ref = $request->getStr('ref'); 53 + if (strlen($ref)) { 54 + $quote = pht('In %s, %s wrote:', $ref, '@'.$author->getName()); 55 + } else { 56 + $quote = pht('%s wrote:', '@'.$author->getName()); 57 + } 58 + 59 + $content = ">>! {$quote}\n{$content}"; 60 + 61 + return id(new AphrontAjaxResponse())->setContent( 62 + array( 63 + 'quoteText' => $content, 64 + )); 65 + } 66 + 67 + }
+31
src/applications/transactions/view/PhabricatorApplicationTransactionView.php
··· 12 12 private $isPreview; 13 13 private $objectPHID; 14 14 private $shouldTerminate = false; 15 + private $quoteTargetID; 16 + private $quoteRef; 17 + 18 + public function setQuoteRef($quote_ref) { 19 + $this->quoteRef = $quote_ref; 20 + return $this; 21 + } 22 + 23 + public function getQuoteRef() { 24 + return $this->quoteRef; 25 + } 26 + 27 + public function setQuoteTargetID($quote_target_id) { 28 + $this->quoteTargetID = $quote_target_id; 29 + return $this; 30 + } 31 + 32 + public function getQuoteTargetID() { 33 + return $this->quoteTargetID; 34 + } 15 35 16 36 public function setObjectPHID($object_phid) { 17 37 $this->objectPHID = $object_phid; ··· 374 394 if ($this->getShowEditActions() && !$this->isPreview) { 375 395 if ($xaction->getCommentVersion() > 1 && !$has_removed_comment) { 376 396 $event->setIsEdited(true); 397 + } 398 + 399 + // If we have a place for quoted text to go and this is a quotable 400 + // comment, pass the quote target ID to the event view. 401 + if ($this->getQuoteTargetID()) { 402 + if ($xaction->hasComment()) { 403 + if (!$has_removed_comment && !$has_deleted_comment) { 404 + $event->setQuoteTargetID($this->getQuoteTargetID()); 405 + $event->setQuoteRef($this->getQuoteRef()); 406 + } 407 + } 377 408 } 378 409 379 410 $can_edit = PhabricatorPolicyCapability::CAN_EDIT;
+45
src/view/phui/PHUITimelineEventView.php
··· 21 21 private $hideByDefault; 22 22 private $token; 23 23 private $tokenRemoved; 24 + private $quoteTargetID; 25 + private $quoteRef; 26 + 27 + public function setQuoteRef($quote_ref) { 28 + $this->quoteRef = $quote_ref; 29 + return $this; 30 + } 31 + 32 + public function getQuoteRef() { 33 + return $this->quoteRef; 34 + } 35 + 36 + public function setQuoteTargetID($quote_target_id) { 37 + $this->quoteTargetID = $quote_target_id; 38 + return $this; 39 + } 40 + 41 + public function getQuoteTargetID() { 42 + return $this->quoteTargetID; 43 + } 24 44 25 45 public function setHideByDefault($hide_by_default) { 26 46 $this->hideByDefault = $hide_by_default; ··· 356 376 $extra[] = pht('PREVIEW'); 357 377 } else { 358 378 $xaction_phid = $this->getTransactionPHID(); 379 + 380 + if ($this->getQuoteTargetID()) { 381 + 382 + $ref = null; 383 + if ($this->getQuoteRef()) { 384 + $ref = $this->getQuoteRef(); 385 + if ($this->anchor) { 386 + $ref = $ref.'#'.$this->anchor; 387 + } 388 + } 389 + 390 + $extra[] = javelin_tag( 391 + 'a', 392 + array( 393 + 'href' => '#', 394 + 'sigil' => 'transaction-quote', 395 + 'mustcapture' => true, 396 + 'meta' => array( 397 + 'targetID' => $this->getQuoteTargetID(), 398 + 'uri' => '/transactions/quote/'.$xaction_phid.'/', 399 + 'ref' => $ref, 400 + ), 401 + ), 402 + pht('Quote')); 403 + } 359 404 360 405 if ($this->getIsEdited()) { 361 406 $extra[] = javelin_tag(
+32
webroot/rsrc/js/application/transactions/behavior-transaction-list.js
··· 6 6 * javelin-dom 7 7 * javelin-fx 8 8 * javelin-util 9 + * phabricator-textareautils 9 10 */ 10 11 11 12 JX.behavior('phabricator-transaction-list', function(config) { ··· 113 114 .start(); 114 115 115 116 e.kill(); 117 + }); 118 + 119 + JX.DOM.listen( 120 + list, 121 + 'click', 122 + 'transaction-quote', 123 + function(e) { 124 + e.kill(); 125 + 126 + var data = e.getNodeData('transaction-quote'); 127 + new JX.Workflow(data.uri) 128 + .setData({ref: data.ref}) 129 + .setHandler(function(r) { 130 + var textarea = JX.$(data.targetID); 131 + 132 + JX.DOM.scrollTo(textarea); 133 + 134 + var value = textarea.value; 135 + if (value.length) { 136 + value += "\n\n"; 137 + } 138 + value += r.quoteText; 139 + value += "\n\n"; 140 + textarea.value = value; 141 + 142 + JX.TextAreaUtils.setSelectionRange( 143 + textarea, 144 + textarea.value.length, 145 + textarea.value.length); 146 + }) 147 + .start(); 116 148 }); 117 149 118 150 JX.Stratcom.listen(