Page MenuHomeWMGMC Issues

No OneTemporary

diff --git a/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php b/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php
index 604004ac5a..930abcaa83 100644
--- a/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php
+++ b/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php
@@ -1,250 +1,264 @@
<?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.
*/
final class DifferentialInlineCommentView extends AphrontView {
private $inlineComment;
private $onRight;
private $buildScaffolding;
private $handles;
private $markupEngine;
private $editable;
private $preview;
public function setInlineComment(PhabricatorInlineCommentInterface $comment) {
$this->inlineComment = $comment;
return $this;
}
public function setOnRight($on_right) {
$this->onRight = $on_right;
return $this;
}
public function setBuildScaffolding($scaffold) {
$this->buildScaffolding = $scaffold;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function setMarkupEngine(PhutilMarkupEngine $engine) {
$this->markupEngine = $engine;
return $this;
}
public function setEditable($editable) {
$this->editable = $editable;
return $this;
}
public function setPreview($preview) {
$this->preview = $preview;
}
public function render() {
$inline = $this->inlineComment;
$start = $inline->getLineNumber();
$length = $inline->getLineLength();
if ($length) {
$end = $start + $length;
$line = 'Lines '.number_format($start).'-'.number_format($end);
} else {
$line = 'Line '.number_format($start);
}
$metadata = array(
'id' => $inline->getID(),
'number' => $inline->getLineNumber(),
'length' => $inline->getLineLength(),
'on_right' => $this->onRight,
'original' => $inline->getContent(),
);
$sigil = 'differential-inline-comment';
$content = $inline->getContent();
$handles = $this->handles;
$links = array();
$is_synthetic = false;
if ($inline->getSyntheticAuthor()) {
$is_synthetic = true;
}
$is_draft = false;
if ($inline->isDraft() && !$is_synthetic) {
$links[] = 'Not Submitted Yet';
$is_draft = true;
}
if (!$this->preview) {
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-prev',
),
'Previous');
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-next',
),
'Next');
if (!$is_synthetic) {
// NOTE: No product reason why you can't reply to these, but the reply
// mechanism currently sends the inline comment ID to the server, not
// file/line information, and synthetic comments don't have an inline
// comment ID.
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-reply',
),
'Reply');
}
}
+ $anchor_name = 'inline-'.$inline->getID();
+
if ($this->editable && !$this->preview) {
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-edit',
),
'Edit');
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-delete',
),
'Delete');
+ } else if ($this->preview) {
+ $links[] = javelin_render_tag(
+ 'a',
+ array(
+ 'meta' => array(
+ 'anchor' => $anchor_name,
+ ),
+ 'sigil' => 'differential-inline-preview-jump',
+ ),
+ 'Not Visible');
}
if ($links) {
$links =
'<span class="differential-inline-comment-links">'.
implode(' &middot; ', $links).
'</span>';
} else {
$links = null;
}
$cache = $inline->getCache();
if (strlen($cache)) {
$content = $cache;
} else {
$content = $this->markupEngine->markupText($content);
if ($inline->getID()) {
$inline->setCache($content);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$inline->save();
unset($unguarded);
}
}
- $anchor_name = 'inline-'.$inline->getID();
-
- $anchor = phutil_render_tag(
- 'a',
- array(
- 'name' => $anchor_name,
- 'id' => $anchor_name,
- 'class' => 'differential-inline-comment-anchor',
- ),
- '');
+ if ($this->preview) {
+ $anchor = null;
+ } else {
+ $anchor = phutil_render_tag(
+ 'a',
+ array(
+ 'name' => $anchor_name,
+ 'id' => $anchor_name,
+ 'class' => 'differential-inline-comment-anchor',
+ ),
+ '');
+ }
$classes = array(
'differential-inline-comment',
);
if ($is_draft) {
$classes[] = 'differential-inline-comment-unsaved-draft';
}
if ($is_synthetic) {
$classes[] = 'differential-inline-comment-synthetic';
}
$classes = implode(' ', $classes);
if ($is_synthetic) {
$author = $inline->getSyntheticAuthor();
} else {
$author = $handles[$inline->getAuthorPHID()]->getName();
}
$markup = javelin_render_tag(
'div',
array(
'class' => $classes,
'sigil' => $sigil,
'meta' => $metadata,
),
'<div class="differential-inline-comment-head">'.
$anchor.
$links.
' <span class="differential-inline-comment-line">'.$line.'</span> '.
phutil_escape_html($author).
'</div>'.
'<div class="differential-inline-comment-content">'.
'<div class="phabricator-remarkup">'.
$content.
'</div>'.
'</div>');
return $this->scaffoldMarkup($markup);
}
private function scaffoldMarkup($markup) {
if (!$this->buildScaffolding) {
return $markup;
}
$left_markup = !$this->onRight ? $markup : '';
$right_markup = $this->onRight ? $markup : '';
return
'<table>'.
'<tr class="inline">'.
'<th></th>'.
'<td>'.$left_markup.'</td>'.
'<th></th>'.
'<td>'.$right_markup.'</td>'.
'</tr>'.
'</table>';
}
}
diff --git a/webroot/rsrc/css/application/differential/revision-comment.css b/webroot/rsrc/css/application/differential/revision-comment.css
index 99f802df03..6fb291101b 100644
--- a/webroot/rsrc/css/application/differential/revision-comment.css
+++ b/webroot/rsrc/css/application/differential/revision-comment.css
@@ -1,95 +1,106 @@
/**
* @provides differential-revision-comment-css
*/
.differential-comment-list {
max-width: 1162px;
}
.differential-add-comment-panel {
max-width: 1162px;
}
-/* Spooky haunted panel which floats on the bottom of the screen. */
-.differential-haunted-panel .differential-add-comment-panel {
+/* Spooky haunted panel which floats on the bottom of the screen.
+ Haunt modes are:
+
+ - Mode 1: Just the comment box.
+ - Mode 2: Comment box, comment preview, and inline comment previews.
+*/
+.differential-haunt-mode-1 .differential-add-comment-panel,
+.differential-haunt-mode-2 .differential-add-comment-panel {
position: fixed;
width: 100%;
bottom: 0;
right: 0;
left: 0;
z-index: 5;
overflow: auto;
max-height: 375px;
max-width: none;
box-shadow: 0 0 4px #000;
-webkit-box-shadow: 0 0 4px #000;
-moz-box-shadow: 0 0 4px #000;
}
-.differential-haunted-panel .differential-add-comment-panel h1 {
+.differential-haunt-mode-2 .differential-add-comment-panel {
+ max-height: 75%;
+}
+
+.differential-haunt-mode-1 .differential-add-comment-panel h1,
+.differential-haunt-mode-2 .differential-add-comment-panel h1 {
display: none;
}
-.differential-haunted-panel .aphront-panel-preview {
+.differential-haunt-mode-1 .aphront-panel-preview {
display: none;
}
-.differential-haunted-panel {
+.differential-haunt-mode-1 {
padding-bottom: 250px;
}
.differential-comment-list .anchor-target {
background-color: #ffffdd;
border-color: #ffff00;
}
.differential-inline-comment-content {
overflow: auto;
}
.differential-comment-core .phabricator-remarkup .remarkup-code-block {
width: 88ex;
width: 81ch;
}
.phabricator-transaction-view .differential-comment-action-testplan {
border-color: #660099;
}
.phabricator-transaction-view .differential-comment-action-abandon {
border-color: #222222;
}
.phabricator-transaction-view .differential-comment-action-accept {
border-color: #009966;
}
.phabricator-transaction-view .differential-comment-action-reject {
border-color: #aa0000;
}
.phabricator-transaction-view .differential-comment-action-rethink {
border-color: #aa0000;
}
.phabricator-transaction-view .differential-comment-action-commit {
border-color: #006699;
}
.phabricator-transaction-view .differential-comment-action-reclaim {
border-color: #0099aa;
}
.phabricator-transaction-view .differential-comment-action-update {
border-color: #6699cc;
}
.phabricator-transaction-view .differential-comment-action-add_reviewers {
border-color: #aa99cc;
}
.phabricator-transaction-view .differential-comment-action-request_review {
border-color: #cc9966;
}
diff --git a/webroot/rsrc/js/application/differential/behavior-comment-preview.js b/webroot/rsrc/js/application/differential/behavior-comment-preview.js
index 48ffaaa681..104c6e072d 100644
--- a/webroot/rsrc/js/application/differential/behavior-comment-preview.js
+++ b/webroot/rsrc/js/application/differential/behavior-comment-preview.js
@@ -1,62 +1,82 @@
/**
* @provides javelin-behavior-differential-feedback-preview
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* javelin-request
* javelin-util
* phabricator-shaped-request
*/
JX.behavior('differential-feedback-preview', function(config) {
var action = JX.$(config.action);
var content = JX.$(config.content);
var previewTokenizers = {};
for (var field in config.previewTokenizers) {
var tokenizer = JX.$(config.previewTokenizers[field]);
previewTokenizers[field] = JX.Stratcom.getData(tokenizer).tokenizer;
}
var callback = function(r) {
JX.DOM.setContent(JX.$(config.preview), JX.$H(r));
};
var getdata = function() {
var data = {
content : content.value,
action : action.value
};
for (var field in previewTokenizers) {
data[field] = JX.keys(previewTokenizers[field].getTokens()).join(',');
}
return data;
};
var request = new JX.PhabricatorShapedRequest(config.uri, callback, getdata);
var trigger = JX.bind(request, request.trigger);
JX.DOM.listen(content, 'keydown', null, trigger);
JX.DOM.listen(action, 'change', null, trigger);
for (var field in previewTokenizers) {
previewTokenizers[field].listen('change', trigger);
}
request.start();
function refreshInlinePreview() {
new JX.Request(config.inlineuri, function(r) {
- JX.DOM.setContent(JX.$(config.inline), JX.$H(r));
+ var inline = JX.$(config.inline);
+
+ JX.DOM.setContent(inline, JX.$H(r));
+
+ // Go through the previews and activate any "View" links where the
+ // actual comment appears in the document.
+
+ var links = JX.DOM.scry(
+ inline,
+ 'a',
+ 'differential-inline-preview-jump');
+ for (var ii = 0; ii < links.length; ii++) {
+ var data = JX.Stratcom.getData(links[ii]);
+ try {
+ JX.$(data.anchor);
+ links[ii].href = '#' + data.anchor;
+ JX.DOM.setContent(links[ii], 'View');
+ } catch (ignored) {
+ // This inline comment isn't visible, e.g. on some other diff.
+ }
+ }
})
.setTimeout(5000)
.send();
}
JX.Stratcom.listen(
'differential-inline-comment-update',
null,
refreshInlinePreview);
refreshInlinePreview();
});
diff --git a/webroot/rsrc/js/application/differential/behavior-keyboard-nav.js b/webroot/rsrc/js/application/differential/behavior-keyboard-nav.js
index 2944095d47..b465efc5f3 100644
--- a/webroot/rsrc/js/application/differential/behavior-keyboard-nav.js
+++ b/webroot/rsrc/js/application/differential/behavior-keyboard-nav.js
@@ -1,230 +1,233 @@
/**
* @provides javelin-behavior-differential-keyboard-navigation
* @requires javelin-behavior
* javelin-dom
* javelin-stratcom
* phabricator-keyboard-shortcut
*/
JX.behavior('differential-keyboard-navigation', function(config) {
var cursor = -1;
var changesets;
var selection_begin = null;
var selection_end = null;
function init() {
if (changesets) {
return;
}
changesets = JX.DOM.scry(document.body, 'div', 'differential-changeset');
}
function getBlocks(cursor) {
// TODO: This might not be terribly fast; we can't currently memoize it
// because it can change as ajax requests come in (e.g., content loads).
var rows = JX.DOM.scry(changesets[cursor], 'tr');
var blocks = [[changesets[cursor], changesets[cursor]]];
var start = null;
var type;
var ii;
function push() {
if (start) {
blocks.push([start, rows[ii - 1]]);
}
start = null;
}
for (ii = 0; ii < rows.length; ii++) {
type = getRowType(rows[ii]);
if (type == 'comment') {
// If we see these types of rows, make a block for each one.
push();
}
if (!type) {
push();
} else if (type && !start) {
start = rows[ii];
}
}
push();
return blocks;
}
function getRowType(row) {
// NOTE: Being somewhat over-general here to allow other types of objects
// to be easily focused in the future (inline comments, 'show more..').
if (row.className.indexOf('inline') !== -1) {
return 'comment';
}
if (row.className.indexOf('differential-changeset') !== -1) {
return 'file';
}
var cells = JX.DOM.scry(row, 'td');
for (var ii = 0; ii < cells.length; ii++) {
// NOTE: The semantic use of classnames here is for performance; don't
// emulate this elsewhere since it's super terrible.
if (cells[ii].className.indexOf('old') !== -1 ||
cells[ii].className.indexOf('new') !== -1) {
return 'change';
}
}
return null;
}
function jump(manager, delta, jump_to_type) {
init();
if (cursor < 0) {
if (delta < 0) {
// If the user goes "back" without a selection, just reject the action.
return;
} else {
cursor = 0;
}
}
while (true) {
var blocks = getBlocks(cursor);
var focus;
if (delta < 0) {
focus = blocks.length;
} else {
focus = -1;
}
for (var ii = 0; ii < blocks.length; ii++) {
if (blocks[ii][0] == selection_begin) {
focus = ii;
break;
}
}
while (true) {
focus += delta;
if (blocks[focus]) {
var row_type = getRowType(blocks[focus][0]);
if (jump_to_type && row_type != jump_to_type) {
continue;
}
selection_begin = blocks[focus][0];
selection_end = blocks[focus][1];
manager.scrollTo(selection_begin);
manager.focusOn(selection_begin, selection_end);
return;
} else {
var adjusted = (cursor + delta);
if (adjusted < 0 || adjusted >= changesets.length) {
// Stop cursor movement when the user reaches either end.
return;
}
cursor = adjusted;
// Break the inner loop and go to the next file.
break;
}
}
}
}
// When inline comments are updated, wipe out our cache of blocks since
// comments may have been added or deleted.
JX.Stratcom.listen(
null,
'differential-inline-comment-update',
function() {
changesets = null;
});
- var is_haunted = false;
+ var haunt_mode = 0;
function haunt() {
- is_haunted = !is_haunted;
- var haunt = JX.$(config.haunt)
- JX.DOM.alterClass(haunt, 'differential-haunted-panel', is_haunted);
+ haunt_mode = (haunt_mode + 1) % 3;
+
+ var el = JX.$(config.haunt);
+ for (var ii = 1; ii <= 2; ii++) {
+ JX.DOM.alterClass(el, 'differential-haunt-mode-'+ii, (haunt_mode == ii));
+ }
}
new JX.KeyboardShortcut('j', 'Jump to next change.')
.setHandler(function(manager) {
jump(manager, 1);
})
.register();
new JX.KeyboardShortcut('k', 'Jump to previous change.')
.setHandler(function(manager) {
jump(manager, -1);
})
.register();
new JX.KeyboardShortcut('J', 'Jump to next file.')
.setHandler(function(manager) {
jump(manager, 1, 'file');
})
.register();
new JX.KeyboardShortcut('K', 'Jump to previous file.')
.setHandler(function(manager) {
jump(manager, -1, 'file');
})
.register();
new JX.KeyboardShortcut('n', 'Jump to next inline comment.')
.setHandler(function(manager) {
jump(manager, 1, 'comment');
})
.register();
new JX.KeyboardShortcut('p', 'Jump to previous inline comment.')
.setHandler(function(manager) {
jump(manager, -1, 'comment');
})
.register();
function inline_op(node, op) {
if (!JX.DOM.scry(node, 'a', 'differential-inline-' + op)) {
// No link for this operation, e.g. editing a comment you can't edit.
return;
}
var data = {
node: JX.DOM.find(node, 'div', 'differential-inline-comment'),
op: op
};
JX.Stratcom.invoke('differential-inline-action', null, data);
}
new JX.KeyboardShortcut('r', 'Reply to selected inline comment.')
.setHandler(function(manager) {
inline_op(selection_begin, 'reply');
})
.register();
new JX.KeyboardShortcut('e', 'Edit selected inline comment.')
.setHandler(function(manager) {
inline_op(selection_begin, 'edit');
})
.register();
if (config.haunt) {
- new JX.KeyboardShortcut('z', 'Haunt / unhaunt comment panel.')
+ new JX.KeyboardShortcut('z', 'Cycle comment panel haunting modes.')
.setHandler(haunt)
.register();
}
});

File Metadata

Mime Type
text/x-diff
Expires
9月 12 Fri, 3:02 AM (23 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5747
默认替代文本
(19 KB)

Event Timeline