Fix prev/next links on public profile page (#6497)

* Fix prev/next links on public profile page

* Don't make pagination urls if no available statuses

* Fix empty check method

* Put left chevron before prev page link

* Add scope for pagination "starting at" a given id

* Status pagination try 2:

s/prev/older and s/next/newer
"older" on left, "newer" on right
Use new scope for "newer" link
Extract magic 20 page size to constant
Remove max_id from feed pagination as it's not respected

* Reinstate max_id for accounts atom stream

* normalize
This commit is contained in:
Ian McCowan 2018-02-25 18:31:28 -08:00 committed by Eugen Rochko
parent 5cc716688a
commit c33931b613
5 changed files with 53 additions and 17 deletions

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class AccountsController < ApplicationController class AccountsController < ApplicationController
PAGE_SIZE = 20
include AccountControllerConcern include AccountControllerConcern
before_action :set_cache_headers before_action :set_cache_headers
@ -16,13 +18,16 @@ class AccountsController < ApplicationController
end end
@pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses? @pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses?
@statuses = filtered_statuses.paginate_by_max_id(20, params[:max_id], params[:since_id]) @statuses = filtered_status_page(params)
@statuses = cache_collection(@statuses, Status) @statuses = cache_collection(@statuses, Status)
@next_url = next_url unless @statuses.empty? unless @statuses.empty?
@older_url = older_url if @statuses.last.id > filtered_statuses.last.id
@newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id
end
end end
format.atom do format.atom do
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id]) @entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id])
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? })) render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? }))
end end
@ -69,13 +74,22 @@ class AccountsController < ApplicationController
@account = Account.find_local!(params[:username]) @account = Account.find_local!(params[:username])
end end
def next_url def older_url
::Rails.logger.info("older: max_id #{@statuses.last.id}, url #{pagination_url(max_id: @statuses.last.id)}")
pagination_url(max_id: @statuses.last.id)
end
def newer_url
pagination_url(min_id: @statuses.first.id)
end
def pagination_url(max_id: nil, min_id: nil)
if media_requested? if media_requested?
short_account_media_url(@account, max_id: @statuses.last.id) short_account_media_url(@account, max_id: max_id, min_id: min_id)
elsif replies_requested? elsif replies_requested?
short_account_with_replies_url(@account, max_id: @statuses.last.id) short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
else else
short_account_url(@account, max_id: @statuses.last.id) short_account_url(@account, max_id: max_id, min_id: min_id)
end end
end end
@ -86,4 +100,12 @@ class AccountsController < ApplicationController
def replies_requested? def replies_requested?
request.path.ends_with?('/with_replies') request.path.ends_with?('/with_replies')
end end
def filtered_status_page(params)
if params[:min_id].present?
filtered_statuses.paginate_by_min_id(PAGE_SIZE, params[:min_id]).reverse
else
filtered_statuses.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id]).to_a
end
end
end end

View file

@ -233,8 +233,8 @@
a, a,
.current, .current,
.next, .newer,
.prev, .older,
.page, .page,
.gap { .gap {
font-size: 14px; font-size: 14px;
@ -257,13 +257,13 @@
cursor: default; cursor: default;
} }
.prev, .older,
.next { .newer {
text-transform: uppercase; text-transform: uppercase;
color: $ui-secondary-color; color: $ui-secondary-color;
} }
.prev { .older {
float: left; float: left;
padding-left: 0; padding-left: 0;
@ -273,7 +273,7 @@
} }
} }
.next { .newer {
float: right; float: right;
padding-right: 0; padding-right: 0;
@ -295,8 +295,8 @@
display: none; display: none;
} }
.next, .newer,
.prev { .older {
display: inline-block; display: inline-block;
} }
} }

View file

@ -10,5 +10,14 @@ module Paginable
query = query.where(arel_table[:id].gt(since_id)) if since_id.present? query = query.where(arel_table[:id].gt(since_id)) if since_id.present?
query query
} }
# Differs from :paginate_by_max_id in that it gives the results immediately following min_id,
# whereas since_id gives the items with largest id, but with since_id as a cutoff.
# Results will be in ascending order by id.
scope :paginate_by_min_id, ->(limit, min_id = nil) {
query = reorder(arel_table[:id]).limit(limit)
query = query.where(arel_table[:id].gt(min_id)) if min_id.present?
query
}
end end
end end

View file

@ -39,6 +39,9 @@
= render partial: 'stream_entries/status', collection: @statuses, as: :status = render partial: 'stream_entries/status', collection: @statuses, as: :status
- if @statuses.size == 20 - if @newer_url || @older_url
.pagination .pagination
= link_to safe_join([t('pagination.next'), fa_icon('chevron-right')], ' '), @next_url, class: 'next', rel: 'next' - if @older_url
= link_to safe_join([fa_icon('chevron-left'), t('pagination.older')], ' '), @older_url, class: 'older', rel: 'older'
- if @newer_url
= link_to safe_join([t('pagination.newer'), fa_icon('chevron-right')], ' '), @newer_url, class: 'newer', rel: 'newer'

View file

@ -545,7 +545,9 @@ en:
trillion: T trillion: T
unit: '' unit: ''
pagination: pagination:
newer: Newer
next: Next next: Next
older: Older
prev: Prev prev: Prev
truncate: "&hellip;" truncate: "&hellip;"
preferences: preferences: