diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/diffs/components/app.vue | 58 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/components/diff_content.vue | 4 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/components/diff_file.vue | 3 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/getters.js | 3 | ||||
-rw-r--r-- | app/assets/stylesheets/framework/diffs.scss | 2 | ||||
-rw-r--r-- | app/assets/stylesheets/page_bundles/merge_requests.scss | 4 | ||||
-rw-r--r-- | app/controllers/projects/merge_requests_controller.rb | 1 | ||||
-rw-r--r-- | app/models/project.rb | 37 | ||||
-rw-r--r-- | app/presenters/project_presenter.rb | 8 |
9 files changed, 95 insertions, 25 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 66157dfeaba..6a3f5993a22 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -3,6 +3,7 @@ import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import Mousetrap from 'mousetrap'; import { mapState, mapGetters, mapActions } from 'vuex'; +import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller'; import api from '~/api'; import { keysFor, @@ -17,7 +18,6 @@ import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils'; import { updateHistory } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; import PanelResizer from '~/vue_shared/components/panel_resizer.vue'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import notesEventHub from '../../notes/event_hub'; import { @@ -69,8 +69,9 @@ export default { PanelResizer, GlPagination, GlSprintf, + DynamicScroller, + DynamicScrollerItem, }, - mixins: [glFeatureFlagsMixin()], alerts: { ALERT_OVERFLOW_HIDDEN, ALERT_MERGE_CONFLICT, @@ -196,7 +197,12 @@ export default { 'renderTreeList', 'showWhitespace', ]), - ...mapGetters('diffs', ['whichCollapsedTypes', 'isParallelView', 'currentDiffIndex']), + ...mapGetters('diffs', [ + 'whichCollapsedTypes', + 'isParallelView', + 'currentDiffIndex', + 'isVirtualScrollingEnabled', + ]), ...mapGetters('batchComments', ['draftsCount']), ...mapGetters(['isNotesFetched', 'getNoteableData']), diffs() { @@ -561,17 +567,41 @@ export default { <commit-widget v-if="commit" :commit="commit" :collapsible="false" /> <div v-if="isBatchLoading" class="loading"><gl-loading-icon size="lg" /></div> <template v-else-if="renderDiffFiles"> - <diff-file - v-for="(file, index) in diffs" - :key="file.newPath" - :file="file" - :reviewed="fileReviews[file.id]" - :is-first-file="index === 0" - :is-last-file="index === diffFilesLength - 1" - :help-page-path="helpPagePath" - :can-current-user-fork="canCurrentUserFork" - :view-diffs-file-by-file="viewDiffsFileByFile" - /> + <dynamic-scroller + v-if="isVirtualScrollingEnabled" + :items="diffs" + :min-item-size="70" + :buffer="1000" + :use-transform="false" + page-mode + > + <template #default="{ item, index, active }"> + <dynamic-scroller-item :item="item" :active="active"> + <diff-file + :file="item" + :reviewed="fileReviews[item.id]" + :is-first-file="index === 0" + :is-last-file="index === diffFilesLength - 1" + :help-page-path="helpPagePath" + :can-current-user-fork="canCurrentUserFork" + :view-diffs-file-by-file="viewDiffsFileByFile" + /> + </dynamic-scroller-item> + </template> + </dynamic-scroller> + <template v-else> + <diff-file + v-for="(file, index) in diffs" + :key="file.new_path" + :file="file" + :reviewed="fileReviews[file.id]" + :is-first-file="index === 0" + :is-last-file="index === diffFilesLength - 1" + :help-page-path="helpPagePath" + :can-current-user-fork="canCurrentUserFork" + :view-diffs-file-by-file="viewDiffsFileByFile" + /> + </template> <div v-if="showFileByFileNavigation" data-testid="file-by-file-navigation" diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue index 663d2bb3cf8..283dbc6031c 100644 --- a/app/assets/javascripts/diffs/components/diff_content.vue +++ b/app/assets/javascripts/diffs/components/diff_content.vue @@ -49,9 +49,7 @@ export default { }, }, computed: { - ...mapState({ - projectPath: (state) => state.diffs.projectPath, - }), + ...mapState('diffs', ['projectPath']), ...mapGetters('diffs', [ 'isInlineView', 'isParallelView', diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue index d9887c2ce05..ce867dbb9e0 100644 --- a/app/assets/javascripts/diffs/components/diff_file.vue +++ b/app/assets/javascripts/diffs/components/diff_file.vue @@ -83,7 +83,7 @@ export default { computed: { ...mapState('diffs', ['currentDiffFileId', 'codequalityDiff']), ...mapGetters(['isNotesFetched']), - ...mapGetters('diffs', ['getDiffFileDiscussions']), + ...mapGetters('diffs', ['getDiffFileDiscussions', 'isVirtualScrollingEnabled']), viewBlobHref() { return escape(this.file.view_path); }, @@ -290,6 +290,7 @@ export default { 'is-active': currentDiffFileId === file.file_hash, 'comments-disabled': Boolean(file.brokenSymlink), 'has-body': showBody, + 'is-virtual-scrolling': isVirtualScrollingEnabled, }" :data-path="file.new_path" class="diff-file file-holder gl-border-none" diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js index dec3f87b03e..0a9623c13a3 100644 --- a/app/assets/javascripts/diffs/store/getters.js +++ b/app/assets/javascripts/diffs/store/getters.js @@ -170,3 +170,6 @@ export function suggestionCommitMessage(state, _, rootState) { }, }); } + +export const isVirtualScrollingEnabled = (state) => + !state.viewDiffsFileByFile && window.gon?.features?.diffsVirtualScrolling; diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss index dd0c0bd9b60..a07e0b48cff 100644 --- a/app/assets/stylesheets/framework/diffs.scss +++ b/app/assets/stylesheets/framework/diffs.scss @@ -729,7 +729,7 @@ table.code { } .files { - .diff-file:last-child { + .diff-file:not(.is-virtual-scrolling):last-child { margin-bottom: 0; } } diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss index 9fdc30359f8..5e9dd883635 100644 --- a/app/assets/stylesheets/page_bundles/merge_requests.scss +++ b/app/assets/stylesheets/page_bundles/merge_requests.scss @@ -7,6 +7,10 @@ .diff-files-holder { flex: 1; min-width: 0; + + .vue-recycle-scroller__item-wrapper { + overflow: visible; + } } .with-system-header { diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index d1d83f35d5f..613faa200d1 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -42,6 +42,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml) push_frontend_feature_flag(:usage_data_i_testing_summary_widget_total, @project, default_enabled: :yaml) push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml) + push_frontend_feature_flag(:diffs_virtual_scrolling, project, default_enabled: :yaml) # Usage data feature flags push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml) diff --git a/app/models/project.rb b/app/models/project.rb index cd7e49d2c4a..8f6c81485ba 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -128,8 +128,41 @@ class Project < ApplicationRecord after_initialize :use_hashed_storage after_create :check_repository_absence! - acts_as_ordered_taggable - alias_method :topics, :tag_list + acts_as_ordered_taggable_on :topics + # The 'tag_list' alias and the 'has_many' associations are required during the 'tags -> topics' migration + # TODO: eliminate 'tag_list', 'topic_taggings' and 'tags' in the further process of the migration + # https://gitlab.com/gitlab-org/gitlab/-/issues/331081 + alias_attribute :tag_list, :topic_list + has_many :topic_taggings, -> { includes(:tag).order("#{ActsAsTaggableOn::Tagging.table_name}.id") }, + as: :taggable, + class_name: 'ActsAsTaggableOn::Tagging', + after_add: :dirtify_tag_list, + after_remove: :dirtify_tag_list + has_many :topics, -> { order("#{ActsAsTaggableOn::Tagging.table_name}.id") }, + class_name: 'ActsAsTaggableOn::Tag', + through: :topic_taggings, + source: :tag + has_many :tags, -> { order("#{ActsAsTaggableOn::Tagging.table_name}.id") }, + class_name: 'ActsAsTaggableOn::Tag', + through: :topic_taggings, + source: :tag + + # Overwriting 'topic_list' and 'topic_list=' is necessary to ensure functionality during the background migration [1]. + # [1] https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61237 + # TODO: remove 'topic_list' and 'topic_list=' once the background migration is complete + # https://gitlab.com/gitlab-org/gitlab/-/issues/331081 + def topic_list + # Return both old topics (context 'tags') and new topics (context 'topics') + tag_list_on('tags') + tag_list_on('topics') + end + + def topic_list=(new_tags) + # Old topics with context 'tags' are added as new topics with context 'topics' + super(new_tags) + + # Remove old topics with context 'tags' + set_tag_list_on('tags', '') + end attr_accessor :old_path_with_namespace attr_accessor :template_name diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb index 3726238474f..4f803ba34f4 100644 --- a/app/presenters/project_presenter.rb +++ b/app/presenters/project_presenter.rb @@ -401,16 +401,16 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated end def topics_to_show - project.topics.take(MAX_TOPICS_TO_SHOW) # rubocop: disable CodeReuse/ActiveRecord + project.topic_list.take(MAX_TOPICS_TO_SHOW) # rubocop: disable CodeReuse/ActiveRecord end def topics_not_shown - project.topics - topics_to_show + project.topic_list - topics_to_show end def count_of_extra_topics_not_shown - if project.topics.count > MAX_TOPICS_TO_SHOW - project.topics.count - MAX_TOPICS_TO_SHOW + if project.topic_list.count > MAX_TOPICS_TO_SHOW + project.topic_list.count - MAX_TOPICS_TO_SHOW else 0 end |