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.

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