Remove a TODO about checking `comment-side` in thread elements
All users of gr-diff are using `diff-side` attribute.
Release-Notes: skip
Change-Id: I4d836ebba6eebfb45a2b20ebb874f8743968951b
diff --git a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts
index d9f5a4d..92cf968 100644
--- a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts
+++ b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts
@@ -86,8 +86,6 @@
@property({type: Object}) diff?: DiffInfo;
- @property({type: Object}) section?: HTMLElement;
-
@property({type: Object}) group?: GrDiffGroup;
@property({type: String, reflect: true})
@@ -361,10 +359,9 @@
lineRange: this.group.lineRange,
});
} else {
- assertIsDefined(this.section, 'section');
fire(this, 'diff-context-expanded', {
+ contextGroup: this.group,
groups,
- section: this.section!,
numLines: this.numLines(),
buttonType: type,
expandedLines: linesToExpand,
@@ -491,7 +488,7 @@
}
private hasValidProperties() {
- return !!(this.diff && this.section && this.group?.contextGroups?.length);
+ return !!(this.diff && this.group?.contextGroups?.length);
}
override render() {
diff --git a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls_test.ts b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls_test.ts
index 92debda..7af40ed 100644
--- a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls_test.ts
@@ -34,7 +34,6 @@
element = document.createElement('gr-context-controls');
element.diff = {content: []} as any as DiffInfo;
element.renderPreferences = {};
- element.section = document.createElement('div');
blankFixture.instantiate().appendChild(element);
await flush();
});
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
index 14277f8..6854ef34 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
@@ -146,8 +146,15 @@
@property({type: Object})
_builder?: DiffBuilder;
- // This is written to only from the processor via property notify
- // And then passed to the builder via a property observer.
+ /**
+ * The gr-diff-processor adds (and only adds!) to this array. It does so by
+ * using `this.push()` and Polymer's two-way data binding.
+ * Below (@observe('_groups.splices')) we are observing the groups that the
+ * processor adds, and pass them on to the builder for rendering. Henceforth
+ * the builder groups are the source of truth, because when
+ * expanding/collapsing groups only the builder is updated. This field and the
+ * corresponsing one in the processor are not updated.
+ */
@property({type: Array})
_groups: GrDiffGroup[] = [];
@@ -206,7 +213,7 @@
(e: CustomEvent<DiffContextExpandedEventDetail>) => {
// Don't stop propagation. The host may listen for reporting or
// resizing.
- this.rerenderSection(e.detail.groups, e.detail.section);
+ this.replaceGroup(e.detail.contextGroup, e.detail.groups);
}
);
});
@@ -353,12 +360,9 @@
*/
unhideLine(lineNum: number, side: Side) {
if (!this._builder) return;
- const groupIndex = this.$.processor.groups.findIndex(group =>
- group.containsLine(side, lineNum)
- );
+ const group = this._builder.findGroup(side, lineNum);
// Cannot unhide a line that is not part of the diff.
- if (groupIndex < 0) return;
- const group = this._groups[groupIndex];
+ if (!group) return;
// If it's already visible, great!
if (group.type !== GrDiffGroupType.CONTEXT_CONTROL) return;
const lineRange = group.lineRange[side];
@@ -384,25 +388,24 @@
lineRange.end_line - lineRange.start_line + 1
)
);
- this._builder.spliceGroups(groupIndex, 1, ...newGroups);
+ this._builder.replaceGroup(group, newGroups);
setTimeout(() => fireEvent(this, 'render-content'), 1);
}
/**
- * Replace the provided section by rendering the provided groups.
+ * Replace the group of a context control section by rendering the provided
+ * groups instead. This happens in response to expanding a context control
+ * group.
*
- * @param newGroups The groups to be rendered in the place of the section.
- * @param sectionEl The context section that should be expanded from.
+ * @param contextGroup The context control group to replace
+ * @param newGroups The groups that are replacing the context control group
*/
- private rerenderSection(
- newGroups: readonly GrDiffGroup[],
- sectionEl: HTMLElement
+ private replaceGroup(
+ contextGroup: GrDiffGroup,
+ newGroups: readonly GrDiffGroup[]
) {
if (!this._builder) return;
-
- const contextIndex = this._builder.getIndexOfSection(sectionEl);
- this._builder.spliceGroups(contextIndex, 1, ...newGroups);
-
+ this._builder.replaceGroup(contextGroup, newGroups);
setTimeout(() => fireEvent(this, 'render-content'), 1);
}
@@ -482,18 +485,28 @@
this.diffElement.innerHTML = '';
}
+ /**
+ * Forward groups added by the processor to the builder for rendering.
+ */
@observe('_groups.splices')
_groupsChanged(changeRecord: PolymerSpliceChange<GrDiffGroup[]>) {
- if (!changeRecord || !this._builder) {
+ if (!changeRecord || !this._builder) return;
+
+ // The processor either removes all groups or adds new ones to the end,
+ // so let's simplify the Polymer splices.
+ const isRemoval = changeRecord.indexSplices.find(
+ splice => splice.removed.length > 0
+ );
+ if (isRemoval) {
+ this._builder.clearGroups();
return;
}
- // Forward any splices to the builder
for (const splice of changeRecord.indexSplices) {
const added = splice.object.slice(
splice.index,
splice.index + splice.addedCount
);
- this._builder.spliceGroups(splice.index, splice.removed.length, ...added);
+ this._builder.addGroups(added);
}
}
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-legacy.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-legacy.ts
index a4fd7d2..7758aa0 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-legacy.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-legacy.ts
@@ -197,13 +197,7 @@
section.appendChild(paddingRow);
}
section.appendChild(
- this.createContextControlRow(
- section,
- group,
- showAbove,
- showBelow,
- viewMode
- )
+ this.createContextControlRow(group, showAbove, showBelow, viewMode)
);
if (showBelow) {
const paddingRow = this.createContextControlPaddingRow(viewMode);
@@ -218,7 +212,6 @@
* method up or down into the area of code that they affect.
*/
private createContextControlRow(
- section: HTMLElement,
group: GrDiffGroup,
showAbove: boolean,
showBelow: boolean,
@@ -252,7 +245,6 @@
) as GrContextControls;
contextControls.diff = this._diff;
contextControls.renderPreferences = this.renderPrefs;
- contextControls.section = section;
contextControls.group = group;
contextControls.showConfig = showConfig;
cell.appendChild(contextControls);
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts
index 930731c..8b7a308 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts
@@ -30,8 +30,9 @@
export interface DiffContextExpandedEventDetail
extends DiffContextExpandedExternalDetail {
+ /** The context control group that should be replaced by `groups`. */
+ contextGroup: GrDiffGroup;
groups: GrDiffGroup[];
- section: HTMLElement;
numLines: number;
}
@@ -49,12 +50,13 @@
*/
export interface DiffBuilder {
clear(): void;
- spliceGroups(
- start: number,
- deleteCount: number,
- ...addedGroups: GrDiffGroup[]
- ): GrDiffGroup[];
- getIndexOfSection(sectionEl: HTMLElement): number;
+ addGroups(groups: readonly GrDiffGroup[]): void;
+ clearGroups(): void;
+ replaceGroup(
+ contextControl: GrDiffGroup,
+ groups: readonly GrDiffGroup[]
+ ): void;
+ findGroup(side: Side, line: LineNumber): GrDiffGroup | undefined;
addColumns(outputEl: HTMLElement, fontSize: number): void;
// TODO: Change `null` to `undefined`.
getContentTdByLine(
@@ -77,9 +79,8 @@
*
* The builder takes GrDiffGroups, and builds the corresponding DOM elements,
* called sections. Only the builder should add or remove sections from the
- * DOM. Callers can use the spliceGroups method to add groups that
- * will then be rendered - or remove groups whose sections will then be
- * removed from the DOM.
+ * DOM. Callers can use the ...group() methods to modify groups and thus cause
+ * rendering changes.
*
* TODO: Do not subclass `GrDiffBuilder`. Use composition and interfaces.
*/
@@ -94,7 +95,7 @@
protected readonly outputEl: HTMLElement;
- protected readonly groups: GrDiffGroup[];
+ protected groups: GrDiffGroup[];
private blameInfo: BlameInfo[] = [];
@@ -155,41 +156,41 @@
protected abstract buildSectionElement(group: GrDiffGroup): HTMLElement;
- getIndexOfSection(sectionEl: HTMLElement) {
- return this.groups.findIndex(group => group.element === sectionEl);
+ addGroups(groups: readonly GrDiffGroup[]) {
+ for (const group of groups) {
+ this.groups.push(group);
+ this.emitGroup(group);
+ }
}
- spliceGroups(
- start: number,
- deleteCount: number,
- ...addedGroups: GrDiffGroup[]
- ) {
- // TODO: Change `null` to `undefined`.
- const sectionBeforeWhichToInsert =
- start < this.groups.length ? this.groups[start].element ?? null : null;
- // Update the groups array
- const deletedGroups = this.groups.splice(
- start,
- deleteCount,
- ...addedGroups
- );
-
- // Add new sections for the new groups
- for (const addedGroup of addedGroups) {
- this.emitGroup(addedGroup, sectionBeforeWhichToInsert);
+ clearGroups() {
+ for (const deletedGroup of this.groups) {
+ deletedGroup.element?.remove();
}
- // Remove sections corresponding to deleted groups from the DOM
- for (const deletedGroup of deletedGroups) {
- const section = deletedGroup.element;
- section?.parentNode?.removeChild(section);
- }
- return deletedGroups;
+ this.groups = [];
}
- // TODO: Change `null` to `undefined`.
- private emitGroup(group: GrDiffGroup, beforeSection: HTMLElement | null) {
+ replaceGroup(contextControl: GrDiffGroup, groups: readonly GrDiffGroup[]) {
+ const i = this.groups.indexOf(contextControl);
+ if (i === -1) throw new Error('cannot find context control group');
+
+ const contextControlSection = this.groups[i].element;
+ if (!contextControlSection) throw new Error('diff group element not set');
+
+ this.groups.splice(i, 1, ...groups);
+ for (const group of groups) {
+ this.emitGroup(group, contextControlSection);
+ }
+ contextControlSection?.remove();
+ }
+
+ findGroup(side: Side, line: LineNumber) {
+ return this.groups.find(group => group.containsLine(side, line));
+ }
+
+ private emitGroup(group: GrDiffGroup, beforeSection?: HTMLElement) {
const element = this.buildSectionElement(group);
- this.outputEl.insertBefore(element, beforeSection);
+ this.outputEl.insertBefore(element, beforeSection ?? null);
group.element = element;
}
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
index 4d8efed..b588bc7 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
@@ -97,6 +97,13 @@
@property({type: Number})
context = 3;
+ /**
+ * The builder elements watches this (two-way data binding and @observe) and
+ * thus passes each added group on to the renderer (i.e. gr-diff-builder).
+ * You must only add to this array and not modify it later (only when
+ * resetting). The source of truth is then held by gr-diff-builder, which also
+ * reflects expanding and collapsing of groups.
+ */
@property({type: Array, notify: true})
groups: GrDiffGroup[] = [];
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts
index 56c5d79..b8262e0 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts
@@ -320,6 +320,9 @@
*/
readonly keyLocation: boolean = false;
+ /**
+ * Once rendered the diff builder sets this to the diff section element.
+ */
element?: HTMLElement;
readonly lines: GrDiffLine[] = [];
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts
index 94a7a84..182d48e 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts
@@ -146,10 +146,7 @@
}
export function getSide(threadEl: HTMLElement): Side | undefined {
- // TODO(dhruvsri): Remove check for comment-side once all users of gr-diff
- // start setting diff-side
- const sideAtt =
- threadEl.getAttribute('diff-side') || threadEl.getAttribute('comment-side');
+ const sideAtt = threadEl.getAttribute('diff-side');
if (!sideAtt) {
console.warn('comment thread without side');
return undefined;