[MM-53650] Add disable emoticon rendering setting to webapp (#29414)
* add renderEmoticonsAsEmoji to post_markdown * add renderEmoticonsAsEmoji to preferences, config * add EnableRenderEmoticonsAsEmoji to GenerateClientConfig * add EnableRenderEmoticonsAsEmoji to TeamSettings * create renderEmoticonsAsEmoji component * update translation file * update tests * add tests for RenderEmoticonsAsEmoji * remove unused prop * remove unused variables * add test cases for undefined/false values for renderemoticonsasemoji * switch strings from backticks to single quotes * Update webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji.tsx Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com> * Update webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji.tsx Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com> * Update webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji.tsx Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com> * Update webapp/channels/src/utils/emoticons.tsx Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com> * remove server setting * remove usestate * update i18n * remove config setting * fix broken test * fix focus edit button logic * update tests for when render emoticons option is undefined * remove config usage from selectors * update setting display text * remove 'automatically' from setting description * use default from preferences instead of hardcoded true * update component snapshot * remove renderemoticonsasemoji = true from emoticons tests * Apply suggestions from code review * Switch from useEffect to useDidUpdate * Run fix-style * Add RenderEmoticonsAsEmoji component to test spec * Rewrite RenderEmoticonsAsEmoji to mirror ManageTimezones and ManageLanguages * Update UserSettingsDisplay snapshot * Switch test to renderWithContext, update props * Move options into const objects * Wrap functions in useCallback --------- Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com> Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
@@ -50,6 +50,7 @@ describe('Verify Accessibility Support in different sections in Settings and Pro
|
||||
{key: 'click_to_reply', label: 'Click to open threads', type: 'radio'},
|
||||
{key: 'channel_display_mode', label: 'Channel Display', type: 'radio'},
|
||||
{key: 'one_click_reactions_enabled', label: 'Quick reactions on messages', type: 'radio'},
|
||||
{key: 'renderEmoticonsAsEmoji', label: 'Render emoticons as emojis', type: 'radio'},
|
||||
{key: 'languages', label: 'Language', type: 'dropdown'},
|
||||
],
|
||||
sidebar: [
|
||||
|
||||
@@ -82,6 +82,7 @@ function makeMapStateToProps() {
|
||||
hideGuestTags: getConfig(state).HideGuestTags === 'true',
|
||||
isEnterpriseOrCloudOrSKUStarterFree: isEnterpriseOrCloudOrSKUStarterFree(license, subscriptionProduct, isEnterpriseReady),
|
||||
isEnterpriseReady,
|
||||
renderEmoticonsAsEmoji: getBool(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.RENDER_EMOTICONS_AS_EMOJI, Preferences.RENDER_EMOTICONS_AS_EMOJI_DEFAULT === 'true'),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ describe('components/PostMarkdown', () => {
|
||||
isEnterpriseOrCloudOrSKUStarterFree: true,
|
||||
isEnterpriseReady: false,
|
||||
dispatch: jest.fn(),
|
||||
renderEmoticonsAsEmoji: true,
|
||||
};
|
||||
|
||||
const state = {entities: {
|
||||
|
||||
@@ -40,6 +40,11 @@ export type OwnProps = {
|
||||
*/
|
||||
showPostEditedIndicator?: boolean;
|
||||
options?: TextFormattingOptions;
|
||||
|
||||
/**
|
||||
* Whether or not to render text emoticons (:D) as emojis
|
||||
*/
|
||||
renderEmoticonsAsEmoji?: boolean;
|
||||
};
|
||||
|
||||
type Props = PropsFromRedux & OwnProps;
|
||||
@@ -52,12 +57,13 @@ export default class PostMarkdown extends React.PureComponent<Props> {
|
||||
};
|
||||
|
||||
getOptions = memoize(
|
||||
(options?: TextFormattingOptions, disableGroupHighlight?: boolean, mentionHighlight?: boolean, editedAt?: number) => {
|
||||
(options?: TextFormattingOptions, disableGroupHighlight?: boolean, mentionHighlight?: boolean, editedAt?: number, renderEmoticonsAsEmoji?: boolean) => {
|
||||
return {
|
||||
...options,
|
||||
disableGroupHighlight,
|
||||
mentionHighlight,
|
||||
editedAt,
|
||||
renderEmoticonsAsEmoji,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -110,6 +116,7 @@ export default class PostMarkdown extends React.PureComponent<Props> {
|
||||
this.props.post?.props?.disable_group_highlight === true,
|
||||
mentionHighlight,
|
||||
this.props.post?.edit_at,
|
||||
this.props?.renderEmoticonsAsEmoji,
|
||||
);
|
||||
|
||||
let highlightKeys;
|
||||
|
||||
@@ -314,6 +314,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -669,6 +711,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -1024,6 +1108,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -1379,6 +1505,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -1661,6 +1829,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={true}
|
||||
@@ -1925,6 +2135,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -2280,6 +2532,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -2653,6 +2947,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -2935,6 +3271,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={true}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -3217,6 +3595,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -3499,6 +3919,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -3793,6 +4255,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -4075,6 +4579,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={false}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
@@ -4333,6 +4879,48 @@ exports[`components/user_settings/display/UserSettingsDisplay should not show la
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
areAllSectionsInactive={true}
|
||||
describe={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Off"
|
||||
id="user.settings.advance.off"
|
||||
/>
|
||||
}
|
||||
max={
|
||||
<Memo(Connect(RenderEmoticonsAsEmoji))
|
||||
adminMode={false}
|
||||
renderEmoticonsAsEmoji=""
|
||||
updateSection={[Function]}
|
||||
user={
|
||||
Object {
|
||||
"id": "user_id",
|
||||
"locale": "en",
|
||||
"timezone": Object {
|
||||
"automaticTimezone": "America/New_York",
|
||||
"manualTimezone": "",
|
||||
"useAutomaticTimezone": "true",
|
||||
},
|
||||
"username": "username",
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
section="renderEmoticonsAsEmoji"
|
||||
title={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="Render emoticons as emojis"
|
||||
id="user.settings.display.renderEmoticonsAsEmojiTitle"
|
||||
/>
|
||||
}
|
||||
updateSection={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="divider-dark"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Memo(SettingItem)
|
||||
active={false}
|
||||
|
||||
@@ -86,6 +86,7 @@ export function makeMapStateToProps() {
|
||||
clickToReply: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CLICK_TO_REPLY, Preferences.CLICK_TO_REPLY_DEFAULT, userPreference),
|
||||
linkPreviewDisplay: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.LINK_PREVIEW_DISPLAY, Preferences.LINK_PREVIEW_DISPLAY_DEFAULT, userPreference),
|
||||
oneClickReactionsOnPosts: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.ONE_CLICK_REACTIONS_ENABLED, Preferences.ONE_CLICK_REACTIONS_ENABLED_DEFAULT, userPreference),
|
||||
renderEmoticonsAsEmoji: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.RENDER_EMOTICONS_AS_EMOJI, Preferences.RENDER_EMOTICONS_AS_EMOJI_DEFAULT, userPreference),
|
||||
emojiPickerEnabled,
|
||||
lastActiveDisplay,
|
||||
lastActiveTimeEnabled,
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji should match snapshot 1`] = `
|
||||
<div>
|
||||
<section
|
||||
class="section-max form-horizontal "
|
||||
>
|
||||
<h4
|
||||
class="col-sm-12 section-title"
|
||||
id="settingTitle"
|
||||
>
|
||||
Render emoticons as emojis
|
||||
</h4>
|
||||
<div
|
||||
class="sectionContent col-sm-10 col-sm-offset-2"
|
||||
>
|
||||
<div
|
||||
class="setting-list"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="setting-list-item"
|
||||
>
|
||||
<fieldset>
|
||||
<legend
|
||||
class="form-legend hidden-label"
|
||||
>
|
||||
Render emoticons as emojis
|
||||
</legend>
|
||||
<div
|
||||
class="radio"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
checked=""
|
||||
class="a11y--active a11y--focused"
|
||||
id="renderEmoticonsAsEmojiOn"
|
||||
name="renderEmoticonsAsEmoji"
|
||||
type="radio"
|
||||
value="true"
|
||||
/>
|
||||
On
|
||||
</label>
|
||||
<br />
|
||||
</div>
|
||||
<div
|
||||
class="radio"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
id="renderEmoticonsAsEmojiOff"
|
||||
name="renderEmoticonsAsEmoji"
|
||||
type="radio"
|
||||
value="false"
|
||||
/>
|
||||
Off
|
||||
</label>
|
||||
<br />
|
||||
</div>
|
||||
<div
|
||||
class="mt-5"
|
||||
>
|
||||
When enabled, text emoticons in messages will be rendered as emojis (For example :D as 😄)
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div
|
||||
class="setting-list-item"
|
||||
>
|
||||
<hr />
|
||||
<button
|
||||
class="btn btn-primary "
|
||||
data-testid="saveSetting"
|
||||
id="saveSetting"
|
||||
type="submit"
|
||||
>
|
||||
<span>
|
||||
Save
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-tertiary"
|
||||
id="cancelSetting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import type {Dispatch} from 'redux';
|
||||
|
||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
|
||||
import RenderEmoticonsAsEmoji from './render_emoticons_as_emoji';
|
||||
|
||||
function mapDispatchToProps(dispatch: Dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
savePreferences,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(RenderEmoticonsAsEmoji);
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import type {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {renderWithContext, userEvent} from 'tests/react_testing_utils';
|
||||
|
||||
import RenderEmoticonsAsEmoji from './render_emoticons_as_emoji';
|
||||
|
||||
describe('components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji', () => {
|
||||
const user = {
|
||||
id: 'user_id',
|
||||
username: 'username',
|
||||
locale: 'en',
|
||||
timezone: {
|
||||
useAutomaticTimezone: 'true',
|
||||
automaticTimezone: 'America/New_York',
|
||||
manualTimezone: '',
|
||||
},
|
||||
};
|
||||
|
||||
const props = {
|
||||
user: user as UserProfile,
|
||||
renderEmoticonsAsEmoji: 'true',
|
||||
updateSection: jest.fn(),
|
||||
adminMode: false,
|
||||
userPreferences: undefined,
|
||||
actions: {
|
||||
savePreferences: jest.fn(() => {
|
||||
return new Promise<void>((resolve) => {
|
||||
process.nextTick(() => resolve());
|
||||
});
|
||||
})},
|
||||
};
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const {container} = renderWithContext(<RenderEmoticonsAsEmoji {...props}/>);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call updateSection on submit', async () => {
|
||||
const {getByRole, getByLabelText} = renderWithContext(<RenderEmoticonsAsEmoji {...props}/>);
|
||||
|
||||
const radioButtonOff = getByLabelText(/off/i);
|
||||
userEvent.click(radioButtonOff);
|
||||
|
||||
const submitButton = getByRole('button', {name: /save/i});
|
||||
userEvent.click(submitButton);
|
||||
|
||||
expect(props.actions.savePreferences).toHaveBeenCalled();
|
||||
expect(props.updateSection).toHaveBeenCalledWith('');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback, useState} from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import type {PreferencesType, PreferenceType} from '@mattermost/types/preferences';
|
||||
import type {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {Preferences} from 'mattermost-redux/constants';
|
||||
|
||||
import SettingItemMax from 'components/setting_item_max';
|
||||
|
||||
export type Actions = {
|
||||
savePreferences: (userId: string, preferences: PreferenceType[]) => void;
|
||||
};
|
||||
|
||||
export type OwnProps = {
|
||||
user: UserProfile;
|
||||
updateSection: (section: string) => void;
|
||||
adminMode?: boolean;
|
||||
userPreferences?: PreferencesType;
|
||||
}
|
||||
|
||||
type Props = OwnProps & {
|
||||
renderEmoticonsAsEmoji: string;
|
||||
actions: Actions;
|
||||
}
|
||||
|
||||
const RenderEmoticonsAsEmoji: React.FC<Props> = ({user, renderEmoticonsAsEmoji, updateSection, actions}) => {
|
||||
const [value, setValue] = useState<string>(renderEmoticonsAsEmoji);
|
||||
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||
|
||||
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setValue(e.currentTarget.value);
|
||||
}, []);
|
||||
|
||||
const submitPreference = useCallback(() => {
|
||||
setIsSaving(true);
|
||||
const pref: PreferenceType = {
|
||||
user_id: user.id,
|
||||
category: Preferences.CATEGORY_DISPLAY_SETTINGS,
|
||||
name: Preferences.RENDER_EMOTICONS_AS_EMOJI,
|
||||
value,
|
||||
};
|
||||
actions.savePreferences(user.id, [pref]);
|
||||
setIsSaving(false);
|
||||
updateSection('');
|
||||
}, [user.id, updateSection, actions, value]);
|
||||
|
||||
const changePreference = useCallback(() => {
|
||||
if (value === renderEmoticonsAsEmoji) {
|
||||
updateSection('');
|
||||
return;
|
||||
}
|
||||
|
||||
submitPreference();
|
||||
}, [renderEmoticonsAsEmoji, updateSection, value, submitPreference]);
|
||||
|
||||
const options = [
|
||||
{
|
||||
option: 'true',
|
||||
inputId: 'renderEmoticonsAsEmojiOn',
|
||||
messageId: 'user.settings.advance.on',
|
||||
defaultMessage: 'On',
|
||||
},
|
||||
{
|
||||
option: 'false',
|
||||
inputId: 'renderEmoticonsAsEmojiOff',
|
||||
messageId: 'user.settings.advance.off',
|
||||
defaultMessage: 'Off',
|
||||
},
|
||||
];
|
||||
|
||||
const input = (
|
||||
<fieldset key='renderEmoticonsAsEmojiSetting'>
|
||||
<legend className='form-legend hidden-label'>
|
||||
<FormattedMessage
|
||||
id='user.settings.display.renderEmoticonsAsEmojiTitle'
|
||||
defaultMessage='Render emoticons as emojis'
|
||||
/>
|
||||
</legend>
|
||||
{options.map(({option, inputId, messageId, defaultMessage}) => {
|
||||
return (
|
||||
<div
|
||||
className='radio'
|
||||
key={option}
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
id={inputId}
|
||||
type='radio'
|
||||
name='renderEmoticonsAsEmoji'
|
||||
value={option}
|
||||
checked={value === option}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id={messageId}
|
||||
defaultMessage={defaultMessage}
|
||||
/>
|
||||
</label>
|
||||
<br/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className='mt-5'>
|
||||
<FormattedMessage
|
||||
id='user.settings.display.renderEmoticonsAsEmojiDesc'
|
||||
defaultMessage='When enabled, text emoticons in messages will be rendered as emojis (For example :D as 😄)'
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingItemMax
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='user.settings.display.renderEmoticonsAsEmojiTitle'
|
||||
defaultMessage='Render emoticons as emojis'
|
||||
/>
|
||||
}
|
||||
inputs={[input]}
|
||||
submit={changePreference}
|
||||
saving={isSaving}
|
||||
updateSection={updateSection}
|
||||
disableEnterSubmit={true}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default RenderEmoticonsAsEmoji;
|
||||
@@ -94,6 +94,7 @@ describe('components/user_settings/display/UserSettingsDisplay', () => {
|
||||
globalHeaderAllowed: true,
|
||||
lastActiveDisplay: true,
|
||||
oneClickReactionsOnPosts: '',
|
||||
renderEmoticonsAsEmoji: '',
|
||||
emojiPickerEnabled: true,
|
||||
clickToReply: '',
|
||||
lastActiveTimeEnabled: true,
|
||||
|
||||
@@ -28,6 +28,7 @@ import {a11yFocus} from 'utils/utils';
|
||||
|
||||
import ManageLanguages from './manage_languages';
|
||||
import ManageTimezones from './manage_timezones';
|
||||
import RenderEmoticonsAsEmoji from './render_emoticons_as_emoji';
|
||||
|
||||
import SettingDesktopHeader from '../headers/setting_desktop_header';
|
||||
import SettingMobileHeader from '../headers/setting_mobile_header';
|
||||
@@ -120,6 +121,7 @@ type Props = OwnProps & {
|
||||
timezoneLabel: string;
|
||||
lastActiveDisplay: boolean;
|
||||
lastActiveTimeEnabled: boolean;
|
||||
renderEmoticonsAsEmoji: string;
|
||||
actions: {
|
||||
savePreferences: (userId: string, preferences: PreferenceType[]) => void;
|
||||
autoUpdateTimezone: (deviceTimezone: string) => void;
|
||||
@@ -1147,6 +1149,46 @@ export default class UserSettingsDisplay extends React.PureComponent<Props, Stat
|
||||
});
|
||||
}
|
||||
|
||||
const renderEmoticonsAsEmojiSection = (
|
||||
<div>
|
||||
<SettingItem
|
||||
active={this.props.activeSection === 'renderEmoticonsAsEmoji'}
|
||||
areAllSectionsInactive={this.props.activeSection === ''}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='user.settings.display.renderEmoticonsAsEmojiTitle'
|
||||
defaultMessage='Render emoticons as emojis'
|
||||
/>
|
||||
}
|
||||
describe={
|
||||
this.props.renderEmoticonsAsEmoji === 'true' ? (
|
||||
<FormattedMessage
|
||||
id='user.settings.advance.on'
|
||||
defaultMessage='On'
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id='user.settings.advance.off'
|
||||
defaultMessage='Off'
|
||||
/>
|
||||
)
|
||||
}
|
||||
section='renderEmoticonsAsEmoji'
|
||||
updateSection={this.updateSection}
|
||||
max={(
|
||||
<RenderEmoticonsAsEmoji
|
||||
renderEmoticonsAsEmoji={this.props.renderEmoticonsAsEmoji}
|
||||
user={this.props.user}
|
||||
updateSection={this.updateSection}
|
||||
adminMode={this.props.adminMode}
|
||||
userPreferences={this.props.userPreferences}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div className='divider-dark'/>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
id='displaySettings'
|
||||
@@ -1187,6 +1229,7 @@ export default class UserSettingsDisplay extends React.PureComponent<Props, Stat
|
||||
{clickToReply}
|
||||
{channelDisplayModeSection}
|
||||
{oneClickReactionsOnPostsSection}
|
||||
{renderEmoticonsAsEmojiSection}
|
||||
{languagesSection}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5903,6 +5903,8 @@
|
||||
"user.settings.display.oneClickReactionsOnPostsDescription": "When enabled, you can react quickly with recently used reactions when hovering over a message.",
|
||||
"user.settings.display.oneClickReactionsOnPostsTitle": "Quick reactions on messages",
|
||||
"user.settings.display.preferTime": "Select how you prefer time displayed.",
|
||||
"user.settings.display.renderEmoticonsAsEmojiDesc": "When enabled, text emoticons in messages will automatically be rendered as emojis (For example :D as 😄)",
|
||||
"user.settings.display.renderEmoticonsAsEmojiTitle": "Render emoticons as emojis",
|
||||
"user.settings.display.teammateNameDisplay": "This field is handled through your System Administrator. If you want to change it, you need to do so through your System Administrator.",
|
||||
"user.settings.display.teammateNameDisplayDescription": "Set how to display other user's names in posts and the Direct Messages list.",
|
||||
"user.settings.display.teammateNameDisplayFullname": "Show first and last name",
|
||||
|
||||
@@ -48,6 +48,7 @@ const Preferences = {
|
||||
SHOW_UNREAD_SECTION: 'show_unread_section',
|
||||
CATEGORY_ADVANCED_SETTINGS: 'advanced_settings',
|
||||
ADVANCED_FILTER_JOIN_LEAVE: 'join_leave',
|
||||
RENDER_EMOTICONS_AS_EMOJI: 'render_emoticons_as_emoji',
|
||||
ADVANCED_CODE_BLOCK_ON_CTRL_ENTER: 'code_block_ctrl_enter',
|
||||
ADVANCED_SEND_ON_CTRL_ENTER: 'send_on_ctrl_enter',
|
||||
ADVANCED_SYNC_DRAFTS: 'sync_drafts',
|
||||
|
||||
@@ -91,6 +91,8 @@ export const Preferences = {
|
||||
CLICK_TO_REPLY: 'click_to_reply',
|
||||
CLICK_TO_REPLY_DEFAULT: 'true',
|
||||
COLLAPSED_REPLY_THREADS_FALLBACK_DEFAULT: 'off',
|
||||
RENDER_EMOTICONS_AS_EMOJI: 'render_emoticons_as_emoji',
|
||||
RENDER_EMOTICONS_AS_EMOJI_DEFAULT: 'true',
|
||||
LINK_PREVIEW_DISPLAY: 'link_previews',
|
||||
LINK_PREVIEW_DISPLAY_DEFAULT: 'true',
|
||||
COLLAPSE_DISPLAY: 'collapse_previews',
|
||||
|
||||
@@ -92,6 +92,11 @@ describe('Emoticons', () => {
|
||||
expect(Emoticons.handleEmoticons('":P"', new Map())).
|
||||
toEqual('"$MM_EMOTICON0$"');
|
||||
});
|
||||
|
||||
test('shouldn\'t render text-based emoticons as emoji when renderEmoticonsAsEmoji is false', () => {
|
||||
expect(Emoticons.handleEmoticons('":P"', new Map(), false)).
|
||||
toEqual('":P"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('matchEmoticons', () => {
|
||||
|
||||
@@ -50,6 +50,7 @@ export function matchEmoticons(text: string): string[] | null {
|
||||
export function handleEmoticons(
|
||||
text: string,
|
||||
tokens: Map<string, {value: string; originalText: string}>,
|
||||
renderEmoticonsAsEmoji = true,
|
||||
): string {
|
||||
let output = text;
|
||||
|
||||
@@ -85,12 +86,14 @@ export function handleEmoticons(
|
||||
);
|
||||
|
||||
// match text smilies like :D
|
||||
for (const name of Object.keys(emoticonPatterns)) {
|
||||
const pattern = emoticonPatterns[name];
|
||||
if (renderEmoticonsAsEmoji) {
|
||||
for (const name of Object.keys(emoticonPatterns)) {
|
||||
const pattern = emoticonPatterns[name];
|
||||
|
||||
// this might look a bit funny, but since the name isn't contained in the actual match
|
||||
// like with the named emoticons, we need to add it in manually
|
||||
output = output.replace(pattern, (fullMatch, prefix, matchText) => replaceEmoticonWithToken(fullMatch, prefix, matchText, name));
|
||||
// this might look a bit funny, but since the name isn't contained in the actual match
|
||||
// like with the named emoticons, we need to add it in manually
|
||||
output = output.replace(pattern, (fullMatch, prefix, matchText) => replaceEmoticonWithToken(fullMatch, prefix, matchText, name));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -90,6 +90,11 @@ describe('formatText', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('emoticons should not be rendered as emojis when renderEmoticonsAsEmoji is false', () => {
|
||||
const output = formatText(':)', {renderEmoticonsAsEmoji: false}, emptyEmojiMap);
|
||||
expect(output).toBe('<p>:)</p>');
|
||||
});
|
||||
|
||||
test('code blocks newlines are not converted into <br/> with inline markdown image in the post', () => {
|
||||
const output = formatText('```\nsome text\nsecond line\n```\n ', {}, emptyEmojiMap);
|
||||
expect(output).not.toContain('<br/>');
|
||||
|
||||
@@ -230,6 +230,11 @@ export interface TextFormattingOptionsBase {
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
unsafeLinks: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not to render text emoticons (:D) as emojis
|
||||
*/
|
||||
renderEmoticonsAsEmoji: boolean;
|
||||
}
|
||||
|
||||
export type TextFormattingOptions = Partial<TextFormattingOptionsBase>;
|
||||
@@ -258,6 +263,7 @@ const DEFAULT_OPTIONS: TextFormattingOptions = {
|
||||
editedAt: 0,
|
||||
postId: '',
|
||||
unsafeLinks: false,
|
||||
renderEmoticonsAsEmoji: true,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -401,7 +407,7 @@ export function doFormatText(text: string, options: TextFormattingOptions, emoji
|
||||
output = autolinkHashtags(output, tokens, options.minimumHashtagLength);
|
||||
|
||||
if (!('emoticons' in options) || options.emoticons) {
|
||||
output = Emoticons.handleEmoticons(output, tokens);
|
||||
output = Emoticons.handleEmoticons(output, tokens, options.renderEmoticonsAsEmoji);
|
||||
}
|
||||
|
||||
if (options.searchPatterns) {
|
||||
|
||||
Ссылка в новой задаче
Block a user