Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 14:59:07 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 14:59:07 +0300
commit8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch)
tree544930fb309b30317ae9797a9683768705d664c4 /app/assets/javascripts/diffs
parent4b1de649d0168371549608993deac953eb692019 (diff)
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/diffs')
-rw-r--r--app/assets/javascripts/diffs/components/app.vue56
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue7
-rw-r--r--app/assets/javascripts/diffs/components/compare_dropdown_layout.vue85
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue8
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue26
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue24
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue3
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_row.vue4
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue12
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue28
-rw-r--r--app/assets/javascripts/diffs/components/image_diff_overlay.vue45
-rw-r--r--app/assets/javascripts/diffs/components/merge_conflict_warning.vue8
-rw-r--r--app/assets/javascripts/diffs/components/settings_dropdown.vue41
-rw-r--r--app/assets/javascripts/diffs/constants.js6
-rw-r--r--app/assets/javascripts/diffs/i18n.js4
-rw-r--r--app/assets/javascripts/diffs/index.js2
-rw-r--r--app/assets/javascripts/diffs/store/actions.js159
-rw-r--r--app/assets/javascripts/diffs/store/getters.js48
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js3
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js6
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js105
-rw-r--r--app/assets/javascripts/diffs/store/utils.js196
-rw-r--r--app/assets/javascripts/diffs/utils/diff_file.js (renamed from app/assets/javascripts/diffs/diff_file.js)24
-rw-r--r--app/assets/javascripts/diffs/utils/preferences.js22
25 files changed, 378 insertions, 546 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 9d8d184a3f6..7827c78b658 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -1,6 +1,7 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui';
+import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Mousetrap from 'mousetrap';
import { __ } from '~/locale';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
@@ -9,7 +10,10 @@ import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { isSingleViewStyle } from '~/helpers/diffs_helper';
import { updateHistory } from '~/lib/utils/url_utility';
-import eventHub from '../../notes/event_hub';
+
+import notesEventHub from '../../notes/event_hub';
+import eventHub from '../event_hub';
+
import CompareVersions from './compare_versions.vue';
import DiffFile from './diff_file.vue';
import NoChanges from './no_changes.vue';
@@ -21,6 +25,7 @@ import MergeConflictWarning from './merge_conflict_warning.vue';
import CollapsedFilesWarning from './collapsed_files_warning.vue';
import { diffsApp } from '../utils/performance';
+import { fileByFile } from '../utils/preferences';
import {
TREE_LIST_WIDTH_STORAGE_KEY,
@@ -33,6 +38,7 @@ import {
ALERT_OVERFLOW_HIDDEN,
ALERT_MERGE_CONFLICT,
ALERT_COLLAPSED_FILES,
+ EVT_VIEW_FILE_BY_FILE,
} from '../constants';
export default {
@@ -113,7 +119,7 @@ export default {
required: false,
default: false,
},
- viewDiffsFileByFile: {
+ fileByFileUserPreference: {
type: Boolean,
required: false,
default: false,
@@ -153,6 +159,7 @@ export default {
'conflictResolutionPath',
'canMerge',
'hasConflicts',
+ 'viewDiffsFileByFile',
]),
...mapGetters('diffs', ['whichCollapsedTypes', 'isParallelView', 'currentDiffIndex']),
...mapGetters(['isNotesFetched', 'getNoteableData']),
@@ -230,9 +237,6 @@ export default {
}
},
diffViewType() {
- if (!this.glFeatures.unifiedDiffLines && (this.needsReload() || this.needsFirstLoad())) {
- this.refetchDiffData();
- }
this.adjustView();
},
shouldShow() {
@@ -256,7 +260,7 @@ export default {
projectPath: this.projectPath,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
- viewDiffsFileByFile: this.viewDiffsFileByFile,
+ viewDiffsFileByFile: fileByFile(this.fileByFileUserPreference),
});
if (this.shouldShow) {
@@ -279,9 +283,8 @@ export default {
},
created() {
this.adjustView();
+ this.subscribeToEvents();
- eventHub.$once('fetchDiffData', this.fetchData);
- eventHub.$on('refetchDiffData', this.refetchDiffData);
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
this.unwatchDiscussions = this.$watch(
@@ -301,9 +304,7 @@ export default {
},
beforeDestroy() {
diffsApp.deinstrument();
-
- eventHub.$off('fetchDiffData', this.fetchData);
- eventHub.$off('refetchDiffData', this.refetchDiffData);
+ this.unsubscribeFromEvents();
this.removeEventListeners();
},
methods: {
@@ -319,9 +320,23 @@ export default {
'setHighlightedRow',
'cacheTreeListWidth',
'scrollToFile',
- 'toggleShowTreeList',
+ 'setShowTreeList',
'navigateToDiffFileIndex',
+ 'setFileByFile',
]),
+ subscribeToEvents() {
+ notesEventHub.$once('fetchDiffData', this.fetchData);
+ notesEventHub.$on('refetchDiffData', this.refetchDiffData);
+ eventHub.$on(EVT_VIEW_FILE_BY_FILE, this.fileByFileListener);
+ },
+ unsubscribeFromEvents() {
+ eventHub.$off(EVT_VIEW_FILE_BY_FILE, this.fileByFileListener);
+ notesEventHub.$off('refetchDiffData', this.refetchDiffData);
+ notesEventHub.$off('fetchDiffData', this.fetchData);
+ },
+ fileByFileListener({ setting } = {}) {
+ this.setFileByFile({ fileByFile: setting });
+ },
navigateToDiffFileNumber(number) {
this.navigateToDiffFileIndex(number - 1);
},
@@ -346,7 +361,7 @@ export default {
this.fetchDiffFilesMeta()
.then(({ real_size }) => {
this.diffFilesLength = parseInt(real_size, 10);
- if (toggleTree) this.hideTreeListIfJustOneFile();
+ if (toggleTree) this.setTreeDisplay();
this.startDiffRendering();
})
@@ -356,6 +371,7 @@ export default {
this.fetchDiffFilesBatch()
.then(() => {
+ if (toggleTree) this.setTreeDisplay();
// Guarantee the discussions are assigned after the batch finishes.
// Just watching the length of the discussions or the diff files
// isn't enough, because with split diff loading, neither will
@@ -372,7 +388,7 @@ export default {
}
if (!this.isNotesFetched) {
- eventHub.$emit('fetchNotesData');
+ notesEventHub.$emit('fetchNotesData');
}
},
setDiscussions() {
@@ -425,12 +441,17 @@ export default {
this.scrollToFile(this.diffFiles[targetIndex].file_path);
}
},
- hideTreeListIfJustOneFile() {
+ setTreeDisplay() {
const storedTreeShow = localStorage.getItem(MR_TREE_SHOW_KEY);
+ let showTreeList = true;
- if ((storedTreeShow === null && this.diffFiles.length <= 1) || storedTreeShow === 'false') {
- this.toggleShowTreeList(false);
+ if (storedTreeShow !== null) {
+ showTreeList = parseBoolean(storedTreeShow);
+ } else if (!bp.isDesktop() || (!this.isBatchLoading && this.diffFiles.length <= 1)) {
+ showTreeList = false;
}
+
+ return this.setShowTreeList({ showTreeList, saving: false });
},
},
minTreeWidth: MIN_TREE_WIDTH,
@@ -521,6 +542,7 @@ export default {
<template #total>{{ diffFiles.length }}</template>
</gl-sprintf>
</div>
+ <gl-loading-icon v-else-if="retrievingBatches" size="lg" />
</template>
<no-changes v-else :changes-empty-state-illustration="changesEmptyStateIllustration" />
</div>
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 1b747fb7f20..a548354f257 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -136,7 +136,12 @@ export default {
class="d-inline-flex mb-2"
/>
<gl-button-group class="gl-ml-4 gl-mb-4" data-testid="commit-sha-group">
- <gl-button label class="gl-font-monospace" v-text="commit.short_id" />
+ <gl-button
+ label
+ class="gl-font-monospace"
+ data-testid="commit-sha-short-id"
+ v-text="commit.short_id"
+ />
<clipboard-button
:text="commit.id"
:title="__('Copy commit SHA')"
diff --git a/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue b/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
index adef5d94624..da34a7ee19b 100644
--- a/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
+++ b/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
@@ -1,10 +1,11 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
- GlIcon,
+ GlDropdown,
+ GlDropdownItem,
TimeAgo,
},
props: {
@@ -22,57 +23,35 @@ export default {
</script>
<template>
- <span class="dropdown inline">
- <a
- class="dropdown-menu-toggle btn btn-default w-100"
- data-toggle="dropdown"
- aria-expanded="false"
+ <gl-dropdown :text="selectedVersionName" data-qa-selector="dropdown_content">
+ <gl-dropdown-item
+ v-for="version in versions"
+ :key="version.id"
+ :class="{
+ 'is-active': version.selected,
+ }"
+ :is-check-item="true"
+ :is-checked="version.selected"
+ :href="version.href"
>
- <span> {{ selectedVersionName }} </span>
- <gl-icon :size="12" name="angle-down" class="position-absolute" />
- </a>
- <div class="dropdown-menu dropdown-select dropdown-menu-selectable">
- <div class="dropdown-content" data-qa-selector="dropdown_content">
- <ul>
- <li v-for="version in versions" :key="version.id">
- <a :class="{ 'is-active': version.selected }" :href="version.href">
- <div>
- <strong>
- {{ version.versionName }}
- <template v-if="version.isHead">{{
- s__('DiffsCompareBaseBranch|(HEAD)')
- }}</template>
- <template v-else-if="version.isBase">{{
- s__('DiffsCompareBaseBranch|(base)')
- }}</template>
- </strong>
- </div>
- <div>
- <small class="commit-sha"> {{ version.short_commit_sha }} </small>
- </div>
- <div>
- <small>
- <template v-if="version.commitsText">
- {{ version.commitsText }}
- </template>
- <time-ago
- v-if="version.created_at"
- :time="version.created_at"
- class="js-timeago"
- />
- </small>
- </div>
- </a>
- </li>
- </ul>
+ <div>
+ <strong>
+ {{ version.versionName }}
+ <template v-if="version.isHead">{{ s__('DiffsCompareBaseBranch|(HEAD)') }}</template>
+ <template v-else-if="version.isBase">{{ s__('DiffsCompareBaseBranch|(base)') }}</template>
+ </strong>
</div>
- </div>
- </span>
+ <div>
+ <small class="commit-sha"> {{ version.short_commit_sha }} </small>
+ </div>
+ <div>
+ <small>
+ <template v-if="version.commitsText">
+ {{ version.commitsText }}
+ </template>
+ <time-ago v-if="version.created_at" :time="version.created_at" class="js-timeago" />
+ </small>
+ </div>
+ </gl-dropdown-item>
+ </gl-dropdown>
</template>
-
-<style>
-.dropdown {
- min-width: 0;
- max-height: 170px;
-}
-</style>
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 700d5ec86c8..f3cc359a679 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -65,11 +65,7 @@ export default {
polyfillSticky(this.$el);
},
methods: {
- ...mapActions('diffs', [
- 'setInlineDiffViewType',
- 'setParallelDiffViewType',
- 'toggleShowTreeList',
- ]),
+ ...mapActions('diffs', ['setInlineDiffViewType', 'setParallelDiffViewType', 'setShowTreeList']),
expandAllFiles() {
eventHub.$emit(EVT_EXPAND_ALL_FILES);
},
@@ -92,7 +88,7 @@ export default {
class="gl-mr-3 js-toggle-tree-list"
:title="toggleFileBrowserTitle"
:selected="showTreeList"
- @click="toggleShowTreeList"
+ @click="setShowTreeList({ showTreeList: !showTreeList })"
/>
<gl-sprintf
v-if="showDropdowns"
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index 401064fb18f..f938ea368d8 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -87,7 +87,7 @@ export default {
return this.getUserData;
},
mappedLines() {
- if (this.glFeatures.unifiedDiffLines && this.glFeatures.unifiedDiffComponents) {
+ if (this.glFeatures.unifiedDiffComponents) {
return this.diffLines(this.diffFile, true).map(mapParallel(this)) || [];
}
@@ -95,9 +95,7 @@ export default {
if (this.isInlineView) {
return this.diffFile.highlighted_diff_lines.map(mapInline(this));
}
- return this.glFeatures.unifiedDiffLines
- ? this.diffLines(this.diffFile).map(mapParallel(this))
- : this.diffFile.parallel_diff_lines.map(mapParallel(this)) || [];
+ return this.diffLines(this.diffFile).map(mapParallel(this));
},
},
updated() {
@@ -129,9 +127,7 @@ export default {
<template>
<div class="diff-content">
<div class="diff-viewer">
- <template
- v-if="isTextFile && glFeatures.unifiedDiffLines && glFeatures.unifiedDiffComponents"
- >
+ <template v-if="isTextFile && glFeatures.unifiedDiffComponents">
<diff-view
:diff-file="diffFile"
:diff-lines="mappedLines"
@@ -173,12 +169,16 @@ export default {
:a-mode="diffFile.a_mode"
:b-mode="diffFile.b_mode"
>
- <image-diff-overlay
- slot="image-overlay"
- :discussions="imageDiscussions"
- :file-hash="diffFileHash"
- :can-comment="getNoteableData.current_user.can_create_note && !diffFile.brokenSymlink"
- />
+ <template #image-overlay="{ renderedWidth, renderedHeight }">
+ <image-diff-overlay
+ v-if="renderedWidth"
+ :rendered-width="renderedWidth"
+ :rendered-height="renderedHeight"
+ :discussions="imageDiscussions"
+ :file-hash="diffFileHash"
+ :can-comment="getNoteableData.current_user.can_create_note && !diffFile.brokenSymlink"
+ />
+ </template>
<div v-if="showNotesContainer" class="note-container">
<user-avatar-link
v-if="diffFileCommentForm && author"
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 4c49dfb5de9..2401e12e4f6 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -4,7 +4,7 @@ import { GlIcon } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { UNFOLD_COUNT, INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
+import { UNFOLD_COUNT, INLINE_DIFF_VIEW_TYPE, INLINE_DIFF_LINES_KEY } from '../constants';
import * as utils from '../store/utils';
const EXPAND_ALL = 0;
@@ -14,7 +14,6 @@ const EXPAND_DOWN = 2;
const lineNumberByViewType = (viewType, diffLine) => {
const numberGetters = {
[INLINE_DIFF_VIEW_TYPE]: line => line?.new_line,
- [PARALLEL_DIFF_VIEW_TYPE]: line => (line?.right || line?.left)?.new_line,
};
const numberGetter = numberGetters[viewType];
return numberGetter && numberGetter(diffLine);
@@ -57,9 +56,6 @@ export default {
},
computed: {
...mapState({
- diffViewType(state) {
- return this.glFeatures.unifiedDiffLines ? INLINE_DIFF_VIEW_TYPE : state.diffs.diffViewType;
- },
diffFiles: state => state.diffs.diffFiles,
}),
canExpandUp() {
@@ -77,16 +73,14 @@ export default {
...mapActions('diffs', ['loadMoreLines']),
getPrevLineNumber(oldLineNumber, newLineNumber) {
const diffFile = utils.findDiffFile(this.diffFiles, this.fileHash);
- const lines = {
- [INLINE_DIFF_VIEW_TYPE]: diffFile.highlighted_diff_lines,
- [PARALLEL_DIFF_VIEW_TYPE]: diffFile.parallel_diff_lines,
- };
- const index = utils.getPreviousLineIndex(this.diffViewType, diffFile, {
+ const index = utils.getPreviousLineIndex(INLINE_DIFF_VIEW_TYPE, diffFile, {
oldLineNumber,
newLineNumber,
});
- return lineNumberByViewType(this.diffViewType, lines[this.diffViewType][index - 2]) || 0;
+ return (
+ lineNumberByViewType(INLINE_DIFF_VIEW_TYPE, diffFile[INLINE_DIFF_LINES_KEY][index - 2]) || 0
+ );
},
callLoadMoreLines(
endpoint,
@@ -113,7 +107,7 @@ export default {
this.isRequesting = true;
const endpoint = this.contextLinesPath;
const { fileHash } = this;
- const view = this.diffViewType;
+ const view = INLINE_DIFF_VIEW_TYPE;
const oldLineNumber = this.line.meta_data.old_pos || 0;
const newLineNumber = this.line.meta_data.new_pos || 0;
const offset = newLineNumber - oldLineNumber;
@@ -232,11 +226,11 @@ export default {
class="gl-mx-2 gl-cursor-pointer js-unfold-down gl-display-inline-block gl-py-4"
@click="handleExpandLines(EXPAND_DOWN)"
>
- <gl-icon :size="12" name="expand-down" aria-hidden="true" />
+ <gl-icon :size="12" name="expand-down" />
<span>{{ $options.i18n.showMore }}</span>
</a>
<a class="gl-mx-2 cursor-pointer js-unfold-all" @click="handleExpandLines()">
- <gl-icon :size="12" name="expand" aria-hidden="true" />
+ <gl-icon :size="12" name="expand" />
<span>{{ $options.i18n.showAll }}</span>
</a>
<a
@@ -244,7 +238,7 @@ export default {
class="gl-mx-2 gl-cursor-pointer js-unfold gl-display-inline-block gl-py-4"
@click="handleExpandLines(EXPAND_UP)"
>
- <gl-icon :size="12" name="expand-up" aria-hidden="true" />
+ <gl-icon :size="12" name="expand-up" />
<span>{{ $options.i18n.showMore }}</span>
</a>
</div>
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 32191d7e309..ed94cabe124 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -10,7 +10,7 @@ import notesEventHub from '../../notes/event_hub';
import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue';
import { diffViewerErrors } from '~/ide/constants';
-import { collapsedType, isCollapsed } from '../diff_file';
+import { collapsedType, isCollapsed } from '../utils/diff_file';
import {
DIFF_FILE_AUTOMATIC_COLLAPSE,
DIFF_FILE_MANUAL_COLLAPSE,
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 0d99a2e8a60..53d1383b82e 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -19,7 +19,7 @@ import { __, s__, sprintf } from '~/locale';
import { diffViewerModes } from '~/ide/constants';
import DiffStats from './diff_stats.vue';
import { scrollToElement } from '~/lib/utils/common_utils';
-import { isCollapsed } from '../diff_file';
+import { isCollapsed } from '../utils/diff_file';
import { DIFF_FILE_HEADER } from '../i18n';
export default {
@@ -221,7 +221,6 @@ export default {
ref="collapseIcon"
:name="collapseIcon"
:size="16"
- aria-hidden="true"
class="diff-toggle-caret gl-mr-2"
@click.stop="handleToggleFile"
/>
diff --git a/app/assets/javascripts/diffs/components/diff_file_row.vue b/app/assets/javascripts/diffs/components/diff_file_row.vue
index 3888eb781fb..6c5d9170c9e 100644
--- a/app/assets/javascripts/diffs/components/diff_file_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_row.vue
@@ -41,10 +41,6 @@ export default {
return !this.hideFileStats && this.file.type === 'blob';
},
fileClasses() {
- if (!this.glFeatures.highlightCurrentDiffRow) {
- return '';
- }
-
return this.file.type === 'blob' && !this.viewedFiles[this.file.fileHash]
? 'gl-font-weight-bold'
: '';
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index 55f5a736cdf..172a2bdde7d 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -7,7 +7,7 @@ import noteForm from '../../notes/components/note_form.vue';
import MultilineCommentForm from '../../notes/components/multiline_comment_form.vue';
import autosave from '../../notes/mixins/autosave';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import { DIFF_NOTE_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
+import { DIFF_NOTE_TYPE, INLINE_DIFF_LINES_KEY, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
import {
commentLineOptions,
formatLineRange,
@@ -102,13 +102,13 @@ export default {
};
const getDiffLines = () => {
if (this.diffViewType === PARALLEL_DIFF_VIEW_TYPE) {
- return (this.glFeatures.unifiedDiffLines
- ? this.diffLines(this.diffFile)
- : this.diffFile.parallel_diff_lines
- ).reduce(combineSides, []);
+ return this.diffLines(this.diffFile, this.glFeatures.unifiedDiffComponents).reduce(
+ combineSides,
+ [],
+ );
}
- return this.diffFile.highlighted_diff_lines;
+ return this.diffFile[INLINE_DIFF_LINES_KEY];
};
const side = this.line.type === 'new' ? 'right' : 'left';
const lines = getDiffLines();
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index 77a97c67f3b..c0719e2a7d9 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -157,10 +157,10 @@ export default {
"
/>
</div>
- <div :class="classNameMapCellLeft" class="diff-td diff-line-num old_line">
+ <div v-if="inline" :class="classNameMapCellLeft" class="diff-td diff-line-num old_line">
<a
- v-if="line.left.old_line"
- :data-linenumber="line.left.old_line"
+ v-if="line.left.new_line"
+ :data-linenumber="line.left.new_line"
:href="line.lineHrefOld"
@click="setHighlightedRow(line.lineCode)"
>
@@ -179,21 +179,14 @@ export default {
</template>
<template v-else>
<div data-testid="leftEmptyCell" class="diff-td diff-line-num old_line empty-cell"></div>
- <div class="diff-td diff-line-num old_line empty-cell"></div>
+ <div v-if="inline" class="diff-td diff-line-num old_line empty-cell"></div>
<div class="diff-td line-coverage left-side empty-cell"></div>
<div class="diff-td line_content with-coverage parallel left-side empty-cell"></div>
</template>
</div>
- <div
- v-if="!inline || (line.right && Boolean(line.right.type))"
- class="diff-grid-right right-side"
- >
+ <div v-if="!inline" class="diff-grid-right right-side">
<template v-if="line.right">
- <div
- :class="classNameMapCellRight"
- data-testid="rightLineNumber"
- class="diff-td diff-line-num new_line"
- >
+ <div :class="classNameMapCellRight" class="diff-td diff-line-num new_line">
<span
v-if="shouldRenderCommentButton"
v-gl-tooltip
@@ -231,15 +224,6 @@ export default {
"
/>
</div>
- <div :class="classNameMapCellRight" class="diff-td diff-line-num new_line">
- <a
- v-if="line.right.new_line"
- :data-linenumber="line.right.new_line"
- :href="line.lineHrefNew"
- @click="setHighlightedRow(line.lineCode)"
- >
- </a>
- </div>
<div
v-gl-tooltip.hover
:title="coverageState.text"
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
index 3956c2fab49..6a1e0d8cbd6 100644
--- a/app/assets/javascripts/diffs/components/image_diff_overlay.vue
+++ b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
@@ -4,6 +4,10 @@ import { isArray } from 'lodash';
import imageDiffMixin from 'ee_else_ce/diffs/mixins/image_diff';
import { GlIcon } from '@gitlab/ui';
+function calcPercent(pos, size, renderedSize) {
+ return (((pos / size) * 100) / ((renderedSize / size) * 100)) * 100;
+}
+
export default {
name: 'ImageDiffOverlay',
components: {
@@ -39,6 +43,14 @@ export default {
required: false,
default: true,
},
+ renderedWidth: {
+ type: Number,
+ required: true,
+ },
+ renderedHeight: {
+ type: Number,
+ required: true,
+ },
},
computed: {
...mapGetters('diffs', ['getDiffFileByHash', 'getCommentFormForDiffFile']),
@@ -59,33 +71,33 @@ export default {
},
getPositionForObject(meta) {
const { x, y, width, height } = meta;
- const imageWidth = this.getImageDimensions().width;
- const imageHeight = this.getImageDimensions().height;
- const widthRatio = imageWidth / width;
- const heightRatio = imageHeight / height;
return {
- x: Math.round(x * widthRatio),
- y: Math.round(y * heightRatio),
+ x: (x / width) * 100,
+ y: (y / height) * 100,
};
},
getPosition(discussion) {
const { x, y } = this.getPositionForObject(discussion.position);
return {
- left: `${x}px`,
- top: `${y}px`,
+ left: `${x}%`,
+ top: `${y}%`,
};
},
clickedImage(x, y) {
const { width, height } = this.getImageDimensions();
+ const xPercent = calcPercent(x, width, this.renderedWidth);
+ const yPercent = calcPercent(y, height, this.renderedHeight);
this.openDiffFileCommentForm({
fileHash: this.fileHash,
width,
height,
- x,
- y,
+ x: width * (xPercent / 100),
+ y: height * (yPercent / 100),
+ xPercent,
+ yPercent,
});
},
},
@@ -112,22 +124,19 @@ export default {
type="button"
@click="clickedToggle(discussion)"
>
- <gl-icon v-if="showCommentIcon" name="image-comment-dark" />
+ <gl-icon v-if="showCommentIcon" name="image-comment-dark" :size="24" />
<template v-else>
{{ toggleText(discussion, index) }}
</template>
</button>
<button
- v-if="currentCommentForm"
- :style="{
- left: `${currentCommentForm.x}px`,
- top: `${currentCommentForm.y}px`,
- }"
+ v-if="canComment && currentCommentForm"
+ :style="{ left: `${currentCommentForm.xPercent}%`, top: `${currentCommentForm.yPercent}%` }"
:aria-label="__('Comment form position')"
- class="btn-transparent comment-indicator"
+ class="btn-transparent comment-indicator position-absolute"
type="button"
>
- <gl-icon name="image-comment-dark" />
+ <gl-icon name="image-comment-dark" :size="24" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/merge_conflict_warning.vue b/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
index e47bea8e589..587efd6ed41 100644
--- a/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
+++ b/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlAlert } from '@gitlab/ui';
+import { GlButton, GlAlert, GlModalDirective } from '@gitlab/ui';
import { CENTERED_LIMITED_CONTAINER_CLASSES } from '../constants';
export default {
@@ -7,6 +7,9 @@ export default {
GlAlert,
GlButton,
},
+ directives: {
+ GlModalDirective,
+ },
props: {
limited: {
type: Boolean,
@@ -60,9 +63,8 @@ export default {
</gl-button>
<gl-button
v-if="mergeable"
+ v-gl-modal-directive="'modal-merge-info'"
class="gl-alert-action"
- data-toggle="modal"
- data-target="#modal_merge_info"
>
{{ __('Merge locally') }}
</gl-button>
diff --git a/app/assets/javascripts/diffs/components/settings_dropdown.vue b/app/assets/javascripts/diffs/components/settings_dropdown.vue
index 78647065c8e..2fe2fd6b3d8 100644
--- a/app/assets/javascripts/diffs/components/settings_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/settings_dropdown.vue
@@ -1,23 +1,22 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlButtonGroup, GlButton, GlDropdown } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { GlButtonGroup, GlButton, GlDropdown, GlFormCheckbox } from '@gitlab/ui';
+
+import eventHub from '../event_hub';
+import { EVT_VIEW_FILE_BY_FILE } from '../constants';
+import { SETTINGS_DROPDOWN } from '../i18n';
export default {
+ i18n: SETTINGS_DROPDOWN,
components: {
GlButtonGroup,
GlButton,
GlDropdown,
+ GlFormCheckbox,
},
computed: {
...mapGetters('diffs', ['isInlineView', 'isParallelView']),
- ...mapState('diffs', ['renderTreeList', 'showWhitespace']),
- },
- mounted() {
- this.patchAriaLabel();
- },
- updated() {
- this.patchAriaLabel();
+ ...mapState('diffs', ['renderTreeList', 'showWhitespace', 'viewDiffsFileByFile']),
},
methods: {
...mapActions('diffs', [
@@ -26,17 +25,21 @@ export default {
'setRenderTreeList',
'setShowWhitespace',
]),
- patchAriaLabel() {
- this.$el
- .querySelector('.js-show-diff-settings')
- .setAttribute('aria-label', __('Diff view settings'));
+ toggleFileByFile() {
+ eventHub.$emit(EVT_VIEW_FILE_BY_FILE, { setting: !this.viewDiffsFileByFile });
},
},
};
</script>
<template>
- <gl-dropdown icon="settings" toggle-class="js-show-diff-settings" right>
+ <gl-dropdown
+ icon="settings"
+ :text="__('Diff view settings')"
+ :text-sr-only="true"
+ toggle-class="js-show-diff-settings"
+ right
+ >
<div class="gl-px-3">
<span class="gl-font-weight-bold gl-display-block gl-mb-2">{{ __('File browser') }}</span>
<gl-button-group class="gl-display-flex">
@@ -90,5 +93,15 @@ export default {
{{ __('Show whitespace changes') }}
</label>
</div>
+ <div class="gl-mt-3 gl-px-3">
+ <gl-form-checkbox
+ data-testid="file-by-file"
+ class="gl-mb-0"
+ :checked="viewDiffsFileByFile"
+ @input="toggleFileByFile"
+ >
+ {{ $options.i18n.fileByFile }}
+ </gl-form-checkbox>
+ </div>
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 79f8c08e389..07e27bd8e47 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -77,6 +77,11 @@ export const ALERT_COLLAPSED_FILES = 'collapsed';
export const DIFF_FILE_AUTOMATIC_COLLAPSE = 'automatic';
export const DIFF_FILE_MANUAL_COLLAPSE = 'manual';
+// Diff view single file mode
+export const DIFF_FILE_BY_FILE_COOKIE_NAME = 'fileViewMode';
+export const DIFF_VIEW_FILE_BY_FILE = 'single';
+export const DIFF_VIEW_ALL_FILES = 'all';
+
// State machine states
export const STATE_IDLING = 'idle';
export const STATE_LOADING = 'loading';
@@ -98,6 +103,7 @@ export const RENAMED_DIFF_TRANSITIONS = {
// MR Diffs known events
export const EVT_EXPAND_ALL_FILES = 'mr:diffs:expandAllFiles';
+export const EVT_VIEW_FILE_BY_FILE = 'mr:diffs:preference:fileByFile';
export const EVT_PERF_MARK_FILE_TREE_START = 'mr:diffs:perf:fileTreeStart';
export const EVT_PERF_MARK_FILE_TREE_END = 'mr:diffs:perf:fileTreeEnd';
export const EVT_PERF_MARK_DIFF_FILES_START = 'mr:diffs:perf:filesStart';
diff --git a/app/assets/javascripts/diffs/i18n.js b/app/assets/javascripts/diffs/i18n.js
index 4ec24d452bf..c4ac99ead91 100644
--- a/app/assets/javascripts/diffs/i18n.js
+++ b/app/assets/javascripts/diffs/i18n.js
@@ -16,3 +16,7 @@ export const DIFF_FILE = {
autoCollapsed: __('Files with large changes are collapsed by default.'),
expand: __('Expand file'),
};
+
+export const SETTINGS_DROPDOWN = {
+ fileByFile: __('Show one file at a time'),
+};
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 06a138b1e13..587220488be 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -116,7 +116,7 @@ export default function initDiffsApp(store) {
isFluidLayout: this.isFluidLayout,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
- viewDiffsFileByFile: this.viewDiffsFileByFile,
+ fileByFileUserPreference: this.viewDiffsFileByFile,
},
});
},
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 91c4c51487f..5b410051705 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -30,13 +30,11 @@ import {
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,
DIFFS_PER_PAGE,
DIFF_WHITESPACE_COOKIE_NAME,
SHOW_WHITESPACE,
@@ -46,9 +44,12 @@ import {
EVT_PERF_MARK_FILE_TREE_START,
EVT_PERF_MARK_FILE_TREE_END,
EVT_PERF_MARK_DIFF_FILES_START,
+ DIFF_VIEW_FILE_BY_FILE,
+ DIFF_VIEW_ALL_FILES,
+ DIFF_FILE_BY_FILE_COOKIE_NAME,
} from '../constants';
import { diffViewerModes } from '~/ide/constants';
-import { isCollapsed } from '../diff_file';
+import { isCollapsed } from '../utils/diff_file';
export const setBaseConfig = ({ commit }, options) => {
const {
@@ -59,6 +60,7 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ viewDiffsFileByFile,
} = options;
commit(types.SET_BASE_CONFIG, {
endpoint,
@@ -68,26 +70,38 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ viewDiffsFileByFile,
});
};
export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
+ const diffsGradualLoad = window.gon?.features?.diffsGradualLoad;
+ let perPage = DIFFS_PER_PAGE;
+ let increaseAmount = 1.4;
+
+ if (diffsGradualLoad) {
+ perPage = state.viewDiffsFileByFile ? 1 : 5;
+ }
+
+ const startPage = diffsGradualLoad ? 0 : 1;
const id = window?.location?.hash;
const isNoteLink = id.indexOf('#note') === 0;
const urlParams = {
- per_page: DIFFS_PER_PAGE,
w: state.showWhitespace ? '0' : '1',
- view: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
+ view: 'inline',
};
+ let totalLoaded = 0;
commit(types.SET_BATCH_LOADING, true);
commit(types.SET_RETRIEVING_BATCHES, true);
eventHub.$emit(EVT_PERF_MARK_DIFF_FILES_START);
- const getBatch = (page = 1) =>
+ const getBatch = (page = startPage) =>
axios
- .get(mergeUrlParams({ ...urlParams, page }, state.endpointBatch))
+ .get(mergeUrlParams({ ...urlParams, page, per_page: perPage }, state.endpointBatch))
.then(({ data: { pagination, diff_files } }) => {
+ totalLoaded += diff_files.length;
+
commit(types.SET_DIFF_DATA_BATCH, { diff_files });
commit(types.SET_BATCH_LOADING, false);
@@ -99,7 +113,11 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
dispatch('setCurrentDiffFileIdFromNote', id.split('_').pop());
}
- if (!pagination.next_page) {
+ if (
+ (diffsGradualLoad &&
+ (totalLoaded === pagination.total_pages || pagination.total_pages === null)) ||
+ (!diffsGradualLoad && !pagination.next_page)
+ ) {
commit(types.SET_RETRIEVING_BATCHES, false);
// We need to check that the currentDiffFileId points to a file that exists
@@ -125,6 +143,16 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
}),
);
}
+
+ return null;
+ }
+
+ if (diffsGradualLoad) {
+ const nextPage = page + perPage;
+ perPage = Math.min(Math.ceil(perPage * increaseAmount), 30);
+ increaseAmount = Math.min(increaseAmount + 0.2, 2);
+
+ return nextPage;
}
return pagination.next_page;
@@ -140,7 +168,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
export const fetchDiffFilesMeta = ({ commit, state }) => {
const worker = new TreeWorker();
const urlParams = {
- view: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
+ view: 'inline',
};
commit(types.SET_LOADING, true);
@@ -157,13 +185,19 @@ export const fetchDiffFilesMeta = ({ commit, state }) => {
.get(mergeUrlParams(urlParams, state.endpointMetadata))
.then(({ data }) => {
const strippedData = { ...data };
-
delete strippedData.diff_files;
+
commit(types.SET_LOADING, false);
commit(types.SET_MERGE_REQUEST_DIFFS, data.merge_request_diffs || []);
- commit(types.SET_DIFF_DATA, strippedData);
+ commit(types.SET_DIFF_METADATA, strippedData);
- worker.postMessage(prepareDiffData(data, state.diffFiles));
+ worker.postMessage(
+ prepareDiffData({
+ diff: data,
+ priorFiles: state.diffFiles,
+ meta: true,
+ }),
+ );
return data;
})
@@ -401,15 +435,10 @@ export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
export const toggleFileDiscussionWrappers = ({ commit }, diff) => {
const discussionWrappersExpanded = allDiscussionWrappersExpanded(diff);
const lineCodesWithDiscussions = new Set();
- const { parallel_diff_lines: parallelLines, highlighted_diff_lines: inlineLines } = diff;
- const allLines = inlineLines.concat(
- parallelLines.map(line => line.left),
- parallelLines.map(line => line.right),
- );
const lineHasDiscussion = line => Boolean(line?.discussions.length);
const registerDiscussionLine = line => lineCodesWithDiscussions.add(line.line_code);
- allLines.filter(lineHasDiscussion).forEach(registerDiscussionLine);
+ diff[INLINE_DIFF_LINES_KEY].filter(lineHasDiscussion).forEach(registerDiscussionLine);
if (lineCodesWithDiscussions.size) {
Array.from(lineCodesWithDiscussions).forEach(lineCode => {
@@ -454,11 +483,11 @@ export const scrollToFile = ({ state, commit }, path) => {
commit(types.VIEW_DIFF_FILE, fileHash);
};
-export const toggleShowTreeList = ({ commit, state }, saving = true) => {
- commit(types.TOGGLE_SHOW_TREE_LIST);
+export const setShowTreeList = ({ commit }, { showTreeList, saving = true }) => {
+ commit(types.SET_SHOW_TREE_LIST, showTreeList);
if (saving) {
- localStorage.setItem(MR_TREE_SHOW_KEY, state.showTreeList);
+ localStorage.setItem(MR_TREE_SHOW_KEY, showTreeList);
}
};
@@ -508,61 +537,26 @@ export const receiveFullDiffError = ({ commit }, filePath) => {
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}`,
- },
+export const setExpandedDiffLines = ({ commit }, { file, data }) => {
+ const expandedDiffLines = convertExpandLines({
+ diffLines: file[INLINE_DIFF_LINES_KEY],
+ 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}`,
}),
- }),
- };
- const unifiedDiffLinesEnabled = window.gon?.features?.unifiedDiffLines;
- const currentDiffLinesKey =
- state.diffViewType === INLINE_DIFF_VIEW_TYPE || unifiedDiffLinesEnabled
- ? INLINE_DIFF_LINES_KEY
- : PARALLEL_DIFF_LINES_KEY;
- const hiddenDiffLinesKey =
- state.diffViewType === INLINE_DIFF_VIEW_TYPE ? PARALLEL_DIFF_LINES_KEY : INLINE_DIFF_LINES_KEY;
-
- if (!unifiedDiffLinesEnabled) {
- commit(types.SET_HIDDEN_VIEW_DIFF_FILE_LINES, {
- filePath: file.file_path,
- lines: expandedDiffLines[hiddenDiffLinesKey],
- });
- }
+ });
- if (expandedDiffLines[currentDiffLinesKey].length > MAX_RENDERING_DIFF_LINES) {
+ if (expandedDiffLines.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),
+ lines: expandedDiffLines.slice(0, index),
});
commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path);
@@ -571,10 +565,10 @@ export const setExpandedDiffLines = ({ commit, state }, { file, data }) => {
while (
t.timeRemaining() >= MIN_RENDERING_MS &&
- index !== expandedDiffLines[currentDiffLinesKey].length &&
+ index !== expandedDiffLines.length &&
index - startIndex !== MAX_RENDERING_BULK_ROWS
) {
- const line = expandedDiffLines[currentDiffLinesKey][index];
+ const line = expandedDiffLines[index];
if (line) {
commit(types.ADD_CURRENT_VIEW_DIFF_FILE_LINES, { filePath: file.file_path, line });
@@ -582,7 +576,7 @@ export const setExpandedDiffLines = ({ commit, state }, { file, data }) => {
}
}
- if (index !== expandedDiffLines[currentDiffLinesKey].length) {
+ if (index !== expandedDiffLines.length) {
idleCallback(idleCb);
} else {
commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path);
@@ -593,7 +587,7 @@ export const setExpandedDiffLines = ({ commit, state }, { file, data }) => {
} else {
commit(types.SET_CURRENT_VIEW_DIFF_FILE_LINES, {
filePath: file.file_path,
- lines: expandedDiffLines[currentDiffLinesKey],
+ lines: expandedDiffLines,
});
}
};
@@ -627,7 +621,7 @@ export const toggleFullDiff = ({ dispatch, commit, getters, state }, filePath) =
}
};
-export function switchToFullDiffFromRenamedFile({ commit, dispatch, state }, { diffFile }) {
+export function switchToFullDiffFromRenamedFile({ commit, dispatch }, { diffFile }) {
return axios
.get(diffFile.context_lines_path, {
params: {
@@ -638,7 +632,7 @@ export function switchToFullDiffFromRenamedFile({ commit, dispatch, state }, { d
.then(({ data }) => {
const lines = data.map((line, index) =>
prepareLineForRenamedFile({
- diffViewType: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
+ diffViewType: 'inline',
line,
diffFile,
index,
@@ -736,3 +730,14 @@ export const navigateToDiffFileIndex = ({ commit, state }, index) => {
commit(types.VIEW_DIFF_FILE, fileHash);
};
+
+export const setFileByFile = ({ commit }, { fileByFile }) => {
+ const fileViewMode = fileByFile ? DIFF_VIEW_FILE_BY_FILE : DIFF_VIEW_ALL_FILES;
+ commit(types.SET_FILE_BY_FILE, fileByFile);
+
+ Cookies.set(DIFF_FILE_BY_FILE_COOKIE_NAME, fileViewMode);
+
+ historyPushState(
+ mergeUrlParams({ [DIFF_FILE_BY_FILE_COOKIE_NAME]: fileViewMode }, window.location.href),
+ );
+};
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index 9ee73998177..baf54188932 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,6 +1,10 @@
import { __, n__ } from '~/locale';
import { parallelizeDiffLines } from './utils';
-import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '../constants';
+import {
+ PARALLEL_DIFF_VIEW_TYPE,
+ INLINE_DIFF_VIEW_TYPE,
+ INLINE_DIFF_LINES_KEY,
+} from '../constants';
export * from './getters_versions_dropdowns';
@@ -54,24 +58,10 @@ export const diffHasAllCollapsedDiscussions = (state, getters) => diff => {
* @param {Object} diff
* @returns {Boolean}
*/
-export const diffHasExpandedDiscussions = state => diff => {
- const lines = {
- [INLINE_DIFF_VIEW_TYPE]: diff.highlighted_diff_lines || [],
- [PARALLEL_DIFF_VIEW_TYPE]: (diff.parallel_diff_lines || []).reduce((acc, line) => {
- if (line.left) {
- acc.push(line.left);
- }
-
- if (line.right) {
- acc.push(line.right);
- }
-
- return acc;
- }, []),
- };
- return lines[window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType]
- .filter(l => l.discussions.length >= 1)
- .some(l => l.discussionsExpanded);
+export const diffHasExpandedDiscussions = () => diff => {
+ return diff[INLINE_DIFF_LINES_KEY].filter(l => l.discussions.length >= 1).some(
+ l => l.discussionsExpanded,
+ );
};
/**
@@ -79,24 +69,8 @@ export const diffHasExpandedDiscussions = state => diff => {
* @param {Boolean} diff
* @returns {Boolean}
*/
-export const diffHasDiscussions = state => diff => {
- const lines = {
- [INLINE_DIFF_VIEW_TYPE]: diff.highlighted_diff_lines || [],
- [PARALLEL_DIFF_VIEW_TYPE]: (diff.parallel_diff_lines || []).reduce((acc, line) => {
- if (line.left) {
- acc.push(line.left);
- }
-
- if (line.right) {
- acc.push(line.right);
- }
-
- return acc;
- }, []),
- };
- return lines[window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType].some(
- l => l.discussions.length >= 1,
- );
+export const diffHasDiscussions = () => diff => {
+ return diff[INLINE_DIFF_LINES_KEY].some(l => l.discussions.length >= 1);
};
/**
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index 001d9d9f594..c331e52c887 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -5,6 +5,8 @@ import {
DIFF_VIEW_COOKIE_NAME,
DIFF_WHITESPACE_COOKIE_NAME,
} from '../../constants';
+
+import { fileByFile } from '../../utils/preferences';
import { getDefaultWhitespace } from '../utils';
const viewTypeFromQueryString = getParameterValues('view')[0];
@@ -39,6 +41,7 @@ export default () => ({
highlightedRow: null,
renderTreeList: true,
showWhitespace: getDefaultWhitespace(whiteSpaceFromQueryString, whiteSpaceFromCookie),
+ viewDiffsFileByFile: fileByFile(),
fileFinderVisible: false,
dismissEndpoint: '',
showSuggestPopover: true,
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index 19a9e65edc9..30097239aaa 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -3,7 +3,7 @@ export const SET_LOADING = 'SET_LOADING';
export const SET_BATCH_LOADING = 'SET_BATCH_LOADING';
export const SET_RETRIEVING_BATCHES = 'SET_RETRIEVING_BATCHES';
-export const SET_DIFF_DATA = 'SET_DIFF_DATA';
+export const SET_DIFF_METADATA = 'SET_DIFF_METADATA';
export const SET_DIFF_DATA_BATCH = 'SET_DIFF_DATA_BATCH';
export const SET_DIFF_FILES = 'SET_DIFF_FILES';
@@ -17,7 +17,7 @@ export const RENDER_FILE = 'RENDER_FILE';
export const SET_LINE_DISCUSSIONS_FOR_FILE = 'SET_LINE_DISCUSSIONS_FOR_FILE';
export const REMOVE_LINE_DISCUSSIONS_FOR_FILE = 'REMOVE_LINE_DISCUSSIONS_FOR_FILE';
export const TOGGLE_FOLDER_OPEN = 'TOGGLE_FOLDER_OPEN';
-export const TOGGLE_SHOW_TREE_LIST = 'TOGGLE_SHOW_TREE_LIST';
+export const SET_SHOW_TREE_LIST = 'SET_SHOW_TREE_LIST';
export const VIEW_DIFF_FILE = 'VIEW_DIFF_FILE';
export const OPEN_DIFF_FILE_COMMENT_FORM = 'OPEN_DIFF_FILE_COMMENT_FORM';
@@ -28,6 +28,7 @@ export const SET_HIGHLIGHTED_ROW = 'SET_HIGHLIGHTED_ROW';
export const SET_TREE_DATA = 'SET_TREE_DATA';
export const SET_RENDER_TREE_LIST = 'SET_RENDER_TREE_LIST';
export const SET_SHOW_WHITESPACE = 'SET_SHOW_WHITESPACE';
+export const SET_FILE_BY_FILE = 'SET_FILE_BY_FILE';
export const TOGGLE_FILE_FINDER_VISIBLE = 'TOGGLE_FILE_FINDER_VISIBLE';
export const REQUEST_FULL_DIFF = 'REQUEST_FULL_DIFF';
@@ -35,7 +36,6 @@ export const RECEIVE_FULL_DIFF_SUCCESS = 'RECEIVE_FULL_DIFF_SUCCESS';
export const RECEIVE_FULL_DIFF_ERROR = 'RECEIVE_FULL_DIFF_ERROR';
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';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 096c4f69439..19122c3096f 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -1,11 +1,6 @@
import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import {
- DIFF_FILE_MANUAL_COLLAPSE,
- DIFF_FILE_AUTOMATIC_COLLAPSE,
- INLINE_DIFF_VIEW_TYPE,
-} from '../constants';
-import {
findDiffFile,
addLineReferences,
removeMatchLine,
@@ -14,6 +9,11 @@ import {
isDiscussionApplicableToLine,
updateLineInFile,
} from './utils';
+import {
+ DIFF_FILE_MANUAL_COLLAPSE,
+ DIFF_FILE_AUTOMATIC_COLLAPSE,
+ INLINE_DIFF_LINES_KEY,
+} from '../constants';
import * as types from './mutation_types';
function updateDiffFilesInState(state, files) {
@@ -36,6 +36,7 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ viewDiffsFileByFile,
} = options;
Object.assign(state, {
endpoint,
@@ -45,6 +46,7 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ viewDiffsFileByFile,
});
},
@@ -64,21 +66,17 @@ export default {
updateDiffFilesInState(state, files);
},
- [types.SET_DIFF_DATA](state, data) {
- let files = state.diffFiles;
-
- if (window.location.search.indexOf('diff_id') !== -1 && data.diff_files) {
- files = prepareDiffData(data, files);
- }
-
+ [types.SET_DIFF_METADATA](state, data) {
Object.assign(state, {
...convertObjectPropsToCamelCase(data),
});
- updateDiffFilesInState(state, files);
},
[types.SET_DIFF_DATA_BATCH](state, data) {
- const files = prepareDiffData(data, state.diffFiles);
+ const files = prepareDiffData({
+ diff: data,
+ priorFiles: state.diffFiles,
+ });
Object.assign(state, {
...convertObjectPropsToCamelCase(data),
@@ -109,25 +107,7 @@ export default {
if (!diffFile) return;
- if (diffFile.highlighted_diff_lines.length) {
- diffFile.highlighted_diff_lines.find(l => l.line_code === lineCode).hasForm = hasForm;
- }
-
- if (diffFile.parallel_diff_lines.length) {
- const line = diffFile.parallel_diff_lines.find(l => {
- const { left, right } = l;
-
- return (left && left.line_code === lineCode) || (right && right.line_code === lineCode);
- });
-
- if (line.left && line.left.line_code === lineCode) {
- line.left.hasForm = hasForm;
- }
-
- if (line.right && line.right.line_code === lineCode) {
- line.right.hasForm = hasForm;
- }
- }
+ diffFile[INLINE_DIFF_LINES_KEY].find(l => l.line_code === lineCode).hasForm = hasForm;
},
[types.ADD_CONTEXT_LINES](state, options) {
@@ -157,11 +137,7 @@ export default {
});
addContextLines({
- inlineLines: diffFile.highlighted_diff_lines,
- parallelLines: diffFile.parallel_diff_lines,
- diffViewType: window.gon?.features?.unifiedDiffLines
- ? INLINE_DIFF_VIEW_TYPE
- : state.diffViewType,
+ inlineLines: diffFile[INLINE_DIFF_LINES_KEY],
contextLines: lines,
bottom,
lineNumbers,
@@ -170,7 +146,7 @@ export default {
},
[types.ADD_COLLAPSED_DIFFS](state, { file, data }) {
- const files = prepareDiffData(data);
+ const files = prepareDiffData({ diff: data });
const [newFileData] = files.filter(f => f.file_hash === file.file_hash);
const selectedFile = state.diffFiles.find(f => f.file_hash === file.file_hash);
Object.assign(selectedFile, { ...newFileData });
@@ -219,8 +195,8 @@ export default {
state.diffFiles.forEach(file => {
if (file.file_hash === fileHash) {
- if (file.highlighted_diff_lines.length) {
- file.highlighted_diff_lines.forEach(line => {
+ if (file[INLINE_DIFF_LINES_KEY].length) {
+ file[INLINE_DIFF_LINES_KEY].forEach(line => {
Object.assign(
line,
setDiscussionsExpanded(lineCheck(line) ? mapDiscussions(line) : line),
@@ -228,25 +204,7 @@ export default {
});
}
- if (file.parallel_diff_lines.length) {
- file.parallel_diff_lines.forEach(line => {
- const left = line.left && lineCheck(line.left);
- const right = line.right && lineCheck(line.right);
-
- if (left || right) {
- Object.assign(line, {
- left: line.left ? setDiscussionsExpanded(mapDiscussions(line.left)) : null,
- right: line.right
- ? setDiscussionsExpanded(mapDiscussions(line.right, () => !left))
- : null,
- });
- }
-
- return line;
- });
- }
-
- if (!file.parallel_diff_lines.length || !file.highlighted_diff_lines.length) {
+ if (!file[INLINE_DIFF_LINES_KEY].length) {
const newDiscussions = (file.discussions || [])
.filter(d => d.id !== discussion.id)
.concat(discussion);
@@ -287,8 +245,8 @@ export default {
[types.TOGGLE_FOLDER_OPEN](state, path) {
state.treeEntries[path].opened = !state.treeEntries[path].opened;
},
- [types.TOGGLE_SHOW_TREE_LIST](state) {
- state.showTreeList = !state.showTreeList;
+ [types.SET_SHOW_TREE_LIST](state, showTreeList) {
+ state.showTreeList = showTreeList;
},
[types.VIEW_DIFF_FILE](state, fileId) {
state.currentDiffFileId = fileId;
@@ -369,31 +327,15 @@ export default {
renderFile(file);
}
},
- [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);
- let currentDiffLinesKey;
- if (window.gon?.features?.unifiedDiffLines || state.diffViewType === 'inline') {
- currentDiffLinesKey = 'highlighted_diff_lines';
- } else {
- currentDiffLinesKey = 'parallel_diff_lines';
- }
-
- file[currentDiffLinesKey] = lines;
+ file[INLINE_DIFF_LINES_KEY] = 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);
+ file[INLINE_DIFF_LINES_KEY].push(line);
},
[types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, filePath) {
const file = state.diffFiles.find(f => f.file_path === filePath);
@@ -408,4 +350,7 @@ export default {
[types.SET_SHOW_SUGGEST_POPOVER](state) {
state.showSuggestPopover = false;
},
+ [types.SET_FILE_BY_FILE](state, fileByFile) {
+ state.viewDiffsFileByFile = fileByFile;
+ },
};
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index f87f57c32c3..1839df12c96 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -12,12 +12,11 @@ import {
MATCH_LINE_TYPE,
LINES_TO_BE_RENDERED_DIRECTLY,
TREE_TYPE,
- INLINE_DIFF_VIEW_TYPE,
- PARALLEL_DIFF_VIEW_TYPE,
+ INLINE_DIFF_LINES_KEY,
SHOW_WHITESPACE,
NO_SHOW_WHITESPACE,
} from '../constants';
-import { prepareRawDiffFile } from '../diff_file';
+import { prepareRawDiffFile } from '../utils/diff_file';
export const isAdded = line => ['new', 'new-nonewline'].includes(line.type);
export const isRemoved = line => ['old', 'old-nonewline'].includes(line.type);
@@ -48,7 +47,7 @@ export const parallelizeDiffLines = (diffLines, inline) => {
for (let i = 0, diffLinesLength = diffLines.length, index = 0; i < diffLinesLength; i += 1) {
const line = diffLines[i];
- if (isRemoved(line)) {
+ if (isRemoved(line) || inline) {
lines.push({
[LINE_POSITION_LEFT]: line,
[LINE_POSITION_RIGHT]: null,
@@ -60,7 +59,7 @@ export const parallelizeDiffLines = (diffLines, inline) => {
}
index += 1;
} else if (isAdded(line)) {
- if (freeRightIndex !== null && !inline) {
+ if (freeRightIndex !== null) {
// If an old line came before this without a line on the right, this
// line can be put to the right of it.
lines[freeRightIndex].right = line;
@@ -178,43 +177,16 @@ export const findIndexInInlineLines = (lines, lineNumbers) => {
);
};
-export const findIndexInParallelLines = (lines, lineNumbers) => {
- const { oldLineNumber, newLineNumber } = lineNumbers;
-
- return lines.findIndex(
- line =>
- line.left &&
- line.right &&
- line.left.old_line === oldLineNumber &&
- line.right.new_line === newLineNumber,
- );
-};
-
-const indexGettersByViewType = {
- [INLINE_DIFF_VIEW_TYPE]: findIndexInInlineLines,
- [PARALLEL_DIFF_VIEW_TYPE]: findIndexInParallelLines,
-};
-
export const getPreviousLineIndex = (diffViewType, file, lineNumbers) => {
- const findIndex = indexGettersByViewType[diffViewType];
- const lines = {
- [INLINE_DIFF_VIEW_TYPE]: file.highlighted_diff_lines,
- [PARALLEL_DIFF_VIEW_TYPE]: file.parallel_diff_lines,
- };
-
- return findIndex && findIndex(lines[diffViewType], lineNumbers);
+ return findIndexInInlineLines(file[INLINE_DIFF_LINES_KEY], lineNumbers);
};
export function removeMatchLine(diffFile, lineNumbers, bottom) {
- const indexForInline = findIndexInInlineLines(diffFile.highlighted_diff_lines, lineNumbers);
- const indexForParallel = findIndexInParallelLines(diffFile.parallel_diff_lines, lineNumbers);
+ const indexForInline = findIndexInInlineLines(diffFile[INLINE_DIFF_LINES_KEY], lineNumbers);
const factor = bottom ? 1 : -1;
if (indexForInline > -1) {
- diffFile.highlighted_diff_lines.splice(indexForInline + factor, 1);
- }
- if (indexForParallel > -1) {
- diffFile.parallel_diff_lines.splice(indexForParallel + factor, 1);
+ diffFile[INLINE_DIFF_LINES_KEY].splice(indexForInline + factor, 1);
}
}
@@ -257,24 +229,6 @@ export function addLineReferences(lines, lineNumbers, bottom, isExpandDown, next
return linesWithNumbers;
}
-function addParallelContextLines(options) {
- const { parallelLines, contextLines, lineNumbers, isExpandDown } = options;
- const normalizedParallelLines = contextLines.map(line => ({
- left: line,
- right: line,
- line_code: line.line_code,
- }));
- const factor = isExpandDown ? 1 : 0;
-
- if (!isExpandDown && options.bottom) {
- parallelLines.push(...normalizedParallelLines);
- } else {
- const parallelIndex = findIndexInParallelLines(parallelLines, lineNumbers);
-
- parallelLines.splice(parallelIndex + factor, 0, ...normalizedParallelLines);
- }
-}
-
function addInlineContextLines(options) {
const { inlineLines, contextLines, lineNumbers, isExpandDown } = options;
const factor = isExpandDown ? 1 : 0;
@@ -289,16 +243,7 @@ function addInlineContextLines(options) {
}
export function addContextLines(options) {
- const { diffViewType } = options;
- const contextLineHandlers = {
- [INLINE_DIFF_VIEW_TYPE]: addInlineContextLines,
- [PARALLEL_DIFF_VIEW_TYPE]: addParallelContextLines,
- };
- const contextLineHandler = contextLineHandlers[diffViewType];
-
- if (contextLineHandler) {
- contextLineHandler(options);
- }
+ addInlineContextLines(options);
}
/**
@@ -324,41 +269,29 @@ export function trimFirstCharOfLineContent(line = {}) {
return parsedLine;
}
-function getLineCode({ left, right }, index) {
- if (left && left.line_code) {
- return left.line_code;
- } else if (right && right.line_code) {
- return right.line_code;
- }
- return index;
-}
-
function diffFileUniqueId(file) {
return `${file.content_sha}-${file.file_hash}`;
}
function mergeTwoFiles(target, source) {
- const originalInline = target.highlighted_diff_lines;
- const originalParallel = target.parallel_diff_lines;
+ const originalInline = target[INLINE_DIFF_LINES_KEY];
const missingInline = !originalInline.length;
- const missingParallel = !originalParallel.length;
return {
...target,
- highlighted_diff_lines: missingInline ? source.highlighted_diff_lines : originalInline,
- parallel_diff_lines: missingParallel ? source.parallel_diff_lines : originalParallel,
+ [INLINE_DIFF_LINES_KEY]: missingInline ? source[INLINE_DIFF_LINES_KEY] : originalInline,
+ parallel_diff_lines: null,
renderIt: source.renderIt,
collapsed: source.collapsed,
};
}
function ensureBasicDiffFileLines(file) {
- const missingInline = !file.highlighted_diff_lines;
- const missingParallel = !file.parallel_diff_lines || window.gon?.features?.unifiedDiffLines;
+ const missingInline = !file[INLINE_DIFF_LINES_KEY];
Object.assign(file, {
- highlighted_diff_lines: missingInline ? [] : file.highlighted_diff_lines,
- parallel_diff_lines: missingParallel ? [] : file.parallel_diff_lines,
+ [INLINE_DIFF_LINES_KEY]: missingInline ? [] : file[INLINE_DIFF_LINES_KEY],
+ parallel_diff_lines: null,
});
return file;
@@ -382,7 +315,7 @@ function prepareLine(line, file) {
}
}
-export function prepareLineForRenamedFile({ line, diffViewType, diffFile, index = 0 }) {
+export function prepareLineForRenamedFile({ line, diffFile, index = 0 }) {
/*
Renamed files are a little different than other diffs, which
is why this is distinct from `prepareDiffFileLines` below.
@@ -407,48 +340,23 @@ export function prepareLineForRenamedFile({ line, diffViewType, diffFile, index
prepareLine(cleanLine, diffFile); // WARNING: In-Place Mutations!
- if (diffViewType === PARALLEL_DIFF_VIEW_TYPE) {
- return {
- left: { ...cleanLine },
- right: { ...cleanLine },
- line_code: cleanLine.line_code,
- };
- }
-
return cleanLine;
}
function prepareDiffFileLines(file) {
- const inlineLines = file.highlighted_diff_lines;
- const parallelLines = file.parallel_diff_lines;
- let parallelLinesCount = 0;
+ const inlineLines = file[INLINE_DIFF_LINES_KEY];
inlineLines.forEach(line => prepareLine(line, file)); // WARNING: In-Place Mutations!
- parallelLines.forEach((line, index) => {
- Object.assign(line, { line_code: getLineCode(line, index) });
-
- if (line.left) {
- parallelLinesCount += 1;
- prepareLine(line.left, file); // WARNING: In-Place Mutations!
- }
-
- if (line.right) {
- parallelLinesCount += 1;
- prepareLine(line.right, file); // WARNING: In-Place Mutations!
- }
- });
-
Object.assign(file, {
inlineLinesCount: inlineLines.length,
- parallelLinesCount,
});
return file;
}
function getVisibleDiffLines(file) {
- return Math.max(file.inlineLinesCount, file.parallelLinesCount);
+ return file.inlineLinesCount;
}
function finalizeDiffFile(file) {
@@ -478,9 +386,9 @@ function deduplicateFilesList(files) {
return Object.values(dedupedFiles);
}
-export function prepareDiffData(diff, priorFiles = []) {
+export function prepareDiffData({ diff, priorFiles = [], meta = false }) {
const cleanedFiles = (diff.diff_files || [])
- .map((file, index, allFiles) => prepareRawDiffFile({ file, allFiles }))
+ .map((file, index, allFiles) => prepareRawDiffFile({ file, allFiles, meta }))
.map(ensureBasicDiffFileLines)
.map(prepareDiffFileLines)
.map(finalizeDiffFile);
@@ -490,43 +398,14 @@ export function prepareDiffData(diff, priorFiles = []) {
export function getDiffPositionByLineCode(diffFiles) {
let lines = [];
- const hasInlineDiffs = diffFiles.some(file => file.highlighted_diff_lines.length > 0);
-
- if (hasInlineDiffs) {
- // In either of these cases, we can use `highlighted_diff_lines` because
- // that will include all of the parallel diff lines, too
-
- lines = diffFiles.reduce((acc, diffFile) => {
- diffFile.highlighted_diff_lines.forEach(line => {
- acc.push({ file: diffFile, line });
- });
-
- return acc;
- }, []);
- } else {
- // If we're in single diff view mode and the inline lines haven't been
- // loaded yet, we need to parse the parallel lines
-
- lines = diffFiles.reduce((acc, diffFile) => {
- diffFile.parallel_diff_lines.forEach(pair => {
- // It's possible for a parallel line to have an opposite line that doesn't exist
- // For example: *deleted* lines will have `null` right lines, while
- // *added* lines will have `null` left lines.
- // So we have to check each line before we push it onto the array so we're not
- // pushing null line diffs
-
- if (pair.left) {
- acc.push({ file: diffFile, line: pair.left });
- }
- if (pair.right) {
- acc.push({ file: diffFile, line: pair.right });
- }
- });
+ lines = diffFiles.reduce((acc, diffFile) => {
+ diffFile[INLINE_DIFF_LINES_KEY].forEach(line => {
+ acc.push({ file: diffFile, line });
+ });
- return acc;
- }, []);
- }
+ return acc;
+ }, []);
return lines.reduce((acc, { file, line }) => {
if (line.line_code) {
@@ -739,24 +618,10 @@ export const convertExpandLines = ({
export const idleCallback = cb => requestIdleCallback(cb);
function getLinesFromFileByLineCode(file, lineCode) {
- const parallelLines = file.parallel_diff_lines;
- const inlineLines = file.highlighted_diff_lines;
+ const inlineLines = file[INLINE_DIFF_LINES_KEY];
const matchesCode = line => line.line_code === lineCode;
- return [
- ...parallelLines.reduce((acc, line) => {
- if (line.left) {
- acc.push(line.left);
- }
-
- if (line.right) {
- acc.push(line.right);
- }
-
- return acc;
- }, []),
- ...inlineLines,
- ].filter(matchesCode);
+ return inlineLines.filter(matchesCode);
}
export const updateLineInFile = (selectedFile, lineCode, updateFn) => {
@@ -771,12 +636,7 @@ export const allDiscussionWrappersExpanded = diff => {
}
};
- diff.parallel_diff_lines.forEach(line => {
- changeExpandedResult(line.left);
- changeExpandedResult(line.right);
- });
-
- diff.highlighted_diff_lines.forEach(line => {
+ diff[INLINE_DIFF_LINES_KEY].forEach(line => {
changeExpandedResult(line);
});
diff --git a/app/assets/javascripts/diffs/diff_file.js b/app/assets/javascripts/diffs/utils/diff_file.js
index a14a30b41a9..69d0e49e501 100644
--- a/app/assets/javascripts/diffs/diff_file.js
+++ b/app/assets/javascripts/diffs/utils/diff_file.js
@@ -3,7 +3,8 @@ import {
DIFF_FILE_DELETED_MODE,
DIFF_FILE_MANUAL_COLLAPSE,
DIFF_FILE_AUTOMATIC_COLLAPSE,
-} from './constants';
+} from '../constants';
+import { uuids } from './uuids';
function fileSymlinkInformation(file, fileList) {
const duplicates = fileList.filter(iteratedFile => iteratedFile.file_hash === file.file_hash);
@@ -32,16 +33,29 @@ function collapsed(file) {
};
}
-export function prepareRawDiffFile({ file, allFiles }) {
- Object.assign(file, {
+function identifier(file) {
+ return uuids({
+ seeds: [file.file_identifier_hash, file.blob?.id],
+ })[0];
+}
+
+export function prepareRawDiffFile({ file, allFiles, meta = false }) {
+ const additionalProperties = {
brokenSymlink: fileSymlinkInformation(file, allFiles),
viewer: {
...file.viewer,
...collapsed(file),
},
- });
+ };
+
+ // It's possible, but not confirmed, that `content_sha` isn't available sometimes
+ // See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49506#note_464692057
+ // We don't want duplicate IDs if that's the case, so we just don't assign an ID
+ if (!meta && file.blob?.id) {
+ additionalProperties.id = identifier(file);
+ }
- return file;
+ return Object.assign(file, additionalProperties);
}
export function collapsedType(file) {
diff --git a/app/assets/javascripts/diffs/utils/preferences.js b/app/assets/javascripts/diffs/utils/preferences.js
new file mode 100644
index 00000000000..e440de3350a
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/preferences.js
@@ -0,0 +1,22 @@
+import Cookies from 'js-cookie';
+import { getParameterValues } from '~/lib/utils/url_utility';
+
+import { DIFF_FILE_BY_FILE_COOKIE_NAME, DIFF_VIEW_FILE_BY_FILE } from '../constants';
+
+export function fileByFile(pref = false) {
+ const search = getParameterValues(DIFF_FILE_BY_FILE_COOKIE_NAME)?.[0];
+ const cookie = Cookies.get(DIFF_FILE_BY_FILE_COOKIE_NAME);
+ let viewFileByFile = pref;
+
+ // use the cookie first, if it exists
+ if (cookie) {
+ viewFileByFile = cookie === DIFF_VIEW_FILE_BY_FILE;
+ }
+
+ // the search parameter of the URL should override, if it exists
+ if (search) {
+ viewFileByFile = search === DIFF_VIEW_FILE_BY_FILE;
+ }
+
+ return viewFileByFile;
+}