From b0477ac1e1f356fa459b5ef4d3606c735d037c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 7 Jan 2022 00:41:07 +0100 Subject: [PATCH] fix broken modals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/actions/modal.js | 3 ++- app/soapbox/components/modal_root.js | 5 ++++- .../ui/components/favourites_modal.js | 19 +++++++++++++++++-- .../features/ui/components/mentions_modal.js | 19 +++++++++++++++++-- .../features/ui/components/modal_root.js | 9 +++++---- .../features/ui/components/reactions_modal.js | 19 +++++++++++++++++-- .../features/ui/components/reblogs_modal.js | 19 +++++++++++++++++-- .../features/ui/containers/modal_container.js | 5 +++-- app/soapbox/reducers/__tests__/modal-test.js | 3 +++ app/soapbox/reducers/modal.js | 8 +++++++- 10 files changed, 92 insertions(+), 17 deletions(-) diff --git a/app/soapbox/actions/modal.js b/app/soapbox/actions/modal.js index 72604ecc6..8c0eed922 100644 --- a/app/soapbox/actions/modal.js +++ b/app/soapbox/actions/modal.js @@ -9,9 +9,10 @@ export function openModal(type, props) { }; } -export function closeModal(type) { +export function closeModal(type, noPop) { return { type: MODAL_CLOSE, modalType: type, + noPop, }; } diff --git a/app/soapbox/components/modal_root.js b/app/soapbox/components/modal_root.js index 1ee69a7de..53e4dc01b 100644 --- a/app/soapbox/components/modal_root.js +++ b/app/soapbox/components/modal_root.js @@ -45,6 +45,7 @@ class ModalRoot extends React.PureComponent { hasComposeContent: PropTypes.bool, type: PropTypes.string, onCancel: PropTypes.func, + noPop: PropTypes.bool, }; state = { @@ -120,7 +121,9 @@ class ModalRoot extends React.PureComponent { this.activeElement = null; this.getSiblings().forEach(sibling => sibling.removeAttribute('inert')); - this._handleModalClose(); + if (!this.props.noPop) { + this._handleModalClose(); + } } if (this.props.children) { diff --git a/app/soapbox/features/ui/components/favourites_modal.js b/app/soapbox/features/ui/components/favourites_modal.js index f0cf51965..e81a251e2 100644 --- a/app/soapbox/features/ui/components/favourites_modal.js +++ b/app/soapbox/features/ui/components/favourites_modal.js @@ -23,6 +23,10 @@ export default @connect(mapStateToProps) @injectIntl class FavouritesModal extends React.PureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -40,10 +44,21 @@ class FavouritesModal extends React.PureComponent { componentDidMount() { this.fetchData(); + this.unlistenHistory = this.context.router.history.listen((_, action) => { + if (action === 'PUSH') { + this.onClickClose(null, true); + } + }); } - onClickClose = () => { - this.props.onClose('FAVOURITES'); + componentWillUnmount() { + if (this.unlistenHistory) { + this.unlistenHistory(); + } + } + + onClickClose = (_, noPop) => { + this.props.onClose('FAVOURITES', noPop); }; render() { diff --git a/app/soapbox/features/ui/components/mentions_modal.js b/app/soapbox/features/ui/components/mentions_modal.js index b1554c2d2..aaad7a3a4 100644 --- a/app/soapbox/features/ui/components/mentions_modal.js +++ b/app/soapbox/features/ui/components/mentions_modal.js @@ -31,6 +31,10 @@ export default @connect(mapStateToProps) @injectIntl class MentionsModal extends React.PureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -48,10 +52,21 @@ class MentionsModal extends React.PureComponent { componentDidMount() { this.fetchData(); + this.unlistenHistory = this.context.router.history.listen((_, action) => { + if (action === 'PUSH') { + this.onClickClose(null, true); + } + }); } - onClickClose = () => { - this.props.onClose('MENTIONS'); + componentWillUnmount() { + if (this.unlistenHistory) { + this.unlistenHistory(); + } + } + + onClickClose = (_, noPop) => { + this.props.onClose('MENTIONS', noPop); }; render() { diff --git a/app/soapbox/features/ui/components/modal_root.js b/app/soapbox/features/ui/components/modal_root.js index 52f94871d..b1e1714a8 100644 --- a/app/soapbox/features/ui/components/modal_root.js +++ b/app/soapbox/features/ui/components/modal_root.js @@ -62,6 +62,7 @@ export default class ModalRoot extends React.PureComponent { static propTypes = { type: PropTypes.string, props: PropTypes.object, + noPop: PropTypes.bool, onClose: PropTypes.func.isRequired, }; @@ -85,17 +86,17 @@ export default class ModalRoot extends React.PureComponent { return ; } - onClickClose = () => { + onClickClose = (_, noPop) => { const { onClose, type } = this.props; - onClose(type); + onClose(type, noPop); } render() { - const { type, props } = this.props; + const { type, props, noPop } = this.props; const visible = !!type; return ( - + {visible && ( {(SpecificComponent) => } diff --git a/app/soapbox/features/ui/components/reactions_modal.js b/app/soapbox/features/ui/components/reactions_modal.js index 8b905ac25..66f69453f 100644 --- a/app/soapbox/features/ui/components/reactions_modal.js +++ b/app/soapbox/features/ui/components/reactions_modal.js @@ -29,6 +29,10 @@ export default @connect(mapStateToProps) @injectIntl class ReactionsModal extends React.PureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -52,10 +56,21 @@ class ReactionsModal extends React.PureComponent { componentDidMount() { this.fetchData(); + this.unlistenHistory = this.context.router.history.listen((_, action) => { + if (action === 'PUSH') { + this.onClickClose(null, true); + } + }); } - onClickClose = () => { - this.props.onClose('REACTIONS'); + componentWillUnmount() { + if (this.unlistenHistory) { + this.unlistenHistory(); + } + } + + onClickClose = (_, noPop) => { + this.props.onClose('REACTIONS', noPop); }; handleFilterChange = (reaction) => () => { diff --git a/app/soapbox/features/ui/components/reblogs_modal.js b/app/soapbox/features/ui/components/reblogs_modal.js index c6d4811f5..585273538 100644 --- a/app/soapbox/features/ui/components/reblogs_modal.js +++ b/app/soapbox/features/ui/components/reblogs_modal.js @@ -24,6 +24,10 @@ export default @connect(mapStateToProps) @injectIntl class ReblogsModal extends React.PureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -42,10 +46,21 @@ class ReblogsModal extends React.PureComponent { componentDidMount() { this.fetchData(); + this.unlistenHistory = this.context.router.history.listen((_, action) => { + if (action === 'PUSH') { + this.onClickClose(null, true); + } + }); } - onClickClose = () => { - this.props.onClose('REBLOGS'); + componentWillUnmount() { + if (this.unlistenHistory) { + this.unlistenHistory(); + } + } + + onClickClose = (_, noPop) => { + this.props.onClose('REBLOGS', noPop); }; render() { diff --git a/app/soapbox/features/ui/containers/modal_container.js b/app/soapbox/features/ui/containers/modal_container.js index ba0e52785..f0f81e59b 100644 --- a/app/soapbox/features/ui/containers/modal_container.js +++ b/app/soapbox/features/ui/containers/modal_container.js @@ -6,15 +6,16 @@ import ModalRoot from '../components/modal_root'; const mapStateToProps = state => ({ type: state.get('modal').modalType, props: state.get('modal').modalProps, + noPop: state.get('modal').noPop, }); const mapDispatchToProps = (dispatch) => ({ - onClose(optionalType) { + onClose(optionalType, noPop) { if (optionalType === 'COMPOSE') { dispatch(cancelReplyCompose()); } - dispatch(closeModal()); + dispatch(closeModal(undefined, noPop)); }, }); diff --git a/app/soapbox/reducers/__tests__/modal-test.js b/app/soapbox/reducers/__tests__/modal-test.js index 09281e82f..3b0a054e8 100644 --- a/app/soapbox/reducers/__tests__/modal-test.js +++ b/app/soapbox/reducers/__tests__/modal-test.js @@ -6,6 +6,7 @@ describe('modal reducer', () => { expect(reducer(undefined, {})).toEqual({ modalType: null, modalProps: {}, + noPop: false, }); }); @@ -13,6 +14,7 @@ describe('modal reducer', () => { const state = { modalType: null, modalProps: {}, + noPop: false, }; const action = { type: MODAL_OPEN, @@ -36,6 +38,7 @@ describe('modal reducer', () => { expect(reducer(state, action)).toMatchObject({ modalType: null, modalProps: {}, + noPop: false, }); }); diff --git a/app/soapbox/reducers/modal.js b/app/soapbox/reducers/modal.js index 69a991fa7..5c0cba93d 100644 --- a/app/soapbox/reducers/modal.js +++ b/app/soapbox/reducers/modal.js @@ -3,6 +3,7 @@ import { MODAL_OPEN, MODAL_CLOSE } from '../actions/modal'; const initialState = { modalType: null, modalProps: {}, + noPop: false, }; export default function modal(state = initialState, action) { @@ -10,7 +11,12 @@ export default function modal(state = initialState, action) { case MODAL_OPEN: return { modalType: action.modalType, modalProps: action.modalProps }; case MODAL_CLOSE: - return (action.modalType === undefined || action.modalType === state.modalType) ? initialState : state; + return { + ...(action.modalType === undefined || action.modalType === state.modalType) + ? initialState + : state, + noPop: !!action.noPop, + }; default: return state; }