1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-11 17:32:41 +01:00
phorge-phorge/src/applications/differential/view/changesetdetailview/DifferentialChangesetDetailView.php
epriestley bf3dd8663c Add "buoyant" headers to Differential
Summary:
As you scroll through a diff, add a fixed-position header to the top of the
document to provide context. This is particularly useful with keyboard
navigation.

The technical implementation is that we seed the document with invisible
markers. When the user scrolls past one, we show a header with that text until
they scroll past another.

Test Plan:
Scrolled through a revision, was presented with context.

https://secure.phabricator.com/file/data/5xhh2jmoon6ukr5qjkh3/PHID-FILE-463ituscyhyw7utnox7m/Screen_Shot_2012-02-22_at_2.48.19_PM.png

Reviewers: btrahan

Reviewed By: btrahan

CC: aran, epriestley

Maniphest Tasks: T696

Differential Revision: https://secure.phabricator.com/D1673
2012-02-23 12:26:14 -08:00

151 lines
3.7 KiB
PHP

<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class DifferentialChangesetDetailView extends AphrontView {
private $changeset;
private $buttons = array();
private $revisionID;
private $symbolIndex;
private $id;
private $vsChangesetID;
public function setChangeset($changeset) {
$this->changeset = $changeset;
return $this;
}
public function addButton($button) {
$this->buttons[] = $button;
return $this;
}
public function setRevisionID($revision_id) {
$this->revisionID = $revision_id;
return $this;
}
public function setSymbolIndex($symbol_index) {
$this->symbolIndex = $symbol_index;
return $this;
}
public function getID() {
if (!$this->id) {
$this->id = celerity_generate_unique_node_id();
}
return $this->id;
}
public function setVsChangesetID($vs_changeset_id) {
$this->vsChangesetID = $vs_changeset_id;
return $this;
}
public function getVsChangesetID() {
return $this->vsChangesetID;
}
public function render() {
require_celerity_resource('differential-changeset-view-css');
require_celerity_resource('syntax-highlighting-css');
if ($this->revisionID) {
$edit = true;
} else {
$edit = false;
}
$changeset = $this->changeset;
$class = 'differential-changeset';
if (!$edit) {
$class .= ' differential-changeset-immutable';
}
$buttons = null;
if ($this->buttons) {
$buttons =
'<div class="differential-changeset-buttons">'.
implode('', $this->buttons).
'</div>';
}
$id = $this->getID();
if ($this->symbolIndex) {
Javelin::initBehavior(
'repository-crossreference',
array(
'container' => $id,
) + $this->symbolIndex);
}
$display_filename = $changeset->getDisplayFilename();
$buoyant_begin = $this->renderBuoyant($display_filename);
$buoyant_end = $this->renderBuoyant(null);
$output = javelin_render_tag(
'div',
array(
'sigil' => 'differential-changeset',
'meta' => array(
'left' => nonempty(
$this->getVsChangesetID(),
$this->changeset->getID()),
'right' => $this->changeset->getID(),
),
'class' => $class,
'id' => $id,
),
$buoyant_begin.
phutil_render_tag(
'a',
array(
'name' => $changeset->getAnchorName(),
),
'').
$buttons.
'<h1>'.phutil_escape_html($display_filename).'</h1>'.
'<div style="clear: both;"></div>'.
$this->renderChildren().
$buoyant_end);
return $output;
}
private function renderBuoyant($text) {
return javelin_render_tag(
'div',
array(
'sigil' => 'buoyant',
'meta' => array(
'text' => $text,
),
'style' => ($text === null)
// Current CSS spacing rules cause the "end" anchor to appear too
// late in the display document. Shift it up a bit so we drop the
// buoyant header sooner. This reduces confusion when using keystroke
// navigation.
? 'bottom: 60px; position: absolute;'
: null,
),
'');
}
}