Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
ABC-122 Handle custom emojis in channel header and login page (#677)
Browse files Browse the repository at this point in the history
* Temporary redux commit

* Add async custom emoji loading to channel header

* Handle emojis in login page banner text

* Update mattermost-redux

* Fix accidental removal
  • Loading branch information
jwilander committed Feb 2, 2018
1 parent 8c7f189 commit f0f7ec9
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 30 deletions.
19 changes: 14 additions & 5 deletions components/channel_header/channel_header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {ActionTypes, Constants, RHSStates, UserStatuses, ModalIdentifiers} from
import * as TextFormatting from 'utils/text_formatting.jsx';
import {getSiteURL} from 'utils/url.jsx';
import * as Utils from 'utils/utils.jsx';
import {messageHtmlToComponent} from 'utils/post_utils.jsx';
import ChannelInfoModal from 'components/channel_info_modal';
import ChannelInviteModal from 'components/channel_invite_modal';
import ChannelMembersModal from 'components/channel_members_modal';
Expand Down Expand Up @@ -62,7 +63,8 @@ export default class ChannelHeader extends React.Component {
showPinnedPosts: PropTypes.func.isRequired,
showMentions: PropTypes.func.isRequired,
closeRightHandSide: PropTypes.func.isRequired,
openModal: PropTypes.func.isRequired
openModal: PropTypes.func.isRequired,
getCustomEmojisInText: PropTypes.func.isRequired
}).isRequired
}

Expand All @@ -85,6 +87,7 @@ export default class ChannelHeader extends React.Component {
}

componentDidMount() {
this.props.actions.getCustomEmojisInText(this.props.channel.header);
WebrtcStore.addChangedListener(this.onWebrtcChange);
WebrtcStore.addBusyListener(this.onBusy);
document.addEventListener('keydown', this.handleShortcut);
Expand All @@ -96,6 +99,12 @@ export default class ChannelHeader extends React.Component {
document.removeEventListener('keydown', this.handleShortcut);
}

componentWillReceiveProps(nextProps) {
if (this.props.channel.id !== nextProps.channel.id) {
this.props.actions.getCustomEmojisInText(nextProps.channel.header);
}
}

onWebrtcChange = () => {
this.setState({isBusy: WebrtcStore.isBusy()});
}
Expand Down Expand Up @@ -775,6 +784,7 @@ export default class ChannelHeader extends React.Component {
let headerTextContainer;
if (channel.header) {
let headerTextElement;
const formattedText = TextFormatting.formatText(channel.header, textFormattingOptions);
if (this.props.enableFormatting) {
headerTextElement = (
<div
Expand All @@ -783,10 +793,9 @@ export default class ChannelHeader extends React.Component {
>
{dmHeaderIconStatus}
{dmHeaderTextStatus}
<span
onClick={Utils.handleFormattedTextClick}
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(channel.header, textFormattingOptions)}}
/>
<span onClick={Utils.handleFormattedTextClick}>
{messageHtmlToComponent(formattedText, false, {mentions: false})}
</span>
</div>
);
} else {
Expand Down
4 changes: 3 additions & 1 deletion components/channel_header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {favoriteChannel, leaveChannel, unfavoriteChannel} from 'mattermost-redux/actions/channels';
import {getCustomEmojisInText} from 'mattermost-redux/actions/emojis';
import {General, Preferences} from 'mattermost-redux/constants';
import {getChannel, getMyChannelMember} from 'mattermost-redux/selectors/entities/channels';
import {getBool} from 'mattermost-redux/selectors/entities/preferences';
Expand Down Expand Up @@ -56,7 +57,8 @@ function mapDispatchToProps(dispatch) {
showPinnedPosts,
showMentions,
closeRightHandSide,
openModal
openModal,
getCustomEmojisInText
}, dispatch)
};
}
Expand Down
6 changes: 5 additions & 1 deletion components/login/login_controller.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import TeamStore from 'stores/team_store.jsx';
import Constants from 'utils/constants.jsx';
import * as TextFormatting from 'utils/text_formatting.jsx';
import * as Utils from 'utils/utils.jsx';
import {messageHtmlToComponent} from 'utils/post_utils.jsx';
import logoImage from 'images/logo.png';
import AnnouncementBar from 'components/announcement_bar';
import FormError from 'components/form_error.jsx';
Expand Down Expand Up @@ -249,13 +250,16 @@ export default class LoginController extends React.Component {
global.window.mm_license.CustomBrand === 'true' &&
global.window.mm_config.EnableCustomBrand === 'true') {
const text = global.window.mm_config.CustomBrandText || '';
const formattedText = TextFormatting.formatText(text);

return (
<div>
<img
src={Client4.getBrandImageUrl(0)}
/>
<p dangerouslySetInnerHTML={{__html: TextFormatting.formatText(text)}}/>
<p>
{messageHtmlToComponent(formattedText, false, {mentions: false})}
</p>
</div>
);
}
Expand Down
10 changes: 6 additions & 4 deletions components/message_wrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React from 'react';
import * as TextFormatting from 'utils/text_formatting.jsx';
import {getSiteURL} from 'utils/url.jsx';
import * as Utils from 'utils/utils.jsx';
import {messageHtmlToComponent} from 'utils/post_utils.jsx';

export default class MessageWrapper extends React.Component {
constructor(props) {
Expand All @@ -20,11 +21,12 @@ export default class MessageWrapper extends React.Component {
siteURL: getSiteURL()
});

const formattedText = TextFormatting.formatText(this.props.message, options);

return (
<div
onClick={Utils.handleFormattedTextClick}
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(this.props.message, options)}}
/>
<div onClick={Utils.handleFormattedTextClick}>
{messageHtmlToComponent(formattedText, false, {mentions: false})}
</div>
);
}

Expand Down
4 changes: 3 additions & 1 deletion components/post_emoji/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {connect} from 'react-redux';

import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';

import EmojiStore from 'stores/emoji_store.jsx';
import {getEmojiMap} from 'selectors/emojis';
Expand All @@ -20,7 +21,8 @@ function mapStateToProps(state, ownProps) {
imageUrl = EmojiStore.getEmojiImageUrl(emoji);
} else {
displayTextOnly = state.entities.emojis.nonExistentEmoji.has(ownProps.name) ||
getConfig(state).EnableCustomEmoji !== 'true';
getConfig(state).EnableCustomEmoji !== 'true' ||
getCurrentUserId(state) === '';
}

return {
Expand Down
2 changes: 1 addition & 1 deletion components/post_markdown/post_markdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,6 @@ export default class PostMarkdown extends React.PureComponent {
}

const htmlFormattedText = TextFormatting.formatText(this.props.message, options);
return <span>{PostUtils.postMessageHtmlToComponent(htmlFormattedText, this.props.isRHS)}</span>;
return <span>{PostUtils.messageHtmlToComponent(htmlFormattedText, this.props.isRHS)}</span>;
}
}
54 changes: 37 additions & 17 deletions utils/post_utils.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,26 @@ export function removeCode(text) {
return text.replace(codeBlockPattern, '').replace(inlineCodePattern, ' ');
}

export function postMessageHtmlToComponent(html, isRHS) {
/*
* Converts HTML to React components using html-to-react.
* The following options can be specified:
* - mentions - If specified, mentions are replaced with the AtMention component. Defaults to true.
* - emoji - If specified, emoji text is replaced with the PostEmoji component. Defaults to true.
* - images - If specified, markdown images are replaced with the PostMarkdown component. Defaults to true.
* - latex - If specified, latex is replaced with the LatexBlock component. Defaults to true.
*/
export function messageHtmlToComponent(html, isRHS, options = {}) {
const parser = new Parser();
const mentionAttrib = 'data-mention';
const emojiAttrib = 'data-emoticon';
const processNodeDefinitions = new ProcessNodeDefinitions(React);

function isValidNode() {
return true;
}

const processingInstructions = [
{
const processingInstructions = [];
if (!('mentions' in options) || options.mentions) {
const mentionAttrib = 'data-mention';
processingInstructions.push({
replaceChildren: true,
shouldProcessNode: (node) => node.attribs && node.attribs[mentionAttrib],
processNode: (node) => {
Expand All @@ -161,8 +169,12 @@ export function postMessageHtmlToComponent(html, isRHS) {
);
return callAtMention;
}
},
{
});
}

if (!('emoji' in options) || options.emoji) {
const emojiAttrib = 'data-emoticon';
processingInstructions.push({
replaceChildren: true,
shouldProcessNode: (node) => node.attribs && node.attribs[emojiAttrib],
processNode: (node) => {
Expand All @@ -174,8 +186,11 @@ export function postMessageHtmlToComponent(html, isRHS) {
);
return callPostEmoji;
}
},
{
});
}

if (!('images' in options) || options.images) {
processingInstructions.push({
shouldProcessNode: (node) => node.type === 'tag' && node.name === 'img',
processNode: (node) => {
const {
Expand All @@ -190,19 +205,24 @@ export function postMessageHtmlToComponent(html, isRHS) {
);
return callMarkdownImage;
}
},
{
});
}

if (!('latex' in options) || options.latex) {
processingInstructions.push({
shouldProcessNode: (node) => node.attribs && node.attribs['data-latex'],
processNode: (node) => {
return (
<LatexBlock content={node.attribs['data-latex']}/>
);
}
},
{
shouldProcessNode: () => true,
processNode: processNodeDefinitions.processDefaultNode
}
];
});
}

processingInstructions.push({
shouldProcessNode: () => true,
processNode: processNodeDefinitions.processDefaultNode
});

return parser.parseWithInstructions(html, isValidNode, processingInstructions);
}

0 comments on commit f0f7ec9

Please sign in to comment.