FEATURE: Allow the base font size to be changed on a per-user basis (#6859)
This commit is contained in:
parent
59e3eecfa6
commit
1ebd3dbbd0
|
@ -20,6 +20,8 @@ const USER_HOMES = {
|
||||||
5: "top"
|
5: "top"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TEXT_SIZES = ["normal", "larger", "largest"];
|
||||||
|
|
||||||
export default Ember.Controller.extend(PreferencesTabController, {
|
export default Ember.Controller.extend(PreferencesTabController, {
|
||||||
@computed("makeThemeDefault")
|
@computed("makeThemeDefault")
|
||||||
saveAttrNames(makeDefault) {
|
saveAttrNames(makeDefault) {
|
||||||
|
@ -32,7 +34,8 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||||
"automatically_unpin_topics",
|
"automatically_unpin_topics",
|
||||||
"allow_private_messages",
|
"allow_private_messages",
|
||||||
"homepage_id",
|
"homepage_id",
|
||||||
"hide_profile_and_presence"
|
"hide_profile_and_presence",
|
||||||
|
"text_size"
|
||||||
];
|
];
|
||||||
|
|
||||||
if (makeDefault) {
|
if (makeDefault) {
|
||||||
|
@ -55,6 +58,13 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||||
return currentThemeId();
|
return currentThemeId();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@computed
|
||||||
|
textSizes() {
|
||||||
|
return TEXT_SIZES.map(value => {
|
||||||
|
return { name: I18n.t(`user.text_size.${value}`), value };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
userSelectableThemes: function() {
|
userSelectableThemes: function() {
|
||||||
return listThemes(this.site);
|
return listThemes(this.site);
|
||||||
}.property(),
|
}.property(),
|
||||||
|
@ -114,6 +124,22 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||||
this.homeChanged();
|
this.homeChanged();
|
||||||
})
|
})
|
||||||
.catch(popupAjaxError);
|
.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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -285,7 +285,8 @@ const User = RestModel.extend({
|
||||||
"theme_ids",
|
"theme_ids",
|
||||||
"allow_private_messages",
|
"allow_private_messages",
|
||||||
"homepage_id",
|
"homepage_id",
|
||||||
"hide_profile_and_presence"
|
"hide_profile_and_presence",
|
||||||
|
"text_size"
|
||||||
];
|
];
|
||||||
|
|
||||||
if (fields) {
|
if (fields) {
|
||||||
|
|
|
@ -10,6 +10,13 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/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}}
|
{{#if siteSettings.allow_user_locale}}
|
||||||
<div class="control-group pref-locale">
|
<div class="control-group pref-locale">
|
||||||
<label class="control-label">{{i18n 'user.locale.title'}}</label>
|
<label class="control-label">{{i18n 'user.locale.title'}}</label>
|
||||||
|
|
|
@ -13,6 +13,14 @@ html {
|
||||||
background-color: $secondary;
|
background-color: $secondary;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
|
|
||||||
|
&.text-size-larger {
|
||||||
|
font-size: $base-font-size-larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.text-size-largest {
|
||||||
|
font-size: $base-font-size-largest;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Links
|
// Links
|
||||||
|
|
|
@ -33,6 +33,8 @@ $bronze: #cd7f32 !default;
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
$base-font-size: 14px !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;
|
$base-font-family: Helvetica, Arial, sans-serif !default;
|
||||||
|
|
||||||
// Font-size defintions, multiplier ^ (step / interval)
|
// Font-size defintions, multiplier ^ (step / interval)
|
||||||
|
|
|
@ -109,7 +109,12 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def html_classes
|
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
|
end
|
||||||
|
|
||||||
def body_classes
|
def body_classes
|
||||||
|
@ -126,8 +131,9 @@ module ApplicationHelper
|
||||||
result.join(' ')
|
result.join(' ')
|
||||||
end
|
end
|
||||||
|
|
||||||
def rtl_class
|
def text_size_class
|
||||||
rtl? ? 'rtl' : ''
|
size = current_user&.user_option&.text_size || SiteSetting.default_text_size
|
||||||
|
"text-size-#{size}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def escape_unicode(javascript)
|
def escape_unicode(javascript)
|
||||||
|
|
|
@ -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)
|
@like_notification_frequency_type ||= Enum.new(always: 0, first_time_and_daily: 1, first_time: 2, never: 3)
|
||||||
end
|
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
|
def set_defaults
|
||||||
self.email_always = SiteSetting.default_email_always
|
self.email_always = SiteSetting.default_email_always
|
||||||
self.mailing_list_mode = SiteSetting.default_email_mailing_list_mode
|
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.include_tl0_in_digests = SiteSetting.default_include_tl0_in_digests
|
||||||
|
|
||||||
|
self.text_size = SiteSetting.default_text_size
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -146,6 +154,14 @@ class UserOption < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
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
|
private
|
||||||
|
|
||||||
def update_tracked_topics
|
def update_tracked_topics
|
||||||
|
@ -185,6 +201,7 @@ end
|
||||||
# homepage_id :integer
|
# homepage_id :integer
|
||||||
# theme_ids :integer default([]), not null, is an Array
|
# theme_ids :integer default([]), not null, is an Array
|
||||||
# hide_profile_and_presence :boolean default(FALSE), not null
|
# hide_profile_and_presence :boolean default(FALSE), not null
|
||||||
|
# text_size_key :integer default(0), not null
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
|
|
@ -23,7 +23,8 @@ class UserOptionSerializer < ApplicationSerializer
|
||||||
:theme_key_seq,
|
:theme_key_seq,
|
||||||
:allow_private_messages,
|
:allow_private_messages,
|
||||||
:homepage_id,
|
:homepage_id,
|
||||||
:hide_profile_and_presence
|
:hide_profile_and_presence,
|
||||||
|
:text_size
|
||||||
|
|
||||||
def auto_track_topics_after_msecs
|
def auto_track_topics_after_msecs
|
||||||
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
||||||
|
|
|
@ -37,7 +37,8 @@ class UserUpdater
|
||||||
:theme_ids,
|
:theme_ids,
|
||||||
:allow_private_messages,
|
:allow_private_messages,
|
||||||
:homepage_id,
|
:homepage_id,
|
||||||
:hide_profile_and_presence
|
:hide_profile_and_presence,
|
||||||
|
:text_size
|
||||||
]
|
]
|
||||||
|
|
||||||
def initialize(actor, user)
|
def initialize(actor, user)
|
||||||
|
|
|
@ -909,6 +909,13 @@ en:
|
||||||
website: "Web Site"
|
website: "Web Site"
|
||||||
email_settings: "Email"
|
email_settings: "Email"
|
||||||
hide_profile_and_presence: "Hide my public profile and presence features"
|
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:
|
like_notification_frequency:
|
||||||
title: "Notify when liked"
|
title: "Notify when liked"
|
||||||
always: "Always"
|
always: "Always"
|
||||||
|
|
|
@ -1877,6 +1877,8 @@ en:
|
||||||
default_categories_muted: "List of categories that are muted by default."
|
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_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."
|
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."
|
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."
|
||||||
|
|
||||||
|
|
|
@ -1812,6 +1812,14 @@ user_preferences:
|
||||||
type: category_list
|
type: category_list
|
||||||
default: ''
|
default: ''
|
||||||
|
|
||||||
|
default_text_size:
|
||||||
|
type: enum
|
||||||
|
default: normal
|
||||||
|
choices:
|
||||||
|
- normal
|
||||||
|
- larger
|
||||||
|
- largest
|
||||||
|
|
||||||
api:
|
api:
|
||||||
retain_web_hook_events_period_days:
|
retain_web_hook_events_period_days:
|
||||||
default: 30
|
default: 30
|
||||||
|
|
|
@ -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
|
|
@ -147,15 +147,29 @@ describe ApplicationHelper do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#rtl_class' do
|
describe '#html_classes' do
|
||||||
it "returns 'rtl' when the I18n.locale is rtl" do
|
it "includes 'rtl' when the I18n.locale is rtl" do
|
||||||
I18n.stubs(:locale).returns(:he)
|
I18n.stubs(:locale).returns(:he)
|
||||||
expect(helper.rtl_class).to eq('rtl')
|
expect(helper.html_classes.split(" ")).to include('rtl')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns an empty string when the I18n.locale is not rtl' do
|
it 'returns an empty string when the I18n.locale is not rtl' do
|
||||||
I18n.stubs(:locale).returns(:zh_TW)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue