Add SHRINK_ONLY responsive mode.
The current "Fit to screen" mode has the
drawback it always use 100% of available space.
We want a mode where the diff is responsive to
narrow screens but still doesn't use more
width than it would need (initial width).
Change-Id: I4a8a68cbe5c7cccbced7133dd0e1bb2b3d026f86
diff --git a/polygerrit-ui/app/api/diff.ts b/polygerrit-ui/app/api/diff.ts
index 7400295..4b20072 100644
--- a/polygerrit-ui/app/api/diff.ts
+++ b/polygerrit-ui/app/api/diff.ts
@@ -213,6 +213,10 @@
automatic_blink?: boolean;
}
+export declare type DiffResponsiveMode =
+ | 'FULL_RESPONSIVE'
+ | 'SHRINK_ONLY'
+ | 'NONE';
export declare interface RenderPreferences {
hide_left_side?: boolean;
disable_context_control_buttons?: boolean;
@@ -220,6 +224,7 @@
hide_line_length_indicator?: boolean;
use_block_expansion?: boolean;
image_diff_prefs?: ImageDiffPreferences;
+ responsive_mode?: DiffResponsiveMode;
}
/**
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
index 733c940..462c334 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
@@ -64,6 +64,10 @@
};
}
+export function getLineNumberCellWidth(prefs: DiffPreferencesInfo) {
+ return prefs.font_size * 4;
+}
+
@customElement('gr-diff-builder')
export class GrDiffBuilderElement extends PolymerElement {
static get template() {
@@ -212,7 +216,7 @@
this.$.processor.keyLocations = keyLocations;
this._clearDiffContent();
- this._builder.addColumns(this.diffElement, prefs.font_size);
+ this._builder.addColumns(this.diffElement, getLineNumberCellWidth(prefs));
const isBinary = !!(this.isImageDiff || this.diff.binary);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.ts
index da1d971..51360b9 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.ts
@@ -74,8 +74,7 @@
return sectionEl;
}
- addColumns(outputEl: HTMLElement, fontSize: number): void {
- const width = fontSize * 4;
+ addColumns(outputEl: HTMLElement, lineNumberWidth: number): void {
const colgroup = document.createElement('colgroup');
// Add the blame column.
@@ -84,7 +83,7 @@
// Add left-side line number.
col = this._createElement('col', 'left');
- col.setAttribute('width', width.toString());
+ col.setAttribute('width', lineNumberWidth.toString());
colgroup.appendChild(col);
// Add left-side content.
@@ -92,7 +91,7 @@
// Add right-side line number.
col = document.createElement('col');
- col.setAttribute('width', width.toString());
+ col.setAttribute('width', lineNumberWidth.toString());
colgroup.appendChild(col);
// Add right-side content.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.ts
index 4ecfcbf..a16aa07 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.ts
@@ -78,8 +78,7 @@
return sectionEl;
}
- addColumns(outputEl: HTMLElement, fontSize: number): void {
- const width = fontSize * 4;
+ addColumns(outputEl: HTMLElement, lineNumberWidth: number): void {
const colgroup = document.createElement('colgroup');
// Add the blame column.
@@ -88,12 +87,12 @@
// Add left-side line number.
col = document.createElement('col');
- col.setAttribute('width', width.toString());
+ col.setAttribute('width', lineNumberWidth.toString());
colgroup.appendChild(col);
// Add right-side line number.
col = document.createElement('col');
- col.setAttribute('width', width.toString());
+ col.setAttribute('width', lineNumberWidth.toString());
colgroup.appendChild(col);
// Add the content.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
index 5634238..eb50914 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
@@ -31,7 +31,11 @@
GrContextControlsShowConfig,
} from '../gr-context-controls/gr-context-controls';
import {BlameInfo} from '../../../types/common';
-import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
+import {
+ DiffInfo,
+ DiffPreferencesInfo,
+ DiffResponsiveMode,
+} from '../../../types/diff';
import {DiffViewMode, Side} from '../../../constants/constants';
import {DiffLayer} from '../../../types/types';
@@ -71,6 +75,20 @@
}
}
+export function getResponsiveMode(
+ prefs: DiffPreferencesInfo,
+ renderPrefs?: RenderPreferences
+): DiffResponsiveMode {
+ if (renderPrefs?.responsive_mode) {
+ return renderPrefs.responsive_mode;
+ }
+ // Backwards compatibility to the line_wrapping param.
+ if (prefs.line_wrapping) {
+ return 'FULL_RESPONSIVE';
+ }
+ return 'NONE';
+}
+
export abstract class GrDiffBuilder {
private readonly _diff: DiffInfo;
@@ -494,9 +512,11 @@
const {beforeNumber, afterNumber} = line;
if (beforeNumber !== 'FILE' && beforeNumber !== 'LOST') {
- const lineLimit = !this._prefs.line_wrapping
- ? this._prefs.line_length
- : Infinity;
+ const responsiveMode = getResponsiveMode(this._prefs, this._renderPrefs);
+ const lineLimit =
+ responsiveMode !== 'FULL_RESPONSIVE'
+ ? this._prefs.line_length
+ : Infinity;
const contentText = this._formatText(
line.text,
this._prefs.tab_size,
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
index 3d9bba7..fdde355 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
@@ -47,7 +47,10 @@
DiffPreferencesInfoKey,
} from '../../../types/diff';
import {GrDiffHighlight} from '../gr-diff-highlight/gr-diff-highlight';
-import {GrDiffBuilderElement} from '../gr-diff-builder/gr-diff-builder-element';
+import {
+ GrDiffBuilderElement,
+ getLineNumberCellWidth,
+} from '../gr-diff-builder/gr-diff-builder-element';
import {
CoverageRange,
DiffLayer,
@@ -74,7 +77,10 @@
import {isSafari, toggleClass} from '../../../utils/dom-util';
import {assertIsDefined} from '../../../utils/common-util';
import {debounce, DelayedTask} from '../../../utils/async-util';
-import {DiffContextExpandedEventDetail} from '../gr-diff-builder/gr-diff-builder';
+import {
+ DiffContextExpandedEventDetail,
+ getResponsiveMode,
+} from '../gr-diff-builder/gr-diff-builder';
const NO_NEWLINE_BASE = 'No newline at end of base file.';
const NO_NEWLINE_REVISION = 'No newline at end of revision file.';
@@ -726,33 +732,46 @@
if (!prefs) return;
this.blame = null;
+ this._updatePreferenceStyles(prefs, this.renderPrefs);
+ if (this.diff && !this.noRenderOnPrefsChange) {
+ this._debounceRenderDiffTable();
+ }
+ }
+
+ _updatePreferenceStyles(
+ prefs: DiffPreferencesInfo,
+ renderPrefs?: RenderPreferences
+ ) {
const lineLength =
this.path === COMMIT_MSG_PATH
? COMMIT_MSG_LINE_LENGTH
: prefs.line_length;
+ const sideBySide = this.viewMode === 'SIDE_BY_SIDE';
const stylesToUpdate: {[key: string]: string} = {};
- if (prefs.line_wrapping) {
- this._diffTableClass = 'full-width';
- if (this.viewMode === 'SIDE_BY_SIDE') {
- stylesToUpdate['--content-width'] = 'none';
- stylesToUpdate['--line-limit'] = `${lineLength}ch`;
- }
+ const responsiveMode = getResponsiveMode(prefs, renderPrefs);
+ const responsive =
+ responsiveMode === 'FULL_RESPONSIVE' || responsiveMode === 'SHRINK_ONLY';
+ this._diffTableClass = responsive ? 'responsive' : '';
+ const lineLimit = `${lineLength}ch`;
+ stylesToUpdate['--line-limit'] = lineLimit;
+ stylesToUpdate['--content-width'] = responsive ? 'none' : lineLimit;
+ if (responsiveMode === 'SHRINK_ONLY') {
+ // Calculating ideal (initial) width for the whole table.
+ const contentWidth = `${sideBySide ? 2 : 1} * ${lineLimit}`;
+ const lineNumberWidth = `2 * ${getLineNumberCellWidth(prefs)}px`;
+ stylesToUpdate[
+ '--diff-max-width'
+ ] = `calc(${contentWidth} + ${lineNumberWidth})`;
} else {
- this._diffTableClass = '';
- stylesToUpdate['--content-width'] = `${lineLength}ch`;
+ stylesToUpdate['--diff-max-width'] = 'none';
}
-
if (prefs.font_size) {
stylesToUpdate['--font-size'] = `${prefs.font_size}px`;
}
this.updateStyles(stylesToUpdate);
-
- if (this.diff && !this.noRenderOnPrefsChange) {
- this._debounceRenderDiffTable();
- }
}
_renderPrefsChanged(renderPrefs?: RenderPreferences) {
@@ -766,6 +785,9 @@
if (renderPrefs.hide_line_length_indicator) {
this.classList.add('hide-line-length-indicator');
}
+ if (this.prefs) {
+ this._updatePreferenceStyles(this.prefs, renderPrefs);
+ }
this.$.diffBuilder.updateRenderPrefs(renderPrefs);
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts
index d01943c..5b248da 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts
@@ -50,6 +50,9 @@
background-color: var(--diff-blank-background-color);
}
.diffContainer {
+ max-width: var(--diff-max-width, none);
+ }
+ .diffContainer {
display: flex;
font-family: var(--monospace-font-family);
@apply --diff-container-styles;
@@ -169,10 +172,10 @@
.image-diff .content {
background-color: var(--diff-blank-background-color);
}
- .full-width {
+ .responsive {
width: 100%;
}
- .full-width .contentText {
+ .responsive .contentText {
white-space: break-spaces;
word-wrap: break-word;
}
@@ -423,12 +426,12 @@
color: var(--link-color);
text-decoration: none;
}
- .full-width td.blame {
+ .responsive td.blame {
overflow: hidden;
width: 200px;
}
/** Support the line length indicator **/
- .full-width td.content .contentText {
+ .responsive td.content .contentText {
/*
Same strategy as in https://stackoverflow.com/questions/1179928/how-can-i-put-a-vertical-line-down-the-center-of-a-div
*/
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
index 53a2915..73b587b 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
@@ -36,7 +36,7 @@
suite('gr-diff tests', () => {
let element;
- const MINIMAL_PREFS = {tab_size: 2, line_length: 80};
+ const MINIMAL_PREFS = {tab_size: 2, line_length: 80, font_size: 12};
setup(() => {
@@ -85,7 +85,66 @@
element = basicFixture.instantiate();
element.prefs = {...MINIMAL_PREFS, line_wrapping: false};
flush();
- assert.isNotOk(getComputedStyleValue('--line-limit', element));
+ assert.equal(getComputedStyleValue('--line-limit', element), '80ch');
+ });
+ suite('FULL_RESPONSIVE mode', () => {
+ setup(() => {
+ element = basicFixture.instantiate();
+ element.prefs = {...MINIMAL_PREFS};
+ element.renderPrefs = {responsive_mode: 'FULL_RESPONSIVE'};
+ });
+
+ test('line limit is based on line_length', () => {
+ element.prefs = {...element.prefs, line_length: 100};
+ flush();
+ assert.equal(getComputedStyleValue('--line-limit', element), '100ch');
+ });
+
+ test('content-width should not be defined', () => {
+ flush();
+ assert.equal(getComputedStyleValue('--content-width', element), 'none');
+ });
+ });
+
+ suite('SHRINK_ONLY mode', () => {
+ setup(() => {
+ element = basicFixture.instantiate();
+ element.prefs = {...MINIMAL_PREFS};
+ element.renderPrefs = {responsive_mode: 'SHRINK_ONLY'};
+ });
+
+ test('line limit is based on line_length', () => {
+ element.prefs = {...element.prefs, line_length: 100};
+ flush();
+ assert.equal(getComputedStyleValue('--line-limit', element), '100ch');
+ });
+
+ test('content-width should not be defined', () => {
+ flush();
+ assert.equal(getComputedStyleValue('--content-width', element), 'none');
+ });
+
+ test('max-width considers two content columns in side-by-side', () => {
+ element.viewMode = 'SIDE_BY_SIDE';
+ flush();
+ assert.equal(getComputedStyleValue('--diff-max-width', element),
+ 'calc(2 * 80ch + 2 * 48px)');
+ });
+
+ test('max-width considers one content column in unified', () => {
+ element.viewMode = 'UNIFIED_DIFF';
+ flush();
+ assert.equal(getComputedStyleValue('--diff-max-width', element),
+ 'calc(1 * 80ch + 2 * 48px)');
+ });
+
+ test('max-width considers font-size', () => {
+ element.prefs = {...element.prefs, font_size: 13};
+ flush();
+ // Each line number column: 4 * 13 = 52px
+ assert.equal(getComputedStyleValue('--diff-max-width', element),
+ 'calc(2 * 80ch + 2 * 52px)');
+ });
});
suite('not logged in', () => {
diff --git a/polygerrit-ui/app/types/diff.ts b/polygerrit-ui/app/types/diff.ts
index 16338335..223f290 100644
--- a/polygerrit-ui/app/types/diff.ts
+++ b/polygerrit-ui/app/types/diff.ts
@@ -27,6 +27,7 @@
DiffFileMetaInfo as DiffFileMetaInfoApi,
DiffInfo as DiffInfoApi,
DiffIntralineInfo,
+ DiffResponsiveMode,
DiffPreferencesInfo as DiffPreferenceInfoApi,
IgnoreWhitespaceType,
MarkLength,
@@ -37,6 +38,7 @@
export {
ChangeType,
DiffIntralineInfo,
+ DiffResponsiveMode,
IgnoreWhitespaceType,
MarkLength,
MoveDetails,