29 Commits

Author SHA1 Message Date
Wyatt Allen
455c91c88b Merge "Allow multiple threads per line, with different ranges" 2017-02-02 00:39:40 +00:00
Becky Siegel
562a30493e Allow multiple threads per line, with different ranges
- Add concept of diff comment thread groups, which are all of the
  threads at a particular line number.

- The thread group is responsible for breaking up comments into threads
  based on the range of the comment.

- Thread groups are ordered by the updated time of the first comment in
  the group.

- Thread groups are given a key, based on comment range, which is used
  to determine what thread group a new comment should go in (or if it
  needs a new one).

Feature: Issue 5292
Change-Id: If544e8bb879262de3ce5397e86124837b66ada04
2017-02-01 16:10:08 -08:00
Wyatt Allen
3b824c577d Remove unnecessary HTML escaping
Because the `_computeAccountTitle` method was only used in a binding to
an HTML attribute, the manual HTML escaping performed in that method was
in not needed.

Since removing this, the only use-site for the `util.escapeHTML`
function is the `GrDiffBuilder`. To discourage general use of manual
HTML escaping (in favor of default escaping in Polymer bindings) -- as
well as to lighten util.js -- the escapeHTML function is moved into
`GrDiffBuilder`, its regex is made a constant, and is given a unit test.

Change-Id: I28c9f546cf50461e96995ecd6da8653e75554023
2017-01-30 17:28:57 -08:00
Becky Siegel
e6bb34fbf0 Fix lint errors
Change-Id: I71e0c481c4408058dd48b6295876d7b952cdbd38
2017-01-04 13:38:54 -08:00
Wyatt Allen
1e3cd47707 Highlight add/remove diff lines more consistently
Diffs in PolyGerrit apply two shades of highlight to changed lines
(light and dark) to indicate the granularity of modifications and to
distinguish intraline edits. However, the logic for choosing the
background shade for diff lines would differ from that of GWT UI diffs
subtly.

 +----------------------------------+----------------------------------+
 |       GWT UI Shading Logic       |   PG Shading Logic (incorrect)   |
 +----------------------------------+----------------------------------+
 | Diff lines get a dark background | Diff lines get a dark background |
 | IFF they appear in a delta chunk | IFF they do NOT contain any      |
 | that is empty on the left OR     | intraline differences.           |
 | empty on the right.              |                                  |
 +----------------------------------+----------------------------------+
 |            Diff lines get a light background otherwise.             |
 +---------------------------------------------------------------------+

With this change, the shading logic in PolyGerrit is modified to match
that of the GWT UI.

Bug: Issue 4219
Bug: Issue 5117
Change-Id: Ice24292df777118c08c3e73f771720f8a186a183
2016-12-22 10:41:39 -08:00
Wyatt Allen
32fb1d9e2b Allow totally empty lines of diff content
Empty diff lines had been coerced to non-breaking spaces in order to
preserve blank lines when copying to the clipboard [1]. Since then, copy
was upgraded to traverse the diff object rather than the DOM [2],
thereby obviating the need for non-breaking space to preserve blank
lines.

Remove the non-breaking space.

[1] 613b49c6
[2] 9fcec743

Bug: Issue 4854
Change-Id: I4039c76d996ed97e9fb237f2f6ca20f70be77675
2016-11-23 10:33:09 -08:00
Wyatt Allen
d970500d62 Annotate trailing whitespace per user preference
Add a simple annotation layer that marks trailing whitespace in diffs
(guarded by the `show_whitespace_errors` diff preference). The newly
supported diff preference is added to both diff preference controls. The
requirement that all annotation layers must implement `addListener` is
relaxed as the trailing whitespace layer is the third layer that doesn't
use it.

Adds tests for the layer and the diff preference.

Feature: Issue 4836
Change-Id: Ifba05216bf0bc3c0a8a094f5ef392b983091d59f
2016-11-20 13:31:30 -08:00
Becky Siegel
e7d19a9976 Add preference for line wrapping in diff preferences
Previously in Polygerrit, diff views were always displayed in the width
specified in diff preferences. This change gives the option to wrap
lines instead, which takes precedence over column width (the column
width option is hidden when line wrapping is selected), and fits the
diff view to screen.

The gerrit API already supports the 'lineWrapping' preference so this
change uses that already existing option.

Feature: Issue 4809
Change-Id: I0d9e292739b5910abfd04af63ec4c745bf06e446
2016-10-31 17:35:21 -07:00
Wyatt Allen
072a0a9266 Fix spelling error in a comment
Change-Id: Ie3429019ab5ce58870db20af8bb52e7ab7e2766f
2016-09-13 15:50:55 -07:00
Kasper Nilsson
613b49c64e Fix copy/paste in diff view
The addition of syntax highlighting silently broke copy/paste
functionality due to the addition of another layer of div nesting.

Related to this bug are some issues with correct text selection in
unified diff view, so this patch addresses them as well.

Bug: Issue 4317
Change-Id: Iac7379de4131ab4e44905a54218d42fcfe67ce62
2016-08-29 16:18:47 -07:00
Wyatt Allen
be0142ca03 Improves visible tabs rendering
This change reverts visible tabs to use the » character. A few different
approaches have been used for rendering these tab indicators:

I:  Before the Annotation Pipeline, tab indicators were configured by a
    class that was optionally applied to tab elements by the diff
    builder. The class was guarded by the show_tabs preference and a CSS
    rule created a `::before` pseudo element to insert the character.
    (Thus also preventing the » from being copyable text.)

II: When the Annotation Pipeline was implemented, the ordering of layers
    called for intraline difference elements being rendered *inside* tab
    indicators. As a result, the » indicator would sometimes have a
    different background than the intraline difference, looking sloppy.

    To solve this, the pseudo element was positioned using absolute,
    allowing the pseudo element to consume no horizontal space and and
    the intraline background to extend across the entire tab.

III:When performance tuning, it was discovered that the
    absolute-positioned tab indicators were positioned incorrectly when
    GPU acceleration was hinted for the diff, so the containing tab
    elements were made relative.

IV: Continuing performance tuning, the tab indicators seemed to slow
    scrolling on very large diffs with tabs. It was mistakenly assumed
    (by me) that this was related to the pseudo-elements when it was
    actually caused by the thousands of positioning contexts they
    created using relative and absolute.

    Instead they were modified to use strike-through instead of a pseudo
    element, which was more-performant, but less-usable (it looked bad).

With this change, we roll-back the clock a little and solve a core
problem: namely that tab indicators were not annotated inside the
intraline differences. Fixing that, positioning tricks are no-longer
needed to make the background look right.

To do this, we decouple the tab elements (which control tab width) from
the tab indicators (which optionally make tabs visible). This is done
using an annotation layer that inserts tab indicator elements wherever
a tab character is used in the source content, and it does so after
intraline differences have been applied.

Bug: Issue 4441
Change-Id: I4fea2a3a20a7039bfeb746bd1e1c1004e43c4801
2016-08-25 11:47:17 -07:00
Wyatt Allen
5c5f00fb13 Refactors annotation layer
Formerly, the annotation layer interface provided the GrAnnotation
library as a parameter to the `annotate` method. This was so the layer
would not necessarily need to import the library at the module level
and instead could use it as a utility toolbox.

With this change, the library is no-longer part of the interface and the
layers are now expected to import it at the module layer (if they have
a use for it).

Change-Id: I49b96c67ec724708c2861ab6be3ce27a53cc1b05
2016-07-25 22:47:01 -07:00
Wyatt Allen
650c529276 Syntax highlighting
Introduces the gr-syntax-layer element. This element works as an
annotation layer that is configured with the diff and asynchronously
computes/applies syntax for the diff.

Introduces a custom build of Highlight.js which gr-syntax-layer makes
use of. Building the script is documented in
scripts/vendor/highlight/building.md.

The layer is connected to the annotation pipeline in gr-diff-builder as
the lowest layer and syntax processing is triggered only after a diff
has been completely rendered.

A number of styles are added to the gr-diff element for syntax markers.
Tests added for gr-syntax-layer.

Bug: Issue 3916
Change-Id: Ic33e40f4fe39dfce1a62de133cfaf32be5e3f25a
2016-07-25 13:47:30 -07:00
Wyatt Allen
ea97c5b49a Adds diff traversal helper and make diff object a builder property
Adds a polymorphic method to GrDiffBuilder subclasses named
`_getNextContentOnSide` which gets the a content element by traversing
from its preceding content on the same side. This method is dramatically
faster than the query-based method when diff sections are large.

In preparation for the syntax highlighting change, the gr-diff-builder
is refactored to use a property for the diff object, rather than
accepting it as a parameter to the `render` function.

Tests are included for new functions.

Change-Id: Ifd0edb530a303de2626d55a691c3ba1eaed6167c
2016-07-21 22:26:56 -07:00
Wyatt Allen
d0dd392794 Establish annotation pipeline
Apply diff annotations (intraline differences and comment ranges) by
executing the annotation layers in order to each line. The diff builder
maintains an ordered array of annotation layers which are communicated
to GrDiffBuilder subclass instances. The builder also listens to each
layer for notifications that annotations have changed for some line
range and re-renders (i.e. re-applies the pipeline on DIV.contentText
elements) accordingly.

Change-Id: Iea0599d4869cafaadc0974158153a91d927913e8
2016-07-20 12:25:40 -07:00
Wyatt Allen
9317bafd74 Upgrades and tests for GrDiffBuilder utility methods
A new method is added to the GrDiffBuilder class named
`_renderContentByRange`. It will replace DIV.contentText elements with
newly-rendered versions for the given line-range and side.

Two utility methods found on GR-DIFF-BUILDER are pushed down into the
GrDiffBuilder class. In particular, `getContentByLine` is moved as-is
and a wrapper is added to original place. `getContentsByLineRange` is
moved and converted to be more general. A wrapper is put in its original
location which follows the original signature. These moves make the
functions available to other methods of the class.

Tests are added for these new and existing methods.

Change-Id: I77634d05828756c46b802f9ec789ab767faca3cf
2016-07-18 09:30:38 -07:00
Wyatt Allen
b7fa5dd929 Applies intraline differences as annotations
The `_addIntralineHighlights` method of GrDiffBuilder is rewritten to
take advantage of GrAnnotate. In particular, formerly, the method would
apply intraline difference highlights by modifying an HTML string.
With this change, the highlight positions are translated as calls to
`GrAnnotate.annotateElement`, which works on the `DIV.contentText`
element.

Change-Id: I2838ef29f057f1108e2ffd196bb48a239366dc87
2016-07-13 21:07:13 -07:00
Wyatt Allen
812f225b79 Dynamic tab width
Previously tabs were configured to all use the same width. However, the
tab width setting is supposed to configure the distance between
tab-stops, not the width of the tabs themselves. Additionally, the width
of a tab element as it's inserted into diff content should be the width
needed to get to the next tab-stop.

Reconfigures the `_textLength` and `_addTabWrappers` methods to respect
this aspect of tab behavior.

Notably, `_addTabWrappers` formerly accepted an HTML string as input,
and was called after intraline differences were applied. With this
change it acts only on raw (non-HTML) strings so that it can directly
determine the position of the tab within the line, and it is called
before intraline differences are applied.

Bug: Issue 4252
Change-Id: I44826d917a505a245fd2b20ccf0ac19378f2806c
2016-07-12 15:25:55 -07:00
Wyatt Allen
1e8216cc35 Upgrade text-length method
The `_textLength` method of gr-diff-builder now correctly handles astral
symbols.

Change-Id: I5e148968cfc3e53733bf6b89703e1cba9117a6d6
2016-07-12 10:32:20 -07:00
Wyatt Allen
025e65d7d5 Reorganized DOM for diff content in PolyGerrit
Formerly, diff content elements mixed text with comment threads. For
example, a diff content node with an intraline highlight, a ranged
comment, and a gr-diff-comment-thread may have been organized as below:

    TD.content
      ╠ #text
      ╠ HL (intraline difference)
      ║ ╚ #text
      ╠ #text
      ╠ HL.range (ranged comment highlight)
      ║ ╚ #text
      ╠ #text
      ╚ GR-DIFF-COMMENT-THREAD
        ╠ GR-DIFF-COMMENT
        ╚ ...

Note that the comment thread was inserted at the same level as the text
of the diff line.

With this change, the text is separated from the comment thread by
introducing a DIV to contain the text with class `contentText` as
sibling to comment threads.

    TD.content
      ╠ DIV.contentText
      ║ ╠ #text
      ║ ╠ HL
      ║ ║ ╚ #text
      ║ ╠ #text
      ║ ╠ HL.range
      ║ ║ ╚ #text
      ║ ╚ #text
      ╚ GR-DIFF-COMMENT-THREAD
        ╠ GR-DIFF-COMMENT
        ╚ ...

Modifies the `getContentByLine` method of gr-diff-builder to return the
`DIV.contentText` element rather than the `TD.content` element which is
its parent. In most uses of this function, the text is what is needed
rather than the TD or comment thread, but in other cases, they can be
easily DOM traversed.

Change-Id: I0eded34afd3d22963252efc7eabfee290ae21a9c
2016-07-11 11:20:09 -07:00
Wyatt Allen
7bbc6b49c0 Add line range information to group objects
Group objects now keep track of the range of line numbers for the lines
they contain, making specific groups easier to identify.

Change-Id: I37873d83e1003d75df7da77e619e23208d1c30b3
2016-07-08 12:50:48 -07:00
Wyatt Allen
db881fa0ad Asynchronous diff rendering
Building on existing support for asynchronous diff processing, the
rendering stage is now also asynchronous. The `emitGroup` method of
gr-diff-builder (which constructs a DOM fragment and attaches it to the
document) is now called whenever the processor emits a new group, rather
than waiting for all groups to be available and looping over them.

Adds support for canceling the processor, and removes a behavior where
the diff was being re-rendered needlessly, causing visible flicker.
Updates a test that broke when rendering became asynchronous.

Change-Id: I37fcd65efc8c901b85fc93e91611c022edc10dc4
2016-06-30 10:09:19 -07:00
Wyatt Allen
8e20db3119 Refactor gr-diff-processor to use an asynchronous loop
Modifies the `process` method of gr-diff-processor to traverse diff
content using an asynchronous recursive loop rather than a blocking
for-loop. The async version maintains the promise interface already
established.

Refactored to constrain side-effects to the `process` method. Whereas,
formerly, helper methods in gr-diff-processor both read and wrote the
component's internal state, they are rewritten to be more pure, making
them simpler to understand, test, and invoke asynchronously.

Documentation is added throughout as well as tests for helper functions.

Note that this change only makes the processing step asynchronous.
Upgrading the diff-rendering stage to be non-blocking will come in a
later change.

Change-Id: Ifd50eeb75797b173937890caacc92cad5675fc20
2016-06-29 10:36:41 -07:00
Wyatt Allen
7f2bd97901 Separates diff processing from diff building
Moves the diff-processing functionality of the gr-diff-builder component
into a new gr-diff-processor component which exposes a promise-based
interface. This is step one of creating an asynchronous (non-blocking)
diff rendering system.

As much as possible, this change is a transfer of code (with tests) from
one component to another, making it easier to verify that functionality
has not changed. Cleanup of the code, and refactoring it into a
more-testable form will come with later changes.

Feature: Issue 3916
Change-Id: I875b03b20bf953b128cbe3c5001ba1f8eba12c61
2016-06-27 16:44:19 -07:00
Wyatt Allen
16810999f6 Prevent redefinition of class libraries
A number of classes used in PolyGerrit are defined in vanilla JS files
that are included multiple times by various elements.  For example,
gr-diff-line.js is included by the gr-diff-builder and by gr-diff
elements. Adds #ifndef-style guards to each of these libraries to
prevent redefinition and avoid different elements potentially referring
to different versions of the same class.

Change-Id: I45e3ba425a59989b328475b1fe58fd9f350c8ae0
2016-06-27 09:43:06 -07:00
Viktar Donich
b2198e8233 Ranged comments integration
- gr-file-list recognizes local preferences (for hasRangedComments flag)
- gr-file-list reacts to cursor hotkey only if there is no range
  selected (currently always false).
- Remove dead code from GrDiffBuilderSideBySide, GrDiffBuilder,
  gr-diff-builder.html
- Bugfix: GrDiffBuilder.prototype.getGroupsByLineRange handles one-line
  BOTH code sections correctly. Test updated as well.
- Added utitily methods added to gr-diff-builder.html to reduce
  dependency on DOM structure and reduce amount of code copy-pasting:
  - renderLineRange, getContentByLine, etc
- For gr-diff.js and gr-diff-comment-thread.js addDraft renamed to
  addOrEditDraft because that's what it does.
- For both, addDraft method always creates a draft comment.
- Added support for ranged comments in gr-diff, gr-diff-comment-thread.
- Added mouseenter and mouseout events to gr-comment.js
- Refactored gr-comment.js to reduce code copy-paste, unify event
  payload, and to eliminate need of accessing component instance for
  patchNum. Tests updated as well.
- Refactored gr-diff.js UI data model update using gr-diff-builder.html
  utility methods to make code more readable.
- Added support for creating ranged comments to gr-diff.js.
- gr-selection-action-box now reacts to click and tap to create a 
  comment.

Change-Id: I01480a4c6f460774a8b2826915702800b3f81d25
2016-06-13 22:44:47 +00:00
Viktar Donich
0f02cda57e Make gr-builder a Polymer component
Updated tests, fixed draft comments, context expanding.

Change-Id: Ic4bd9682c63edd8e80fbc2abcb4fa5e406a202ab
2016-06-03 10:22:47 -07:00
Andrew Bonventre
6c9d862e10 Revert "Make gr-builder a Polymer component"
This reverts commit 56689af0f92ce13f90ff9369544c5f9cc0412f09.

Reason for revert: This change broke adding draft comments in the diff
view.

Change-Id: Icfbd3eb4e24cce3e1690e7eaf12e14e5705c7e3e
2016-06-03 13:07:33 +00:00
Viktar Donich
56689af0f9 Make gr-builder a Polymer component
Change-Id: I0d99775332b0ef473459ad481970ad6033427c7d
2016-06-02 13:09:39 -07:00