diff --git a/src/applications/phriction/controller/PhrictionDiffController.php b/src/applications/phriction/controller/PhrictionDiffController.php index 5b1a81f940..8ae9618bbd 100644 --- a/src/applications/phriction/controller/PhrictionDiffController.php +++ b/src/applications/phriction/controller/PhrictionDiffController.php @@ -1,298 +1,257 @@ getViewer(); $id = $request->getURIData('id'); $document = id(new PhrictionDocumentQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needContent(true) ->executeOne(); if (!$document) { return new Aphront404Response(); } $current = $document->getContent(); $l = $request->getInt('l'); $r = $request->getInt('r'); $ref = $request->getStr('ref'); if ($ref) { list($l, $r) = explode(',', $ref); } $content = id(new PhrictionContent())->loadAllWhere( 'documentID = %d AND version IN (%Ld)', $document->getID(), array($l, $r)); $content = mpull($content, null, 'getVersion'); $content_l = idx($content, $l, null); $content_r = idx($content, $r, null); if (!$content_l || !$content_r) { return new Aphront404Response(); } $text_l = $content_l->getContent(); $text_r = $content_r->getContent(); - $text_l = phutil_utf8_hard_wrap($text_l, 80); - $text_l = implode("\n", $text_l); - $text_r = phutil_utf8_hard_wrap($text_r, 80); - $text_r = implode("\n", $text_r); + $diff_view = id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setOldText($text_l) + ->setNewText($text_r); - $engine = new PhabricatorDifferenceEngine(); - $changeset = $engine->generateChangesetFromFileContent($text_l, $text_r); - - $changeset->setFilename($content_r->getTitle()); - - $changeset->setOldProperties( - array( - 'Title' => $content_l->getTitle(), - )); - $changeset->setNewProperties( - array( - 'Title' => $content_r->getTitle(), - )); - - $whitespace_mode = DifferentialChangesetParser::WHITESPACE_SHOW_ALL; - - $parser = id(new DifferentialChangesetParser()) - ->setUser($viewer) - ->setChangeset($changeset) - ->setRenderingReference("{$l},{$r}"); - - $parser->readParametersFromRequest($request); - $parser->setWhitespaceMode($whitespace_mode); - - $engine = new PhabricatorMarkupEngine(); - $engine->setViewer($viewer); - $engine->process(); - $parser->setMarkupEngine($engine); - - $spec = $request->getStr('range'); - list($range_s, $range_e, $mask) = - DifferentialChangesetParser::parseRangeSpecification($spec); - - $parser->setRange($range_s, $range_e); - $parser->setMask($mask); - - if ($request->isAjax()) { - return id(new PhabricatorChangesetResponse()) - ->setRenderedChangeset($parser->renderChangeset()); - } - - $changes = id(new DifferentialChangesetListView()) - ->setUser($this->getViewer()) - ->setChangesets(array($changeset)) - ->setVisibleChangesets(array($changeset)) - ->setRenderingReferences(array("{$l},{$r}")) - ->setRenderURI('/phriction/diff/'.$document->getID().'/') - ->setTitle(pht('Changes')) + $changes = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Content Changes')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setParser($parser); + ->appendChild( + phutil_tag( + 'div', + array( + 'class' => 'prose-diff-frame', + ), + $diff_view)); require_celerity_resource('phriction-document-css'); $slug = $document->getSlug(); $revert_l = $this->renderRevertButton($content_l, $current); $revert_r = $this->renderRevertButton($content_r, $current); $crumbs = $this->buildApplicationCrumbs(); $crumb_views = $this->renderBreadcrumbs($slug); foreach ($crumb_views as $view) { $crumbs->addCrumb($view); } $crumbs->addTextCrumb( pht('History'), PhrictionDocument::getSlugURI($slug, 'history')); $title = pht('Version %s vs %s', $l, $r); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon('fa-history'); $crumbs->addTextCrumb($title, $request->getRequestURI()); $comparison_table = $this->renderComparisonTable( array( $content_r, $content_l, )); $navigation_table = null; if ($l + 1 == $r) { $nav_l = ($l > 1); $nav_r = ($r != $current->getVersion()); $uri = $request->getRequestURI(); if ($nav_l) { $link_l = phutil_tag( 'a', array( 'href' => $uri->alter('l', $l - 1)->alter('r', $r - 1), 'class' => 'button grey', ), pht("\xC2\xAB Previous Change")); } else { $link_l = phutil_tag( 'a', array( 'href' => '#', 'class' => 'button grey disabled', ), pht('Original Change')); } $link_r = null; if ($nav_r) { $link_r = phutil_tag( 'a', array( 'href' => $uri->alter('l', $l + 1)->alter('r', $r + 1), 'class' => 'button grey', ), pht("Next Change \xC2\xBB")); } else { $link_r = phutil_tag( 'a', array( 'href' => '#', 'class' => 'button grey disabled', ), pht('Most Recent Change')); } $navigation_table = phutil_tag( 'table', array('class' => 'phriction-history-nav-table'), phutil_tag('tr', array(), array( phutil_tag('td', array('class' => 'nav-prev'), $link_l), phutil_tag('td', array('class' => 'nav-next'), $link_r), ))); } $output = hsprintf( '
'. '%s%s'. ''. ''. '
%s%s
'. '
', $comparison_table->render(), $navigation_table, $revert_l, $revert_r); $object_box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Edits')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->appendChild($output); $crumbs->setBorder(true); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $object_box, $changes, )); return $this->newPage() ->setTitle(pht('Document History')) ->setCrumbs($crumbs) ->appendChild($view); } private function renderRevertButton( PhrictionContent $content, PhrictionContent $current) { $document_id = $content->getDocumentID(); $version = $content->getVersion(); $hidden_statuses = array( PhrictionChangeType::CHANGE_DELETE => true, // Silly PhrictionChangeType::CHANGE_MOVE_AWAY => true, // Plain silly PhrictionChangeType::CHANGE_STUB => true, // Utterly silly ); if (isset($hidden_statuses[$content->getChangeType()])) { // Don't show an edit/revert button for changes which deleted, moved or // stubbed the content since it's silly. return null; } if ($content->getID() == $current->getID()) { return phutil_tag( 'a', array( 'href' => '/phriction/edit/'.$document_id.'/', 'class' => 'button grey', ), pht('Edit Current Version')); } return phutil_tag( 'a', array( 'href' => '/phriction/edit/'.$document_id.'/?revert='.$version, 'class' => 'button grey', ), pht('Revert to Version %s...', $version)); } private function renderComparisonTable(array $content) { assert_instances_of($content, 'PhrictionContent'); $viewer = $this->getViewer(); $phids = mpull($content, 'getAuthorPHID'); $handles = $this->loadViewerHandles($phids); $list = new PHUIObjectItemListView(); $first = true; foreach ($content as $c) { $author = $handles[$c->getAuthorPHID()]->renderLink(); $item = id(new PHUIObjectItemView()) ->setHeader(pht('%s by %s, %s', PhrictionChangeType::getChangeTypeLabel($c->getChangeType()), $author, pht('Version %s', $c->getVersion()))) ->addAttribute(pht('%s %s', phabricator_date($c->getDateCreated(), $viewer), phabricator_time($c->getDateCreated(), $viewer))); if ($c->getDescription()) { $item->addAttribute($c->getDescription()); } if ($first == true) { $item->setStatusIcon('fa-file green'); $first = false; } else { $item->setStatusIcon('fa-file red'); } $list->addItem($item); } return $list; } } diff --git a/webroot/rsrc/css/application/differential/changeset-view.css b/webroot/rsrc/css/application/differential/changeset-view.css index 10b5e4962e..e6ee35e9b9 100644 --- a/webroot/rsrc/css/application/differential/changeset-view.css +++ b/webroot/rsrc/css/application/differential/changeset-view.css @@ -1,382 +1,390 @@ /** * @provides differential-changeset-view-css * @requires phui-inline-comment-view-css */ .differential-changeset { position: relative; margin: 0; padding-top: 16px; overflow-x: auto; /* Fixes what seems to be a layout bug in Firefox which causes scrollbars, to appear unpredictably, see discussion in T7690. */ overflow-y: hidden; } .device-phone .differential-changeset { overflow-x: scroll; -webkit-overflow-scrolling: touch; } .differential-diff { background: #fff; width: 100%; border-top: 1px solid {$lightblueborder}; border-bottom: 1px solid {$lightblueborder}; table-layout: fixed; } .differential-diff.diff-2up { min-width: 780px; } .differential-diff col.num { width: 45px; } .device .differential-diff.diff-1up col.num { width: 32px; } .differential-diff.diff-2up col.left, .differential-diff.diff-2up col.right { width: 49.25%; } .differential-diff.diff-1up col.unified { width: 99.5%; } .differential-diff col.copy { width: 0.5%; } .differential-diff col.cov { width: 1%; } .differential-diff td { vertical-align: top; white-space: pre-wrap; word-wrap: break-word; padding: 1px 8px; } .device .differential-diff td { padding: 1px 4px; } .device .differential-diff .inline td { padding: 4px; } .differential-diff td .zwsp { position: absolute; width: 0; } .differential-diff th { text-align: right; padding: 1px 6px 1px 0; vertical-align: top; background: {$lightbluebackground}; color: {$bluetext}; cursor: pointer; border-right: 1px solid {$thinblueborder}; overflow: hidden; -moz-user-select: -moz-none; -khtml-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; } +.prose-diff { + white-space: pre-wrap; +} + +.prose-diff-frame { + padding: 12px; +} + .prose-diff span.old, .prose-diff span.new { padding: 0 2px; } .prose-diff span.old { color: {$redtext}; } .prose-diff span.new { color: {$greentext}; } .differential-diff th.selected { background-color: {$sh-yellowbackground}; } .differential-changeset-immutable .differential-diff th { cursor: auto; } .differential-diff td.old { background: rgba(251, 175, 175, .3); } .differential-diff td.new { background: rgba(151, 234, 151, .3); } .differential-diff td.old-rebase { background: #ffeeee; } .differential-diff td.new-rebase { background: #eeffee; } .differential-diff td.old-full, .differential-diff td.old span.bright, .prose-diff span.old { background: rgba(251, 175, 175, .7); } .differential-diff td.new-full, .differential-diff td.new span.bright, .prose-diff span.new { background: rgba(151, 234, 151, .6); } .differential-diff td.copy { min-width: 0.5%; width: 0.5%; padding: 0; } .differential-diff td.new-copy, .differential-diff td.new-copy span.bright { background: {$lightyellow}; } .differential-diff td.new-move, .differential-diff td.new-move span.bright { background: {$yellow}; } .differential-diff td.comment { background: #dddddd; } .differential-diff td.cov { padding: 0; } .diffusion-source td.cov { padding: 0 8px; } td.cov-U { background: #dd8866; } td.cov-C { background: #66bbff; } td.cov-N { background: #ddeeff; } td.cov-X { background: #aa00aa; } td.cov-I { background: {$lightgreybackground}; } .differential-diff td.source-cov-C, .differential-diff td.source-cov-C span.bright { background: #cceeff; } .differential-diff td.source-cov-U, .differential-diff td.source-cov-U span.bright { background: #ffbb99; } .differential-diff td.source-cov-N, .differential-diff td.source-cov-N span.bright { background: #f3f6ff; } .differential-diff td.show-more, .differential-diff th.show-context-line, .differential-diff td.show-context, .differential-diff td.differential-shield { background: {$lightbluebackground}; padding: 12px 0; border-top: 1px solid {$thinblueborder}; border-bottom: 1px solid {$thinblueborder}; } .device .differential-diff td.show-more, .device .differential-diff th.show-context-line, .device .differential-diff td.show-context, .device .differential-diff td.differential-shield { padding: 6px 0; } .differential-diff td.show-more, .differential-diff td.differential-shield { font: {$basefont}; font-size: {$smallerfontsize}; white-space: normal; } .differential-diff td.show-more { text-align: center; color: {$bluetext}; } .differential-diff th.show-context-line { padding-right: 6px; } .differential-diff td.show-context { padding-left: 14px; } .differential-diff td.differential-shield { text-align: center; } .differential-diff td.differential-shield a { font-weight: bold; } .differential-diff .differential-image-diff { background-image: url(/rsrc/image/checker_light.png); } .differential-diff .differential-image-diff:hover { background-image: url(/rsrc/image/checker_dark.png); } .differential-diff .differential-image-diff td { padding: 8px; } .differential-image-stage { overflow: auto; } .differential-meta-notice { border-top: 1px solid {$sh-lightyellowborder}; border-bottom: 1px solid {$sh-lightyellowborder}; background-color: {$sh-yellowbackground}; padding: 12px; } .differential-meta-notice + .differential-diff { border-top: none; } .differential-changeset h1 { font-size: {$biggestfontsize}; padding: 2px 0 20px 12px; line-height: 20px; color: #000; } .device-phone .differential-changeset h1 { word-break: break-word; margin-right: 8px; } .differential-reticle { background-color: {$sh-yellowbackground}; border: 1px solid {$sh-yellowborder}; position: absolute; opacity: 0.5; top: 0; left: 0; box-sizing: border-box; } .differential-diff .inline td { padding: 8px 12px; } .differential-loading { border-top: 1px solid {$yellow}; border-bottom: 1px solid {$yellow}; background-color: {$lightyellow}; padding: 12px; text-align: center; } .differential-collapse-undo { color: {$darkbluetext}; padding: 12px; border: 1px solid {$blue}; text-align: center; background-color: {$lightblue}; } .differential-collapse-undo a { font-weight: bold; } .differential-file-icon-header .phui-icon-view { display: inline-block; margin: 0 6px 2px 0; vertical-align: middle; font-size: 14px; } .device-phone .differential-file-icon-header .phui-icon-view { display: none; } .differential-changeset-buttons { float: right; margin-right: 12px; } .device-phone .differential-changeset-buttons { float: none; margin: 0 0 8px 4px; } .differential-changeset-buttons a.button { margin-left: 8px; } .differential-property-table { margin: 12px; background: {$lightgreybackground}; border: 1px solid {$lightblueborder}; border-bottom: 1px solid {$blueborder}; } .differential-property-table td em { color: {$lightgreytext}; } .differential-property-table td.oval { background: #ffd0d0; width: 50%; } .differential-property-table td.nval { background: #d0ffd0; width: 50%; } tr.differential-inline-hidden { display: none; } tr.differential-inline-loading { opacity: 0.5; } .differential-review-stage { position: relative; }