Skip to content
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

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/pages/home/report/EmojiPickerMenu/dynamicEmojiSize.js
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
Copy link
Contributor

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.

) {
return styleVariables.fontSizeNormal;
}

return styleVariables.fontSizeLarge;
};

export default dynamicEmojiSize;
17 changes: 16 additions & 1 deletion src/pages/home/report/EmojiPickerMenu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -72,6 +73,7 @@ class EmojiPickerMenu extends Component {
headerIndices: this.unfilteredHeaderIndices,
highlightedIndex: -1,
arePointerEventsDisabled: false,
emojiSize: dynamicEmojiSize(this.props.windowWidth),
};
}

Expand All @@ -86,6 +88,18 @@ class EmojiPickerMenu extends Component {
this.setupEventHandlers();
}


componentDidUpdate(prevProps) {
if (
this.props.windowWidth !== prevProps.windowWidth
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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 setDynamicEmojiSize and call that method here that would do,

this.setState({emojiSize: dynamicEmojiSize(this.props.windowWidth)});

Then you wouldn't need to disable the eslint rule.

this.setState({
emojiSize: dynamicEmojiSize(this.props.windowWidth),
});
}
}

componentWillUnmount() {
this.cleanupEventHandlers();
}
Expand Down Expand Up @@ -302,6 +316,7 @@ class EmojiPickerMenu extends Component {
onHover={() => this.setState({highlightedIndex: index})}
emoji={code}
isHighlighted={index === this.state.highlightedIndex}
size={this.state.emojiSize}
/>
);
}
Expand Down Expand Up @@ -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}
/>
Expand Down
25 changes: 24 additions & 1 deletion src/pages/home/report/EmojiPickerMenu/index.native.js
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,
Copy link
Contributor

Choose a reason for hiding this comment

The 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 {
Expand All @@ -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),
};
Copy link
Contributor

Choose a reason for hiding this comment

The 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.
How about if you just did,

emojiSize={fontSize: dynamicEmojiSize(this.props.windowWidth)}

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.
And adding it to the state doesn't create any overhead.

We can remove it from the state and make it a normal class property.

- this.state.emojiSize
+ this.emojiSize

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

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 👍
Could you update?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Copy link
Contributor

@chiragsalian chiragsalian Jun 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment as here

this.setState({
emojiSize: dynamicEmojiSize(this.props.windowWidth),
});
}
}


Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand All @@ -56,6 +77,7 @@ class EmojiPickerMenu extends Component {
<EmojiPickerMenuItem
onPress={this.props.onEmojiSelected}
emoji={item.code}
size={this.state.emojiSize}
/>
);
}
Expand All @@ -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>
Expand All @@ -78,4 +101,4 @@ class EmojiPickerMenu extends Component {

EmojiPickerMenu.propTypes = propTypes;

export default EmojiPickerMenu;
export default compose(withWindowDimensions)(EmojiPickerMenu);
14 changes: 12 additions & 2 deletions src/pages/home/report/EmojiPickerMenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const propTypes = {

/** Whether this menu item is currently highlighted or not */
isHighlighted: PropTypes.bool.isRequired,

size: PropTypes.number.isRequired,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing JS doc.

};

const EmojiPickerMenuItem = props => (
Expand All @@ -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';

Expand Down
10 changes: 8 additions & 2 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -909,15 +909,21 @@ const styles = {
// Emoji Picker Styles
emojiText: {
fontFamily: fontFamily.GTA_BOLD,
fontSize: variables.iconSizeLarge,
textAlign: 'center',
...spacing.pv1,
...spacing.ph2,
},

emojiExtraSmall: {
fontSize: variables.iconSizeExtraSmall,
},

emojiLarge: {
fontSize: variables.iconSizeLarge,
},

emojiItem: {
width: '12.5%',
height: 40,
textAlign: 'center',
borderRadius: 8,
},
Expand Down