Add a setting allowing the use of system's default font in Web UI (#4033)
* add a system_font_ui setting on the server * Plug the system_font_ui on the front-end * add EN/FR locales for the new setting * put Roboto after all other fonts * remove trailing whitespace so CodeClimate is happy * fix user_spec.rb * correctly write user_spect this time * slightly better way of adding the classes * add comments to the system-font stack for clarification * use .system-font for the class instead * don't use multiple lines for comments * remove trailing whitespace * use the classnames module for consistency * use `mastodon-font-sans-serif` instead of Roboto directlygh/stable
parent
f76e71825d
commit
18d3fa953b
|
@ -37,6 +37,7 @@ class Settings::PreferencesController < ApplicationController
|
||||||
:setting_boost_modal,
|
:setting_boost_modal,
|
||||||
:setting_delete_modal,
|
:setting_delete_modal,
|
||||||
:setting_auto_play_gif,
|
:setting_auto_play_gif,
|
||||||
|
:setting_system_font_ui,
|
||||||
notification_emails: %i(follow follow_request reblog favourite mention digest),
|
notification_emails: %i(follow follow_request reblog favourite mention digest),
|
||||||
interactions: %i(must_be_follower must_be_following)
|
interactions: %i(must_be_follower must_be_following)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
import Switch from 'react-router-dom/Switch';
|
import Switch from 'react-router-dom/Switch';
|
||||||
import Route from 'react-router-dom/Route';
|
import Route from 'react-router-dom/Route';
|
||||||
import Redirect from 'react-router-dom/Redirect';
|
import Redirect from 'react-router-dom/Redirect';
|
||||||
|
@ -72,12 +73,17 @@ class WrappedRoute extends React.Component {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@connect()
|
const mapStateToProps = state => ({
|
||||||
|
systemFontUi: state.getIn(['meta', 'system_font_ui']),
|
||||||
|
});
|
||||||
|
|
||||||
|
@connect(mapStateToProps)
|
||||||
export default class UI extends React.PureComponent {
|
export default class UI extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
systemFontUi: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -176,8 +182,12 @@ export default class UI extends React.PureComponent {
|
||||||
const { width, draggingOver } = this.state;
|
const { width, draggingOver } = this.state;
|
||||||
const { children } = this.props;
|
const { children } = this.props;
|
||||||
|
|
||||||
|
const className = classNames('ui', {
|
||||||
|
'system-font': this.props.systemFontUi,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='ui' ref={this.setRef}>
|
<div className={className} ref={this.setRef}>
|
||||||
<TabsBar />
|
<TabsBar />
|
||||||
<ColumnsAreaContainer singleColumn={isMobile(width)}>
|
<ColumnsAreaContainer singleColumn={isMobile(width)}>
|
||||||
<WrappedSwitch>
|
<WrappedSwitch>
|
||||||
|
|
|
@ -63,3 +63,18 @@ button {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.system-font {
|
||||||
|
// system-ui => standard property (Chrome/Android WebView 56+, Opera 43+, Safari 11+)
|
||||||
|
// -apple-system => Safari <11 specific
|
||||||
|
// BlinkMacSystemFont => Chrome <56 on macOS specific
|
||||||
|
// Segoe UI => Windows 7/8/10
|
||||||
|
// Oxygen => KDE
|
||||||
|
// Ubuntu => Unity/Ubuntu
|
||||||
|
// Cantarell => GNOME
|
||||||
|
// Fira Sans => Firefox OS
|
||||||
|
// Droid Sans => Older Androids (<4.0)
|
||||||
|
// Helvetica Neue => Older macOS <10.11
|
||||||
|
// mastodon-font-sans-serif => web-font (Roboto) fallback and newer Androids (>=4.0)
|
||||||
|
font-family: system-ui, -apple-system,BlinkMacSystemFont, "Segoe UI","Oxygen", "Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",mastodon-font-sans-serif, sans-serif;
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ class UserSettingsDecorator
|
||||||
user.settings['boost_modal'] = boost_modal_preference
|
user.settings['boost_modal'] = boost_modal_preference
|
||||||
user.settings['delete_modal'] = delete_modal_preference
|
user.settings['delete_modal'] = delete_modal_preference
|
||||||
user.settings['auto_play_gif'] = auto_play_gif_preference
|
user.settings['auto_play_gif'] = auto_play_gif_preference
|
||||||
|
user.settings['system_font_ui'] = system_font_ui_preference
|
||||||
end
|
end
|
||||||
|
|
||||||
def merged_notification_emails
|
def merged_notification_emails
|
||||||
|
@ -43,6 +44,10 @@ class UserSettingsDecorator
|
||||||
boolean_cast_setting 'setting_delete_modal'
|
boolean_cast_setting 'setting_delete_modal'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def system_font_ui_preference
|
||||||
|
boolean_cast_setting 'setting_system_font_ui'
|
||||||
|
end
|
||||||
|
|
||||||
def auto_play_gif_preference
|
def auto_play_gif_preference
|
||||||
boolean_cast_setting 'setting_auto_play_gif'
|
boolean_cast_setting 'setting_auto_play_gif'
|
||||||
end
|
end
|
||||||
|
|
|
@ -91,6 +91,10 @@ class User < ApplicationRecord
|
||||||
settings.auto_play_gif
|
settings.auto_play_gif
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def setting_system_font_ui
|
||||||
|
settings.system_font_ui
|
||||||
|
end
|
||||||
|
|
||||||
def activate_session(request)
|
def activate_session(request)
|
||||||
session_activations.activate(session_id: SecureRandom.hex,
|
session_activations.activate(session_id: SecureRandom.hex,
|
||||||
user_agent: request.user_agent,
|
user_agent: request.user_agent,
|
||||||
|
|
|
@ -11,6 +11,7 @@ node(:meta) do
|
||||||
boost_modal: current_account.user.setting_boost_modal,
|
boost_modal: current_account.user.setting_boost_modal,
|
||||||
delete_modal: current_account.user.setting_delete_modal,
|
delete_modal: current_account.user.setting_delete_modal,
|
||||||
auto_play_gif: current_account.user.setting_auto_play_gif,
|
auto_play_gif: current_account.user.setting_auto_play_gif,
|
||||||
|
system_font_ui: current_account.user.setting_system_font_ui,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label
|
= f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label
|
||||||
|
= f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.button :button, t('generic.save_changes'), type: :submit
|
= f.button :button, t('generic.save_changes'), type: :submit
|
||||||
|
|
|
@ -38,6 +38,7 @@ en:
|
||||||
setting_boost_modal: Show confirmation dialog before boosting
|
setting_boost_modal: Show confirmation dialog before boosting
|
||||||
setting_default_privacy: Post privacy
|
setting_default_privacy: Post privacy
|
||||||
setting_delete_modal: Show confirmation dialog before deleting a toot
|
setting_delete_modal: Show confirmation dialog before deleting a toot
|
||||||
|
setting_system_font_ui: Use system's default font
|
||||||
severity: Severity
|
severity: Severity
|
||||||
type: Import type
|
type: Import type
|
||||||
username: Username
|
username: Username
|
||||||
|
|
|
@ -28,6 +28,7 @@ fr:
|
||||||
password: Mot de passe
|
password: Mot de passe
|
||||||
setting_boost_modal: Afficher un dialogue de confirmation avant de partager
|
setting_boost_modal: Afficher un dialogue de confirmation avant de partager
|
||||||
setting_default_privacy: Confidentialité des statuts
|
setting_default_privacy: Confidentialité des statuts
|
||||||
|
setting_system_font_ui: Utiliser la police par défaut du système
|
||||||
severity: Séverité
|
severity: Séverité
|
||||||
type: Type d'import
|
type: Type d'import
|
||||||
username: Identifiant
|
username: Identifiant
|
||||||
|
|
|
@ -19,6 +19,7 @@ defaults: &defaults
|
||||||
boost_modal: false
|
boost_modal: false
|
||||||
auto_play_gif: true
|
auto_play_gif: true
|
||||||
delete_modal: true
|
delete_modal: true
|
||||||
|
system_font_ui: false
|
||||||
notification_emails:
|
notification_emails:
|
||||||
follow: false
|
follow: false
|
||||||
reblog: false
|
reblog: false
|
||||||
|
|
|
@ -48,5 +48,12 @@ describe UserSettingsDecorator do
|
||||||
settings.update(values)
|
settings.update(values)
|
||||||
expect(user.settings['auto_play_gif']).to eq false
|
expect(user.settings['auto_play_gif']).to eq false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'updates the user settings value for system font in UI' do
|
||||||
|
values = { 'setting_system_font_ui' => '0' }
|
||||||
|
|
||||||
|
settings.update(values)
|
||||||
|
expect(user.settings['system_font_ui']).to eq false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -184,6 +184,14 @@ RSpec.describe User, type: :model do
|
||||||
expect(user.setting_auto_play_gif).to eq false
|
expect(user.setting_auto_play_gif).to eq false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#setting_system_font_ui' do
|
||||||
|
it 'returns system font ui setting' do
|
||||||
|
user = Fabricate(:user)
|
||||||
|
user.settings[:system_font_ui] = false
|
||||||
|
expect(user.setting_system_font_ui).to eq false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#setting_boost_modal' do
|
describe '#setting_boost_modal' do
|
||||||
it 'returns boost modal setting' do
|
it 'returns boost modal setting' do
|
||||||
|
|
Reference in New Issue