about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/admin/settings_controller.rb1
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/lib/settings/scoped_settings.rb15
-rw-r--r--app/models/form/admin_settings.rb2
-rw-r--r--app/views/admin/settings/edit.html.haml1
-rw-r--r--spec/controllers/application_controller_spec.rb33
6 files changed, 51 insertions, 3 deletions
diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb
index 3234b194f..23e0444d0 100644
--- a/app/controllers/admin/settings_controller.rb
+++ b/app/controllers/admin/settings_controller.rb
@@ -16,6 +16,7 @@ module Admin
       timeline_preview
       show_staff_badge
       bootstrap_timeline_accounts
+      theme
       thumbnail
       hero
       min_invite_role
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index eafe27047..7ddd26ec0 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -95,7 +95,7 @@ class ApplicationController < ActionController::Base
   end
 
   def current_theme
-    return Setting.default_settings['theme'] unless Themes.instance.names.include? current_user&.setting_theme
+    return Setting.theme unless Themes.instance.names.include? current_user&.setting_theme
     current_user.setting_theme
   end
 
diff --git a/app/lib/settings/scoped_settings.rb b/app/lib/settings/scoped_settings.rb
index de4af3009..5ee30825d 100644
--- a/app/lib/settings/scoped_settings.rb
+++ b/app/lib/settings/scoped_settings.rb
@@ -2,6 +2,10 @@
 
 module Settings
   class ScopedSettings
+    DEFAULTING_TO_UNSCOPED = %w(
+      theme
+    ).freeze
+
     def initialize(object)
       @object = object
     end
@@ -50,15 +54,22 @@ module Settings
       Rails.cache.fetch(Setting.cache_key(key, @object)) do
         db_val = thing_scoped.find_by(var: key.to_s)
         if db_val
-          default_value = Setting.default_settings[key]
+          default_value = ScopedSettings.default_settings[key]
           return default_value.with_indifferent_access.merge!(db_val.value) if default_value.is_a?(Hash)
           db_val.value
         else
-          Setting.default_settings[key]
+          ScopedSettings.default_settings[key]
         end
       end
     end
 
+    class << self
+      def default_settings
+        defaulting = DEFAULTING_TO_UNSCOPED.map { |k| [k, Setting[k]] }.to_h
+        Setting.default_settings.merge!(defaulting)
+      end
+    end
+
     protected
 
     def thing_scoped
diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index 010cf7fc3..db46cda7b 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -30,6 +30,8 @@ class Form::AdminSettings
     :show_staff_badge=,
     :bootstrap_timeline_accounts,
     :bootstrap_timeline_accounts=,
+    :theme,
+    :theme=,
     :min_invite_role,
     :min_invite_role=,
     :activity_api_enabled,
diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml
index fda6b00f4..b5aa176a2 100644
--- a/app/views/admin/settings/edit.html.haml
+++ b/app/views/admin/settings/edit.html.haml
@@ -15,6 +15,7 @@
   %hr/
 
   .fields-group
+    = f.input :theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false
     = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html')
     = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html')
 
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index c6c78d3f7..d158625e6 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -92,6 +92,39 @@ describe ApplicationController, type: :controller do
     end
   end
 
+  describe 'helper_method :current_theme' do
+    it 'returns "default" when theme wasn\'t changed in admin settings' do
+      allow(Setting).to receive(:default_settings).and_return({'theme' => 'default'})
+
+      expect(controller.view_context.current_theme).to eq 'default'
+    end
+
+    it 'returns instances\'s theme when user is not signed in' do
+      allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
+
+      expect(controller.view_context.current_theme).to eq 'contrast'
+    end
+
+    it 'returns instances\'s default theme when user didn\'t set theme' do
+      current_user = Fabricate(:user)
+      sign_in current_user
+
+      allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
+
+      expect(controller.view_context.current_theme).to eq 'contrast'
+    end
+
+    it 'returns user\'s theme when it is set' do
+      current_user = Fabricate(:user)
+      current_user.settings['theme'] = 'mastodon-light'
+      sign_in current_user
+
+      allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
+
+      expect(controller.view_context.current_theme).to eq 'mastodon-light'
+    end
+  end
+
   context 'ActionController::RoutingError' do
     subject do
       routes.draw { get 'routing_error' => 'anonymous#routing_error' }