Skip to content

Commit

Permalink
Give the replies collection an identifier and enable pagination (ma…
Browse files Browse the repository at this point in the history
  • Loading branch information
ClearlyClaire authored and Gargron committed Feb 28, 2019
1 parent ab3c77c commit 16e24b9
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 3 deletions.
53 changes: 53 additions & 0 deletions app/controllers/statuses_controller.rb
Expand Up @@ -18,6 +18,7 @@ class StatusesController < ApplicationController
before_action :redirect_to_original, only: [:show]
before_action :set_referrer_policy_header, only: [:show]
before_action :set_cache_headers
before_action :set_replies, only: [:replies]

content_security_policy only: :embed do |p|
p.frame_ancestors(false)
Expand Down Expand Up @@ -63,8 +64,37 @@ def embed
render 'stream_entries/embed', layout: 'embedded'
end

def replies
skip_session!

render json: replies_collection_presenter,
serializer: ActivityPub::CollectionSerializer,
adapter: ActivityPub::Adapter,
content_type: 'application/activity+json',
skip_activities: true
end

private

def replies_collection_presenter
page = ActivityPub::CollectionPresenter.new(
id: replies_account_status_url(@account, @status, page_params),
type: :unordered,
part_of: replies_account_status_url(@account, @status),
next: next_page,
items: @replies.map { |status| status.local ? status : status.id }
)
if page_requested?
page
else
ActivityPub::CollectionPresenter.new(
id: replies_account_status_url(@account, @status),
type: :unordered,
first: page
)
end
end

def create_descendant_thread(starting_depth, statuses)
depth = starting_depth + statuses.size
if depth < DESCENDANTS_DEPTH_LIMIT
Expand Down Expand Up @@ -174,4 +204,27 @@ def set_referrer_policy_header
return if @status.public_visibility? || @status.unlisted_visibility?
response.headers['Referrer-Policy'] = 'origin'
end

def page_requested?
params[:page] == 'true'
end

def set_replies
@replies = page_params[:other_accounts] ? Status.where.not(account_id: @account.id) : @account.statuses
@replies = @replies.where(in_reply_to_id: @status.id, visibility: [:public, :unlisted])
@replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id])
end

def next_page
last_reply = @replies.last
return if last_reply.nil?
same_account = last_reply.account_id == @account.id
return unless same_account || @replies.size == DESCENDANTS_LIMIT
same_account = false unless @replies.size == DESCENDANTS_LIMIT
replies_account_status_url(@account, @status, page: true, min_id: last_reply.id, other_accounts: !same_account)
end

def page_params
{ page: true, other_accounts: params[:other_accounts], min_id: params[:min_id] }.compact
end
end
6 changes: 6 additions & 0 deletions app/lib/activitypub/tag_manager.rb
Expand Up @@ -48,6 +48,12 @@ def activity_uri_for(target)
activity_account_status_url(target.account, target)
end

def replies_uri_for(target, page_params = nil)
raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?

replies_account_status_url(target.account, target, page_params)
end

# Primary audience of a status
# Public statuses go out to primarily the public collection
# Unlisted and private statuses go out primarily to the followers collection
Expand Down
10 changes: 7 additions & 3 deletions app/serializers/activitypub/note_serializer.rb
Expand Up @@ -13,7 +13,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer
has_many :media_attachments, key: :attachment
has_many :virtual_tags, key: :tag

has_one :replies, serializer: ActivityPub::CollectionSerializer
has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local?

def id
ActivityPub::TagManager.instance.uri_for(object)
Expand All @@ -36,12 +36,16 @@ def content_map
end

def replies
replies = object.self_replies(5).pluck(:id, :uri)
last_id = replies.last&.first
ActivityPub::CollectionPresenter.new(
type: :unordered,
id: ActivityPub::TagManager.instance.replies_uri_for(object),
first: ActivityPub::CollectionPresenter.new(
type: :unordered,
page: true,
items: object.self_replies(5).pluck(:uri)
part_of: ActivityPub::TagManager.instance.replies_uri_for(object),
items: replies.map(&:second),
next: last_id ? ActivityPub::TagManager.instance.replies_uri_for(object, page: true, min_id: last_id) : nil
)
)
end
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Expand Up @@ -56,6 +56,7 @@
member do
get :activity
get :embed
get :replies
end
end

Expand Down

0 comments on commit 16e24b9

Please sign in to comment.