diff --git a/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js b/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js index d20de1698..acafd07a2 100644 --- a/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js +++ b/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js @@ -99,7 +99,7 @@ export default class EmojiSuggestion extends Component { {`:${item}:`} diff --git a/app/components/emoji/emoji.js b/app/components/emoji/emoji.js index 4aa3c27aa..2b0510658 100644 --- a/app/components/emoji/emoji.js +++ b/app/components/emoji/emoji.js @@ -15,8 +15,8 @@ export default class Emoji extends React.PureComponent { static propTypes = { customEmojis: PropTypes.object, emojiName: PropTypes.string.isRequired, + fontSize: PropTypes.number, literal: PropTypes.string, - padding: PropTypes.number, size: PropTypes.number.isRequired, textStyle: CustomPropTypes.Style, token: PropTypes.string.isRequired @@ -24,49 +24,131 @@ export default class Emoji extends React.PureComponent { static defaultProps = { customEmojis: new Map(), - literal: '', - padding: 10 + literal: '' }; + constructor(props) { + super(props); + + this.state = { + ...this.getImageUrl(props), + originalWidth: 0, + originalHeight: 0 + }; + } + + componentWillMount() { + if (this.state.imageUrl && this.state.isCustomEmoji) { + this.updateImageHeight(this.state.imageUrl); + } + } + + componentWillReceiveProps(nextProps) { + if (nextProps.customEmojis !== this.props.customEmojis || nextProps.emojiName !== this.props.emojiName) { + this.setState({ + ...this.getImageUrl(nextProps), + originalWidth: 0, + originalHeight: 0 + }); + } + } + + componentWillUpdate(nextProps, nextState) { + if (nextState.imageUrl !== this.state.imageUrl && nextState.imageUrl && nextState.isCustomEmoji) { + this.updateImageHeight(nextState.imageUrl); + } + } + + getImageUrl = (props = this.props) => { + const emojiName = props.emojiName; + + let imageUrl = ''; + let isCustomEmoji = false; + if (EmojiIndicesByAlias.has(emojiName)) { + const emoji = Emojis[EmojiIndicesByAlias.get(emojiName)]; + + imageUrl = Client4.getSystemEmojiImageUrl(emoji.filename); + } else if (props.customEmojis.has(emojiName)) { + const emoji = props.customEmojis.get(emojiName); + + imageUrl = Client4.getCustomEmojiImageUrl(emoji.id); + isCustomEmoji = true; + } + + return { + imageUrl, + isCustomEmoji + }; + } + + updateImageHeight = (imageUrl) => { + Image.getSize(imageUrl, (originalWidth, originalHeight) => { + this.setState({ + originalWidth, + originalHeight + }); + }); + } + render() { const { - customEmojis, - emojiName, + fontSize, literal, - padding, size, textStyle, token } = this.props; - let imageUrl; - if (EmojiIndicesByAlias.has(emojiName)) { - const emoji = Emojis[EmojiIndicesByAlias.get(emojiName)]; - imageUrl = Client4.getSystemEmojiImageUrl(emoji.filename); - } else if (customEmojis.has(emojiName)) { - const emoji = customEmojis.get(emojiName); - imageUrl = Client4.getCustomEmojiImageUrl(emoji.id); - } - - if (!imageUrl) { + if (!this.state.imageUrl) { return {literal}; } - let ImageComponent = FastImage; + let ImageComponent; + if (Platform.OS === 'android') { + ImageComponent = Image; + } else { + ImageComponent = FastImage; + } + const source = { - uri: imageUrl, + uri: this.state.imageUrl, headers: { Authorization: `Bearer ${token}` } }; - if (Platform.OS === 'android') { - ImageComponent = Image; + let width = size; + let height = size; + if (this.state.originalHeight && this.state.originalWidth) { + if (this.state.originalWidth > this.state.originalHeight) { + height = (size * this.state.originalHeight) / this.state.originalWidth; + } else if (this.state.originalWidth < this.state.originalHeight) { + // This may cause text to reflow, but its impossible to add a horizontal margin + width = (size * this.state.originalWidth) / this.state.originalHeight; + } } + let marginTop = 0; + if (fontSize) { + // Center the image vertically on iOS (does nothing on Android) + marginTop = (height - fontSize) / 2; + + // hack to get the vertical alignment looking better + if (fontSize === 17) { + marginTop -= 2; + } else if (fontSize === 15) { + marginTop += 1; + } + } + + // Android can't change the size of an image after its first render, so + // force a new image to be rendered when the size changes + const key = Platform.OS === 'android' ? (height + '-' + width) : null; + return ( diff --git a/app/components/markdown/index.js b/app/components/markdown/index.js index 9ed89ddf4..39dc110b8 100644 --- a/app/components/markdown/index.js +++ b/app/components/markdown/index.js @@ -29,6 +29,7 @@ export default class Markdown extends PureComponent { baseTextStyle: CustomPropTypes.Style, blockStyles: PropTypes.object, emojiSizes: PropTypes.object, + fontSizes: PropTypes.object, isSearchResult: PropTypes.bool, navigator: PropTypes.object.isRequired, onLongPress: PropTypes.func, @@ -52,16 +53,25 @@ export default class Markdown extends PureComponent { text: 20 }, android: { - heading1: 80, - heading2: 80, - heading3: 80, - heading4: 80, - heading5: 80, - heading6: 80, - text: 65 + heading1: 60, + heading2: 60, + heading3: 60, + heading4: 60, + heading5: 60, + heading6: 60, + text: 45 } }) }, + fontSizes: { + heading1: 17, + heading2: 17, + heading3: 17, + heading4: 17, + heading5: 17, + heading6: 17, + text: 15 + }, onLongPress: () => true }; @@ -157,11 +167,14 @@ export default class Markdown extends PureComponent { renderEmoji = ({context, emojiName, literal}) => { let size; + let fontSize; const headingType = context.find((type) => type.startsWith('heading')); if (headingType) { size = this.props.emojiSizes[headingType]; + fontSize = this.props.fontSizes[headingType]; } else { size = this.props.emojiSizes.text; + fontSize = this.props.fontSizes.text; } return ( @@ -169,6 +182,7 @@ export default class Markdown extends PureComponent { emojiName={emojiName} literal={literal} size={size} + fontSize={fontSize} textStyle={this.computeTextStyle(this.props.baseTextStyle, context)} /> ); diff --git a/app/components/post_body/post_body.js b/app/components/post_body/post_body.js index 60976d007..6bae82fa7 100644 --- a/app/components/post_body/post_body.js +++ b/app/components/post_body/post_body.js @@ -292,7 +292,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { return { message: { color: theme.centerChannelColor, - fontSize: 15 + fontSize: 15, + lineHeight: 20 }, messageContainerWithReplyBar: { flexDirection: 'row', diff --git a/app/utils/markdown.js b/app/utils/markdown.js index 69ff1f71c..749fcf590 100644 --- a/app/utils/markdown.js +++ b/app/utils/markdown.js @@ -27,38 +27,32 @@ export const getMarkdownTextStyles = makeStyleSheetFromTheme((theme) => { heading1: { fontSize: 17, fontWeight: '700', - marginTop: 10, - marginBottom: 10 + lineHeight: 25 }, heading2: { fontSize: 17, fontWeight: '700', - marginTop: 10, - marginBottom: 10 + lineHeight: 25 }, heading3: { fontSize: 17, fontWeight: '700', - marginTop: 10, - marginBottom: 10 + lineHeight: 25 }, heading4: { fontSize: 17, fontWeight: '700', - marginTop: 10, - marginBottom: 10 + lineHeight: 25 }, heading5: { fontSize: 17, fontWeight: '700', - marginTop: 10, - marginBottom: 10 + lineHeight: 25 }, heading6: { fontSize: 17, fontWeight: '700', - marginTop: 10, - marginBottom: 10 + lineHeight: 25 }, code: { alignSelf: 'center',