RN-189/RN-241 Updated emoji appearance (#898)
* Removed Emoji padding prop * Reduced emoji size on Android * RN-189 Fixed aspect ratio for wide emojis * Removed margins from headers which didn't actually work * RN-189 Fixed aspect ratio for tall emojis * Adjusted line height so emojis don't cause uneven spacing on iOS * Further reduced emoji size on Android * Slightly adjusted vertical alignment of emojis * Added hack to get vertical alignment of emojis looking better
This commit is contained in:
parent
19502f9aaa
commit
612da49697
5 changed files with 133 additions and 42 deletions
|
|
@ -99,7 +99,7 @@ export default class EmojiSuggestion extends Component {
|
|||
<View style={style.emoji}>
|
||||
<Emoji
|
||||
emojiName={item}
|
||||
size={10}
|
||||
size={20}
|
||||
/>
|
||||
</View>
|
||||
<Text style={style.emojiName}>{`:${item}:`}</Text>
|
||||
|
|
|
|||
|
|
@ -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 <Text style={textStyle}>{literal}</Text>;
|
||||
}
|
||||
|
||||
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 (
|
||||
<ImageComponent
|
||||
style={{width: size, height: size, padding}}
|
||||
key={key}
|
||||
style={{width, height, marginTop}}
|
||||
source={source}
|
||||
onError={this.onError}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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)}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -292,7 +292,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
return {
|
||||
message: {
|
||||
color: theme.centerChannelColor,
|
||||
fontSize: 15
|
||||
fontSize: 15,
|
||||
lineHeight: 20
|
||||
},
|
||||
messageContainerWithReplyBar: {
|
||||
flexDirection: 'row',
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
Loading…
Reference in a new issue