mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 18:36:35 +08:00
e7a84948b9
When preloading topic_list data we were giving it a 'preload key' which was loosely based on the parameters of the list. However, it did not include all parameters, and mismatches between client/server-side logic would cause the preloaded data to be ignored. This commit simplifies things by using a single key for all topic_list preloading. This works on the assumption that "The first topic_list the JS app will load is the one which was preloaded". That assumption also existed to some extent in the old design, so we don't expect any regressions here.
168 lines
3.9 KiB
Ruby
168 lines
3.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class TopicList
|
|
include ActiveModel::Serialization
|
|
|
|
cattr_accessor :preloaded_custom_fields
|
|
self.preloaded_custom_fields = Set.new
|
|
|
|
def self.on_preload(&blk)
|
|
(@preload ||= Set.new) << blk
|
|
end
|
|
|
|
def self.cancel_preload(&blk)
|
|
if @preload
|
|
@preload.delete blk
|
|
if @preload.length == 0
|
|
@preload = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.preload(topics, object)
|
|
if @preload
|
|
@preload.each { |preload| preload.call(topics, object) }
|
|
end
|
|
end
|
|
|
|
def self.on_preload_user_ids(&blk)
|
|
(@preload_user_ids ||= Set.new) << blk
|
|
end
|
|
|
|
def self.preload_user_ids(topics, user_ids, object)
|
|
if @preload_user_ids
|
|
@preload_user_ids.each do |preload_user_ids|
|
|
user_ids = preload_user_ids.call(topics, user_ids, object)
|
|
end
|
|
end
|
|
user_ids
|
|
end
|
|
|
|
attr_accessor(
|
|
:more_topics_url,
|
|
:prev_topics_url,
|
|
:filter,
|
|
:for_period,
|
|
:per_page,
|
|
:top_tags,
|
|
:current_user,
|
|
:tags,
|
|
:shared_drafts,
|
|
:category,
|
|
:publish_read_state
|
|
)
|
|
|
|
def initialize(filter, current_user, topics, opts = nil)
|
|
@filter = filter
|
|
@current_user = current_user
|
|
@topics_input = topics
|
|
@opts = opts || {}
|
|
|
|
if @opts[:category]
|
|
@category = Category.find_by(id: @opts[:category_id])
|
|
end
|
|
|
|
if @opts[:tags]
|
|
@tags = Tag.where(id: @opts[:tags]).all
|
|
end
|
|
|
|
@publish_read_state = !!@opts[:publish_read_state]
|
|
end
|
|
|
|
def top_tags
|
|
opts = @category ? { category: @category } : {}
|
|
opts[:guardian] = Guardian.new(@current_user)
|
|
Tag.top_tags(**opts)
|
|
end
|
|
|
|
def preload_key
|
|
"topic_list"
|
|
end
|
|
|
|
# Lazy initialization
|
|
def topics
|
|
@topics ||= load_topics
|
|
end
|
|
|
|
def load_topics
|
|
@topics = @topics_input
|
|
|
|
# Attach some data for serialization to each topic
|
|
@topic_lookup = TopicUser.lookup_for(@current_user, @topics) if @current_user
|
|
@dismissed_topic_users_lookup = DismissedTopicUser.lookup_for(@current_user, @topics) if @current_user
|
|
|
|
post_action_type =
|
|
if @current_user
|
|
if @opts[:filter].present?
|
|
if @opts[:filter] == "liked"
|
|
PostActionType.types[:like]
|
|
end
|
|
end
|
|
end
|
|
|
|
# Data for bookmarks or likes
|
|
post_action_lookup = PostAction.lookup_for(@current_user, @topics, post_action_type) if post_action_type
|
|
|
|
# Create a lookup for all the user ids we need
|
|
user_ids = []
|
|
@topics.each do |ft|
|
|
user_ids << ft.user_id << ft.last_post_user_id << ft.featured_user_ids << ft.allowed_user_ids
|
|
end
|
|
|
|
user_ids = TopicList.preload_user_ids(@topics, user_ids, self)
|
|
user_lookup = UserLookup.new(user_ids)
|
|
|
|
@topics.each do |ft|
|
|
ft.user_data = @topic_lookup[ft.id] if @topic_lookup.present?
|
|
|
|
if ft.regular? && category_user_lookup.present?
|
|
ft.category_user_data = @category_user_lookup[ft.category_id]
|
|
end
|
|
|
|
ft.dismissed = @current_user && @dismissed_topic_users_lookup.include?(ft.id)
|
|
|
|
if ft.user_data && post_action_lookup && actions = post_action_lookup[ft.id]
|
|
ft.user_data.post_action_data = { post_action_type => actions }
|
|
end
|
|
|
|
ft.posters = ft.posters_summary(
|
|
user_lookup: user_lookup
|
|
)
|
|
|
|
ft.participants = ft.participants_summary(
|
|
user_lookup: user_lookup,
|
|
user: @current_user
|
|
)
|
|
ft.topic_list = self
|
|
end
|
|
|
|
ActiveRecord::Associations::Preloader
|
|
.new(records: @topics, associations: [:image_upload, topic_thumbnails: :optimized_image])
|
|
.call
|
|
|
|
if preloaded_custom_fields.present?
|
|
Topic.preload_custom_fields(@topics, preloaded_custom_fields)
|
|
end
|
|
|
|
TopicList.preload(@topics, self)
|
|
|
|
@topics
|
|
end
|
|
|
|
def attributes
|
|
{ 'more_topics_url' => page }
|
|
end
|
|
|
|
private
|
|
|
|
def category_user_lookup
|
|
@category_user_lookup ||= begin
|
|
if @current_user
|
|
CategoryUser.lookup_for(@current_user, @topics.map(&:category_id).uniq)
|
|
else
|
|
[]
|
|
end
|
|
end
|
|
end
|
|
end
|