diff options
author | Nolan Lawson <nolan@nolanlawson.com> | 2017-05-06 17:42:38 -0700 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2017-05-07 02:42:38 +0200 |
commit | df81bc4a9745288d2eb1f6a924ceb9b79017b04f (patch) | |
tree | a793f9a124247a6ecf66562ce20bb69445cb8408 /app/javascript | |
parent | 87588fa8947c137de1ab75d740318ffc2dfffbbf (diff) |
add asynchronous emojione-picker (code-splitting) (#2863)
Diffstat (limited to 'app/javascript')
-rw-r--r-- | app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js | 41 | ||||
-rw-r--r-- | app/javascript/styles/components.scss | 14 |
2 files changed, 50 insertions, 5 deletions
diff --git a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js index 3e0b290d6..c95b4a279 100644 --- a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js @@ -1,6 +1,5 @@ import React from 'react'; import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown'; -import EmojiPicker from 'emojione-picker'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; @@ -37,12 +36,20 @@ const dropdownTriggerStyle = { width: '24px' } +let EmojiPicker; // load asynchronously + class EmojiPickerDropdown extends React.PureComponent { constructor (props, context) { super(props, context); this.setRef = this.setRef.bind(this); this.handleChange = this.handleChange.bind(this); + this.onHideDropdown = this.onHideDropdown.bind(this); + this.onShowDropdown = this.onShowDropdown.bind(this); + this.state = { + active: false, + loading: false + }; } setRef (c) { @@ -54,6 +61,24 @@ class EmojiPickerDropdown extends React.PureComponent { this.props.onPickEmoji(data); } + onShowDropdown () { + this.setState({active: true}); + if (!EmojiPicker) { + this.setState({loading: true}); + import('emojione-picker').then(TheEmojiPicker => { + EmojiPicker = TheEmojiPicker.default; + this.setState({loading: false}); + }).catch(err => { + // TODO: show the user an error? + this.setState({loading: false}); + }); + } + } + + onHideDropdown () { + this.setState({active: false}); + } + render () { const { intl } = this.props; @@ -92,14 +117,20 @@ class EmojiPickerDropdown extends React.PureComponent { } } + const { active, loading } = this.state; + return ( - <Dropdown ref={this.setRef} style={dropdownStyle}> + <Dropdown ref={this.setRef} style={dropdownStyle} onShow={this.onShowDropdown} onHide={this.onHideDropdown}> <DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)} style={dropdownTriggerStyle}> - <img draggable="false" className="emojione" alt="🙂" src="/emoji/1f602.svg" /> + <img draggable="false" + className={`emojione ${active && loading ? "pulse-loading" : ''}`} + alt="🙂" src="/emoji/1f602.svg" /> </DropdownTrigger> - <DropdownContent className='dropdown__left'> - <EmojiPicker emojione={settings} onChange={this.handleChange} searchPlaceholder={intl.formatMessage(messages.emoji_search)} categories={categories} search={true} /> + { + this.state.active && !this.state.loading && + (<EmojiPicker emojione={settings} onChange={this.handleChange} searchPlaceholder={intl.formatMessage(messages.emoji_search)} categories={categories} search={true} />) + } </DropdownContent> </Dropdown> ); diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss index 93a3d7046..f2d6f988c 100644 --- a/app/javascript/styles/components.scss +++ b/app/javascript/styles/components.scss @@ -2141,6 +2141,20 @@ button.icon-button.active i.fa-retweet { background: radial-gradient(ellipse, rgba($color4, 0.23) 0%, rgba($color4, 0) 60%); } +@keyframes pulse { + 0% { + opacity: 1; + } + 100% { + opacity: 0.5; + } +} + +.pulse-loading { + animation: pulse 1s ease-in-out infinite; + animation-direction: alternate; +} + .emoji-dialog { width: 245px; height: 270px; |