diff --git a/src/applications/differential/parser/DifferentialChangesetParser.php b/src/applications/differential/parser/DifferentialChangesetParser.php --- a/src/applications/differential/parser/DifferentialChangesetParser.php +++ b/src/applications/differential/parser/DifferentialChangesetParser.php @@ -1084,6 +1084,22 @@ $vs = $id; } + if ($mask_force) { + $engine_blocks->setRevealedIndexes(array_keys($mask_force)); + } + + if ($range_start !== null || $range_len !== null) { + $range_min = $range_start; + + if ($range_len === null) { + $range_max = null; + } else { + $range_max = (int)$range_start + (int)$range_len; + } + + $engine_blocks->setRange($range_min, $range_max); + } + $renderer ->setDocumentEngine($engine) ->setDocumentEngineBlocks($engine_blocks); diff --git a/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php b/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php --- a/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php +++ b/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php @@ -496,7 +496,12 @@ * @param int Total number of lines in the changeset. * @return markup Rendered links. */ - protected function renderShowContextLinks($top, $len, $changeset_length) { + protected function renderShowContextLinks( + $top, + $len, + $changeset_length, + $is_blocks = false) { + $block_size = 20; $end = ($top + $len) - $block_size; @@ -509,12 +514,22 @@ $links = array(); + $block_display = new PhutilNumber($block_size); + if ($is_large_block) { $is_first_block = ($top == 0); if ($is_first_block) { - $text = pht('Show First %d Line(s)', $block_size); + if ($is_blocks) { + $text = pht('Show First %s Block(s)', $block_display); + } else { + $text = pht('Show First %s Line(s)', $block_display); + } } else { - $text = pht("\xE2\x96\xB2 Show %d Line(s)", $block_size); + if ($is_blocks) { + $text = pht("\xE2\x96\xB2 Show %s Block(s)", $block_display); + } else { + $text = pht("\xE2\x96\xB2 Show %s Line(s)", $block_display); + } } $links[] = $this->renderShowContextLink( @@ -523,17 +538,31 @@ $text); } + if ($is_blocks) { + $text = pht('Show All %s Block(s)', new PhutilNumber($len)); + } else { + $text = pht('Show All %s Line(s)', new PhutilNumber($len)); + } + $links[] = $this->renderShowContextLink( true, "{$top}-{$len}/{$top}-{$len}", - pht('Show All %d Line(s)', $len)); + $text); if ($is_large_block) { $is_last_block = (($top + $len) >= $changeset_length); if ($is_last_block) { - $text = pht('Show Last %d Line(s)', $block_size); + if ($is_blocks) { + $text = pht('Show Last %s Block(s)', $block_display); + } else { + $text = pht('Show Last %s Line(s)', $block_display); + } } else { - $text = "\xE2\x96\xBC ".pht('Show %d Line(s)', $block_size); + if ($is_blocks) { + $text = pht("\xE2\x96\xBC Show %s Block(s)", $block_display); + } else { + $text = pht("\xE2\x96\xBC Show %s Line(s)", $block_display); + } } $links[] = $this->renderShowContextLink( diff --git a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php --- a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php +++ b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php @@ -381,22 +381,17 @@ $old_comments = $this->getOldComments(); $new_comments = $this->getNewComments(); - $gap_view = javelin_tag( - 'tr', - array( - 'sigil' => 'context-target', - ), - phutil_tag( - 'td', - array( - 'colspan' => 6, - 'class' => 'show-more', - ), - pht("\xE2\x80\xA2 \xE2\x80\xA2 \xE2\x80\xA2"))); - $rows = array(); + $gap = array(); $in_gap = false; - foreach ($block_list->newTwoUpLayout() as $row) { + + // NOTE: The generated layout is affected by range constraints, and may + // represent only a slice of the document. + + $layout = $block_list->newTwoUpLayout(); + $available_count = $block_list->getLayoutAvailableRowCount(); + + foreach ($layout as $idx => $row) { list($old, $new) = $row; if ($old) { @@ -416,13 +411,17 @@ if (!$is_visible) { if (!$in_gap) { $in_gap = true; - $rows[] = $gap_view; } + $gap[$idx] = $row; continue; } if ($in_gap) { $in_gap = false; + $rows[] = $this->renderDocumentEngineGap( + $gap, + $available_count); + $gap = array(); } if ($old) { @@ -577,6 +576,12 @@ ); } + if ($in_gap) { + $rows[] = $this->renderDocumentEngineGap( + $gap, + $available_count); + } + $output = $this->wrapChangeInTable($rows); return $this->renderChangesetTable($output); @@ -616,4 +621,25 @@ ); } + private function renderDocumentEngineGap(array $gap, $available_count) { + $content = $this->renderShowContextLinks( + head_key($gap), + count($gap), + $available_count, + $is_blocks = true); + + return javelin_tag( + 'tr', + array( + 'sigil' => 'context-target', + ), + phutil_tag( + 'td', + array( + 'colspan' => 6, + 'class' => 'show-more', + ), + $content)); + } + } diff --git a/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php b/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php --- a/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php +++ b/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php @@ -5,6 +5,29 @@ private $lists = array(); private $messages = array(); + private $rangeMin; + private $rangeMax; + private $revealedIndexes; + private $layoutAvailableRowCount; + + public function setRange($min, $max) { + $this->rangeMin = $min; + $this->rangeMax = $max; + return $this; + } + + public function setRevealedIndexes(array $indexes) { + $this->revealedIndexes = $indexes; + return $this; + } + + public function getLayoutAvailableRowCount() { + if ($this->layoutAvailableRowCount === null) { + throw new PhutilInvalidStateException('new...Layout'); + } + + return $this->layoutAvailableRowCount; + } public function addMessage($message) { $this->messages[] = $message; @@ -115,6 +138,11 @@ ); } + $this->layoutAvailableRowCount = count($rows); + + $rows = $this->revealIndexes($rows, true); + $rows = $this->sliceRows($rows); + return $rows; } @@ -147,6 +175,11 @@ $idx++; } + $this->layoutAvailableRowCount = count($rows); + + $rows = $this->revealIndexes($rows, false); + $rows = $this->sliceRows($rows); + return $rows; } @@ -172,4 +205,47 @@ ); } + private function sliceRows(array $rows) { + $min = $this->rangeMin; + $max = $this->rangeMax; + + if ($min === null && $max === null) { + return $rows; + } + + if ($max === null) { + return array_slice($rows, $min, null, true); + } + + if ($min === null) { + $min = 0; + } + + return array_slice($rows, $min, $max - $min, true); + } + + private function revealIndexes(array $rows, $is_vector) { + if ($this->revealedIndexes === null) { + return $rows; + } + + foreach ($this->revealedIndexes as $index) { + if (!isset($rows[$index])) { + continue; + } + + if ($is_vector) { + foreach ($rows[$index] as $block) { + if ($block !== null) { + $block->setIsVisible(true); + } + } + } else { + $rows[$index]->setIsVisible(true); + } + } + + return $rows; + } + } diff --git a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php --- a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php +++ b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php @@ -1069,29 +1069,54 @@ ), ), - 'Show First %d Line(s)' => array( + 'Show First %s Line(s)' => array( 'Show First Line', - 'Show First %d Lines', + 'Show First %s Lines', ), - "\xE2\x96\xB2 Show %d Line(s)" => array( + 'Show First %s Block(s)' => array( + 'Show First Block', + 'Show First %s Blocks', + ), + + "\xE2\x96\xB2 Show %s Line(s)" => array( "\xE2\x96\xB2 Show Line", - "\xE2\x96\xB2 Show %d Lines", + "\xE2\x96\xB2 Show %s Lines", ), - 'Show All %d Line(s)' => array( + "\xE2\x96\xB2 Show %s Block(s)" => array( + "\xE2\x96\xB2 Show Block", + "\xE2\x96\xB2 Show %s Blocks", + ), + + 'Show All %s Line(s)' => array( 'Show Line', - 'Show All %d Lines', + 'Show All %s Lines', + ), + + 'Show All %s Block(s)' => array( + 'Show Block', + 'Show All %s Blocks', ), - "\xE2\x96\xBC Show %d Line(s)" => array( + "\xE2\x96\xBC Show %s Line(s)" => array( "\xE2\x96\xBC Show Line", - "\xE2\x96\xBC Show %d Lines", + "\xE2\x96\xBC Show %s Lines", + ), + + "\xE2\x96\xBC Show %s Block(s)" => array( + "\xE2\x96\xBC Show Block", + "\xE2\x96\xBC Show %s Blocks", ), - 'Show Last %d Line(s)' => array( + 'Show Last %s Line(s)' => array( 'Show Last Line', - 'Show Last %d Lines', + 'Show Last %s Lines', + ), + + 'Show Last %s Block(s)' => array( + 'Show Last Block', + 'Show Last %s Blocks', ), '%s marked %s inline comment(s) as done and %s inline comment(s) as '.