@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.

Convert DifferentialRevision view to new PHUIDiffTableOfContentsListView

Summary:
Ref T2183. Introduces a new View which can (in theory) unify the Revision, Diff and Commit table of contents views.

This has the same behavior as before, but accepts slightly more general primitives and parameters and has somewhat cleaner code.

I've made one intentinoal behavior change: removing the "Open All in Editor" button. I suspect this is essentially unused, and is a pain to keep around. We can look at restoring it if anyone notices.

Test Plan: Looked at a bunch of revisions, no changes from before.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T2183

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

+412 -10
+4
src/__phutil_library_map__.php
··· 1362 1362 'PHUIDiffInlineCommentView' => 'infrastructure/diff/view/PHUIDiffInlineCommentView.php', 1363 1363 'PHUIDiffOneUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffOneUpInlineCommentRowScaffold.php', 1364 1364 'PHUIDiffRevealIconView' => 'infrastructure/diff/view/PHUIDiffRevealIconView.php', 1365 + 'PHUIDiffTableOfContentsItemView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php', 1366 + 'PHUIDiffTableOfContentsListView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsListView.php', 1365 1367 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffTwoUpInlineCommentRowScaffold.php', 1366 1368 'PHUIDocumentExample' => 'applications/uiexample/examples/PHUIDocumentExample.php', 1367 1369 'PHUIDocumentView' => 'view/phui/PHUIDocumentView.php', ··· 5157 5159 'PHUIDiffInlineCommentView' => 'AphrontView', 5158 5160 'PHUIDiffOneUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 5159 5161 'PHUIDiffRevealIconView' => 'AphrontView', 5162 + 'PHUIDiffTableOfContentsItemView' => 'AphrontView', 5163 + 'PHUIDiffTableOfContentsListView' => 'AphrontView', 5160 5164 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 5161 5165 'PHUIDocumentExample' => 'PhabricatorUIExample', 5162 5166 'PHUIDocumentView' => 'AphrontTagView',
+33 -10
src/applications/differential/controller/DifferentialRevisionViewController.php
··· 349 349 $other_view = $this->renderOtherRevisions($other_revisions); 350 350 } 351 351 352 - $toc_view = new DifferentialDiffTableOfContentsView(); 353 - $toc_view->setChangesets($changesets); 354 - $toc_view->setVisibleChangesets($visible_changesets); 355 - $toc_view->setRenderingReferences($rendering_references); 356 - $toc_view->setCoverageMap($target->loadCoverageMap($user)); 357 - if ($repository) { 358 - $toc_view->setRepository($repository); 359 - } 360 - $toc_view->setDiff($target); 361 - $toc_view->setUser($user); 352 + $toc_view = $this->buildTableOfContents( 353 + $changesets, 354 + $visible_changesets, 355 + $target->loadCoverageMap($user)); 362 356 363 357 $comment_form = null; 364 358 if (!$viewer_is_anonymous) { ··· 1040 1034 } 1041 1035 1042 1036 return $view; 1037 + } 1038 + 1039 + private function buildTableOfContents( 1040 + array $changesets, 1041 + array $visible_changesets, 1042 + array $coverage) { 1043 + $viewer = $this->getViewer(); 1044 + 1045 + $toc_view = id(new PHUIDiffTableOfContentsListView()) 1046 + ->setUser($viewer); 1047 + 1048 + foreach ($changesets as $changeset_id => $changeset) { 1049 + $is_visible = isset($visible_changesets[$changeset_id]); 1050 + $anchor = $changeset->getAnchorName(); 1051 + 1052 + $filename = $changeset->getFilename(); 1053 + $coverage_id = 'differential-mcoverage-'.md5($filename); 1054 + 1055 + $item = id(new PHUIDiffTableOfContentsItemView()) 1056 + ->setChangeset($changeset) 1057 + ->setIsVisible($is_visible) 1058 + ->setAnchor($anchor) 1059 + ->setCoverage(idx($coverage, $filename)) 1060 + ->setCoverageID($coverage_id); 1061 + 1062 + $toc_view->addItem($item); 1063 + } 1064 + 1065 + return $toc_view; 1043 1066 } 1044 1067 1045 1068
+295
src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php
··· 1 + <?php 2 + 3 + final class PHUIDiffTableOfContentsItemView extends AphrontView { 4 + 5 + private $changeset; 6 + private $isVisible; 7 + private $anchor; 8 + private $coverage; 9 + private $coverageID; 10 + 11 + public function setChangeset(DifferentialChangeset $changeset) { 12 + $this->changeset = $changeset; 13 + return $this; 14 + } 15 + 16 + public function getChangeset() { 17 + return $this->changeset; 18 + } 19 + 20 + public function setIsVisible($is_visible) { 21 + $this->isVisible = $is_visible; 22 + return $this; 23 + } 24 + 25 + public function getIsVisible() { 26 + return $this->isVisible; 27 + } 28 + 29 + public function setAnchor($anchor) { 30 + $this->anchor = $anchor; 31 + return $this; 32 + } 33 + 34 + public function getAnchor() { 35 + return $this->anchor; 36 + } 37 + 38 + public function setCoverage($coverage) { 39 + $this->coverage = $coverage; 40 + return $this; 41 + } 42 + 43 + public function getCoverage() { 44 + return $this->coverage; 45 + } 46 + 47 + public function setCoverageID($coverage_id) { 48 + $this->coverageID = $coverage_id; 49 + return $this; 50 + } 51 + 52 + public function getCoverageID() { 53 + return $this->coverageID; 54 + } 55 + 56 + public function render() { 57 + $changeset = $this->getChangeset(); 58 + 59 + $cells = array(); 60 + 61 + $cells[] = $this->renderPathChangeCharacter(); 62 + $cells[] = $this->renderPropertyChangeCharacter(); 63 + $cells[] = $this->renderPropertyChangeDescription(); 64 + 65 + $link = $this->renderChangesetLink(); 66 + $lines = $this->renderChangesetLines(); 67 + $meta = $this->renderChangesetMetadata(); 68 + 69 + $cells[] = array( 70 + $link, 71 + $lines, 72 + $meta, 73 + ); 74 + 75 + $cells[] = $this->renderCoverage(); 76 + $cells[] = $this->renderModifiedCoverage(); 77 + 78 + return $cells; 79 + } 80 + 81 + private function renderPathChangeCharacter() { 82 + $changeset = $this->getChangeset(); 83 + $type = $changeset->getChangeType(); 84 + 85 + $color = DifferentialChangeType::getSummaryColorForChangeType($type); 86 + $char = DifferentialChangeType::getSummaryCharacterForChangeType($type); 87 + $title = DifferentialChangeType::getFullNameForChangeType($type); 88 + 89 + return javelin_tag( 90 + 'span', 91 + array( 92 + 'sigil' => 'has-tip', 93 + 'meta' => array( 94 + 'tip' => $title, 95 + 'align' => 'E', 96 + ), 97 + 'class' => 'phui-text-'.$color, 98 + ), 99 + $char); 100 + } 101 + 102 + private function renderPropertyChangeCharacter() { 103 + $changeset = $this->getChangeset(); 104 + 105 + $old = $changeset->getOldProperties(); 106 + $new = $changeset->getNewProperties(); 107 + 108 + if ($old === $new) { 109 + return null; 110 + } 111 + 112 + return javelin_tag( 113 + 'span', 114 + array( 115 + 'sigil' => 'has-tip', 116 + 'meta' => array( 117 + 'tip' => pht('Properties Modified'), 118 + 'align' => 'E', 119 + ), 120 + ), 121 + 'M'); 122 + } 123 + 124 + private function renderPropertyChangeDescription() { 125 + $changeset = $this->getChangeset(); 126 + 127 + $file_type = $changeset->getFileType(); 128 + 129 + $desc = DifferentialChangeType::getShortNameForFileType($file_type); 130 + if ($desc === null) { 131 + return null; 132 + } 133 + 134 + return pht('(%s)', $desc); 135 + } 136 + 137 + private function renderChangesetLink() { 138 + $anchor = $this->getAnchor(); 139 + 140 + $changeset = $this->getChangeset(); 141 + $name = $changeset->getDisplayFilename(); 142 + 143 + $change_type = $changeset->getChangeType(); 144 + if (DifferentialChangeType::isOldLocationChangeType($change_type)) { 145 + $away = $changeset->getAwayPaths(); 146 + if (count($away) == 1) { 147 + if ($change_type == DifferentialChangeType::TYPE_MOVE_AWAY) { 148 + $right_arrow = "\xE2\x86\x92"; 149 + $name = $this->renderRename($name, head($away), $right_arrow); 150 + } 151 + } 152 + } else if ($change_type == DifferentialChangeType::TYPE_MOVE_HERE) { 153 + $left_arrow = "\xE2\x86\x90"; 154 + $name = $this->renderRename($name, $changeset->getOldFile(), $left_arrow); 155 + } 156 + 157 + return javelin_tag( 158 + 'a', 159 + array( 160 + 'href' => '#'.$anchor, 161 + 'sigil' => 'differential-load', 162 + 'meta' => array( 163 + 'id' => 'diff-'.$anchor, 164 + ), 165 + ), 166 + $name); 167 + } 168 + 169 + private function renderChangesetLines() { 170 + $changeset = $this->getChangeset(); 171 + 172 + $line_count = $changeset->getAffectedLineCount(); 173 + if (!$line_count) { 174 + return null; 175 + } 176 + 177 + return ' '.pht('(%d line(s))', $line_count); 178 + } 179 + 180 + private function renderCoverage() { 181 + $not_applicable = '-'; 182 + 183 + $coverage = $this->getCoverage(); 184 + if (!strlen($coverage)) { 185 + return $not_applicable; 186 + } 187 + 188 + $covered = substr_count($coverage, 'C'); 189 + $not_covered = substr_count($coverage, 'U'); 190 + 191 + if (!$not_covered && !$covered) { 192 + return $not_applicable; 193 + } 194 + 195 + return sprintf('%d%%', 100 * ($covered / ($covered + $not_covered))); 196 + } 197 + 198 + private function renderModifiedCoverage() { 199 + $not_applicable = '-'; 200 + 201 + $coverage = $this->getCoverage(); 202 + if (!strlen($coverage)) { 203 + return $not_applicable; 204 + } 205 + 206 + if ($this->getIsVisible()) { 207 + $label = pht('Loading...'); 208 + } else { 209 + $label = pht('?'); 210 + } 211 + 212 + return phutil_tag( 213 + 'div', 214 + array( 215 + 'id' => $this->getCoverageID(), 216 + 'class' => 'differential-mcoverage-loading', 217 + ), 218 + $label); 219 + } 220 + 221 + private function renderChangesetMetadata() { 222 + $changeset = $this->getChangeset(); 223 + $type = $changeset->getChangeType(); 224 + 225 + $meta = array(); 226 + if (DifferentialChangeType::isOldLocationChangeType($type)) { 227 + $away = $changeset->getAwayPaths(); 228 + if (count($away) > 1) { 229 + if ($type == DifferentialChangeType::TYPE_MULTICOPY) { 230 + $meta[] = pht('Deleted after being copied to multiple locations:'); 231 + } else { 232 + $meta[] = pht('Copied to multiple locations:'); 233 + } 234 + foreach ($away as $path) { 235 + $meta[] = $path; 236 + } 237 + } else { 238 + if ($type == DifferentialChangeType::TYPE_MOVE_AWAY) { 239 + // This case is handled when we render the path. 240 + } else { 241 + $meta[] = pht('Copied to %s', head($away)); 242 + } 243 + } 244 + } else if ($type == DifferentialChangeType::TYPE_COPY_HERE) { 245 + $meta = pht('Copied from %s', $changeset->getOldFile()); 246 + } 247 + 248 + if (!$meta) { 249 + return null; 250 + } 251 + 252 + $meta = phutil_implode_html(phutil_tag('br'), $meta); 253 + 254 + return phutil_tag( 255 + 'div', 256 + array( 257 + 'class' => 'differential-toc-meta', 258 + ), 259 + $meta); 260 + } 261 + 262 + private function renderRename($self, $other, $arrow) { 263 + $old = explode('/', $self); 264 + $new = explode('/', $other); 265 + 266 + $start = count($old); 267 + foreach ($old as $index => $part) { 268 + if (!isset($new[$index]) || $part != $new[$index]) { 269 + $start = $index; 270 + break; 271 + } 272 + } 273 + 274 + $end = count($old); 275 + foreach (array_reverse($old) as $from_end => $part) { 276 + $index = count($new) - $from_end - 1; 277 + if (!isset($new[$index]) || $part != $new[$index]) { 278 + $end = $from_end; 279 + break; 280 + } 281 + } 282 + 283 + $rename = 284 + '{'. 285 + implode('/', array_slice($old, $start, count($old) - $end - $start)). 286 + ' '.$arrow.' '. 287 + implode('/', array_slice($new, $start, count($new) - $end - $start)). 288 + '}'; 289 + 290 + array_splice($new, $start, count($new) - $end - $start, $rename); 291 + 292 + return implode('/', $new); 293 + } 294 + 295 + }
+80
src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php
··· 1 + <?php 2 + 3 + final class PHUIDiffTableOfContentsListView extends AphrontView { 4 + 5 + private $items = array(); 6 + 7 + public function addItem(PHUIDiffTableOfContentsItemView $item) { 8 + $this->items[] = $item; 9 + return $this; 10 + } 11 + 12 + public function render() { 13 + $this->requireResource('differential-core-view-css'); 14 + $this->requireResource('differential-table-of-contents-css'); 15 + $this->requireResource('phui-text-css'); 16 + 17 + $items = $this->items; 18 + 19 + $rows = array(); 20 + foreach ($items as $item) { 21 + $rows[] = $item->render(); 22 + } 23 + 24 + $reveal_link = javelin_tag( 25 + 'a', 26 + array( 27 + 'sigil' => 'differential-reveal-all', 28 + 'mustcapture' => true, 29 + 'class' => 'button differential-toc-reveal-all', 30 + ), 31 + pht('Show All Context')); 32 + 33 + $buttons = phutil_tag( 34 + 'div', 35 + array( 36 + 'class' => 'differential-toc-buttons grouped', 37 + ), 38 + $reveal_link); 39 + 40 + $table = id(new AphrontTableView($rows)) 41 + ->setHeaders( 42 + array( 43 + '', 44 + '', 45 + '', 46 + pht('Path'), 47 + pht('Coverage (All)'), 48 + pht('Coverage (Touched)'), 49 + )) 50 + ->setColumnClasses( 51 + array( 52 + 'differential-toc-char center', 53 + 'differential-toc-prop center', 54 + 'differential-toc-ftype center', 55 + 'differential-toc-file wide', 56 + 'differential-toc-cov', 57 + 'differential-toc-cov', 58 + )) 59 + ->setDeviceVisibility( 60 + array( 61 + true, 62 + true, 63 + true, 64 + true, 65 + false, 66 + false, 67 + )); 68 + 69 + $anchor = id(new PhabricatorAnchorView()) 70 + ->setAnchorName('toc') 71 + ->setNavigationMarker(true); 72 + 73 + return id(new PHUIObjectBoxView()) 74 + ->setHeaderText(pht('Table of Contents')) 75 + ->setTable($table) 76 + ->appendChild($anchor) 77 + ->appendChild($buttons); 78 + } 79 + 80 + }