You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.7 KiB

  1. import React from 'react';
  2. import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown';
  3. import PropTypes from 'prop-types';
  4. import { defineMessages, injectIntl } from 'react-intl';
  5. const messages = defineMessages({
  6. emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
  7. emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search...' },
  8. people: { id: 'emoji_button.people', defaultMessage: 'People' },
  9. nature: { id: 'emoji_button.nature', defaultMessage: 'Nature' },
  10. food: { id: 'emoji_button.food', defaultMessage: 'Food & Drink' },
  11. activity: { id: 'emoji_button.activity', defaultMessage: 'Activity' },
  12. travel: { id: 'emoji_button.travel', defaultMessage: 'Travel & Places' },
  13. objects: { id: 'emoji_button.objects', defaultMessage: 'Objects' },
  14. symbols: { id: 'emoji_button.symbols', defaultMessage: 'Symbols' },
  15. flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' },
  16. });
  17. const settings = {
  18. imageType: 'png',
  19. sprites: false,
  20. imagePathPNG: '/emoji/',
  21. };
  22. let EmojiPicker; // load asynchronously
  23. @injectIntl
  24. export default class EmojiPickerDropdown extends React.PureComponent {
  25. static propTypes = {
  26. intl: PropTypes.object.isRequired,
  27. onPickEmoji: PropTypes.func.isRequired,
  28. };
  29. state = {
  30. active: false,
  31. loading: false,
  32. };
  33. setRef = (c) => {
  34. this.dropdown = c;
  35. }
  36. handleChange = (data) => {
  37. this.dropdown.hide();
  38. this.props.onPickEmoji(data);
  39. }
  40. onShowDropdown = () => {
  41. this.setState({ active: true });
  42. if (!EmojiPicker) {
  43. this.setState({ loading: true });
  44. import(/* webpackChunkName: "emojione_picker" */ 'emojione-picker').then(TheEmojiPicker => {
  45. EmojiPicker = TheEmojiPicker.default;
  46. this.setState({ loading: false });
  47. }).catch(() => {
  48. // TODO: show the user an error?
  49. this.setState({ loading: false });
  50. });
  51. }
  52. }
  53. onHideDropdown = () => {
  54. this.setState({ active: false });
  55. }
  56. render () {
  57. const { intl } = this.props;
  58. const categories = {
  59. people: {
  60. title: intl.formatMessage(messages.people),
  61. emoji: 'smile',
  62. },
  63. nature: {
  64. title: intl.formatMessage(messages.nature),
  65. emoji: 'hamster',
  66. },
  67. food: {
  68. title: intl.formatMessage(messages.food),
  69. emoji: 'pizza',
  70. },
  71. activity: {
  72. title: intl.formatMessage(messages.activity),
  73. emoji: 'soccer',
  74. },
  75. travel: {
  76. title: intl.formatMessage(messages.travel),
  77. emoji: 'earth_americas',
  78. },
  79. objects: {
  80. title: intl.formatMessage(messages.objects),
  81. emoji: 'bulb',
  82. },
  83. symbols: {
  84. title: intl.formatMessage(messages.symbols),
  85. emoji: 'clock9',
  86. },
  87. flags: {
  88. title: intl.formatMessage(messages.flags),
  89. emoji: 'flag_gb',
  90. },
  91. };
  92. const { active, loading } = this.state;
  93. return (
  94. <Dropdown ref={this.setRef} className='emoji-picker__dropdown' onShow={this.onShowDropdown} onHide={this.onHideDropdown}>
  95. <DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)}>
  96. <img
  97. draggable='false'
  98. className={`emojione ${active && loading ? 'pulse-loading' : ''}`}
  99. alt='🙂' src='/emoji/1f602.svg'
  100. />
  101. </DropdownTrigger>
  102. <DropdownContent className='dropdown__left'>
  103. {
  104. this.state.active && !this.state.loading &&
  105. (<EmojiPicker emojione={settings} onChange={this.handleChange} searchPlaceholder={intl.formatMessage(messages.emoji_search)} categories={categories} search />)
  106. }
  107. </DropdownContent>
  108. </Dropdown>
  109. );
  110. }
  111. }