FEATURE: Allow the base font size to be changed on a per-user basis (#6859)

FEATURE: Allow the base font size to be changed on a per-user basis (#6859)

diff --git a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
index 97cab16..c9b8d79 100644
--- a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
+++ b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
@@ -20,6 +20,8 @@ const USER_HOMES = {
   5: "top"
 };
 
+const TEXT_SIZES = ["normal", "larger", "largest"];
+
 export default Ember.Controller.extend(PreferencesTabController, {
   @computed("makeThemeDefault")
   saveAttrNames(makeDefault) {
@@ -32,7 +34,8 @@ export default Ember.Controller.extend(PreferencesTabController, {
       "automatically_unpin_topics",
       "allow_private_messages",
       "homepage_id",
-      "hide_profile_and_presence"
+      "hide_profile_and_presence",
+      "text_size"
     ];
 
     if (makeDefault) {
@@ -55,6 +58,13 @@ export default Ember.Controller.extend(PreferencesTabController, {
     return currentThemeId();
   },
 
+  @computed
+  textSizes() {
+    return TEXT_SIZES.map(value => {
+      return { name: I18n.t(`user.text_size.${value}`), value };
+    });
+  },
+
   userSelectableThemes: function() {
     return listThemes(this.site);
   }.property(),
@@ -114,6 +124,22 @@ export default Ember.Controller.extend(PreferencesTabController, {
           this.homeChanged();
         })
         .catch(popupAjaxError);
+    },
+
+    selectTextSize(newSize) {
+      const classList = document.documentElement.classList;
+
+      TEXT_SIZES.forEach(name => {
+        const className = `text-size-${name}`;
+        if (newSize === name) {
+          classList.add(className);
+        } else {
+          classList.remove(className);
+        }
+      });
+
+      // Force refresh when leaving this screen
+      Discourse.set("assetVersion", "forceRefresh");
     }
   }
 });
diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6
index 9b7d28e..70b6dbc 100644
--- a/app/assets/javascripts/discourse/models/user.js.es6
+++ b/app/assets/javascripts/discourse/models/user.js.es6
@@ -285,7 +285,8 @@ const User = RestModel.extend({
       "theme_ids",
       "allow_private_messages",
       "homepage_id",
-      "hide_profile_and_presence"
+      "hide_profile_and_presence",
+      "text_size"
     ];
 
     if (fields) {
diff --git a/app/assets/javascripts/discourse/templates/preferences/interface.hbs b/app/assets/javascripts/discourse/templates/preferences/interface.hbs
index da84c8c..1be49ff 100644
--- a/app/assets/javascripts/discourse/templates/preferences/interface.hbs
+++ b/app/assets/javascripts/discourse/templates/preferences/interface.hbs
@@ -10,6 +10,13 @@
 </div>
 {{/if}}
 
+<div class="control-group text-size">
+  <label class="control-label">{{i18n 'user.text_size.title'}}</label>
+  <div class="controls">
+    {{combo-box valueAttribute="value" content=textSizes value=model.user_option.text_size onSelect=(action "selectTextSize")}}
+  </div>
+</div>
+
 {{#if siteSettings.allow_user_locale}}
   <div class="control-group pref-locale">
     <label class="control-label">{{i18n 'user.locale.title'}}</label>
diff --git a/app/assets/stylesheets/common/foundation/base.scss b/app/assets/stylesheets/common/foundation/base.scss
index 03fa374..adf8476 100644
--- a/app/assets/stylesheets/common/foundation/base.scss
+++ b/app/assets/stylesheets/common/foundation/base.scss
@@ -13,6 +13,14 @@ html {
   background-color: $secondary;
   overflow-y: scroll;
   direction: ltr;
+
+  &.text-size-larger {
+    font-size: $base-font-size-larger;
+  }
+
+  &.text-size-largest {
+    font-size: $base-font-size-largest;
+  }
 }
 
 // Links
diff --git a/app/assets/stylesheets/common/foundation/variables.scss b/app/assets/stylesheets/common/foundation/variables.scss
index e0da4fc..b2090dd 100644
--- a/app/assets/stylesheets/common/foundation/variables.scss
+++ b/app/assets/stylesheets/common/foundation/variables.scss
@@ -33,6 +33,8 @@ $bronze: #cd7f32 !default;
 // --------------------------------------------------
 
 $base-font-size: 14px !default;
+$base-font-size-larger: 16px !default;
+$base-font-size-largest: 18px !default;
 $base-font-family: Helvetica, Arial, sans-serif !default;
 
 // Font-size defintions, multiplier ^ (step / interval)
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 82a5d5f..d4a60fe 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -109,7 +109,12 @@ module ApplicationHelper
   end
 
   def html_classes
-    "#{mobile_view? ? 'mobile-view' : 'desktop-view'} #{mobile_device? ? 'mobile-device' : 'not-mobile-device'} #{rtl_class} #{current_user ? '' : 'anon'}"
+    list = []
+    list << (mobile_view? ? 'mobile-view' : 'desktop-view')
+    list << (mobile_device? ? 'mobile-device' : 'not-mobile-device')
+    list << 'rtl' if rtl?
+    list << text_size_class
+    list.join(' ')
   end
 
   def body_classes
@@ -126,8 +131,9 @@ module ApplicationHelper
     result.join(' ')
   end
 
-  def rtl_class
-    rtl? ? 'rtl' : ''
+  def text_size_class
+    size = current_user&.user_option&.text_size || SiteSetting.default_text_size
+    "text-size-#{size}"
   end
 
   def escape_unicode(javascript)
diff --git a/app/models/user_option.rb b/app/models/user_option.rb
index 4f2ba15..95b0d75 100644
--- a/app/models/user_option.rb
+++ b/app/models/user_option.rb
@@ -28,6 +28,12 @@ class UserOption < ActiveRecord::Base
     @like_notification_frequency_type ||= Enum.new(always: 0, first_time_and_daily: 1, first_time: 2, never: 3)
   end
 
+  def self.text_sizes
+    @text_sizes ||= Enum.new(normal: 0, larger: 1, largest: 2)
+  end
+
+  validates :text_size_key, inclusion: { in: UserOption.text_sizes.values }
+
   def set_defaults
     self.email_always = SiteSetting.default_email_always
     self.mailing_list_mode = SiteSetting.default_email_mailing_list_mode
@@ -58,6 +64,8 @@ class UserOption < ActiveRecord::Base
 
     self.include_tl0_in_digests = SiteSetting.default_include_tl0_in_digests
 
+    self.text_size = SiteSetting.default_text_size
+
     true
   end
 
@@ -146,6 +154,14 @@ class UserOption < ActiveRecord::Base
     end
   end
 
+  def text_size
+    UserOption.text_sizes[text_size_key]
+  end
+
+  def text_size=(value)
+    self.text_size_key = UserOption.text_sizes[value.to_sym]
+  end
+
   private
 
   def update_tracked_topics
@@ -185,6 +201,7 @@ end
 #  homepage_id                      :integer
 #  theme_ids                        :integer          default([]), not null, is an Array
 #  hide_profile_and_presence        :boolean          default(FALSE), not null
+#  text_size_key                    :integer          default(0), not null
 #
 # Indexes
 #
diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb
index 9df725e..0a0e704 100644
--- a/app/serializers/user_option_serializer.rb
+++ b/app/serializers/user_option_serializer.rb
@@ -23,7 +23,8 @@ class UserOptionSerializer < ApplicationSerializer
              :theme_key_seq,
              :allow_private_messages,
              :homepage_id,
-             :hide_profile_and_presence
+             :hide_profile_and_presence,
+             :text_size
 
   def auto_track_topics_after_msecs
     object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index 558f089..3828b1d 100644
--- a/app/services/user_updater.rb
+++ b/app/services/user_updater.rb
@@ -37,7 +37,8 @@ class UserUpdater
     :theme_ids,
     :allow_private_messages,
     :homepage_id,
-    :hide_profile_and_presence
+    :hide_profile_and_presence,
+    :text_size
   ]
 
   def initialize(actor, user)
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index b6d65d5..a0ab970 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -909,6 +909,13 @@ en:
       website: "Web Site"

[... diff too long, it was truncated ...]

GitHub sha: 1ebd3dbb

2 Likes

This commit has been mentioned on Discourse Meta. There might be relevant details there:

This commit has been mentioned on Discourse Meta. There might be relevant details there: