闭社主体 forked from https://github.com/tootsuite/mastodon
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.

125 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. class EmojiPickerDropdown extends React.PureComponent {
  24. static propTypes = {
  25. intl: PropTypes.object.isRequired,
  26. onPickEmoji: PropTypes.func.isRequired,
  27. };
  28. state = {
  29. active: false,
  30. loading: false,
  31. };
  32. setRef = (c) => {
  33. this.dropdown = c;
  34. }
  35. handleChange = (data) => {
  36. this.dropdown.hide();
  37. this.props.onPickEmoji(data);
  38. }
  39. onShowDropdown = () => {
  40. this.setState({active: true});
  41. if (!EmojiPicker) {
  42. this.setState({loading: true});
  43. import(/* webpackChunkName: "emojione_picker" */ 'emojione-picker').then(TheEmojiPicker => {
  44. EmojiPicker = TheEmojiPicker.default;
  45. this.setState({loading: false});
  46. }).catch(err => {
  47. // TODO: show the user an error?
  48. this.setState({loading: false});
  49. });
  50. }
  51. }
  52. onHideDropdown = () => {
  53. this.setState({active: false});
  54. }
  55. render () {
  56. const { intl } = this.props;
  57. const categories = {
  58. people: {
  59. title: intl.formatMessage(messages.people),
  60. emoji: 'smile',
  61. },
  62. nature: {
  63. title: intl.formatMessage(messages.nature),
  64. emoji: 'hamster',
  65. },
  66. food: {
  67. title: intl.formatMessage(messages.food),
  68. emoji: 'pizza',
  69. },
  70. activity: {
  71. title: intl.formatMessage(messages.activity),
  72. emoji: 'soccer',
  73. },
  74. travel: {
  75. title: intl.formatMessage(messages.travel),
  76. emoji: 'earth_americas',
  77. },
  78. objects: {
  79. title: intl.formatMessage(messages.objects),
  80. emoji: 'bulb',
  81. },
  82. symbols: {
  83. title: intl.formatMessage(messages.symbols),
  84. emoji: 'clock9',
  85. },
  86. flags: {
  87. title: intl.formatMessage(messages.flags),
  88. emoji: 'flag_gb',
  89. },
  90. };
  91. const { active, loading } = this.state;
  92. return (
  93. <Dropdown ref={this.setRef} className='emoji-picker__dropdown' onShow={this.onShowDropdown} onHide={this.onHideDropdown}>
  94. <DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)}>
  95. <img draggable="false"
  96. className={`emojione ${active && loading ? "pulse-loading" : ''}`}
  97. alt="🙂" src="/emoji/1f602.svg" />
  98. </DropdownTrigger>
  99. <DropdownContent className='dropdown__left'>
  100. {
  101. this.state.active && !this.state.loading &&
  102. (<EmojiPicker emojione={settings} onChange={this.handleChange} searchPlaceholder={intl.formatMessage(messages.emoji_search)} categories={categories} search={true} />)
  103. }
  104. </DropdownContent>
  105. </Dropdown>
  106. );
  107. }
  108. }
  109. export default injectIntl(EmojiPickerDropdown);