-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Dynamic emoji size #3561
feat: Dynamic emoji size #3561
Changes from 1 commit
8baee4f
7fa65be
1f1956c
379b771
156fe87
734ee3e
bcc0882
0b34771
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import styleVariables from '../../../../styles/variables'; | ||
|
||
const dynamicEmojiSize = (windowWidth) => { | ||
if (windowWidth <= 320) { | ||
return styleVariables.fontSizeSmall; | ||
} | ||
if ( | ||
windowWidth <= 480 | ||
) { | ||
return styleVariables.fontSizeNormal; | ||
} | ||
|
||
return styleVariables.fontSizeLarge; | ||
}; | ||
|
||
export default dynamicEmojiSize; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../compo | |
import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; | ||
import compose from '../../../../libs/compose'; | ||
import getOperatingSystem from '../../../../libs/getOperatingSystem'; | ||
import dynamicEmojiSize from './dynamicEmojiSize'; | ||
|
||
const propTypes = { | ||
/** Function to add the selected emoji to the main compose text input */ | ||
|
@@ -72,6 +73,7 @@ class EmojiPickerMenu extends Component { | |
headerIndices: this.unfilteredHeaderIndices, | ||
highlightedIndex: -1, | ||
arePointerEventsDisabled: false, | ||
emojiSize: dynamicEmojiSize(this.props.windowWidth), | ||
}; | ||
} | ||
|
||
|
@@ -86,6 +88,18 @@ class EmojiPickerMenu extends Component { | |
this.setupEventHandlers(); | ||
} | ||
|
||
|
||
componentDidUpdate(prevProps) { | ||
if ( | ||
this.props.windowWidth !== prevProps.windowWidth | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as before, let's make this a single line if statement. |
||
) { | ||
// eslint-disable-next-line react/no-did-update-set-state | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason you would prefer to disable this rule. IMO it feels just as easy to create a method like
Then you wouldn't need to disable the eslint rule. |
||
this.setState({ | ||
emojiSize: dynamicEmojiSize(this.props.windowWidth), | ||
}); | ||
} | ||
} | ||
|
||
componentWillUnmount() { | ||
this.cleanupEventHandlers(); | ||
} | ||
|
@@ -302,6 +316,7 @@ class EmojiPickerMenu extends Component { | |
onHover={() => this.setState({highlightedIndex: index})} | ||
emoji={code} | ||
isHighlighted={index === this.state.highlightedIndex} | ||
size={this.state.emojiSize} | ||
/> | ||
); | ||
} | ||
|
@@ -333,7 +348,7 @@ class EmojiPickerMenu extends Component { | |
keyExtractor={item => `emoji_picker_${item.code}`} | ||
numColumns={this.numColumns} | ||
style={styles.emojiPickerList} | ||
extraData={[this.state.filteredEmojis, this.state.highlightedIndex]} | ||
extraData={this.state} | ||
stickyHeaderIndices={this.state.headerIndices} | ||
onScroll={e => this.currentScrollOffset = e.nativeEvent.contentOffset.y} | ||
/> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,19 @@ | ||
import React, {Component} from 'react'; | ||
import {View, FlatList, Text} from 'react-native'; | ||
import PropTypes from 'prop-types'; | ||
import compose from '../../../../libs/compose'; | ||
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions'; | ||
import CONST from '../../../../CONST'; | ||
import styles from '../../../../styles/styles'; | ||
import emojis from '../../../../../assets/emojis'; | ||
import EmojiPickerMenuItem from '../EmojiPickerMenuItem'; | ||
import dynamicEmojiSize from './dynamicEmojiSize'; | ||
|
||
const propTypes = { | ||
/** Function to add the selected emoji to the main compose text input */ | ||
onEmojiSelected: PropTypes.func.isRequired, | ||
|
||
...windowDimensionsPropTypes, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NAB: I see there are many places in our code where this is prop is not documented but as per our style guide it would be nice if you include a JS comment doc for this for consistency. |
||
}; | ||
|
||
class EmojiPickerMenu extends Component { | ||
|
@@ -29,8 +34,24 @@ class EmojiPickerMenu extends Component { | |
this.unfilteredHeaderIndices = [0, 33, 59, 87, 98, 120, 147]; | ||
|
||
this.renderItem = this.renderItem.bind(this); | ||
|
||
this.state = { | ||
emojiSize: dynamicEmojiSize(this.props.windowWidth), | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need this state variable? Its not really changing anywhere in the component so I don't quite see the benefit.
over here. If you think that's not too readable then we should just do this.emojiSize than save it in a state variable. Thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea of keeping it in a state opens the door for any future development for reactivity for emoji sizes. We can remove it from the state and make it a normal class property. - this.state.emojiSize
+ this.emojiSize There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Making code more complex than it needs to be with the assumption that it will be modified in the future is unnecessary preoptimization. When its needed to be a state variable for any reason then its easy enough to convert so let's not have it be a state variable right now. Sure I'm fine with class property 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done I have updated the PR |
||
} | ||
|
||
componentDidUpdate(prevProps) { | ||
if ( | ||
this.props.windowWidth !== prevProps.windowWidth | ||
) { | ||
// eslint-disable-next-line react/no-did-update-set-state | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar comment as here |
||
this.setState({ | ||
emojiSize: dynamicEmojiSize(this.props.windowWidth), | ||
}); | ||
} | ||
} | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove unnecessary line break |
||
/** | ||
* Given an emoji item object, render a component based on its type. | ||
* Items with the code "SPACER" return nothing and are used to fill rows up to 8 | ||
|
@@ -56,6 +77,7 @@ class EmojiPickerMenu extends Component { | |
<EmojiPickerMenuItem | ||
onPress={this.props.onEmojiSelected} | ||
emoji={item.code} | ||
size={this.state.emojiSize} | ||
/> | ||
); | ||
} | ||
|
@@ -69,6 +91,7 @@ class EmojiPickerMenu extends Component { | |
keyExtractor={item => (`emoji_picker_${item.code}`)} | ||
numColumns={this.numColumns} | ||
style={styles.emojiPickerList} | ||
extraData={this.state} | ||
stickyHeaderIndices={this.unfilteredHeaderIndices} | ||
/> | ||
</View> | ||
|
@@ -78,4 +101,4 @@ class EmojiPickerMenu extends Component { | |
|
||
EmojiPickerMenu.propTypes = propTypes; | ||
|
||
export default EmojiPickerMenu; | ||
export default compose(withWindowDimensions)(EmojiPickerMenu); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,8 @@ const propTypes = { | |
|
||
/** Whether this menu item is currently highlighted or not */ | ||
isHighlighted: PropTypes.bool.isRequired, | ||
|
||
size: PropTypes.number.isRequired, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing JS doc. |
||
}; | ||
|
||
const EmojiPickerMenuItem = props => ( | ||
|
@@ -26,17 +28,25 @@ const EmojiPickerMenuItem = props => ( | |
pressed, | ||
}) => ([ | ||
styles.emojiItem, | ||
styles.pv1, | ||
getButtonBackgroundColorStyle(getButtonState(false, pressed)), | ||
props.isHighlighted ? styles.emojiItemHighlighted : {}, | ||
{ | ||
fontSize: props.size, | ||
}, | ||
])} | ||
> | ||
<Hoverable onHoverIn={props.onHover}> | ||
<Text style={styles.emojiText}>{props.emoji}</Text> | ||
<Text style={[styles.emojiText, { | ||
fontSize: props.size, | ||
}]} | ||
> | ||
{props.emoji} | ||
</Text> | ||
</Hoverable> | ||
</Pressable> | ||
|
||
); | ||
|
||
EmojiPickerMenuItem.propTypes = propTypes; | ||
EmojiPickerMenuItem.displayName = 'EmojiPickerMenuItem'; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's convert this to a single line if condition for consistency. Its weird seeing a mix of single and double line if statements when they have just 1 condition in them.