diff --git a/app/models/theme.rb b/app/models/theme.rb
index de06a767bfc..2fcd7c62417 100644
--- a/app/models/theme.rb
+++ b/app/models/theme.rb
@@ -241,6 +241,19 @@ class Theme < ActiveRecord::Base
end
end
+ def self.enabled_theme_and_component_ids
+ get_set_cache "enabled_theme_and_component_ids" do
+ theme_ids = Theme.user_selectable.where(enabled: true).pluck(:id)
+ component_ids =
+ ChildTheme
+ .where(parent_theme_id: theme_ids)
+ .joins(:child_theme)
+ .where(themes: { enabled: true })
+ .pluck(:child_theme_id)
+ (theme_ids | component_ids)
+ end
+ end
+
def self.allowed_remote_theme_ids
return nil if GlobalSetting.allowed_theme_repos.blank?
diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb
index dba348d7a2d..ca7734f7e3d 100644
--- a/app/serializers/user_serializer.rb
+++ b/app/serializers/user_serializer.rb
@@ -324,7 +324,7 @@ class UserSerializer < UserCardSerializer
end
def can_pick_theme_with_custom_homepage
- ThemeModifierHelper.new(theme_ids: Theme.user_theme_ids).custom_homepage
+ ThemeModifierHelper.new(theme_ids: Theme.enabled_theme_and_component_ids).custom_homepage
end
private
diff --git a/spec/models/theme_spec.rb b/spec/models/theme_spec.rb
index d3a561537c0..9d77da0e167 100644
--- a/spec/models/theme_spec.rb
+++ b/spec/models/theme_spec.rb
@@ -466,6 +466,47 @@ HTML
expect(Theme.user_theme_ids).to eq([])
end
+ it "correctly caches enabled_theme_and_component_ids" do
+ Theme.destroy_all
+
+ theme2 = Fabricate(:theme)
+
+ expect(Theme.enabled_theme_and_component_ids).to eq([])
+
+ theme2.update!(user_selectable: true)
+
+ expect(Theme.enabled_theme_and_component_ids).to contain_exactly(theme2.id)
+
+ theme2.update!(user_selectable: false)
+ theme2.set_default!
+ expect(Theme.enabled_theme_and_component_ids).to contain_exactly(theme2.id)
+
+ child2 = Fabricate(:theme, component: true)
+ theme2.add_relative_theme!(:child, child2)
+ expect(Theme.enabled_theme_and_component_ids).to contain_exactly(theme2.id, child2.id)
+
+ child2.update!(enabled: false)
+ expect(Theme.enabled_theme_and_component_ids).to contain_exactly(theme2.id)
+
+ theme3 = Fabricate(:theme, user_selectable: true)
+ child2.update!(enabled: true)
+
+ expect(Theme.enabled_theme_and_component_ids).to contain_exactly(
+ theme2.id,
+ child2.id,
+ theme3.id,
+ )
+
+ theme3.update!(enabled: false)
+
+ expect(Theme.enabled_theme_and_component_ids).to contain_exactly(theme2.id, child2.id)
+
+ theme2.destroy
+ theme3.destroy
+
+ expect(Theme.enabled_theme_and_component_ids).to eq([])
+ end
+
it "correctly caches user_themes template" do
Theme.destroy_all
diff --git a/spec/system/homepage_spec.rb b/spec/system/homepage_spec.rb
index 56c851c5dda..f38d3dc3626 100644
--- a/spec/system/homepage_spec.rb
+++ b/spec/system/homepage_spec.rb
@@ -5,7 +5,7 @@ describe "Homepage", type: :system do
fab!(:user)
fab!(:topics) { Fabricate.times(5, :post).map(&:topic) }
let(:discovery) { PageObjects::Pages::Discovery.new }
- let!(:theme) { Fabricate(:theme) }
+ fab!(:theme)
before do
# A workaround to avoid the global notice from interfering with the tests
@@ -76,23 +76,8 @@ describe "Homepage", type: :system do
expect(page).to have_css(".alert-info")
end
- context "when the theme adds content to the [custom-homepage] connector" do
- let!(:basic_html_field) do
- Fabricate(
- :theme_field,
- theme: theme,
- type_id: ThemeField.types[:html],
- target_id: Theme.targets[:common],
- name: "head_tag",
- value: <<~HTML,
-
- HTML
- )
- end
-
- it "shows the custom homepage from the theme on the homepage" do
+ shared_examples "a custom homepage" do
+ it "shows the custom homepage component" do
visit "/"
expect(page).to have_css(".new-home", text: "Hi friends!")
@@ -148,5 +133,46 @@ describe "Homepage", type: :system do
expect(page).to have_css(".new-home", text: "Hi friends!")
end
end
+
+ context "when the theme adds content to the [custom-homepage] connector" do
+ let!(:basic_html_field) do
+ Fabricate(
+ :theme_field,
+ theme: theme,
+ type_id: ThemeField.types[:html],
+ target_id: Theme.targets[:common],
+ name: "head_tag",
+ value: <<~HTML,
+
+ HTML
+ )
+ end
+
+ include_examples "a custom homepage"
+ end
+
+ context "when a theme component adds content to the [custom-homepage] connector" do
+ let!(:component) { Fabricate(:theme, component: true) }
+ let!(:component_html_field) do
+ Fabricate(
+ :theme_field,
+ theme: component,
+ type_id: ThemeField.types[:html],
+ target_id: Theme.targets[:common],
+ name: "head_tag",
+ value: <<~HTML,
+
+ HTML
+ )
+ end
+
+ before { theme.add_relative_theme!(:child, component) }
+
+ include_examples "a custom homepage"
+ end
end
end