Add emoji picker and single emoji resizing

This commit is contained in:
noellabo 2022-10-01 18:16:00 +09:00
parent dc138ccb32
commit 1885016a4c
15 changed files with 215 additions and 149 deletions

View file

@ -91,6 +91,8 @@ class Settings::PreferencesController < Settings::BaseController
:setting_content_font_size,
:setting_info_font_size,
:setting_content_emoji_reaction_size,
:setting_emoji_scale,
:setting_picker_emoji_size,
:setting_hide_bot_on_public_timeline,
:setting_confirm_follow_from_bot,
:setting_default_search_searchability,

View file

@ -127,6 +127,7 @@ module AccountsHelper
--content-font-size: #{h(user.setting_content_font_size)}px;
--info-font-size: #{h(user.setting_info_font_size)}px;
--content-emoji-reaction-size: #{h(user.setting_content_emoji_reaction_size)}px;
--emoji-scale: #{h(user.setting_emoji_scale)};
}"
end

View file

@ -83,9 +83,44 @@ export function normalizeStatus(status, normalOldStatus) {
docContentElem.querySelector('.quote-inline')?.remove();
docContentElem.querySelector('.reference-link-inline')?.remove();
const flagment = domParser.parseFromString(emojify(normalStatus.content, emojiMap), 'text/html').documentElement;
flagment.querySelectorAll('body>p').forEach(p => {
let imgCount = 0;
let scale = true;
let mix = true;
function emojiScaleCheck(nodes) {
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'IMG' && node.classList.contains('emojione')) {
imgCount++;
} else if (node.nodeType === Node.TEXT_NODE && /[^ \t\u200B\u200C\u3000]/.test(node.textContent)) {
scale = false;
mix = false;
} else if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'A') {
scale = false;
} else if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'SPAN') {
emojiScaleCheck(node.childNodes);
}
}
}
emojiScaleCheck(p.childNodes);
if (scale && imgCount === 1) {
p.classList.add('emoji-single');
} else if (scale && imgCount > 1) {
p.classList.add('emoji-multi');
} else if (mix && imgCount > 0) {
p.classList.add('emoji-mix');
}
});
normalStatus.search_index = docContentElem.textContent;
normalStatus.shortHtml = '<p>'+emojify(normalStatus.search_index.substr(0, 150), emojiMap) + (normalStatus.search_index.substr(150) ? '...' : '')+'</p>';
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
normalStatus.contentHtml = flagment.innerHTML;
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive;
normalStatus.visibility = normalStatus.visibility_ex ? normalStatus.visibility_ex : normalStatus.visibility;

View file

@ -3,30 +3,29 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import IconButton from './icon_button';
import Overlay from 'react-overlays/lib/Overlay';
import Motion from '../features/ui/util/optional_motion';
import spring from 'react-motion/lib/spring';
import { supportsPassiveEvents } from 'detect-passive-events';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { EmojiPicker as EmojiPickerAsync } from '../features/ui/util/async-components';
import { buildCustomEmojis, categoriesFromEmojis } from '../features/emoji/emoji';
import { assetHost } from 'mastodon/utils/config';
import { pickerEmojiSize } from 'mastodon/initial_state';
const messages = defineMessages({
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search...' },
emoji_not_found: { id: 'emoji_button.not_found', defaultMessage: 'No emojos!! (╯°□°)╯︵ ┻━┻' },
custom: { id: 'emoji_button.custom', defaultMessage: 'Custom' },
recent: { id: 'emoji_button.recent', defaultMessage: 'Frequently used' },
search_results: { id: 'emoji_button.search_results', defaultMessage: 'Search results' },
people: { id: 'emoji_button.people', defaultMessage: 'People' },
nature: { id: 'emoji_button.nature', defaultMessage: 'Nature' },
food: { id: 'emoji_button.food', defaultMessage: 'Food & Drink' },
activity: { id: 'emoji_button.activity', defaultMessage: 'Activity' },
travel: { id: 'emoji_button.travel', defaultMessage: 'Travel & Places' },
objects: { id: 'emoji_button.objects', defaultMessage: 'Objects' },
symbols: { id: 'emoji_button.symbols', defaultMessage: 'Symbols' },
flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' },
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search...' },
emoji_not_found: { id: 'emoji_button.not_found', defaultMessage: 'No emojos!! (╯°□°)╯︵ ┻━┻' },
custom: { id: 'emoji_button.custom', defaultMessage: 'Custom' },
recent: { id: 'emoji_button.recent', defaultMessage: 'Frequently used' },
search_results: { id: 'emoji_button.search_results', defaultMessage: 'Search results' },
people: { id: 'emoji_button.people', defaultMessage: 'People' },
nature: { id: 'emoji_button.nature', defaultMessage: 'Nature' },
food: { id: 'emoji_button.food', defaultMessage: 'Food & Drink' },
activity: { id: 'emoji_button.activity', defaultMessage: 'Activity' },
travel: { id: 'emoji_button.travel', defaultMessage: 'Travel & Places' },
objects: { id: 'emoji_button.objects', defaultMessage: 'Objects' },
symbols: { id: 'emoji_button.symbols', defaultMessage: 'Symbols' },
flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' },
});
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
@ -77,7 +76,6 @@ class ReactionPicker extends React.PureComponent {
};
state = {
modifierOpen: false,
placement: null,
};
@ -133,29 +131,15 @@ class ReactionPicker extends React.PureComponent {
this.props.onPickEmoji(emoji);
}
handleModifierOpen = () => {
this.setState({ modifierOpen: true });
}
handleModifierClose = () => {
this.setState({ modifierOpen: false });
}
handleModifierChange = modifier => {
this.props.onSkinTone(modifier);
}
render () {
const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props;
const { loading, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props;
if (loading) {
return <div style={{height: 349,width: 299}} />;
return <div style={{ height: 349,width: 299 }} />;
}
const title = intl.formatMessage(messages.emoji);
const { modifierOpen } = this.state;
const categoriesSort = [
'recent',
'people',
@ -169,28 +153,29 @@ class ReactionPicker extends React.PureComponent {
];
categoriesSort.splice(1, 0, ...Array.from(categoriesFromEmojis(custom_emojis)).sort());
const emojiSize = Number(pickerEmojiSize) || 22;
return (
<EmojiPicker
perLine={8}
emojiSize={22}
sheetSize={32}
custom={buildCustomEmojis(custom_emojis)}
color=''
emoji=''
set='twitter'
title={title}
i18n={this.getI18n()}
onClick={this.handleClick}
include={categoriesSort}
recent={frequentlyUsedEmojis}
skin={skinTone}
showPreview={false}
showSkinTones={false}
notFound={notFoundFn}
autoFocus
emojiTooltip
/>
<EmojiPicker
perLine={Math.floor(24 / emojiSize * 8)}
emojiSize={emojiSize}
sheetSize={32}
custom={buildCustomEmojis(custom_emojis)}
color=''
emoji=''
set='twitter'
title={title}
i18n={this.getI18n()}
onClick={this.handleClick}
include={categoriesSort}
recent={frequentlyUsedEmojis}
skin={skinTone}
showPreview={false}
showSkinTones={false}
notFound={notFoundFn}
autoFocus
emojiTooltip
/>
);
}
}
@ -214,7 +199,6 @@ class ReactionPickerDropdownMenu extends React.PureComponent {
onClose: PropTypes.func.isRequired,
skinTone: PropTypes.number.isRequired,
frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string),
};
static defaultProps = {
@ -223,7 +207,6 @@ class ReactionPickerDropdownMenu extends React.PureComponent {
};
state = {
mounted: false,
loading: true,
};
@ -237,7 +220,6 @@ class ReactionPickerDropdownMenu extends React.PureComponent {
document.addEventListener('click', this.handleDocumentClick, false);
document.addEventListener('keydown', this.handleKeyDown, false);
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
this.setState({ mounted: true });
this.setState({ loading: true });
EmojiPickerAsync().then(EmojiMart => {
EmojiPicker = EmojiMart.Picker;
@ -261,28 +243,21 @@ class ReactionPickerDropdownMenu extends React.PureComponent {
render () {
const { onClose, style, placement, arrowOffsetLeft, arrowOffsetTop } = this.props;
const { custom_emojis, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis } = this.props;
const { mounted, loading } = this.state;
const { loading } = this.state;
return (
<Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
{({ opacity, scaleX, scaleY }) => (
// It should not be transformed when mounting because the resulting
// size will be used to determine the coordinate of the menu by
// react-overlays
<div className={`dropdown-menu dropdown-menu-reaction ${placement}`} style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}>
<div className={`dropdown-menu__arrow ${placement}`} style={{ left: arrowOffsetLeft, top: arrowOffsetTop }} />
<ReactionPicker
custom_emojis={custom_emojis}
loading={loading}
onClose={onClose}
onPickEmoji={onPickEmoji}
onSkinTone={onSkinTone}
skinTone={skinTone}
frequentlyUsedEmojis={frequentlyUsedEmojis}
/>
</div>
)}
</Motion>
<div className={`dropdown-menu dropdown-menu-reaction ${placement}`} style={style} ref={this.setRef}>
<div className={`dropdown-menu__arrow ${placement}`} style={{ left: arrowOffsetLeft, top: arrowOffsetTop }} />
<ReactionPicker
custom_emojis={custom_emojis}
loading={loading}
onClose={onClose}
onPickEmoji={onPickEmoji}
onSkinTone={onSkinTone}
skinTone={skinTone}
frequentlyUsedEmojis={frequentlyUsedEmojis}
/>
</div>
);
}
@ -333,7 +308,7 @@ export default class ReactionPickerDropdown extends React.PureComponent {
if (this.props.pressed) {
this.props.onRemoveEmoji();
} else if (this.state.id === this.props.openDropdownId) {
this.handleClose();
this.handleClose();
} else {
const { top } = target.getBoundingClientRect();
const placement = top * 2 < innerHeight ? 'bottom' : 'top';

View file

@ -8,6 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { supportsPassiveEvents } from 'detect-passive-events';
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
import { assetHost } from 'mastodon/utils/config';
import { pickerEmojiSize } from 'mastodon/initial_state';
const messages = defineMessages({
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
@ -260,12 +261,13 @@ class EmojiPickerMenu extends React.PureComponent {
];
categoriesSort.splice(1, 0, ...Array.from(categoriesFromEmojis(custom_emojis)).sort());
const emojiSize = Number(pickerEmojiSize) || 22;
return (
<div className={classNames('emoji-picker-dropdown__menu', { selecting: modifierOpen })} style={style} ref={this.setRef}>
<EmojiPicker
perLine={8}
emojiSize={22}
perLine={Math.floor(24 / emojiSize * 8)}
emojiSize={emojiSize}
sheetSize={32}
custom={buildCustomEmojis(custom_emojis)}
color=''

View file

@ -12,6 +12,7 @@ import { supportsPassiveEvents } from 'detect-passive-events';
import { EmojiPicker as EmojiPickerAsync } from '../util/async-components';
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
import { assetHost } from 'mastodon/utils/config';
import { pickerEmojiSize } from 'mastodon/initial_state';
const messages = defineMessages({
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
@ -169,28 +170,29 @@ class ReactionPicker extends React.PureComponent {
];
categoriesSort.splice(1, 0, ...Array.from(categoriesFromEmojis(custom_emojis)).sort());
const emojiSize = Number(pickerEmojiSize) || 22;
return (
<EmojiPicker
perLine={8}
emojiSize={22}
sheetSize={32}
custom={buildCustomEmojis(custom_emojis)}
color=''
emoji=''
set='twitter'
title={title}
i18n={this.getI18n()}
onClick={this.handleClick}
include={categoriesSort}
recent={frequentlyUsedEmojis}
skin={skinTone}
showPreview={false}
showSkinTones={false}
notFound={notFoundFn}
emojiTooltip
style={{width: '100%'}}
/>
<EmojiPicker
perLine={Math.floor(24 / emojiSize * 8)}
emojiSize={emojiSize}
sheetSize={32}
custom={buildCustomEmojis(custom_emojis)}
color=''
emoji=''
set='twitter'
title={title}
i18n={this.getI18n()}
onClick={this.handleClick}
include={categoriesSort}
recent={frequentlyUsedEmojis}
skin={skinTone}
showPreview={false}
showSkinTones={false}
notFound={notFoundFn}
emojiTooltip
style={{width: '100%'}}
/>
);
}
}
@ -205,23 +207,23 @@ export default class ReactionModal extends ImmutablePureComponent {
onClose: PropTypes.func.isRequired,
skinTone: PropTypes.number.isRequired,
frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string),
};
};
state = {
loading: true,
};
state = {
loading: true,
};
componentDidMount() {
this.setState({ loading: true });
EmojiPickerAsync().then(EmojiMart => {
EmojiPicker = EmojiMart.Picker;
Emoji = EmojiMart.Emoji;
this.setState({ loading: false });
}).catch(() => {
this.setState({ loading: false });
});
}
componentDidMount() {
this.setState({ loading: true });
EmojiPickerAsync().then(EmojiMart => {
EmojiPicker = EmojiMart.Picker;
Emoji = EmojiMart.Emoji;
this.setState({ loading: false });
}).catch(() => {
this.setState({ loading: false });
});
}
render () {
const { custom_emojis, onPickEmoji, onSkinTone, onClose, skinTone, frequentlyUsedEmojis } = this.props;

View file

@ -54,5 +54,6 @@ export const matchVisibilityOfReferences = getMeta('match_visibility_of_referenc
export const enableEmptyColumn = getMeta('enable_empty_column');
export const showReloadButton = getMeta('show_reload_button');
export const defaultColumnWidth = getMeta('default_column_width');
export const pickerEmojiSize = getMeta('picker_emoji_size');
export default initialState;

View file

@ -848,7 +848,7 @@
.quote-indicator__content {
position: relative;
font-size: var(--content-font-size, 15px);
line-height: calc(var(--content-font-size, 15px)*1.33);
line-height: calc(var(--content-font-size, 15px) * 1.33);
word-wrap: break-word;
font-weight: 400;
overflow: hidden;
@ -869,13 +869,37 @@
}
.emojione {
width: calc(var(--content-font-size, 15px)*1.33);
height: calc(var(--content-font-size, 15px)*1.33);
width: calc(var(--content-font-size, 15px) * 1.33);
height: calc(var(--content-font-size, 15px) * 1.33);
margin: -3px 0 0;
}
.emoji-single {
.emojione {
width: calc(var(--content-font-size, 15px) * 1.33 * var(--emoji-scale, 1));
height: calc(var(--content-font-size, 15px) * 1.33 * var(--emoji-scale, 1));
}
}
.emoji-multi {
font-size: calc(var(--content-font-size, 15px) * (var(--emoji-scale, 1) / 3 + 0.67));
line-height: calc(var(--content-font-size, 15px) * 1.33 * (var(--emoji-scale, 1) / 3 + 0.67));
.emojione {
width: calc(var(--content-font-size, 15px) * 1.33 * (var(--emoji-scale, 1) / 3 + 0.67));
height: calc(var(--content-font-size, 15px) * 1.33 * (var(--emoji-scale, 1) / 3 + 0.67));
}
}
.emoji-mix {
.emojione {
width: calc(var(--content-font-size, 15px) * 1.33 * (var(--emoji-scale, 1) / 3 + 0.67));
height: calc(var(--content-font-size, 15px) * 1.33 * (var(--emoji-scale, 1) / 3 + 0.67));
}
}
p {
margin-bottom: calc(var(--content-font-size, 15px)*1.33);
margin-bottom: calc(var(--content-font-size, 15px) * 1.33);
white-space: pre-wrap;
unicode-bidi: plaintext;
@ -949,8 +973,8 @@
overflow-y: auto;
.emojione {
width: calc(var(--content-font-size, 15px)*1.33);
height: calc(var(--content-font-size, 15px)*1.33);
width: calc(var(--content-font-size, 15px) * 1.33);
height: calc(var(--content-font-size, 15px) * 1.33);
margin: -3px 0 0;
}
@ -1298,7 +1322,7 @@
color: $dark-text-color;
padding: 8px 0;
padding-bottom: 2px;
font-size: calc(var(--content-font-size, 15px)*0.933);
font-size: calc(var(--content-font-size, 15px) * 0.933);
position: relative;
.status__display-name strong {
@ -1374,17 +1398,41 @@
}
.status__content {
font-size: calc(var(--content-font-size, 15px)*1.27);
line-height: calc(var(--content-font-size, 15px)*1.6);
font-size: calc(var(--content-font-size, 15px) * 1.27);
line-height: calc(var(--content-font-size, 15px) * 1.6);
.emojione {
width: calc(var(--content-font-size, 15px)*1.6);
height: calc(var(--content-font-size, 15px)*1.6);
width: calc(var(--content-font-size, 15px) * 1.6);
height: calc(var(--content-font-size, 15px) * 1.6);
margin: -1px 0 0;
}
.emoji-single {
.emojione {
width: calc(var(--content-font-size, 15px) * 1.6 * var(--emoji-scale, 1));
height: calc(var(--content-font-size, 15px) * 1.6 * var(--emoji-scale, 1));
}
}
.emoji-multi {
font-size: calc(var(--content-font-size, 15px) * 1.27 * (var(--emoji-scale, 1) / 3 + 0.67));
line-height: calc(var(--content-font-size, 15px) * 1.6 * (var(--emoji-scale, 1) / 3 + 0.67));
.emojione {
width: calc(var(--content-font-size, 15px) * 1.6 * (var(--emoji-scale, 1) / 3 + 0.67));
height: calc(var(--content-font-size, 15px) * 1.6 * (var(--emoji-scale, 1) / 3 + 0.67));
}
}
.emoji-mix {
.emojione {
width: calc(var(--content-font-size, 15px) * 1.6 * (var(--emoji-scale, 1) / 3 + 0.67));
height: calc(var(--content-font-size, 15px) * 1.6 * (var(--emoji-scale, 1) / 3 + 0.67));
}
}
.status__content__spoiler-link {
line-height: calc(var(--content-font-size, 15px)*1.6);
line-height: calc(var(--content-font-size, 15px) * 1.6);
margin: -1px 0 0;
}
}
@ -1864,8 +1912,8 @@ a.account__display-name {
padding: 8px 0 0;
cursor: default;
color: $darker-text-color;
font-size: calc(var(--content-font-size, 15px)*0.933);
line-height: calc(var(--content-font-size, 15px)*1.467);
font-size: calc(var(--content-font-size, 15px) * 0.933);
line-height: calc(var(--content-font-size, 15px) * 1.467);
position: relative;
.fa {

View file

@ -86,6 +86,8 @@ class UserSettingsDecorator
user.settings['content_font_size'] = content_font_size_preference if change?('setting_content_font_size')
user.settings['info_font_size'] = info_font_size_preference if change?('setting_info_font_size')
user.settings['content_emoji_reaction_size'] = content_emoji_reaction_size_preference if change?('setting_content_emoji_reaction_size')
user.settings['emoji_scale'] = emoji_scale_preference if change?('setting_emoji_scale')
user.settings['picker_emoji_size'] = picker_emoji_size_preference if change?('setting_picker_emoji_size')
user.settings['hide_bot_on_public_timeline'] = hide_bot_on_public_timeline_preference if change?('setting_hide_bot_on_public_timeline')
user.settings['confirm_follow_from_bot'] = confirm_follow_from_bot_preference if change?('setting_confirm_follow_from_bot')
user.settings['default_search_searchability'] = default_search_searchability_preference if change?('setting_default_search_searchability')
@ -323,6 +325,14 @@ end
settings['setting_content_emoji_reaction_size']
end
def emoji_scale_preference
settings['setting_emoji_scale']
end
def picker_emoji_size_preference
settings['setting_picker_emoji_size']
end
def hide_bot_on_public_timeline_preference
boolean_cast_setting 'setting_hide_bot_on_public_timeline'
end

View file

@ -137,9 +137,7 @@ class User < ApplicationRecord
:enable_status_reference, :match_visibility_of_references,
:post_reference_modal, :add_reference_modal, :unselect_reference_modal,
:hexagon_avatar, :enable_empty_column,
:content_font_size, :info_font_size, :content_emoji_reaction_size,
:multi_column_customize, :multi_column_content_font_size, :multi_column_info_font_size, :multi_column_content_emoji_reaction_size,
:mobile_customize, :mobile_content_font_size, :mobile_info_font_size, :mobile_content_emoji_reaction_size,
:content_font_size, :info_font_size, :content_emoji_reaction_size, :emoji_scale, :picker_emoji_size,
:hide_bot_on_public_timeline, :confirm_follow_from_bot,
:default_search_searchability, :default_expires_in, :default_expires_action,
:show_reload_button, :default_column_width,

View file

@ -70,6 +70,8 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:content_font_size] = object.current_account.user.setting_content_font_size
store[:info_font_size] = object.current_account.user.setting_info_font_size
store[:content_emoji_reaction_size] = object.current_account.user.setting_content_emoji_reaction_size
store[:emoji_scale] = object.current_account.user.setting_emoji_scale
store[:picker_emoji_size] = object.current_account.user.setting_picker_emoji_size
store[:hide_bot_on_public_timeline] = object.current_account.user.setting_hide_bot_on_public_timeline
store[:confirm_follow_from_bot] = object.current_account.user.setting_confirm_follow_from_bot
store[:show_reload_button] = object.current_account.user.setting_show_reload_button

View file

@ -28,26 +28,10 @@
.fields-group
= f.input :setting_content_font_size, as: :range, input_html: { min: 10, max: 20, list: 'content_font_size_label' }, wrapper: :with_label, hint: false, fedibird_features: true
= f.input :setting_emoji_scale, as: :range, input_html: { min: 1, max: 4, step: 0.1, list: 'emoji_scale_label' }, wrapper: :with_label, false: true, fedibird_features: true
= f.input :setting_info_font_size, as: :range, input_html: { min: 10, max: 20, list: 'info_font_size_label' }, wrapper: :with_label, hint: false, fedibird_features: true
= f.input :setting_content_emoji_reaction_size, as: :range, input_html: { min: 10, max: 48, list: 'emoji_reaction_size_label' }, wrapper: :with_label, false: true, fedibird_features: true
-# %h5= t 'appearance.custom_size.multi_column'
-# .fields-group
-# = f.input :setting_multi_column_customize, as: :boolean, wrapper: :with_label, hint: true, fedibird_features: true
-# .fields-group.multi-column-customize
-# = f.input :setting_multi_column_content_font_size, as: :range, input_html: { min: 10, max: 24, list: 'content_font_size_label' }, wrapper: :with_label, hint: false, fedibird_features: true
-# = f.input :setting_multi_column_content_emoji_reaction_size, as: :range, input_html: { min: 10, max: 48 }, wrapper: :with_label, false: true, fedibird_features: true
-# %h5= t 'appearance.custom_size.mobile'
-# .fields-group
-# = f.input :setting_mobile_customize, as: :boolean, wrapper: :with_label, hint: true, fedibird_features: true
-# .fields-group.mobile-customize
-# = f.input :setting_mobile_content_font_size, as: :range, input_html: { min: 10, max: 24, list: 'content_font_size_label' }, wrapper: :with_label, hint: false, fedibird_features: true
-# = f.input :setting_mobile_content_emoji_reaction_size, as: :range, input_html: { min: 10, max: 48 }, wrapper: :with_label, false: true, fedibird_features: true
= f.input :setting_picker_emoji_size, as: :range, input_html: { min: 22, max: 48, list: 'picker_emoji_size_label' }, wrapper: :with_label, false: true, fedibird_features: true
.fields-group
= f.input :setting_theme_public, as: :boolean, wrapper: :with_label, hint: true, fedibird_features: true

View file

@ -247,6 +247,7 @@ en:
setting_display_media_default: Default
setting_display_media_hide_all: Hide all
setting_display_media_show_all: Show all
setting_emoji_scale: Single emoji size
setting_enable_empty_column: Enable last column to be closed
setting_enable_limited_timeline: Enable limited timeline
setting_enable_reaction: Enable reaction
@ -266,6 +267,7 @@ en:
setting_new_features_policy_conservative: Leave it disabled. I use it if necessary
setting_new_features_policy_default: Follow recommendations (default)
setting_noindex: Opt-out of search engine indexing
setting_picker_emoji_size: Emoji size in picker
setting_place_tab_bar_at_bottom: Place the tab bar at the bottom
setting_post_reference_modal: Show a confirmation dialog before making a post containing references
setting_reduce_motion: Reduce motion in animations

View file

@ -243,6 +243,7 @@ ja:
setting_display_media_default: 標準
setting_display_media_hide_all: 非表示
setting_display_media_show_all: 表示
setting_emoji_scale: 単独絵文字のサイズ
setting_enable_empty_column: 最終カラムを閉じられるようにする
setting_enable_limited_timeline: 限定ホームを有効にする
setting_enable_reaction: リアクションを有効にする
@ -262,6 +263,7 @@ ja:
setting_new_features_policy_default: 推奨に従う(デフォルト)
setting_new_features_policy_tester: ベータテストに参加する
setting_noindex: 検索エンジンによるインデックスを拒否する
setting_picker_emoji_size: 絵文字ピッカーの表示サイズ
setting_place_tab_bar_at_bottom: タブバーを下に配置する
setting_post_reference_modal: 参照を含む投稿をする前に確認ダイアログを表示する
setting_reduce_motion: アニメーションの動きを減らす

View file

@ -66,6 +66,8 @@ defaults: &defaults
content_font_size: 15
info_font_size: 15
content_emoji_reaction_size: 16
emoji_scale: 1,
picker_emoji_size: 22,
notification_emails:
follow: false
reblog: false