From 2d3784eb889ac3979ddde3b05400fd00b07b5d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Thu, 6 Jan 2022 17:45:10 +0100 Subject: [PATCH] =?UTF-8?q?Minor=20changes,=20port=20'Generalize=20?= =?UTF-8?q?=E2=80=9Cpress=20back=20to=20close=20modal=E2=80=9D=20to=20any?= =?UTF-8?q?=20modal=20and=20to=20public=20pages'=20from=20Mastodon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/components/modal_root.js | 37 +++++++++++++++++++ .../components/status_reply_mentions.js | 8 +--- app/soapbox/containers/soapbox.js | 7 +--- .../components/status_interaction_bar.js | 21 ++++++----- .../features/ui/components/media_modal.js | 24 ------------ .../features/ui/components/video_modal.js | 28 -------------- app/styles/components/emoji-reacts.scss | 4 ++ app/styles/components/reply-mentions.scss | 4 ++ package.json | 1 + yarn.lock | 2 +- 10 files changed, 63 insertions(+), 73 deletions(-) diff --git a/app/soapbox/components/modal_root.js b/app/soapbox/components/modal_root.js index a8e8fe746..1ee69a7de 100644 --- a/app/soapbox/components/modal_root.js +++ b/app/soapbox/components/modal_root.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import 'wicg-inert'; +import { createBrowserHistory } from 'history'; import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; import { connect } from 'react-redux'; import { openModal } from '../actions/modal'; @@ -43,6 +44,7 @@ class ModalRoot extends React.PureComponent { intl: PropTypes.object.isRequired, hasComposeContent: PropTypes.bool, type: PropTypes.string, + onCancel: PropTypes.func, }; state = { @@ -100,12 +102,15 @@ class ModalRoot extends React.PureComponent { componentDidMount() { window.addEventListener('keyup', this.handleKeyUp, false); window.addEventListener('keydown', this.handleKeyDown, false); + this.history = this.context.router ? this.context.router.history : createBrowserHistory(); } componentDidUpdate(prevProps) { if (!!this.props.children && !prevProps.children) { this.activeElement = document.activeElement; this.getSiblings().forEach(sibling => sibling.setAttribute('inert', true)); + + this._handleModalOpen(); } else if (!prevProps.children) { this.setState({ revealed: false }); } @@ -114,12 +119,16 @@ class ModalRoot extends React.PureComponent { this.activeElement.focus(); this.activeElement = null; this.getSiblings().forEach(sibling => sibling.removeAttribute('inert')); + + this._handleModalClose(); } if (this.props.children) { requestAnimationFrame(() => { this.setState({ revealed: true }); }); + + this._ensureHistoryBuffer(); } } @@ -128,6 +137,34 @@ class ModalRoot extends React.PureComponent { window.removeEventListener('keydown', this.handleKeyDown); } + _handleModalOpen() { + this._modalHistoryKey = Date.now(); + this.unlistenHistory = this.history.listen((_, action) => { + if (action === 'POP') { + this.handleOnClose(); + + if (this.props.onCancel) this.props.onCancel(); + } + }); + } + + _handleModalClose() { + if (this.unlistenHistory) { + this.unlistenHistory(); + } + const { state } = this.history.location; + if (state && state.soapboxModalKey === this._modalHistoryKey) { + this.history.goBack(); + } + } + + _ensureHistoryBuffer() { + const { pathname, state } = this.history.location; + if (!state || state.soapboxModalKey !== this._modalHistoryKey) { + this.history.push(pathname, { ...state, soapboxModalKey: this._modalHistoryKey }); + } + } + getSiblings = () => { return Array(...this.node.parentElement.childNodes).filter(node => node !== this.node); } diff --git a/app/soapbox/components/status_reply_mentions.js b/app/soapbox/components/status_reply_mentions.js index 1bb43562d..7dd68e942 100644 --- a/app/soapbox/components/status_reply_mentions.js +++ b/app/soapbox/components/status_reply_mentions.js @@ -89,13 +89,9 @@ class StatusReplyMentions extends ImmutablePureComponent { {' '} )), more: to.size > 2 && ( - - + - + ), }} /> diff --git a/app/soapbox/containers/soapbox.js b/app/soapbox/containers/soapbox.js index a4e48c587..9eb9640e6 100644 --- a/app/soapbox/containers/soapbox.js +++ b/app/soapbox/containers/soapbox.js @@ -29,9 +29,6 @@ import { createGlobals } from 'soapbox/globals'; const validLocale = locale => Object.keys(messages).includes(locale); -const previewMediaState = 'previewMediaModal'; -const previewVideoState = 'previewVideoModal'; - export const store = configureStore(); // Configure global functions for developers @@ -117,8 +114,8 @@ class SoapboxMount extends React.PureComponent { this.maybeUpdateMessages(prevProps); } - shouldUpdateScroll(_, { location }) { - return location.state !== previewMediaState && location.state !== previewVideoState; + shouldUpdateScroll(prevRouterProps, { location }) { + return !(location.state?.soapboxModalKey && location.state?.soapboxModalKey !== prevRouterProps?.location?.state?.soapboxModalKey); } render() { diff --git a/app/soapbox/features/status/components/status_interaction_bar.js b/app/soapbox/features/status/components/status_interaction_bar.js index e7f2b0f05..16648a532 100644 --- a/app/soapbox/features/status/components/status_interaction_bar.js +++ b/app/soapbox/features/status/components/status_interaction_bar.js @@ -76,16 +76,17 @@ class StatusInteractionBar extends ImmutablePureComponent { if (status.get('reblogs_count')) { return ( - - + ); } @@ -113,13 +114,14 @@ class StatusInteractionBar extends ImmutablePureComponent { if (features.exposableReactions) { return ( - {favourites} - + ); } else { return ( @@ -164,14 +166,15 @@ class StatusInteractionBar extends ImmutablePureComponent { if (features.exposableReactions) { return ( - {emojiReact} - + ); } diff --git a/app/soapbox/features/ui/components/media_modal.js b/app/soapbox/features/ui/components/media_modal.js index ce002d1c4..603681161 100644 --- a/app/soapbox/features/ui/components/media_modal.js +++ b/app/soapbox/features/ui/components/media_modal.js @@ -18,8 +18,6 @@ const messages = defineMessages({ next: { id: 'lightbox.next', defaultMessage: 'Next' }, }); -export const previewState = 'previewMediaModal'; - export default @injectIntl class MediaModal extends ImmutablePureComponent { @@ -32,10 +30,6 @@ class MediaModal extends ImmutablePureComponent { intl: PropTypes.object.isRequired, }; - static contextTypes = { - router: PropTypes.object, - }; - state = { index: null, navigationHidden: false, @@ -75,28 +69,10 @@ class MediaModal extends ImmutablePureComponent { componentDidMount() { window.addEventListener('keydown', this.handleKeyDown, false); - - if (this.context.router) { - const history = this.context.router.history; - - history.push(history.location.pathname, previewState); - - this.unlistenHistory = history.listen(() => { - this.props.onClose(); - }); - } } componentWillUnmount() { window.removeEventListener('keydown', this.handleKeyDown); - - if (this.context.router) { - this.unlistenHistory(); - - if (this.context.router.history.location.state === previewState) { - this.context.router.history.goBack(); - } - } } getIndex() { diff --git a/app/soapbox/features/ui/components/video_modal.js b/app/soapbox/features/ui/components/video_modal.js index 20bedb48a..086d843b9 100644 --- a/app/soapbox/features/ui/components/video_modal.js +++ b/app/soapbox/features/ui/components/video_modal.js @@ -5,8 +5,6 @@ import Video from 'soapbox/features/video'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; -export const previewState = 'previewVideoModal'; - export default class VideoModal extends ImmutablePureComponent { static propTypes = { @@ -17,32 +15,6 @@ export default class VideoModal extends ImmutablePureComponent { onClose: PropTypes.func.isRequired, }; - static contextTypes = { - router: PropTypes.object, - }; - - componentDidMount() { - if (this.context.router) { - const history = this.context.router.history; - - history.push(history.location.pathname, previewState); - - this.unlistenHistory = history.listen(() => { - this.props.onClose(); - }); - } - } - - componentWillUnmount() { - if (this.context.router) { - this.unlistenHistory(); - - if (this.context.router.history.location.state === previewState) { - this.context.router.history.goBack(); - } - } - } - handleStatusClick = e => { const { status, account } = this.props; if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { diff --git a/app/styles/components/emoji-reacts.scss b/app/styles/components/emoji-reacts.scss index 9af8b33ca..353ab043e 100644 --- a/app/styles/components/emoji-reacts.scss +++ b/app/styles/components/emoji-reacts.scss @@ -19,6 +19,10 @@ + .emoji-react { margin-right: -8px; } + + &[type='button'] { + cursor: pointer; + } } .emoji-react--reblogs, diff --git a/app/styles/components/reply-mentions.scss b/app/styles/components/reply-mentions.scss index 444852026..9eebb19d0 100644 --- a/app/styles/components/reply-mentions.scss +++ b/app/styles/components/reply-mentions.scss @@ -20,5 +20,9 @@ .reply-mentions { display: block; margin: 4px 0 0 0; + + span { + cursor: pointer; + } } } diff --git a/package.json b/package.json index 3c3ce850d..cfc61ef3b 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,7 @@ "escape-html": "^1.0.3", "exif-js": "^2.3.0", "feather-icons": "^4.28.0", + "history": "^4.10.1", "html-webpack-harddisk-plugin": "^2.0.0", "html-webpack-plugin": "^5.3.2", "http-link-header": "^1.0.2", diff --git a/yarn.lock b/yarn.lock index d867807f6..c9338896c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4588,7 +4588,7 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -history@^4.7.2: +history@^4.10.1, history@^4.7.2: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==