diff --git a/app/soapbox/components/column_header.js b/app/soapbox/components/column_header.js index 42f8eebb8..83a61b7ea 100644 --- a/app/soapbox/components/column_header.js +++ b/app/soapbox/components/column_header.js @@ -14,7 +14,6 @@ import SubNavigation from 'soapbox/components/sub_navigation'; // hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' }, // }); -export default @withRouter class ColumnHeader extends React.PureComponent { static propTypes = { @@ -126,3 +125,5 @@ class ColumnHeader extends React.PureComponent { // } } + +export default withRouter(ColumnHeader); \ No newline at end of file diff --git a/app/soapbox/components/filter_bar.js b/app/soapbox/components/filter_bar.js index 601ca04a2..2d6b71d9d 100644 --- a/app/soapbox/components/filter_bar.js +++ b/app/soapbox/components/filter_bar.js @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withRouter } from 'react-router-dom'; -export default @withRouter class FilterBar extends React.PureComponent { static propTypes = { @@ -153,3 +152,5 @@ class FilterBar extends React.PureComponent { } } + +export default withRouter(FilterBar); \ No newline at end of file diff --git a/app/soapbox/features/admin/user_index.js b/app/soapbox/features/admin/user_index.js index 213041f98..032ed6dc2 100644 --- a/app/soapbox/features/admin/user_index.js +++ b/app/soapbox/features/admin/user_index.js @@ -18,8 +18,6 @@ const messages = defineMessages({ searchPlaceholder: { id: 'admin.user_index.search_input_placeholder', defaultMessage: 'Who are you looking for?' }, }); -export default @connect() -@injectIntl class UserIndex extends ImmutablePureComponent { static propTypes = { @@ -130,3 +128,5 @@ class UserIndex extends ImmutablePureComponent { } } + +export default injectIntl(connect()(UserIndex)); \ No newline at end of file diff --git a/app/soapbox/features/community_timeline/components/column_settings.js b/app/soapbox/features/community_timeline/components/column_settings.js index 52781f1f4..a9d2b983a 100644 --- a/app/soapbox/features/community_timeline/components/column_settings.js +++ b/app/soapbox/features/community_timeline/components/column_settings.js @@ -11,7 +11,6 @@ const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, }); -export default @injectIntl class ColumnSettings extends React.PureComponent { static propTypes = { @@ -49,3 +48,5 @@ class ColumnSettings extends React.PureComponent { } } + +export default injectIntl(ColumnSettings); \ No newline at end of file diff --git a/app/soapbox/features/home_timeline/components/column_settings.js b/app/soapbox/features/home_timeline/components/column_settings.js index a643c7e17..aa335060d 100644 --- a/app/soapbox/features/home_timeline/components/column_settings.js +++ b/app/soapbox/features/home_timeline/components/column_settings.js @@ -11,7 +11,6 @@ const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, }); -export default @injectIntl class ColumnSettings extends React.PureComponent { static propTypes = { @@ -53,3 +52,5 @@ class ColumnSettings extends React.PureComponent { } } + +export default injectIntl(ColumnSettings); \ No newline at end of file diff --git a/app/soapbox/features/notifications/components/column_settings.js b/app/soapbox/features/notifications/components/column_settings.js index b71e8fa30..9656e67fc 100644 --- a/app/soapbox/features/notifications/components/column_settings.js +++ b/app/soapbox/features/notifications/components/column_settings.js @@ -13,7 +13,6 @@ const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, }); -export default @injectIntl class ColumnSettings extends React.PureComponent { static propTypes = { @@ -190,3 +189,5 @@ class ColumnSettings extends React.PureComponent { } } + +export default injectIntl(ColumnSettings); \ No newline at end of file diff --git a/app/soapbox/features/notifications/components/follow_request.js b/app/soapbox/features/notifications/components/follow_request.js index be781a948..6fa90b648 100644 --- a/app/soapbox/features/notifications/components/follow_request.js +++ b/app/soapbox/features/notifications/components/follow_request.js @@ -14,7 +14,6 @@ const messages = defineMessages({ reject: { id: 'follow_request.reject', defaultMessage: 'Reject' }, }); -export default @injectIntl class FollowRequest extends ImmutablePureComponent { static propTypes = { @@ -58,3 +57,5 @@ class FollowRequest extends ImmutablePureComponent { } } + +export default injectIntl(FollowRequest); \ No newline at end of file diff --git a/app/soapbox/features/public_timeline/components/column_settings.js b/app/soapbox/features/public_timeline/components/column_settings.js index 1d7022fa4..b9f2de6ae 100644 --- a/app/soapbox/features/public_timeline/components/column_settings.js +++ b/app/soapbox/features/public_timeline/components/column_settings.js @@ -11,7 +11,6 @@ const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, }); -export default @injectIntl class ColumnSettings extends React.PureComponent { static propTypes = { @@ -53,3 +52,5 @@ class ColumnSettings extends React.PureComponent { } } + +export default injectIntl(ColumnSettings); \ No newline at end of file diff --git a/app/soapbox/features/soapbox_config/components/icon-picker-menu.js b/app/soapbox/features/soapbox_config/components/icon-picker-menu.js new file mode 100644 index 000000000..c89b00488 --- /dev/null +++ b/app/soapbox/features/soapbox_config/components/icon-picker-menu.js @@ -0,0 +1,154 @@ +import classNames from 'clsx'; +import { supportsPassiveEvents } from 'detect-passive-events'; +import Picker from 'emoji-mart/dist-es/components/picker/picker'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; + +const messages = defineMessages({ + emoji: { id: 'icon_button.label', defaultMessage: 'Select icon' }, + emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search…' }, + emoji_not_found: { id: 'icon_button.not_found', defaultMessage: 'No icons!! (╯°□°)╯︵ ┻━┻' }, + custom: { id: 'icon_button.icons', defaultMessage: 'Icons' }, + search_results: { id: 'emoji_button.search_results', defaultMessage: 'Search results' }, +}); + +const backgroundImageFn = () => ''; +const listenerOptions = supportsPassiveEvents ? { passive: true } : false; + +const categoriesSort = ['custom']; + + +class IconPickerMenu extends React.PureComponent { + + static propTypes = { + custom_emojis: PropTypes.object, + loading: PropTypes.bool, + onClose: PropTypes.func.isRequired, + onPick: PropTypes.func.isRequired, + style: PropTypes.object, + placement: PropTypes.string, + arrowOffsetLeft: PropTypes.string, + arrowOffsetTop: PropTypes.string, + intl: PropTypes.object.isRequired, + }; + + static defaultProps = { + style: {}, + loading: true, + }; + + state = { + modifierOpen: false, + placement: null, + }; + + handleDocumentClick = e => { + if (this.node && !this.node.contains(e.target)) { + this.props.onClose(); + } + } + + componentDidMount() { + document.addEventListener('click', this.handleDocumentClick, false); + document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); + } + + componentWillUnmount() { + document.removeEventListener('click', this.handleDocumentClick, false); + document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); + } + + setRef = c => { + this.node = c; + + if (!c) return; + + // Nice and dirty hack to display the icons + c.querySelectorAll('button.emoji-mart-emoji > img').forEach(elem => { + const newIcon = document.createElement('span'); + newIcon.innerHTML = ``; + elem.parentNode.replaceChild(newIcon, elem); + }); + } + + getI18n = () => { + const { intl } = this.props; + + return { + search: intl.formatMessage(messages.emoji_search), + notfound: intl.formatMessage(messages.emoji_not_found), + categories: { + search: intl.formatMessage(messages.search_results), + custom: intl.formatMessage(messages.custom), + }, + }; + } + + handleClick = emoji => { + emoji.native = emoji.colons; + + this.props.onClose(); + this.props.onPick(emoji); + } + + buildIcons = (customEmojis, autoplay = false) => { + const emojis = []; + + Object.values(customEmojis).forEach(category => { + category.forEach(function(icon) { + const name = icon.replace('fa fa-', ''); + if (icon !== 'email' && icon !== 'memo') { + emojis.push({ + id: name, + name, + short_names: [name], + emoticons: [], + keywords: [name], + imageUrl: '', + }); + } + }); + }); + + return emojis; + }; + + render() { + const { loading, style, intl, custom_emojis } = this.props; + + if (loading) { + return
; + } + + const data = { compressed: true, categories: [], aliases: [], emojis: [] }; + const title = intl.formatMessage(messages.emoji); + const { modifierOpen } = this.state; + + return ( +