diff --git a/app/javascript/flavours/glitch/components/status.jsx b/app/javascript/flavours/glitch/components/status.jsx index 9339f3e4df..81cd30fd26 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -569,7 +569,7 @@ class Status extends ImmutablePureComponent { openProfile: this.handleHotkeyOpenProfile, moveUp: this.handleHotkeyMoveUp, moveDown: this.handleHotkeyMoveDown, - toggleSpoiler: this.handleExpandedToggle, + toggleHidden: this.handleExpandedToggle, bookmark: this.handleHotkeyBookmark, toggleCollapse: this.handleHotkeyCollapse, toggleSensitive: this.handleHotkeyToggleSensitive, diff --git a/app/javascript/flavours/glitch/features/list_adder/components/list.jsx b/app/javascript/flavours/glitch/features/list_adder/components/list.jsx index f99958fd27..c7a7d9c513 100644 --- a/app/javascript/flavours/glitch/features/list_adder/components/list.jsx +++ b/app/javascript/flavours/glitch/features/list_adder/components/list.jsx @@ -16,7 +16,7 @@ const messages = defineMessages({ add: { id: 'lists.account.add', defaultMessage: 'Add to list' }, }); -const mapStateToProps = (state, { listId, added }) => ({ +const MapStateToProps = (state, { listId, added }) => ({ list: state.get('lists').get(listId), added: typeof added === 'undefined' ? state.getIn(['listAdder', 'lists', 'items']).includes(listId) : added, }); @@ -69,4 +69,4 @@ class List extends ImmutablePureComponent { } -export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(List)); +export default connect(MapStateToProps, mapDispatchToProps)(injectIntl(List)); diff --git a/app/javascript/flavours/glitch/features/list_editor/components/account.jsx b/app/javascript/flavours/glitch/features/list_editor/components/account.jsx index 91a2bdb79d..4618bd1c16 100644 --- a/app/javascript/flavours/glitch/features/list_editor/components/account.jsx +++ b/app/javascript/flavours/glitch/features/list_editor/components/account.jsx @@ -1,20 +1,39 @@ import PropTypes from 'prop-types'; -import { defineMessages } from 'react-intl'; +import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; +import { removeFromListEditor, addToListEditor } from '../../../actions/lists'; import { Avatar } from '../../../components/avatar'; import { DisplayName } from '../../../components/display_name'; import { IconButton } from '../../../components/icon_button'; +import { makeGetAccount } from '../../../selectors'; const messages = defineMessages({ remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' }, add: { id: 'lists.account.add', defaultMessage: 'Add to list' }, }); -export default class Account extends ImmutablePureComponent { +const makeMapStateToProps = () => { + const getAccount = makeGetAccount(); + + const mapStateToProps = (state, { accountId, added }) => ({ + account: getAccount(state, accountId), + added: typeof added === 'undefined' ? state.getIn(['listEditor', 'accounts', 'items']).includes(accountId) : added, + }); + + return mapStateToProps; +}; + +const mapDispatchToProps = (dispatch, { accountId }) => ({ + onRemove: () => dispatch(removeFromListEditor(accountId)), + onAdd: () => dispatch(addToListEditor(accountId)), +}); + +class Account extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map.isRequired, @@ -56,3 +75,5 @@ export default class Account extends ImmutablePureComponent { } } + +export default connect(makeMapStateToProps, mapDispatchToProps)(injectIntl(Account)); diff --git a/app/javascript/flavours/glitch/features/list_editor/components/search.jsx b/app/javascript/flavours/glitch/features/list_editor/components/search.jsx index 43c0358ba6..5434ba0dcb 100644 --- a/app/javascript/flavours/glitch/features/list_editor/components/search.jsx +++ b/app/javascript/flavours/glitch/features/list_editor/components/search.jsx @@ -1,17 +1,31 @@ import PropTypes from 'prop-types'; import { PureComponent } from 'react'; -import { defineMessages } from 'react-intl'; +import { defineMessages, injectIntl } from 'react-intl'; import classNames from 'classnames'; +import { connect } from 'react-redux'; + import { Icon } from 'flavours/glitch/components/icon'; +import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists'; + const messages = defineMessages({ search: { id: 'lists.search', defaultMessage: 'Search among people you follow' }, }); -export default class Search extends PureComponent { +const mapStateToProps = state => ({ + value: state.getIn(['listEditor', 'suggestions', 'value']), +}); + +const mapDispatchToProps = dispatch => ({ + onSubmit: value => dispatch(fetchListSuggestions(value)), + onClear: () => dispatch(clearListSuggestions()), + onChange: value => dispatch(changeListSuggestions(value)), +}); + +class Search extends PureComponent { static propTypes = { intl: PropTypes.object.isRequired, @@ -63,3 +77,5 @@ export default class Search extends PureComponent { } } + +export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(Search)); diff --git a/app/javascript/flavours/glitch/features/list_editor/containers/account_container.js b/app/javascript/flavours/glitch/features/list_editor/containers/account_container.js deleted file mode 100644 index 329a1dcb91..0000000000 --- a/app/javascript/flavours/glitch/features/list_editor/containers/account_container.js +++ /dev/null @@ -1,26 +0,0 @@ -import { injectIntl } from 'react-intl'; - -import { connect } from 'react-redux'; - -import { removeFromListEditor, addToListEditor } from 'flavours/glitch/actions/lists'; -import { makeGetAccount } from 'flavours/glitch/selectors'; - -import Account from '../components/account'; - -const makeMapStateToProps = () => { - const getAccount = makeGetAccount(); - - const mapStateToProps = (state, { accountId, added }) => ({ - account: getAccount(state, accountId), - added: typeof added === 'undefined' ? state.getIn(['listEditor', 'accounts', 'items']).includes(accountId) : added, - }); - - return mapStateToProps; -}; - -const mapDispatchToProps = (dispatch, { accountId }) => ({ - onRemove: () => dispatch(removeFromListEditor(accountId)), - onAdd: () => dispatch(addToListEditor(accountId)), -}); - -export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Account)); diff --git a/app/javascript/flavours/glitch/features/list_editor/containers/search_container.js b/app/javascript/flavours/glitch/features/list_editor/containers/search_container.js deleted file mode 100644 index a7f0009a84..0000000000 --- a/app/javascript/flavours/glitch/features/list_editor/containers/search_container.js +++ /dev/null @@ -1,18 +0,0 @@ -import { injectIntl } from 'react-intl'; - -import { connect } from 'react-redux'; - -import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists'; -import Search from '../components/search'; - -const mapStateToProps = state => ({ - value: state.getIn(['listEditor', 'suggestions', 'value']), -}); - -const mapDispatchToProps = dispatch => ({ - onSubmit: value => dispatch(fetchListSuggestions(value)), - onClear: () => dispatch(clearListSuggestions()), - onChange: value => dispatch(changeListSuggestions(value)), -}); - -export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Search)); diff --git a/app/javascript/flavours/glitch/features/list_editor/index.jsx b/app/javascript/flavours/glitch/features/list_editor/index.jsx index dca690a3ec..85e90169e8 100644 --- a/app/javascript/flavours/glitch/features/list_editor/index.jsx +++ b/app/javascript/flavours/glitch/features/list_editor/index.jsx @@ -11,10 +11,9 @@ import spring from 'react-motion/lib/spring'; import { setupListEditor, clearListSuggestions, resetListEditor } from '../../actions/lists'; import Motion from '../ui/util/optional_motion'; +import Account from './components/account'; import EditListForm from './components/edit_list_form'; -import AccountContainer from './containers/account_container'; -import SearchContainer from './containers/search_container'; - +import Search from './components/search'; const mapStateToProps = state => ({ accountIds: state.getIn(['listEditor', 'accounts', 'items']), @@ -58,21 +57,21 @@ class ListEditor extends ImmutablePureComponent {
- +
- {accountIds.map(accountId => )} + {accountIds.map(accountId => )}
{showSearch &&
} - {({ x }) => - (
- {searchAccountIds.map(accountId => )} -
) - } + {({ x }) => ( +
+ {searchAccountIds.map(accountId => )} +
+ )}
diff --git a/app/javascript/flavours/glitch/features/notifications/components/clear_column_button.jsx b/app/javascript/flavours/glitch/features/notifications/components/clear_column_button.jsx index c75bdf8ad4..0bbfca7831 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/clear_column_button.jsx +++ b/app/javascript/flavours/glitch/features/notifications/components/clear_column_button.jsx @@ -1,11 +1,11 @@ import PropTypes from 'prop-types'; -import { Component } from 'react'; +import { PureComponent } from 'react'; import { FormattedMessage } from 'react-intl'; import { Icon } from 'flavours/glitch/components/icon'; -export default class ClearColumnButton extends Component { +export default class ClearColumnButton extends PureComponent { static propTypes = { onClick: PropTypes.func.isRequired, diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index 1063b5c22b..266c974c4e 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -711,7 +711,7 @@ class Status extends ImmutablePureComponent { bookmark: this.handleHotkeyBookmark, mention: this.handleHotkeyMention, openProfile: this.handleHotkeyOpenProfile, - toggleSpoiler: this.handleToggleHidden, + toggleHidden: this.handleToggleHidden, toggleSensitive: this.handleHotkeyToggleSensitive, openMedia: this.handleHotkeyOpenMedia, }; diff --git a/app/javascript/flavours/glitch/features/ui/components/bundle.jsx b/app/javascript/flavours/glitch/features/ui/components/bundle.jsx index ccbb565fbf..15c4220b34 100644 --- a/app/javascript/flavours/glitch/features/ui/components/bundle.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/bundle.jsx @@ -1,10 +1,10 @@ import PropTypes from 'prop-types'; -import { Component } from 'react'; +import { PureComponent } from 'react'; const emptyComponent = () => null; const noop = () => { }; -class Bundle extends Component { +class Bundle extends PureComponent { static propTypes = { fetchComponent: PropTypes.func.isRequired, @@ -26,7 +26,7 @@ class Bundle extends Component { onFetchFail: noop, }; - static cache = {}; + static cache = new Map; state = { mod: undefined, @@ -51,6 +51,7 @@ class Bundle extends Component { load = (props) => { const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props; + const cachedMod = Bundle.cache.get(fetchComponent); if (fetchComponent === undefined) { this.setState({ mod: null }); @@ -59,10 +60,8 @@ class Bundle extends Component { onFetch(); - if (Bundle.cache[fetchComponent.name]) { - const mod = Bundle.cache[fetchComponent.name]; - - this.setState({ mod: mod.default }); + if (cachedMod) { + this.setState({ mod: cachedMod.default }); onFetchSuccess(); return Promise.resolve(); } @@ -76,7 +75,7 @@ class Bundle extends Component { return fetchComponent() .then((mod) => { - Bundle.cache[fetchComponent.name] = mod; + Bundle.cache.set(fetchComponent, mod); this.setState({ mod: mod.default }); onFetchSuccess(); }) diff --git a/app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx b/app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx index 1d792a2cfe..67dba3ce0c 100644 --- a/app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import { Component } from 'react'; +import { PureComponent } from 'react'; import { defineMessages, injectIntl } from 'react-intl'; @@ -11,7 +11,7 @@ const messages = defineMessages({ close: { id: 'bundle_modal_error.close', defaultMessage: 'Close' }, }); -class BundleModalError extends Component { +class BundleModalError extends PureComponent { static propTypes = { onRetry: PropTypes.func.isRequired, diff --git a/app/javascript/flavours/glitch/features/ui/components/media_modal.jsx b/app/javascript/flavours/glitch/features/ui/components/media_modal.jsx index d3d74136f1..676659c53d 100644 --- a/app/javascript/flavours/glitch/features/ui/components/media_modal.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/media_modal.jsx @@ -99,21 +99,6 @@ class MediaModal extends ImmutablePureComponent { this._sendBackgroundColor(); } - componentWillUnmount () { - window.removeEventListener('keydown', this.handleKeyDown); - this.props.onChangeBackgroundColor(null); - } - - getIndex () { - return this.state.index !== null ? this.state.index : this.props.index; - } - - toggleNavigation = () => { - this.setState(prevState => ({ - navigationHidden: !prevState.navigationHidden, - })); - }; - componentDidUpdate (prevProps, prevState) { if (prevState.index !== this.state.index) { this._sendBackgroundColor(); @@ -131,6 +116,22 @@ class MediaModal extends ImmutablePureComponent { } } + componentWillUnmount () { + window.removeEventListener('keydown', this.handleKeyDown); + + this.props.onChangeBackgroundColor(null); + } + + getIndex () { + return this.state.index !== null ? this.state.index : this.props.index; + } + + toggleNavigation = () => { + this.setState(prevState => ({ + navigationHidden: !prevState.navigationHidden, + })); + }; + render () { const { media, statusId, lang, intl, onClose } = this.props; const { navigationHidden } = this.state; diff --git a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx index 7b47e08234..40fea635a6 100644 --- a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx @@ -48,7 +48,7 @@ class NavigationPanel extends Component { return match || location.pathname.startsWith('/public'); }; - render() { + render () { const { intl, onOpenSettings } = this.props; const { signedIn, disabledAccountId } = this.context.identity; diff --git a/app/javascript/flavours/glitch/features/ui/components/upload_area.jsx b/app/javascript/flavours/glitch/features/ui/components/upload_area.jsx index 9aa8e359f8..b2702d35ef 100644 --- a/app/javascript/flavours/glitch/features/ui/components/upload_area.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/upload_area.jsx @@ -40,14 +40,14 @@ export default class UploadArea extends PureComponent { return ( - {({ backgroundOpacity, backgroundScale }) => - (
+ {({ backgroundOpacity, backgroundScale }) => ( +
-
) - } +
+ )} ); } diff --git a/app/javascript/flavours/glitch/features/ui/index.jsx b/app/javascript/flavours/glitch/features/ui/index.jsx index 48bba29b8a..fa943f579f 100644 --- a/app/javascript/flavours/glitch/features/ui/index.jsx +++ b/app/javascript/flavours/glitch/features/ui/index.jsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import { PureComponent, Component } from 'react'; +import { PureComponent } from 'react'; import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; @@ -68,9 +68,10 @@ import { PrivacyPolicy, } from './util/async-components'; import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers'; + // Dummy import, to make sure that ends up in the application bundle. // Without this it ends up in ~8 very commonly used bundles. -import "../../components/status"; +import '../../components/status'; const messages = defineMessages({ beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Mastodon.' }, @@ -119,7 +120,7 @@ const keyMap = { goToBlocked: 'g b', goToMuted: 'g m', goToRequests: 'g r', - toggleSpoiler: 'x', + toggleHidden: 'x', bookmark: 'd', toggleCollapse: 'shift+x', toggleSensitive: 'h', @@ -255,7 +256,7 @@ class SwitchingColumnsArea extends PureComponent { } -class UI extends Component { +class UI extends PureComponent { static contextTypes = { identity: PropTypes.object.isRequired, @@ -270,7 +271,6 @@ class UI extends Component { hasComposingText: PropTypes.bool, hasMediaAttachments: PropTypes.bool, canUploadMore: PropTypes.bool, - match: PropTypes.object.isRequired, intl: PropTypes.object.isRequired, dropdownMenuIsOpen: PropTypes.bool, unreadNotifications: PropTypes.number, @@ -287,7 +287,7 @@ class UI extends Component { draggingOver: false, }; - handleBeforeUnload = (e) => { + handleBeforeUnload = e => { const { intl, dispatch, hasComposingText, hasMediaAttachments } = this.props; dispatch(synchronouslySubmitMarkers()); @@ -300,6 +300,14 @@ class UI extends Component { } }; + handleVisibilityChange = () => { + const visibility = !document[this.visibilityHiddenProp]; + this.props.dispatch(notificationsSetVisibility(visibility)); + if (visibility) { + this.props.dispatch(submitMarkers({ immediate: true })); + } + }; + handleDragEnter = (e) => { e.preventDefault(); @@ -311,13 +319,14 @@ class UI extends Component { this.dragTargets.push(e.target); } - if (e.dataTransfer && e.dataTransfer.types.includes('Files') && this.props.canUploadMore && this.context.identity.signedIn) { + if (e.dataTransfer && Array.from(e.dataTransfer.types).includes('Files') && this.props.canUploadMore && this.context.identity.signedIn) { this.setState({ draggingOver: true }); } }; handleDragOver = (e) => { if (this.dataTransferIsText(e.dataTransfer)) return false; + e.preventDefault(); e.stopPropagation(); @@ -372,14 +381,6 @@ class UI extends Component { } }; - handleVisibilityChange = () => { - const visibility = !document[this.visibilityHiddenProp]; - this.props.dispatch(notificationsSetVisibility(visibility)); - if (visibility) { - this.props.dispatch(submitMarkers({ immediate: true })); - } - }; - handleLayoutChange = debounce(() => { this.props.dispatch(clearHeight()); // The cached heights are no longer accurate, invalidate }, 500, {