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

This commit is contained in:
David Taylor 2019-01-14 13:21:46 +00:00 committed by GitHub
parent 59e3eecfa6
commit 1ebd3dbbd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 116 additions and 11 deletions

View File

@ -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");
}
}
});

View File

@ -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) {

View File

@ -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>

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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
#

View File

@ -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

View File

@ -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)

View File

@ -909,6 +909,13 @@ en:
website: "Web Site"
email_settings: "Email"
hide_profile_and_presence: "Hide my public profile and presence features"
text_size:
title: "Text Size"
normal: "Normal"
larger: "Larger"
largest: "Largest"
like_notification_frequency:
title: "Notify when liked"
always: "Always"

View File

@ -1877,6 +1877,8 @@ en:
default_categories_muted: "List of categories that are muted by default."
default_categories_watching_first_post: "List of categories in which first post in each new topic will be watched by default."
default_text_size: "Text size which is selected by default"
retain_web_hook_events_period_days: "Number of days to retain web hook event records."
retry_web_hook_events: "Automatically retry failed web hook events for 4 times. Time gaps between the retries are 1, 5, 25 and 125 minutes."

View File

@ -1811,6 +1811,14 @@ user_preferences:
default_categories_watching_first_post:
type: category_list
default: ''
default_text_size:
type: enum
default: normal
choices:
- normal
- larger
- largest
api:
retain_web_hook_events_period_days:

View File

@ -0,0 +1,5 @@
class AddTextSizeKeyToUserOptions < ActiveRecord::Migration[5.2]
def change
add_column :user_options, :text_size_key, :integer, null: false, default: 0
end
end

View File

@ -147,15 +147,29 @@ describe ApplicationHelper do
end
end
describe '#rtl_class' do
it "returns 'rtl' when the I18n.locale is rtl" do
describe '#html_classes' do
it "includes 'rtl' when the I18n.locale is rtl" do
I18n.stubs(:locale).returns(:he)
expect(helper.rtl_class).to eq('rtl')
expect(helper.html_classes.split(" ")).to include('rtl')
end
it 'returns an empty string when the I18n.locale is not rtl' do
I18n.stubs(:locale).returns(:zh_TW)
expect(helper.rtl_class).to eq('')
expect(helper.html_classes.split(" ")).not_to include('rtl')
end
it 'includes the user specified text size' do
user = Fabricate(:user)
user.user_option.text_size = "larger"
user.user_option.save!
helper.request.env[Auth::DefaultCurrentUserProvider::CURRENT_USER_KEY] = user
expect(helper.html_classes.split(" ")).to include('text-size-larger')
end
it 'falls back to the default text size for anon' do
expect(helper.html_classes.split(" ")).to include('text-size-normal')
SiteSetting.default_text_size = "largest"
expect(helper.html_classes.split(" ")).to include('text-size-largest')
end
end