From 85c625d31974e411666812468ddfd7760ab67d4a Mon Sep 17 00:00:00 2001
From: Jason Punyon <jason.punyon@gmail.com>
Date: Wed, 15 May 2024 05:38:16 -0400
Subject: [PATCH] Fix repetitive database queries from #30040 (#30259)

---
 app/helpers/application_helper.rb       | 13 +++++++++----
 app/presenters/instance_presenter.rb    | 12 ++++++++++++
 app/serializers/manifest_serializer.rb  |  2 +-
 app/views/layouts/application.html.haml |  6 +++---
 spec/helpers/application_helper_spec.rb | 15 ++++++++++-----
 5 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index ff351429e..eb03f1e4b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -240,11 +240,16 @@ module ApplicationHelper
     EmojiFormatter.new(html, custom_emojis, other_options.merge(animate: prefers_autoplay?)).to_s
   end
 
-  def site_icon_path(type, size = '48')
-    icon = SiteUpload.find_by(var: type)
-    return nil unless icon
+  def instance_presenter
+    @instance_presenter ||= InstancePresenter.new
+  end
 
-    icon.file.url(size)
+  def favicon_path(size = '48')
+    instance_presenter.favicon&.file&.url(size)
+  end
+
+  def app_icon_path(size = '48')
+    instance_presenter.app_icon&.file&.url(size)
   end
 
   private
diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb
index 25df4d85a..92415a690 100644
--- a/app/presenters/instance_presenter.rb
+++ b/app/presenters/instance_presenter.rb
@@ -81,4 +81,16 @@ class InstancePresenter < ActiveModelSerializers::Model
   def mascot
     @mascot ||= Rails.cache.fetch('site_uploads/mascot') { SiteUpload.find_by(var: 'mascot') }
   end
+
+  def favicon
+    return @favicon if defined?(@favicon)
+
+    @favicon ||= Rails.cache.fetch('site_uploads/favicon') { SiteUpload.find_by(var: 'favicon') }
+  end
+
+  def app_icon
+    return @app_icon if defined?(@app_icon)
+
+    @app_icon ||= Rails.cache.fetch('site_uploads/app_icon') { SiteUpload.find_by(var: 'app_icon') }
+  end
 end
diff --git a/app/serializers/manifest_serializer.rb b/app/serializers/manifest_serializer.rb
index 759490228..a39fb5ef5 100644
--- a/app/serializers/manifest_serializer.rb
+++ b/app/serializers/manifest_serializer.rb
@@ -27,7 +27,7 @@ class ManifestSerializer < ActiveModel::Serializer
 
   def icons
     SiteUpload::ANDROID_ICON_SIZES.map do |size|
-      src = site_icon_path('app_icon', size.to_i)
+      src = app_icon_path(size.to_i)
       src = URI.join(root_url, src).to_s if src.present?
 
       {
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index e3d05226e..5957d1dbf 100755
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -11,13 +11,13 @@
     - if storage_host?
       %link{ rel: 'dns-prefetch', href: storage_host }/
 
-    %link{ rel: 'icon', href: site_icon_path('favicon', 'ico') || '/favicon.ico', type: 'image/x-icon' }/
+    %link{ rel: 'icon', href: favicon_path('ico') || '/favicon.ico', type: 'image/x-icon' }/
 
     - SiteUpload::FAVICON_SIZES.each do |size|
-      %link{ rel: 'icon', sizes: "#{size}x#{size}", href: site_icon_path('favicon', size.to_i) || frontend_asset_path("icons/favicon-#{size}x#{size}.png"), type: 'image/png' }/
+      %link{ rel: 'icon', sizes: "#{size}x#{size}", href: favicon_path(size.to_i) || frontend_asset_path("icons/favicon-#{size}x#{size}.png"), type: 'image/png' }/
 
     - SiteUpload::APPLE_ICON_SIZES.each do |size|
-      %link{ rel: 'apple-touch-icon', sizes: "#{size}x#{size}", href: site_icon_path('app_icon', size.to_i) || frontend_asset_path("icons/apple-touch-icon-#{size}x#{size}.png") }/
+      %link{ rel: 'apple-touch-icon', sizes: "#{size}x#{size}", href: app_icon_path(size.to_i) || frontend_asset_path("icons/apple-touch-icon-#{size}x#{size}.png") }/
 
     %link{ rel: 'mask-icon', href: frontend_asset_path('images/logo-symbol-icon.svg'), color: '#6364FF' }/
     %link{ rel: 'manifest', href: manifest_path(format: :json) }/
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 56501034b..56974513b 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -286,26 +286,31 @@ describe ApplicationHelper do
     end
   end
 
-  describe '#site_icon_path' do
+  describe 'favicon' do
     context 'when an icon exists' do
       let!(:favicon) { Fabricate(:site_upload, var: 'favicon') }
+      let!(:app_icon) { Fabricate(:site_upload, var: 'app_icon') }
 
       it 'returns the URL of the icon' do
-        expect(helper.site_icon_path('favicon')).to eq(favicon.file.url('48'))
+        expect(helper.favicon_path).to eq(favicon.file.url('48'))
+        expect(helper.app_icon_path).to eq(app_icon.file.url('48'))
       end
 
       it 'returns the URL of the icon with size parameter' do
-        expect(helper.site_icon_path('favicon', 16)).to eq(favicon.file.url('16'))
+        expect(helper.favicon_path(16)).to eq(favicon.file.url('16'))
+        expect(helper.app_icon_path(16)).to eq(app_icon.file.url('16'))
       end
     end
 
     context 'when an icon does not exist' do
       it 'returns nil' do
-        expect(helper.site_icon_path('favicon')).to be_nil
+        expect(helper.favicon_path).to be_nil
+        expect(helper.app_icon_path).to be_nil
       end
 
       it 'returns nil with size parameter' do
-        expect(helper.site_icon_path('favicon', 16)).to be_nil
+        expect(helper.favicon_path(16)).to be_nil
+        expect(helper.app_icon_path(16)).to be_nil
       end
     end
   end