summaryrefslogtreecommitdiffstats
path: root/webapp/components/emoji_picker
diff options
context:
space:
mode:
authorChris <ccbrown112@gmail.com>2017-07-25 11:47:03 -0700
committerHarrison Healey <harrisonmhealey@gmail.com>2017-07-25 14:47:03 -0400
commitd49419776de0811732db59eae90c5c6da223f076 (patch)
tree1b684895f37c6f91e239d1f3930c28a652fbcac4 /webapp/components/emoji_picker
parente5e450fc097c14110e942731018041cd1931aa25 (diff)
downloadchat-d49419776de0811732db59eae90c5c6da223f076.tar.gz
chat-d49419776de0811732db59eae90c5c6da223f076.tar.bz2
chat-d49419776de0811732db59eae90c5c6da223f076.zip
Refresh the emoji library (#7001)
* refresh the emoji library * fix img_trans.gif * compress sprite sheet * remove note on compression - webpack seems to handle compression decently * better emoji sheet preloading * requested changes
Diffstat (limited to 'webapp/components/emoji_picker')
-rw-r--r--webapp/components/emoji_picker/components/emoji_picker_item.jsx7
-rw-r--r--webapp/components/emoji_picker/components/emoji_picker_preview.jsx2
-rw-r--r--webapp/components/emoji_picker/emoji_picker.jsx140
3 files changed, 132 insertions, 17 deletions
diff --git a/webapp/components/emoji_picker/components/emoji_picker_item.jsx b/webapp/components/emoji_picker/components/emoji_picker_item.jsx
index 3321bf761..2854a637a 100644
--- a/webapp/components/emoji_picker/components/emoji_picker_item.jsx
+++ b/webapp/components/emoji_picker/components/emoji_picker_item.jsx
@@ -14,7 +14,8 @@ export default class EmojiPickerItem extends React.Component {
onItemOut: PropTypes.func.isRequired,
onItemClick: PropTypes.func.isRequired,
onItemUnmount: PropTypes.func.isRequired,
- category: PropTypes.string.isRequired
+ category: PropTypes.string.isRequired,
+ isLoaded: PropTypes.bool.isRequired
}
constructor(props) {
@@ -61,8 +62,8 @@ export default class EmojiPickerItem extends React.Component {
item =
(<div >
<img
- src='/static/emoji/img_trans.gif'
- className={' emojisprite emoji-' + this.props.emoji.filename + ' '}
+ src='/static/images/img_trans.gif'
+ className={' emojisprite' + (this.props.isLoaded ? '' : '-loading') + ' emoji-' + this.props.emoji.filename + ' '}
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
onClick={this.handleClick}
diff --git a/webapp/components/emoji_picker/components/emoji_picker_preview.jsx b/webapp/components/emoji_picker/components/emoji_picker_preview.jsx
index 914844551..b9f3f4262 100644
--- a/webapp/components/emoji_picker/components/emoji_picker_preview.jsx
+++ b/webapp/components/emoji_picker/components/emoji_picker_preview.jsx
@@ -27,7 +27,7 @@ export default class EmojiPickerPreview extends React.Component {
name = emoji.aliases[0];
aliases = emoji.aliases;
previewImage = (<span className='sprite-preview'><img
- src='/static/emoji/img_trans.gif'
+ src='/static/images/img_trans.gif'
className={' emojisprite-preview emoji-' + emoji.filename + ' '}
/></span>);
} else {
diff --git a/webapp/components/emoji_picker/emoji_picker.jsx b/webapp/components/emoji_picker/emoji_picker.jsx
index 0d9b34176..8b5375000 100644
--- a/webapp/components/emoji_picker/emoji_picker.jsx
+++ b/webapp/components/emoji_picker/emoji_picker.jsx
@@ -14,14 +14,23 @@ import EmojiPickerCategory from './components/emoji_picker_category.jsx';
import EmojiPickerItem from './components/emoji_picker_item.jsx';
import EmojiPickerPreview from './components/emoji_picker_preview.jsx';
+import PeopleSpriteSheet from 'images/emoji-sheets/people.png';
+import NatureSpriteSheet from 'images/emoji-sheets/nature.png';
+import FoodsSpriteSheet from 'images/emoji-sheets/foods.png';
+import ActivitySpriteSheet from 'images/emoji-sheets/activity.png';
+import PlacesSpriteSheet from 'images/emoji-sheets/places.png';
+import ObjectsSpriteSheet from 'images/emoji-sheets/objects.png';
+import SymbolsSpriteSheet from 'images/emoji-sheets/symbols.png';
+import FlagsSpriteSheet from 'images/emoji-sheets/flags.png';
+
// This should include all the categories available in Emoji.CategoryNames
const CATEGORIES = [
'recent',
'people',
'nature',
- 'food',
+ 'foods',
'activity',
- 'travel',
+ 'places',
'objects',
'symbols',
'flags',
@@ -49,6 +58,7 @@ export default class EmojiPicker extends React.Component {
// All props are primitives or treated as immutable
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
+ this.handlePreload = this.handlePreload.bind(this);
this.handleCategoryClick = this.handleCategoryClick.bind(this);
this.handleFilterChange = this.handleFilterChange.bind(this);
this.handleItemOver = this.handleItemOver.bind(this);
@@ -61,7 +71,8 @@ export default class EmojiPicker extends React.Component {
this.state = {
category: 'recent',
filter: '',
- selected: null
+ selected: null,
+ preloaded: []
};
}
@@ -71,6 +82,23 @@ export default class EmojiPicker extends React.Component {
requestAnimationFrame(() => {
this.searchInput.focus();
});
+ beginPreloading();
+ subscribeToPreloads(this.handlePreload);
+ this.handlePreload();
+ }
+
+ componentWillUnmount() {
+ unsubscribeFromPreloads(this.handlePreload);
+ }
+
+ handlePreload() {
+ const preloaded = [];
+ for (const category of CATEGORIES) {
+ if (didPreloadCategory(category)) {
+ preloaded.push(category);
+ }
+ }
+ this.setState({preloaded});
}
handleCategoryClick(category) {
@@ -139,7 +167,8 @@ export default class EmojiPicker extends React.Component {
}
}
}
- renderCategory(category, filter) {
+
+ renderCategory(category, isLoaded, filter) {
const items = [];
let indices = [];
let recentEmojis = [];
@@ -181,6 +210,7 @@ export default class EmojiPicker extends React.Component {
key={'system_' + (category === 'recent' ? 'recent_' : '') + (emoji.name || emoji.aliases[0])}
emoji={emoji}
category={category}
+ isLoaded={isLoaded}
onItemOver={this.handleItemOver}
onItemOut={this.handleItemOut}
onItemClick={this.handleItemClick}
@@ -261,7 +291,7 @@ export default class EmojiPicker extends React.Component {
previewImage = (
<span>
<img
- src='/static/emoji/img_trans.gif'
+ src='/static/images/img_trans.gif'
className={' emojisprite-preview emoji-' + selected.filename + ' '}
align='absmiddle'
/>
@@ -293,9 +323,9 @@ export default class EmojiPicker extends React.Component {
for (const category of CATEGORIES) {
if (category === 'custom') {
- items.push(this.renderCategory('custom', this.state.filter, this.props.customEmojis));
+ items.push(this.renderCategory('custom', true, this.state.filter, this.props.customEmojis));
} else {
- items.push(this.renderCategory(category, this.state.filter));
+ items.push(this.renderCategory(category, category === 'recent' || this.state.preloaded.indexOf(category) >= 0, this.state.filter));
}
}
@@ -357,15 +387,15 @@ export default class EmojiPicker extends React.Component {
selected={this.state.category === 'nature'}
/>
<EmojiPickerCategory
- category='food'
+ category='foods'
icon={
<i
className='fa fa-cutlery'
- title={Utils.localizeMessage('emoji_picker.food', 'Food')}
+ title={Utils.localizeMessage('emoji_picker.foods', 'Foods')}
/>
}
onCategoryClick={this.handleCategoryClick}
- selected={this.state.category === 'food'}
+ selected={this.state.category === 'foods'}
/>
<EmojiPickerCategory
category='activity'
@@ -379,15 +409,15 @@ export default class EmojiPicker extends React.Component {
selected={this.state.category === 'activity'}
/>
<EmojiPickerCategory
- category='travel'
+ category='places'
icon={
<i
className='fa fa-plane'
- title={Utils.localizeMessage('emoji_picker.travel', 'Travel')}
+ title={Utils.localizeMessage('emoji_picker.places', 'Places')}
/>
}
onCategoryClick={this.handleCategoryClick}
- selected={this.state.category === 'travel'}
+ selected={this.state.category === 'places'}
/>
<EmojiPickerCategory
category='objects'
@@ -459,3 +489,87 @@ export default class EmojiPicker extends React.Component {
);
}
}
+
+var preloads = {
+ people: {
+ src: PeopleSpriteSheet,
+ didPreload: false
+ },
+ nature: {
+ src: NatureSpriteSheet,
+ didPreload: false
+ },
+ foods: {
+ src: FoodsSpriteSheet,
+ didPreload: false
+ },
+ activity: {
+ src: ActivitySpriteSheet,
+ didPreload: false
+ },
+ places: {
+ src: PlacesSpriteSheet,
+ didPreload: false
+ },
+ objects: {
+ src: ObjectsSpriteSheet,
+ didPreload: false
+ },
+ symbols: {
+ src: SymbolsSpriteSheet,
+ didPreload: false
+ },
+ flags: {
+ src: FlagsSpriteSheet,
+ didPreload: false
+ }
+};
+
+var didBeginPreloading = false;
+
+var preloadCallback = null;
+
+export function beginPreloading() {
+ if (didBeginPreloading) {
+ return;
+ }
+ didBeginPreloading = true;
+ preloadNextCategory();
+}
+
+function preloadNextCategory() {
+ let sheet = null;
+ for (const category of CATEGORIES) {
+ const preload = preloads[category];
+ if (preload && !preload.didPreload) {
+ sheet = preload;
+ break;
+ }
+ }
+ if (sheet) {
+ const img = new Image();
+ img.onload = () => {
+ sheet.didPreload = true;
+ if (preloadCallback) {
+ preloadCallback();
+ }
+ preloadNextCategory();
+ };
+ img.src = sheet.src;
+ }
+}
+
+export function didPreloadCategory(category) {
+ const preload = preloads[category];
+ return preload && preload.didPreload;
+}
+
+function subscribeToPreloads(callback) {
+ preloadCallback = callback;
+}
+
+function unsubscribeFromPreloads(callback) {
+ if (callback === preloadCallback) {
+ preloadCallback = null;
+ }
+}