diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index cba8f48071bb1a73c354c82adf0032d849fbc6a6..8f12ee407a0faac6774c07e1b0d25d30c742618b 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -159,9 +159,6 @@ // thus reducing TBT in the browser. // Grid is used instead of table layout because content-visibility performs better with it. tr { - content-visibility: auto; - display: grid; - grid-template-columns: 400px max-content auto; border-bottom: 1px solid $gray-darker; &:last-child { diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index 5bfda526fb09031184f9c3fb7febdd98ba70be49..e2ab87bba0b7340b0f43fc90b2042bc80a6d0c84 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -27,7 +27,21 @@ def show @blame = Gitlab::View::Presenter::Factory.new(blame_service.blame, project: @project, path: @path, page: blame_service.page).fabricate! - render locals: { blame_pagination: blame_service.pagination } + render locals: { total_extra_pages: blame_service.total_extra_pages } + end + + def page + @blob = @repository.blob_at(@commit.id, @path) + + environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit } + environment_params[:find_latest] = true + @environment = ::Environments::EnvironmentsByDeploymentsFinder.new(@project, current_user, environment_params).execute.last + + blame_service = Projects::BlameService.new(@blob, @commit, params.permit(:page)) + + @blame = Gitlab::View::Presenter::Factory.new(blame_service.blame, project: @project, path: @path, page: blame_service.page).fabricate! + + render partial: 'page' end end diff --git a/app/services/projects/blame_service.rb b/app/services/projects/blame_service.rb index b324ea27360dd88cb0666c8131acb76178c10d03..4db303795c1fba0235ff33ad79fca506944f4a04 100644 --- a/app/services/projects/blame_service.rb +++ b/app/services/projects/blame_service.rb @@ -4,7 +4,7 @@ # objects module Projects class BlameService - PER_PAGE = 1000 + PER_PAGE = 2000 def initialize(blob, commit, params) @blob = blob @@ -26,6 +26,12 @@ def pagination .page(page) end + def total_extra_pages + return 0 unless pagination_enabled? + + (blob_lines_count / per_page).ceil + end + private attr_reader :blob, :commit diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 84eb2706929fa1edefecfcb869ca3b4ca3d40a35..8bf10e3e6d65a60a23171d1d16f51813993da210 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -10,6 +10,7 @@ %meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' } = render 'layouts/startup_js' + = yield :startup_js - if page_canonical_link %link{ rel: 'canonical', href: page_canonical_link } diff --git a/app/views/projects/blame/_page.html.haml b/app/views/projects/blame/_page.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..280272c416d5367a0aea24e044feb09f4e65d432 --- /dev/null +++ b/app/views/projects/blame/_page.html.haml @@ -0,0 +1,39 @@ +- current_line = @blame.first_line + +.table-responsive.file-content.blame.code{ class: user_color_scheme, data: { qa_selector: 'blame_file_content' } } + %table + - @blame.groups.each do |blame_group| + - commit_data = @blame.commit_data(blame_group[:commit]) + - line_count = blame_group[:lines].count + + %tr{ style: intrinsic_row_css(line_count) } + %td.blame-commit{ class: commit_data.age_map_class } + .commit + = commit_data.author_avatar + + .commit-row-title + %span.item-title.str-truncated-100 + = commit_data.commit_link + %span + = commit_data.project_blame_link +   + + .light + = commit_data.commit_author_link + = _('committed') + #{commit_data.time_ago_tooltip} + + %td.line-numbers + - (current_line...(current_line + line_count)).each do |i| + %a.diff-line-num.gl-justify-content-end{ href: "#L#{i}", id: "L#{i}", 'data-line-number' => i, class: "gl-display-flex!" } + .file-line-num + = i + \ + + %td.lines.gl-w-full + %pre.code.highlight + %code + - blame_group[:lines].each do |line| + #{line} + + - current_line += line_count diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index b44c773adff9594385cd1a20230ffe8dd49de6f9..d2ec2df727a9b742830708cb15f59048ae99e438 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,4 +1,39 @@ - page_title _("Blame"), @blob.path, @ref +- if total_extra_pages != 0 + - content_for :startup_js do + = javascript_tag do + :plain + const requests = Array.from( + { length: #{total_extra_pages} }, + (v, i) => { + const url = new URL(window.location); + url.pathname = url.pathname.replace('-/blame/', '-/blame_page/'); + url.searchParams.set('page', i + 2); + return fetch(url); + }, + ); + window.startStreaming = async () => { + const streamDocument = document.implementation.createHTMLDocument('stream'); + streamDocument.open(); + streamDocument.write(''); + const root = document.querySelector('#stream-container'); + const virtualStreamingElement = streamDocument.querySelector('streaming-element'); + root.appendChild(virtualStreamingElement); + + const textChunks = requests.map((request) => { + return request.then((response) => response.text()); + }); + + for await (const promise of textChunks) { + const text = await promise; + streamDocument.write(text); + } + + streamDocument.write(''); + streamDocument.close(); + + if (location.hash && location.hash !== '#') location.hash = location.hash; + }; #blob-content-holder.tree-holder = render "projects/blob/breadcrumb", blob: @blob, blame: true @@ -20,44 +55,9 @@ %span.legend-box.legend-box-9 %span.right-label Older - .table-responsive.file-content.blame.code{ class: user_color_scheme, data: { qa_selector: 'blame_file_content' } } - %table - - current_line = @blame.first_line - - @blame.groups.each do |blame_group| - - commit_data = @blame.commit_data(blame_group[:commit]) - - line_count = blame_group[:lines].count - - %tr{ style: intrinsic_row_css(line_count) } - %td.blame-commit{ class: commit_data.age_map_class } - .commit - = commit_data.author_avatar - - .commit-row-title - %span.item-title.str-truncated-100 - = commit_data.commit_link - %span - = commit_data.project_blame_link -   - - .light - = commit_data.commit_author_link - = _('committed') - #{commit_data.time_ago_tooltip} - - %td.line-numbers - - (current_line...(current_line + line_count)).each do |i| - %a.diff-line-num.gl-justify-content-end{ href: "#L#{i}", id: "L#{i}", 'data-line-number' => i, class: "gl-display-flex!" } - .file-line-num - = i - \ - - %td.lines.gl-w-full - %pre.code.highlight - %code - - blame_group[:lines].each do |line| - #{line} - - - current_line += line_count - - - if blame_pagination - = paginate(blame_pagination, theme: "gitlab") + %div{ data: { qa_selector: 'blame_file_content' } } + = render partial: 'page' + #stream-container + = javascript_tag do + :plain + window.startStreaming() diff --git a/config/routes/repository.rb b/config/routes/repository.rb index 0202eb80b232728ac2869e74852da1b31d1df28f..60d3d37bdc85ae84464693af60c1d8c40cf7f829 100644 --- a/config/routes/repository.rb +++ b/config/routes/repository.rb @@ -75,6 +75,7 @@ get '/tree/*id', to: 'tree#show', as: :tree get '/raw/*id', to: 'raw#show', as: :raw + get '/blame_page/*id', to: 'blame#page', as: :blame_page get '/blame/*id', to: 'blame#show', as: :blame get '/commits', to: 'commits#commits_root', as: :commits_root