end
def descendants(limit, account = nil, max_child_id = nil, since_child_id = nil, depth = nil)
- find_statuses_from_tree_path(descendant_ids(limit, max_child_id, since_child_id, depth), account)
+ find_statuses_from_tree_path(descendant_ids(limit, max_child_id, since_child_id, depth), account, promote: true)
end
private
descendants_with_self - [self]
end
- def find_statuses_from_tree_path(ids, account)
+ def find_statuses_from_tree_path(ids, account, promote: false)
statuses = statuses_with_accounts(ids).to_a
account_ids = statuses.map(&:account_id).uniq
domains = statuses.map(&:account_domain).compact.uniq
# Order ancestors/descendants by tree path
statuses.sort_by! { |status| ids.index(status.id) }
+
+ # Bring self-replies to the top
+ if promote
+ promote_by!(statuses) { |status| status.in_reply_to_account_id == status.account_id }
+ else
+ statuses
+ end
+ end
+
+ def promote_by!(arr)
+ insert_at = arr.find_index { |item| !yield(item) }
+
+ return arr if insert_at.nil?
+
+ arr.each_with_index do |item, index|
+ next if index <= insert_at || !yield(item)
+
+ arr.insert(insert_at, arr.delete_at(index))
+ insert_at += 1
+ end
+
+ arr
end
def relations_map_for_account(account, account_ids, domains)
viewer.block_domain!('example.com')
expect(status.descendants(4, viewer)).to_not include(reply2)
end
+
+ it 'promotes self-replies to the top while leaving the rest in order' do
+ a = Fabricate(:status, account: alice)
+ d = Fabricate(:status, account: jeff, thread: a)
+ e = Fabricate(:status, account: bob, thread: d)
+ c = Fabricate(:status, account: alice, thread: a)
+ f = Fabricate(:status, account: bob, thread: c)
+
+ expect(a.descendants(20)).to eq [c, d, e, f]
+ end
end
end