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 ( +
+ +
+ ); + } + +} + +export default injectIntl(IconPickerMenu); diff --git a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js index cc2986a7b..5393f0dc8 100644 --- a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js +++ b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js @@ -1,6 +1,3 @@ -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'; @@ -8,153 +5,12 @@ import Overlay from 'react-overlays/lib/Overlay'; import Icon from 'soapbox/components/icon'; +import IconPickerMenu from './icon-picker-menu'; + 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']; - -@injectIntl -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 ( -
- -
- ); - } - -} - -export default @injectIntl class IconPickerDropdown extends React.PureComponent { static propTypes = { @@ -243,3 +99,5 @@ class IconPickerDropdown extends React.PureComponent { } } + +export default injectIntl(IconPickerDropdown); \ No newline at end of file diff --git a/babel.config.js b/babel.config.js index 17af1a21c..f999f83ef 100644 --- a/babel.config.js +++ b/babel.config.js @@ -17,7 +17,6 @@ module.exports = (api) => { plugins: [ '@babel/syntax-dynamic-import', ['@babel/proposal-object-rest-spread', { useBuiltIns: true }], - ['@babel/proposal-decorators', { legacy: true }], '@babel/proposal-class-properties', ['react-intl', { messagesDir: './build/messages/' }], 'preval', diff --git a/package.json b/package.json index 2d25a828b..5c4491321 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "dependencies": { "@babel/core": "^7.18.2", "@babel/plugin-proposal-class-properties": "^7.17.12", - "@babel/plugin-proposal-decorators": "^7.18.2", "@babel/plugin-proposal-object-rest-spread": "^7.18.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-react-inline-elements": "^7.16.7", diff --git a/tsconfig.json b/tsconfig.json index 04ec4a470..c47b1a33f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,6 @@ "allowJs": true, "moduleResolution": "node", "resolveJsonModule": true, - "experimentalDecorators": true, "esModuleInterop": true, "typeRoots": [ "./types", "./node_modules/@types"] }, diff --git a/yarn.lock b/yarn.lock index 423516f95..2b4a3a0cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -538,18 +538,6 @@ "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-decorators@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.2.tgz#dbe4086d2d42db489399783c3aa9272e9700afd4" - integrity sha512-kbDISufFOxeczi0v4NQP3p5kIeW6izn/6klfWBrIIdGZZe4UpHR+QU03FAoWjGGd9SUXAwbw2pup1kaL4OQsJQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.0" - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/helper-replace-supers" "^7.18.2" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/plugin-syntax-decorators" "^7.17.12" - charcodes "^0.2.0" - "@babel/plugin-proposal-dynamic-import@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" @@ -688,13 +676,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-decorators@^7.17.12": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.12.tgz#02e8f678602f0af8222235271efea945cfdb018a" - integrity sha512-D1Hz0qtGTza8K2xGyEdVNCYLdVHukAcbQr4K3/s6r/esadyEriZovpJimQOpu8ju4/jV8dW/1xdaE0UpDroidw== - dependencies: - "@babel/helper-plugin-utils" "^7.17.12" - "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -4196,11 +4177,6 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -charcodes@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4" - integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ== - cheerio-select@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823"