Create comment immediately when double-clicking after a line
This assumes that any empty selection of just one line that ends at the
start of a line is an after-end-of-line selection. We capture it on
mouseup to avoid comments appearing while dragging.
Known issues:
Occasionally, when the comment is created on an empty line, discarding
the comment can trigger another mouseup that creates a new comment.
Occasionally the selection of a line hangs around and double-clicking
after the end of the line doesn't do anything until the selection is cleared.
Change-Id: Ifeea4f25e2ee4d4643766e4bdff31a74fedca68f
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
index 12b30b2..6419a7c 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
@@ -65,14 +65,17 @@
*
* @param {Selection} selection A DOM Selection living in the shadow DOM of
* the diff element.
+ * @param {boolean} isMouseUp If true, this is called due to a mouseup
+ * event, in which case we might want to immediately create a comment.
*/
- handleSelectionChange(selection) {
+ handleSelectionChange(selection, isMouseUp) {
// Can't use up or down events to handle selection started and/or ended in
// in comment threads or outside of diff.
// Debounce removeActionBox to give it a chance to react to click/tap.
this._removeActionBoxDebounced();
this.debounce(
- 'selectionChange', () => this._handleSelection(selection), 200);
+ 'selectionChange', () => this._handleSelection(selection, isMouseUp),
+ 200);
},
_getThreadEl(e) {
@@ -112,8 +115,12 @@
_indexOfCommentRange(side, range) {
function rangesEqual(a, b) {
- if (!a && !b) { return true; }
- if (!a || !b) { return false; }
+ if (!a && !b) {
+ return true;
+ }
+ if (!a || !b) {
+ return false;
+ }
return a.start_line === b.start_line &&
a.start_character === b.start_character &&
a.end_line === b.end_line &&
@@ -290,7 +297,7 @@
actionBox.placeBelow(range);
},
- _handleSelection(selection) {
+ _handleSelection(selection, isMouseUp) {
const normalizedRange = this._getNormalizedRange(selection);
if (!normalizedRange) {
return;
@@ -313,6 +320,24 @@
// TODO (viktard): Drop empty first and last lines from selection.
+ // If this was a mouse-up event, we create a comment immediately if
+ // the selection is from the end of a line to the start of the next line.
+ // Rather than trying to find the line contents, we just check if the
+ // selection is empty to see that it's at the end of a line.
+ // In this case, we select the entire start line.
+ if (isMouseUp && start.line === end.line - 1 && end.column === 0) {
+ const content = domRange.cloneContents().querySelector('.contentText');
+ if (this._getLength(content) === 0) {
+ this.fire('create-range-comment', {side: start.side, range: {
+ start_line: start.line,
+ start_character: 0,
+ end_line: start.line,
+ end_character: start.column,
+ }});
+ return;
+ }
+ }
+
const actionBox = document.createElement('gr-selection-action-box');
const root = Polymer.dom(this.root);
root.insertBefore(actionBox, root.firstElementChild);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index f260646..9fc9232 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -282,22 +282,38 @@
_enableSelectionObserver(loggedIn, isAttached) {
if (loggedIn && isAttached) {
this.listen(document, 'selectionchange', '_handleSelectionChange');
+ this.listen(document, 'mouseup', '_handleMouseUp');
} else {
this.unlisten(document, 'selectionchange', '_handleSelectionChange');
+ this.unlisten(document, 'mouseup', '_handleMouseUp');
}
},
_handleSelectionChange() {
+ // Because of shadow DOM selections, we handle the selectionchange here,
+ // and pass the shadow DOM selection into gr-diff-highlight, where the
+ // corresponding range is determined and normalized.
+ const selection = this._getShadowOrDocumentSelection();
+ this.$.highlights.handleSelectionChange(selection, false);
+ },
+
+ _handleMouseUp(e) {
+ // To handle double-click outside of text creating comments, we check on
+ // mouse-up if there's a selection that just covers a line change. We
+ // can't do that on selection change since the user may still be dragging.
+ const selection = this._getShadowOrDocumentSelection();
+ this.$.highlights.handleSelectionChange(selection, true);
+ },
+
+ /** Gets the current selection, preferring the shadow DOM selection. */
+ _getShadowOrDocumentSelection() {
// When using native shadow DOM, the selection returned by
// document.getSelection() cannot reference the actual DOM elements making
// up the diff, because they are in the shadow DOM of the gr-diff element.
- // For this reason, we handle the selectionchange here, and pass the
- // shadow DOM selection into gr-diff-highlight, where the corresponding
- // range is determined and normalized.
- const selection = this.root.getSelection ?
+ // This takes the shadow DOM selection if one exists.
+ return this.root.getSelection ?
this.root.getSelection() :
document.getSelection();
- this.$.highlights.handleSelectionChange(selection);
},
_observeNodes() {