Merge branch 'expand-diff-performance' into 'master'
Impove the performance of expanding full diff Closes #58597 See merge request gitlab-org/gitlab-ce!27413
This commit is contained in:
commit
6daf4d352e
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapActions, mapGetters, mapState } from 'vuex';
|
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||||
|
import { GlLoadingIcon } from '@gitlab/ui';
|
||||||
import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
|
import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
|
||||||
import draftCommentsMixin from 'ee_else_ce/diffs/mixins/draft_comments';
|
import draftCommentsMixin from 'ee_else_ce/diffs/mixins/draft_comments';
|
||||||
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
|
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
|
||||||
|
@ -16,6 +17,7 @@ import { diffViewerModes } from '~/ide/constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
GlLoadingIcon,
|
||||||
InlineDiffView,
|
InlineDiffView,
|
||||||
ParallelDiffView,
|
ParallelDiffView,
|
||||||
DiffViewer,
|
DiffViewer,
|
||||||
|
@ -108,6 +110,7 @@ export default {
|
||||||
:diff-lines="diffFile.parallel_diff_lines || []"
|
:diff-lines="diffFile.parallel_diff_lines || []"
|
||||||
:help-page-path="helpPagePath"
|
:help-page-path="helpPagePath"
|
||||||
/>
|
/>
|
||||||
|
<gl-loading-icon v-if="diffFile.renderingLines" size="md" class="mt-3" />
|
||||||
</template>
|
</template>
|
||||||
<not-diffable-viewer v-else-if="notDiffable" />
|
<not-diffable-viewer v-else-if="notDiffable" />
|
||||||
<no-preview-viewer v-else-if="noPreview" />
|
<no-preview-viewer v-else-if="noPreview" />
|
||||||
|
|
|
@ -84,8 +84,6 @@ export default {
|
||||||
},
|
},
|
||||||
shouldShowCommentButton() {
|
shouldShowCommentButton() {
|
||||||
return (
|
return (
|
||||||
this.isLoggedIn &&
|
|
||||||
this.showCommentButton &&
|
|
||||||
this.isHover &&
|
this.isHover &&
|
||||||
!this.isMatchLine &&
|
!this.isMatchLine &&
|
||||||
!this.isContextLine &&
|
!this.isContextLine &&
|
||||||
|
@ -102,6 +100,9 @@ export default {
|
||||||
}
|
}
|
||||||
return this.showCommentButton && this.hasDiscussions;
|
return this.showCommentButton && this.hasDiscussions;
|
||||||
},
|
},
|
||||||
|
shouldRenderCommentButton() {
|
||||||
|
return this.isLoggedIn && this.showCommentButton;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions('diffs', ['loadMoreLines', 'showCommentForm', 'setHighlightedRow']),
|
...mapActions('diffs', ['loadMoreLines', 'showCommentForm', 'setHighlightedRow']),
|
||||||
|
@ -167,6 +168,7 @@ export default {
|
||||||
>
|
>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<button
|
<button
|
||||||
|
v-if="shouldRenderCommentButton"
|
||||||
v-show="shouldShowCommentButton"
|
v-show="shouldShowCommentButton"
|
||||||
type="button"
|
type="button"
|
||||||
class="add-diff-note js-add-diff-note-button qa-diff-comment"
|
class="add-diff-note js-add-diff-note-button qa-diff-comment"
|
||||||
|
|
|
@ -89,17 +89,19 @@ export default {
|
||||||
classNameMap() {
|
classNameMap() {
|
||||||
const { type } = this.line;
|
const { type } = this.line;
|
||||||
|
|
||||||
return {
|
return [
|
||||||
hll: this.isHighlighted,
|
type,
|
||||||
[type]: type,
|
{
|
||||||
[LINE_UNFOLD_CLASS_NAME]: this.isMatchLine,
|
hll: this.isHighlighted,
|
||||||
[LINE_HOVER_CLASS_NAME]:
|
[LINE_UNFOLD_CLASS_NAME]: this.isMatchLine,
|
||||||
this.isLoggedIn &&
|
[LINE_HOVER_CLASS_NAME]:
|
||||||
this.isHover &&
|
this.isLoggedIn &&
|
||||||
!this.isMatchLine &&
|
this.isHover &&
|
||||||
!this.isContextLine &&
|
!this.isMatchLine &&
|
||||||
!this.isMetaLine,
|
!this.isContextLine &&
|
||||||
};
|
!this.isMetaLine,
|
||||||
|
},
|
||||||
|
];
|
||||||
},
|
},
|
||||||
lineNumber() {
|
lineNumber() {
|
||||||
return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line;
|
return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line;
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters, mapActions, mapState } from 'vuex';
|
import { mapActions, mapState } from 'vuex';
|
||||||
import DiffTableCell from './diff_table_cell.vue';
|
import DiffTableCell from './diff_table_cell.vue';
|
||||||
import {
|
import {
|
||||||
NEW_LINE_TYPE,
|
NEW_LINE_TYPE,
|
||||||
OLD_LINE_TYPE,
|
OLD_LINE_TYPE,
|
||||||
CONTEXT_LINE_TYPE,
|
CONTEXT_LINE_TYPE,
|
||||||
CONTEXT_LINE_CLASS_NAME,
|
CONTEXT_LINE_CLASS_NAME,
|
||||||
PARALLEL_DIFF_VIEW_TYPE,
|
|
||||||
LINE_POSITION_LEFT,
|
LINE_POSITION_LEFT,
|
||||||
LINE_POSITION_RIGHT,
|
LINE_POSITION_RIGHT,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
|
@ -45,16 +44,16 @@ export default {
|
||||||
return this.line.line_code !== null && this.line.line_code === state.diffs.highlightedRow;
|
return this.line.line_code !== null && this.line.line_code === state.diffs.highlightedRow;
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
...mapGetters('diffs', ['isInlineView']),
|
|
||||||
isContextLine() {
|
isContextLine() {
|
||||||
return this.line.type === CONTEXT_LINE_TYPE;
|
return this.line.type === CONTEXT_LINE_TYPE;
|
||||||
},
|
},
|
||||||
classNameMap() {
|
classNameMap() {
|
||||||
return {
|
return [
|
||||||
[this.line.type]: this.line.type,
|
this.line.type,
|
||||||
[CONTEXT_LINE_CLASS_NAME]: this.isContextLine,
|
{
|
||||||
[PARALLEL_DIFF_VIEW_TYPE]: this.isParallelView,
|
[CONTEXT_LINE_CLASS_NAME]: this.isContextLine,
|
||||||
};
|
},
|
||||||
|
];
|
||||||
},
|
},
|
||||||
inlineRowId() {
|
inlineRowId() {
|
||||||
return this.line.line_code || `${this.fileHash}_${this.line.old_line}_${this.line.new_line}`;
|
return this.line.line_code || `${this.fileHash}_${this.line.old_line}_${this.line.new_line}`;
|
||||||
|
|
|
@ -50,3 +50,10 @@ export const LEFT_LINE_KEY = 'left';
|
||||||
|
|
||||||
export const CENTERED_LIMITED_CONTAINER_CLASSES =
|
export const CENTERED_LIMITED_CONTAINER_CLASSES =
|
||||||
'container-limited limit-container-width mx-lg-auto px-3';
|
'container-limited limit-container-width mx-lg-auto px-3';
|
||||||
|
|
||||||
|
export const MAX_RENDERING_DIFF_LINES = 500;
|
||||||
|
export const MAX_RENDERING_BULK_ROWS = 30;
|
||||||
|
export const MIN_RENDERING_MS = 2;
|
||||||
|
export const START_RENDERING_INDEX = 200;
|
||||||
|
export const INLINE_DIFF_LINES_KEY = 'highlighted_diff_lines';
|
||||||
|
export const PARALLEL_DIFF_LINES_KEY = 'parallel_diff_lines';
|
||||||
|
|
|
@ -7,7 +7,12 @@ import { handleLocationHash, historyPushState, scrollToElement } from '~/lib/uti
|
||||||
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
|
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
|
||||||
import TreeWorker from '../workers/tree_worker';
|
import TreeWorker from '../workers/tree_worker';
|
||||||
import eventHub from '../../notes/event_hub';
|
import eventHub from '../../notes/event_hub';
|
||||||
import { getDiffPositionByLineCode, getNoteFormData } from './utils';
|
import {
|
||||||
|
getDiffPositionByLineCode,
|
||||||
|
getNoteFormData,
|
||||||
|
convertExpandLines,
|
||||||
|
idleCallback,
|
||||||
|
} from './utils';
|
||||||
import * as types from './mutation_types';
|
import * as types from './mutation_types';
|
||||||
import {
|
import {
|
||||||
PARALLEL_DIFF_VIEW_TYPE,
|
PARALLEL_DIFF_VIEW_TYPE,
|
||||||
|
@ -17,6 +22,16 @@ import {
|
||||||
TREE_LIST_STORAGE_KEY,
|
TREE_LIST_STORAGE_KEY,
|
||||||
WHITESPACE_STORAGE_KEY,
|
WHITESPACE_STORAGE_KEY,
|
||||||
TREE_LIST_WIDTH_STORAGE_KEY,
|
TREE_LIST_WIDTH_STORAGE_KEY,
|
||||||
|
OLD_LINE_KEY,
|
||||||
|
NEW_LINE_KEY,
|
||||||
|
TYPE_KEY,
|
||||||
|
LEFT_LINE_KEY,
|
||||||
|
MAX_RENDERING_DIFF_LINES,
|
||||||
|
MAX_RENDERING_BULK_ROWS,
|
||||||
|
MIN_RENDERING_MS,
|
||||||
|
START_RENDERING_INDEX,
|
||||||
|
INLINE_DIFF_LINES_KEY,
|
||||||
|
PARALLEL_DIFF_LINES_KEY,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { diffViewerModes } from '~/ide/constants';
|
import { diffViewerModes } from '~/ide/constants';
|
||||||
|
|
||||||
|
@ -313,13 +328,98 @@ export const cacheTreeListWidth = (_, size) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const requestFullDiff = ({ commit }, filePath) => commit(types.REQUEST_FULL_DIFF, filePath);
|
export const requestFullDiff = ({ commit }, filePath) => commit(types.REQUEST_FULL_DIFF, filePath);
|
||||||
export const receiveFullDiffSucess = ({ commit }, { filePath, data }) =>
|
export const receiveFullDiffSucess = ({ commit }, { filePath }) =>
|
||||||
commit(types.RECEIVE_FULL_DIFF_SUCCESS, { filePath, data });
|
commit(types.RECEIVE_FULL_DIFF_SUCCESS, { filePath });
|
||||||
export const receiveFullDiffError = ({ commit }, filePath) => {
|
export const receiveFullDiffError = ({ commit }, filePath) => {
|
||||||
commit(types.RECEIVE_FULL_DIFF_ERROR, filePath);
|
commit(types.RECEIVE_FULL_DIFF_ERROR, filePath);
|
||||||
createFlash(s__('MergeRequest|Error loading full diff. Please try again.'));
|
createFlash(s__('MergeRequest|Error loading full diff. Please try again.'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const setExpandedDiffLines = ({ commit, state }, { file, data }) => {
|
||||||
|
const expandedDiffLines = {
|
||||||
|
highlighted_diff_lines: convertExpandLines({
|
||||||
|
diffLines: file.highlighted_diff_lines,
|
||||||
|
typeKey: TYPE_KEY,
|
||||||
|
oldLineKey: OLD_LINE_KEY,
|
||||||
|
newLineKey: NEW_LINE_KEY,
|
||||||
|
data,
|
||||||
|
mapLine: ({ line, oldLine, newLine }) =>
|
||||||
|
Object.assign(line, {
|
||||||
|
old_line: oldLine,
|
||||||
|
new_line: newLine,
|
||||||
|
line_code: `${file.file_hash}_${oldLine}_${newLine}`,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
parallel_diff_lines: convertExpandLines({
|
||||||
|
diffLines: file.parallel_diff_lines,
|
||||||
|
typeKey: [LEFT_LINE_KEY, TYPE_KEY],
|
||||||
|
oldLineKey: [LEFT_LINE_KEY, OLD_LINE_KEY],
|
||||||
|
newLineKey: [LEFT_LINE_KEY, NEW_LINE_KEY],
|
||||||
|
data,
|
||||||
|
mapLine: ({ line, oldLine, newLine }) => ({
|
||||||
|
left: {
|
||||||
|
...line,
|
||||||
|
old_line: oldLine,
|
||||||
|
line_code: `${file.file_hash}_${oldLine}_${newLine}`,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
...line,
|
||||||
|
new_line: newLine,
|
||||||
|
line_code: `${file.file_hash}_${newLine}_${oldLine}`,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
const currentDiffLinesKey =
|
||||||
|
state.diffViewType === INLINE_DIFF_VIEW_TYPE ? INLINE_DIFF_LINES_KEY : PARALLEL_DIFF_LINES_KEY;
|
||||||
|
const hiddenDiffLinesKey =
|
||||||
|
state.diffViewType === INLINE_DIFF_VIEW_TYPE ? PARALLEL_DIFF_LINES_KEY : INLINE_DIFF_LINES_KEY;
|
||||||
|
|
||||||
|
commit(types.SET_HIDDEN_VIEW_DIFF_FILE_LINES, {
|
||||||
|
filePath: file.file_path,
|
||||||
|
lines: expandedDiffLines[hiddenDiffLinesKey],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (expandedDiffLines[currentDiffLinesKey].length > MAX_RENDERING_DIFF_LINES) {
|
||||||
|
let index = START_RENDERING_INDEX;
|
||||||
|
commit(types.SET_CURRENT_VIEW_DIFF_FILE_LINES, {
|
||||||
|
filePath: file.file_path,
|
||||||
|
lines: expandedDiffLines[currentDiffLinesKey].slice(0, index),
|
||||||
|
});
|
||||||
|
commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path);
|
||||||
|
|
||||||
|
const idleCb = t => {
|
||||||
|
const startIndex = index;
|
||||||
|
|
||||||
|
while (
|
||||||
|
t.timeRemaining() >= MIN_RENDERING_MS &&
|
||||||
|
index !== expandedDiffLines[currentDiffLinesKey].length &&
|
||||||
|
index - startIndex !== MAX_RENDERING_BULK_ROWS
|
||||||
|
) {
|
||||||
|
const line = expandedDiffLines[currentDiffLinesKey][index];
|
||||||
|
|
||||||
|
if (line) {
|
||||||
|
commit(types.ADD_CURRENT_VIEW_DIFF_FILE_LINES, { filePath: file.file_path, line });
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index !== expandedDiffLines[currentDiffLinesKey].length) {
|
||||||
|
idleCallback(idleCb);
|
||||||
|
} else {
|
||||||
|
commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
idleCallback(idleCb);
|
||||||
|
} else {
|
||||||
|
commit(types.SET_CURRENT_VIEW_DIFF_FILE_LINES, {
|
||||||
|
filePath: file.file_path,
|
||||||
|
lines: expandedDiffLines[currentDiffLinesKey],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const fetchFullDiff = ({ dispatch }, file) =>
|
export const fetchFullDiff = ({ dispatch }, file) =>
|
||||||
axios
|
axios
|
||||||
.get(file.context_lines_path, {
|
.get(file.context_lines_path, {
|
||||||
|
@ -328,8 +428,10 @@ export const fetchFullDiff = ({ dispatch }, file) =>
|
||||||
from_merge_request: true,
|
from_merge_request: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(({ data }) => dispatch('receiveFullDiffSucess', { filePath: file.file_path, data }))
|
.then(({ data }) => {
|
||||||
.then(() => scrollToElement(`#${file.file_hash}`))
|
dispatch('receiveFullDiffSucess', { filePath: file.file_path });
|
||||||
|
dispatch('setExpandedDiffLines', { file, data });
|
||||||
|
})
|
||||||
.catch(() => dispatch('receiveFullDiffError', file.file_path));
|
.catch(() => dispatch('receiveFullDiffError', file.file_path));
|
||||||
|
|
||||||
export const toggleFullDiff = ({ dispatch, getters, state }, filePath) => {
|
export const toggleFullDiff = ({ dispatch, getters, state }, filePath) => {
|
||||||
|
@ -340,7 +442,6 @@ export const toggleFullDiff = ({ dispatch, getters, state }, filePath) => {
|
||||||
if (file.isShowingFullFile) {
|
if (file.isShowingFullFile) {
|
||||||
dispatch('loadCollapsedDiff', file)
|
dispatch('loadCollapsedDiff', file)
|
||||||
.then(() => dispatch('assignDiscussionsToDiff', getters.getDiffFileDiscussions(file)))
|
.then(() => dispatch('assignDiscussionsToDiff', getters.getDiffFileDiscussions(file)))
|
||||||
.then(() => scrollToElement(`#${file.file_hash}`))
|
|
||||||
.catch(() => dispatch('receiveFullDiffError', filePath));
|
.catch(() => dispatch('receiveFullDiffError', filePath));
|
||||||
} else {
|
} else {
|
||||||
dispatch('fetchFullDiff', file);
|
dispatch('fetchFullDiff', file);
|
||||||
|
|
|
@ -28,3 +28,8 @@ export const REQUEST_FULL_DIFF = 'REQUEST_FULL_DIFF';
|
||||||
export const RECEIVE_FULL_DIFF_SUCCESS = 'RECEIVE_FULL_DIFF_SUCCESS';
|
export const RECEIVE_FULL_DIFF_SUCCESS = 'RECEIVE_FULL_DIFF_SUCCESS';
|
||||||
export const RECEIVE_FULL_DIFF_ERROR = 'RECEIVE_FULL_DIFF_ERROR';
|
export const RECEIVE_FULL_DIFF_ERROR = 'RECEIVE_FULL_DIFF_ERROR';
|
||||||
export const SET_FILE_COLLAPSED = 'SET_FILE_COLLAPSED';
|
export const SET_FILE_COLLAPSED = 'SET_FILE_COLLAPSED';
|
||||||
|
|
||||||
|
export const SET_HIDDEN_VIEW_DIFF_FILE_LINES = 'SET_HIDDEN_VIEW_DIFF_FILE_LINES';
|
||||||
|
export const SET_CURRENT_VIEW_DIFF_FILE_LINES = 'SET_CURRENT_VIEW_DIFF_FILE_LINES';
|
||||||
|
export const ADD_CURRENT_VIEW_DIFF_FILE_LINES = 'ADD_CURRENT_VIEW_DIFF_FILE_LINES';
|
||||||
|
export const TOGGLE_DIFF_FILE_RENDERING_MORE = 'TOGGLE_DIFF_FILE_RENDERING_MORE';
|
||||||
|
|
|
@ -6,10 +6,8 @@ import {
|
||||||
addContextLines,
|
addContextLines,
|
||||||
prepareDiffData,
|
prepareDiffData,
|
||||||
isDiscussionApplicableToLine,
|
isDiscussionApplicableToLine,
|
||||||
convertExpandLines,
|
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import * as types from './mutation_types';
|
import * as types from './mutation_types';
|
||||||
import { OLD_LINE_KEY, NEW_LINE_KEY, TYPE_KEY, LEFT_LINE_KEY } from '../constants';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
[types.SET_BASE_CONFIG](state, options) {
|
[types.SET_BASE_CONFIG](state, options) {
|
||||||
|
@ -265,45 +263,11 @@ export default {
|
||||||
|
|
||||||
file.isLoadingFullFile = false;
|
file.isLoadingFullFile = false;
|
||||||
},
|
},
|
||||||
[types.RECEIVE_FULL_DIFF_SUCCESS](state, { filePath, data }) {
|
[types.RECEIVE_FULL_DIFF_SUCCESS](state, { filePath }) {
|
||||||
const file = findDiffFile(state.diffFiles, filePath, 'file_path');
|
const file = findDiffFile(state.diffFiles, filePath, 'file_path');
|
||||||
|
|
||||||
file.isShowingFullFile = true;
|
file.isShowingFullFile = true;
|
||||||
file.isLoadingFullFile = false;
|
file.isLoadingFullFile = false;
|
||||||
|
|
||||||
file.highlighted_diff_lines = convertExpandLines({
|
|
||||||
diffLines: file.highlighted_diff_lines,
|
|
||||||
typeKey: [TYPE_KEY],
|
|
||||||
oldLineKey: [OLD_LINE_KEY],
|
|
||||||
newLineKey: [NEW_LINE_KEY],
|
|
||||||
data,
|
|
||||||
mapLine: ({ line, oldLine, newLine }) => ({
|
|
||||||
...line,
|
|
||||||
old_line: oldLine,
|
|
||||||
new_line: newLine,
|
|
||||||
line_code: `${file.file_hash}_${oldLine}_${newLine}`,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
file.parallel_diff_lines = convertExpandLines({
|
|
||||||
diffLines: file.parallel_diff_lines,
|
|
||||||
typeKey: [LEFT_LINE_KEY, TYPE_KEY],
|
|
||||||
oldLineKey: [LEFT_LINE_KEY, OLD_LINE_KEY],
|
|
||||||
newLineKey: [LEFT_LINE_KEY, NEW_LINE_KEY],
|
|
||||||
data,
|
|
||||||
mapLine: ({ line, oldLine, newLine }) => ({
|
|
||||||
left: {
|
|
||||||
...line,
|
|
||||||
old_line: oldLine,
|
|
||||||
line_code: `${file.file_hash}_${oldLine}_${newLine}`,
|
|
||||||
},
|
|
||||||
right: {
|
|
||||||
...line,
|
|
||||||
new_line: newLine,
|
|
||||||
line_code: `${file.file_hash}_${newLine}_${oldLine}`,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[types.SET_FILE_COLLAPSED](state, { filePath, collapsed }) {
|
[types.SET_FILE_COLLAPSED](state, { filePath, collapsed }) {
|
||||||
const file = state.diffFiles.find(f => f.file_path === filePath);
|
const file = state.diffFiles.find(f => f.file_path === filePath);
|
||||||
|
@ -312,4 +276,30 @@ export default {
|
||||||
file.viewer.collapsed = collapsed;
|
file.viewer.collapsed = collapsed;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
[types.SET_HIDDEN_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) {
|
||||||
|
const file = state.diffFiles.find(f => f.file_path === filePath);
|
||||||
|
const hiddenDiffLinesKey =
|
||||||
|
state.diffViewType === 'inline' ? 'parallel_diff_lines' : 'highlighted_diff_lines';
|
||||||
|
|
||||||
|
file[hiddenDiffLinesKey] = lines;
|
||||||
|
},
|
||||||
|
[types.SET_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) {
|
||||||
|
const file = state.diffFiles.find(f => f.file_path === filePath);
|
||||||
|
const currentDiffLinesKey =
|
||||||
|
state.diffViewType === 'inline' ? 'highlighted_diff_lines' : 'parallel_diff_lines';
|
||||||
|
|
||||||
|
file[currentDiffLinesKey] = lines;
|
||||||
|
},
|
||||||
|
[types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, line }) {
|
||||||
|
const file = state.diffFiles.find(f => f.file_path === filePath);
|
||||||
|
const currentDiffLinesKey =
|
||||||
|
state.diffViewType === 'inline' ? 'highlighted_diff_lines' : 'parallel_diff_lines';
|
||||||
|
|
||||||
|
file[currentDiffLinesKey].push(line);
|
||||||
|
},
|
||||||
|
[types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, filePath) {
|
||||||
|
const file = state.diffFiles.find(f => f.file_path === filePath);
|
||||||
|
|
||||||
|
file.renderingLines = !file.renderingLines;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -253,6 +253,7 @@ export function prepareDiffData(diffData) {
|
||||||
isShowingFullFile: false,
|
isShowingFullFile: false,
|
||||||
isLoadingFullFile: false,
|
isLoadingFullFile: false,
|
||||||
discussions: [],
|
discussions: [],
|
||||||
|
renderingLines: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,27 +424,33 @@ export const convertExpandLines = ({
|
||||||
mapLine,
|
mapLine,
|
||||||
}) => {
|
}) => {
|
||||||
const dataLength = data.length;
|
const dataLength = data.length;
|
||||||
|
const lines = [];
|
||||||
|
|
||||||
|
for (let i = 0, diffLinesLength = diffLines.length; i < diffLinesLength; i += 1) {
|
||||||
|
const line = diffLines[i];
|
||||||
|
|
||||||
return diffLines.reduce((acc, line, i) => {
|
|
||||||
if (_.property(typeKey)(line) === 'match') {
|
if (_.property(typeKey)(line) === 'match') {
|
||||||
const beforeLine = diffLines[i - 1];
|
const beforeLine = diffLines[i - 1];
|
||||||
const afterLine = diffLines[i + 1];
|
const afterLine = diffLines[i + 1];
|
||||||
const beforeLineIndex = _.property(newLineKey)(beforeLine) || 0;
|
const newLineProperty = _.property(newLineKey);
|
||||||
const afterLineIndex = _.property(newLineKey)(afterLine) - 1 || dataLength;
|
const beforeLineIndex = newLineProperty(beforeLine) || 0;
|
||||||
|
const afterLineIndex = newLineProperty(afterLine) - 1 || dataLength;
|
||||||
|
|
||||||
acc.push(
|
lines.push(
|
||||||
...data.slice(beforeLineIndex, afterLineIndex).map((l, index) => ({
|
...data.slice(beforeLineIndex, afterLineIndex).map((l, index) =>
|
||||||
...mapLine({
|
mapLine({
|
||||||
line: { ...l, hasForm: false, discussions: [] },
|
line: Object.assign(l, { hasForm: false, discussions: [] }),
|
||||||
oldLine: (_.property(oldLineKey)(beforeLine) || 0) + index + 1,
|
oldLine: (_.property(oldLineKey)(beforeLine) || 0) + index + 1,
|
||||||
newLine: (_.property(newLineKey)(beforeLine) || 0) + index + 1,
|
newLine: (newLineProperty(beforeLine) || 0) + index + 1,
|
||||||
}),
|
}),
|
||||||
})),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
acc.push(line);
|
lines.push(line);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return acc;
|
return lines;
|
||||||
}, []);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const idleCallback = cb => requestIdleCallback(cb);
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Improve expanding diff to full file performance
|
||||||
|
merge_request:
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -29,6 +29,10 @@ describe('DiffContent', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vm.$destroy();
|
||||||
|
});
|
||||||
|
|
||||||
describe('text based files', () => {
|
describe('text based files', () => {
|
||||||
it('should render diff inline view', done => {
|
it('should render diff inline view', done => {
|
||||||
vm.$store.state.diffs.diffViewType = 'inline';
|
vm.$store.state.diffs.diffViewType = 'inline';
|
||||||
|
@ -49,6 +53,16 @@ describe('DiffContent', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders rendering more lines loading icon', done => {
|
||||||
|
vm.diffFile.renderingLines = true;
|
||||||
|
|
||||||
|
vm.$nextTick(() => {
|
||||||
|
expect(vm.$el.querySelector('.loading-container')).not.toBe(null);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('empty files', () => {
|
describe('empty files', () => {
|
||||||
|
|
|
@ -240,4 +240,5 @@ export default {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
discussions: [],
|
discussions: [],
|
||||||
|
renderingLines: false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,6 +36,7 @@ import actions, {
|
||||||
fetchFullDiff,
|
fetchFullDiff,
|
||||||
toggleFullDiff,
|
toggleFullDiff,
|
||||||
setFileCollapsed,
|
setFileCollapsed,
|
||||||
|
setExpandedDiffLines,
|
||||||
} from '~/diffs/store/actions';
|
} from '~/diffs/store/actions';
|
||||||
import eventHub from '~/notes/event_hub';
|
import eventHub from '~/notes/event_hub';
|
||||||
import * as types from '~/diffs/store/mutation_types';
|
import * as types from '~/diffs/store/mutation_types';
|
||||||
|
@ -879,9 +880,9 @@ describe('DiffsStoreActions', () => {
|
||||||
it('commits REQUEST_FULL_DIFF', done => {
|
it('commits REQUEST_FULL_DIFF', done => {
|
||||||
testAction(
|
testAction(
|
||||||
receiveFullDiffSucess,
|
receiveFullDiffSucess,
|
||||||
{ filePath: 'test', data: 'test' },
|
{ filePath: 'test' },
|
||||||
{},
|
{},
|
||||||
[{ type: types.RECEIVE_FULL_DIFF_SUCCESS, payload: { filePath: 'test', data: 'test' } }],
|
[{ type: types.RECEIVE_FULL_DIFF_SUCCESS, payload: { filePath: 'test' } }],
|
||||||
[],
|
[],
|
||||||
done,
|
done,
|
||||||
);
|
);
|
||||||
|
@ -903,11 +904,8 @@ describe('DiffsStoreActions', () => {
|
||||||
|
|
||||||
describe('fetchFullDiff', () => {
|
describe('fetchFullDiff', () => {
|
||||||
let mock;
|
let mock;
|
||||||
let scrollToElementSpy;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
scrollToElementSpy = spyOnDependency(actions, 'scrollToElement').and.stub();
|
|
||||||
|
|
||||||
mock = new MockAdapter(axios);
|
mock = new MockAdapter(axios);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -921,28 +919,23 @@ describe('DiffsStoreActions', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dispatches receiveFullDiffSucess', done => {
|
it('dispatches receiveFullDiffSucess', done => {
|
||||||
|
const file = {
|
||||||
|
context_lines_path: `${gl.TEST_HOST}/context`,
|
||||||
|
file_path: 'test',
|
||||||
|
file_hash: 'test',
|
||||||
|
};
|
||||||
testAction(
|
testAction(
|
||||||
fetchFullDiff,
|
fetchFullDiff,
|
||||||
{ context_lines_path: `${gl.TEST_HOST}/context`, file_path: 'test', file_hash: 'test' },
|
file,
|
||||||
null,
|
null,
|
||||||
[],
|
[],
|
||||||
[{ type: 'receiveFullDiffSucess', payload: { filePath: 'test', data: ['test'] } }],
|
[
|
||||||
|
{ type: 'receiveFullDiffSucess', payload: { filePath: 'test' } },
|
||||||
|
{ type: 'setExpandedDiffLines', payload: { file, data: ['test'] } },
|
||||||
|
],
|
||||||
done,
|
done,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('scrolls to element', done => {
|
|
||||||
fetchFullDiff(
|
|
||||||
{ dispatch() {} },
|
|
||||||
{ context_lines_path: `${gl.TEST_HOST}/context`, file_path: 'test', file_hash: 'test' },
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
expect(scrollToElementSpy).toHaveBeenCalledWith('#test');
|
|
||||||
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(done.fail);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('error', () => {
|
describe('error', () => {
|
||||||
|
@ -999,4 +992,63 @@ describe('DiffsStoreActions', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('setExpandedDiffLines', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOnDependency(actions, 'idleCallback').and.callFake(cb => {
|
||||||
|
cb({ timeRemaining: () => 50 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('commits SET_CURRENT_VIEW_DIFF_FILE_LINES when lines less than MAX_RENDERING_DIFF_LINES', done => {
|
||||||
|
spyOnDependency(actions, 'convertExpandLines').and.callFake(() => ['test']);
|
||||||
|
|
||||||
|
testAction(
|
||||||
|
setExpandedDiffLines,
|
||||||
|
{ file: { file_path: 'path' }, data: [] },
|
||||||
|
{ diffViewType: 'inline' },
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: 'SET_HIDDEN_VIEW_DIFF_FILE_LINES',
|
||||||
|
payload: { filePath: 'path', lines: ['test'] },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'SET_CURRENT_VIEW_DIFF_FILE_LINES',
|
||||||
|
payload: { filePath: 'path', lines: ['test'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
done,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('commits ADD_CURRENT_VIEW_DIFF_FILE_LINES when lines more than MAX_RENDERING_DIFF_LINES', done => {
|
||||||
|
const lines = new Array(501).fill().map((_, i) => `line-${i}`);
|
||||||
|
spyOnDependency(actions, 'convertExpandLines').and.callFake(() => lines);
|
||||||
|
|
||||||
|
testAction(
|
||||||
|
setExpandedDiffLines,
|
||||||
|
{ file: { file_path: 'path' }, data: [] },
|
||||||
|
{ diffViewType: 'inline' },
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: 'SET_HIDDEN_VIEW_DIFF_FILE_LINES',
|
||||||
|
payload: { filePath: 'path', lines },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'SET_CURRENT_VIEW_DIFF_FILE_LINES',
|
||||||
|
payload: { filePath: 'path', lines: lines.slice(0, 200) },
|
||||||
|
},
|
||||||
|
{ type: 'TOGGLE_DIFF_FILE_RENDERING_MORE', payload: 'path' },
|
||||||
|
...new Array(301).fill().map((_, i) => ({
|
||||||
|
type: 'ADD_CURRENT_VIEW_DIFF_FILE_LINES',
|
||||||
|
payload: { filePath: 'path', line: `line-${i + 200}` },
|
||||||
|
})),
|
||||||
|
{ type: 'TOGGLE_DIFF_FILE_RENDERING_MORE', payload: 'path' },
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
done,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -756,4 +756,98 @@ describe('DiffsStoreMutations', () => {
|
||||||
expect(state.diffFiles[0].viewer.collapsed).toBe(true);
|
expect(state.diffFiles[0].viewer.collapsed).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('SET_HIDDEN_VIEW_DIFF_FILE_LINES', () => {
|
||||||
|
[
|
||||||
|
{ current: 'highlighted', hidden: 'parallel', diffViewType: 'inline' },
|
||||||
|
{ current: 'parallel', hidden: 'highlighted', diffViewType: 'parallel' },
|
||||||
|
].forEach(({ current, hidden, diffViewType }) => {
|
||||||
|
it(`sets the ${hidden} lines when diff view is ${diffViewType}`, () => {
|
||||||
|
const file = { file_path: 'test', parallel_diff_lines: [], highlighted_diff_lines: [] };
|
||||||
|
const state = {
|
||||||
|
diffFiles: [file],
|
||||||
|
diffViewType,
|
||||||
|
};
|
||||||
|
|
||||||
|
mutations[types.SET_HIDDEN_VIEW_DIFF_FILE_LINES](state, {
|
||||||
|
filePath: 'test',
|
||||||
|
lines: ['test'],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(file[`${current}_diff_lines`]).toEqual([]);
|
||||||
|
expect(file[`${hidden}_diff_lines`]).toEqual(['test']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('SET_CURRENT_VIEW_DIFF_FILE_LINES', () => {
|
||||||
|
[
|
||||||
|
{ current: 'highlighted', hidden: 'parallel', diffViewType: 'inline' },
|
||||||
|
{ current: 'parallel', hidden: 'highlighted', diffViewType: 'parallel' },
|
||||||
|
].forEach(({ current, hidden, diffViewType }) => {
|
||||||
|
it(`sets the ${current} lines when diff view is ${diffViewType}`, () => {
|
||||||
|
const file = { file_path: 'test', parallel_diff_lines: [], highlighted_diff_lines: [] };
|
||||||
|
const state = {
|
||||||
|
diffFiles: [file],
|
||||||
|
diffViewType,
|
||||||
|
};
|
||||||
|
|
||||||
|
mutations[types.SET_CURRENT_VIEW_DIFF_FILE_LINES](state, {
|
||||||
|
filePath: 'test',
|
||||||
|
lines: ['test'],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(file[`${current}_diff_lines`]).toEqual(['test']);
|
||||||
|
expect(file[`${hidden}_diff_lines`]).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ADD_CURRENT_VIEW_DIFF_FILE_LINES', () => {
|
||||||
|
[
|
||||||
|
{ current: 'highlighted', hidden: 'parallel', diffViewType: 'inline' },
|
||||||
|
{ current: 'parallel', hidden: 'highlighted', diffViewType: 'parallel' },
|
||||||
|
].forEach(({ current, hidden, diffViewType }) => {
|
||||||
|
it(`pushes to ${current} lines when diff view is ${diffViewType}`, () => {
|
||||||
|
const file = { file_path: 'test', parallel_diff_lines: [], highlighted_diff_lines: [] };
|
||||||
|
const state = {
|
||||||
|
diffFiles: [file],
|
||||||
|
diffViewType,
|
||||||
|
};
|
||||||
|
|
||||||
|
mutations[types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, {
|
||||||
|
filePath: 'test',
|
||||||
|
line: 'test',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(file[`${current}_diff_lines`]).toEqual(['test']);
|
||||||
|
expect(file[`${hidden}_diff_lines`]).toEqual([]);
|
||||||
|
|
||||||
|
mutations[types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, {
|
||||||
|
filePath: 'test',
|
||||||
|
line: 'test2',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(file[`${current}_diff_lines`]).toEqual(['test', 'test2']);
|
||||||
|
expect(file[`${hidden}_diff_lines`]).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('TOGGLE_DIFF_FILE_RENDERING_MORE', () => {
|
||||||
|
it('toggles renderingLines on file', () => {
|
||||||
|
const file = { file_path: 'test', renderingLines: false };
|
||||||
|
const state = {
|
||||||
|
diffFiles: [file],
|
||||||
|
};
|
||||||
|
|
||||||
|
mutations[types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, 'test');
|
||||||
|
|
||||||
|
expect(file.renderingLines).toBe(true);
|
||||||
|
|
||||||
|
mutations[types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, 'test');
|
||||||
|
|
||||||
|
expect(file.renderingLines).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue