diff --git a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
index 324c3da7d2b..401d757bfa8 100644
--- a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
+++ b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
@@ -2,7 +2,6 @@ import PreferencesTabController from "discourse/mixins/preferences-tab-controlle
import { default as computed, observes } from "ember-addons/ember-computed-decorators";
import { listThemes, previewTheme } from 'discourse/lib/theme-selector';
import { popupAjaxError } from 'discourse/lib/ajax-error';
-import { selectDefaultTheme } from 'discourse/lib/theme-selector';
export default Ember.Controller.extend(PreferencesTabController, {
@@ -12,7 +11,8 @@ export default Ember.Controller.extend(PreferencesTabController, {
'dynamic_favicon',
'enable_quoting',
'disable_jump_reply',
- 'automatically_unpin_topics'
+ 'automatically_unpin_topics',
+ 'theme_key'
],
preferencesController: Ember.inject.controller('preferences'),
@@ -26,10 +26,9 @@ export default Ember.Controller.extend(PreferencesTabController, {
return listThemes(this.site);
}.property(),
- @observes("selectedTheme")
+ @observes("model.user_option.theme_key")
themeKeyChanged() {
- let key = this.get("selectedTheme");
- this.get('preferencesController').set('selectedTheme', key);
+ let key = this.get("model.user_option.theme_key");
previewTheme(key);
},
@@ -38,7 +37,6 @@ export default Ember.Controller.extend(PreferencesTabController, {
this.set('saved', false);
return this.get('model').save(this.get('saveAttrNames')).then(() => {
this.set('saved', true);
- selectDefaultTheme(this.get('selectedTheme'));
}).catch(popupAjaxError);
}
}
diff --git a/app/assets/javascripts/discourse/lib/theme-selector.js.es6 b/app/assets/javascripts/discourse/lib/theme-selector.js.es6
index 597fc6569f9..af0f8da3903 100644
--- a/app/assets/javascripts/discourse/lib/theme-selector.js.es6
+++ b/app/assets/javascripts/discourse/lib/theme-selector.js.es6
@@ -13,14 +13,6 @@ export function currentThemeKey() {
return themeKey;
}
-export function selectDefaultTheme(key) {
- if (key) {
- $.cookie('theme_key', key, {path: '/', expires: 9999});
- } else {
- $.cookie('theme_key', null, {path: '/', expires: 1});
- }
-}
-
export function refreshCSS(node, hash, newHref, options) {
let $orig = $(node);
diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6
index 17fb983eaa7..93dce420151 100644
--- a/app/assets/javascripts/discourse/models/user.js.es6
+++ b/app/assets/javascripts/discourse/models/user.js.es6
@@ -242,7 +242,8 @@ const User = RestModel.extend({
'auto_track_topics_after_msecs',
'notification_level_when_replying',
'like_notification_frequency',
- 'include_tl0_in_digests'
+ 'include_tl0_in_digests',
+ 'theme_key'
];
if (fields) {
diff --git a/app/assets/javascripts/discourse/routes/preferences-interface.js.es6 b/app/assets/javascripts/discourse/routes/preferences-interface.js.es6
index 16f0ba0ca23..f58658956fc 100644
--- a/app/assets/javascripts/discourse/routes/preferences-interface.js.es6
+++ b/app/assets/javascripts/discourse/routes/preferences-interface.js.es6
@@ -1,11 +1,9 @@
import RestrictedUserRoute from "discourse/routes/restricted-user";
-import { currentThemeKey } from 'discourse/lib/theme-selector';
export default RestrictedUserRoute.extend({
setupController(controller, user) {
controller.setProperties({
- model: user,
- selectedTheme: $.cookie('theme_key') || currentThemeKey()
+ model: user
});
}
});
diff --git a/app/assets/javascripts/discourse/templates/preferences/interface.hbs b/app/assets/javascripts/discourse/templates/preferences/interface.hbs
index 17db5f1ca32..c6e822b2cea 100644
--- a/app/assets/javascripts/discourse/templates/preferences/interface.hbs
+++ b/app/assets/javascripts/discourse/templates/preferences/interface.hbs
@@ -2,7 +2,7 @@
- {{combo-box content=userSelectableThemes value=selectedTheme}}
+ {{combo-box content=userSelectableThemes value=model.user_option.theme_key}}
{{/if}}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index feacb151095..0cd39cd3a57 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -18,6 +18,8 @@ class ApplicationController < ActionController::Base
include JsonError
include GlobalPath
+ attr_reader :theme_key
+
serialization_scope :guardian
protect_from_forgery
@@ -265,12 +267,15 @@ class ApplicationController < ActionController::Base
resolve_safe_mode
return if request.env[NO_CUSTOM]
- theme_key = flash[:preview_theme_key] || cookies[:theme_key] || session[:theme_key]
+ theme_key = flash[:preview_theme_key] || current_user&.user_option&.theme_key
+
+ # TODO 2018: delete this, old cookie cleanup code
+ if cookies[:theme_key]
+ cookies.delete(:theme_key)
+ end
if theme_key && !guardian.allow_theme?(theme_key)
theme_key = nil
- cookies[:theme_key] = nil
- session[:theme_key] = nil
end
theme_key ||= SiteSetting.default_theme_key
diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb
index 33cc3f4cc8a..534913323b6 100644
--- a/app/serializers/user_option_serializer.rb
+++ b/app/serializers/user_option_serializer.rb
@@ -18,7 +18,8 @@ class UserOptionSerializer < ApplicationSerializer
:email_previous_replies,
:email_in_reply_to,
:like_notification_frequency,
- :include_tl0_in_digests
+ :include_tl0_in_digests,
+ :theme_key
def auto_track_topics_after_msecs
@@ -33,4 +34,8 @@ class UserOptionSerializer < ApplicationSerializer
object.new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes
end
+ def theme_key
+ object.theme_key || SiteSetting.default_theme_key
+ end
+
end
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index cbb3c479c49..30bed45d60a 100644
--- a/app/services/user_updater.rb
+++ b/app/services/user_updater.rb
@@ -33,7 +33,8 @@ class UserUpdater
:email_previous_replies,
:email_in_reply_to,
:like_notification_frequency,
- :include_tl0_in_digests
+ :include_tl0_in_digests,
+ :theme_key
]
def initialize(actor, user)
diff --git a/db/migrate/20170512153318_add_theme_key_to_user_options.rb b/db/migrate/20170512153318_add_theme_key_to_user_options.rb
new file mode 100644
index 00000000000..8f8fc0e99d5
--- /dev/null
+++ b/db/migrate/20170512153318_add_theme_key_to_user_options.rb
@@ -0,0 +1,5 @@
+class AddThemeKeyToUserOptions < ActiveRecord::Migration
+ def change
+ add_column :user_options, :theme_key, :string
+ end
+end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 62b9bb5afd8..c59fb9120ca 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -17,6 +17,22 @@ describe TopicsController do
request.env['HTTP_ACCEPT_LANGUAGE'] = locale
end
+ describe "themes" do
+ it "selects the theme the user has selected" do
+ theme = Theme.create!(user_id: -1, name: 'bob', user_selectable: true)
+ user = log_in
+ user.user_option.update_columns(theme_key: theme.key)
+
+ get :show, id: 666
+ expect(controller.theme_key).to eq(theme.key)
+
+ theme.update_columns(user_selectable: false)
+
+ get :show, id: 666
+ expect(controller.theme_key).not_to eq(theme.key)
+ end
+ end
+
it "doesn't store an incoming link when there's no referer" do
expect {
get :show, id: topic.id
@@ -32,20 +48,19 @@ describe TopicsController do
render_views
context "when the SiteSetting is disabled" do
- before do
- SiteSetting.stubs(:enable_escaped_fragments?).returns(false)
- end
it "uses the application layout even with an escaped fragment param" do
+ SiteSetting.enable_escaped_fragments = false
get :show, {'topic_id' => topic.id, 'slug' => topic.slug, '_escaped_fragment_' => 'true'}
expect(response).to render_template(layout: 'application')
assert_select "meta[name=fragment]", false, "it doesn't have the meta tag"
end
+
end
context "when the SiteSetting is enabled" do
before do
- SiteSetting.stubs(:enable_escaped_fragments?).returns(true)
+ SiteSetting.enable_escaped_fragments = true
end
it "uses the application layout when there's no param" do
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index fab6193a921..e5ca94d734c 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -1221,13 +1221,17 @@ describe UsersController do
expect(user.custom_fields['test']).to eq 'it'
expect(user.muted_users.pluck(:username).sort).to eq [user2.username,user3.username].sort
+ theme = Theme.create(name: "test", user_selectable: true, user_id: -1)
+
put :update,
username: user.username,
- muted_usernames: ""
+ muted_usernames: "",
+ theme_key: theme.key
user.reload
expect(user.muted_users.pluck(:username).sort).to be_empty
+ expect(user.user_option.theme_key).to eq(theme.key)
end