From dc0b1948beea5eed657bc32a3a7deaab0d41c693 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Mon, 28 Oct 2024 14:27:37 +0100 Subject: [PATCH] Feat: Implement interaction modal for Polls (#32609) --- app/javascript/mastodon/components/poll.jsx | 12 +++++++++--- .../mastodon/components/status_content.jsx | 2 +- app/javascript/mastodon/containers/poll_container.js | 12 ++++++++++++ .../mastodon/features/interaction_modal/index.jsx | 8 +++++++- app/javascript/mastodon/locales/en.json | 2 ++ 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx index 7b836f00b1..06b09f5b35 100644 --- a/app/javascript/mastodon/components/poll.jsx +++ b/app/javascript/mastodon/components/poll.jsx @@ -41,12 +41,14 @@ const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => { class Poll extends ImmutablePureComponent { static propTypes = { identity: identityContextPropShape, - poll: ImmutablePropTypes.map, + poll: ImmutablePropTypes.map.isRequired, + status: ImmutablePropTypes.map.isRequired, lang: PropTypes.string, intl: PropTypes.object.isRequired, disabled: PropTypes.bool, refresh: PropTypes.func, onVote: PropTypes.func, + onInteractionModal: PropTypes.func, }; state = { @@ -117,7 +119,11 @@ class Poll extends ImmutablePureComponent { return; } - this.props.onVote(Object.keys(this.state.selected)); + if (this.props.identity.signedIn) { + this.props.onVote(Object.keys(this.state.selected)); + } else { + this.props.onInteractionModal('vote', this.props.status); + } }; handleRefresh = () => { @@ -232,7 +238,7 @@ class Poll extends ImmutablePureComponent {
- {!showResults && } + {!showResults && } {!showResults && <> · } {showResults && !this.props.disabled && <> · } {votesCount} diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index 3316be8350..4950c896f9 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -245,7 +245,7 @@ class StatusContent extends PureComponent { ); const poll = !!status.get('poll') && ( - + ); if (this.props.onClick) { diff --git a/app/javascript/mastodon/containers/poll_container.js b/app/javascript/mastodon/containers/poll_container.js index 8482345431..db378cba7c 100644 --- a/app/javascript/mastodon/containers/poll_container.js +++ b/app/javascript/mastodon/containers/poll_container.js @@ -2,6 +2,7 @@ import { connect } from 'react-redux'; import { debounce } from 'lodash'; +import { openModal } from 'mastodon/actions/modal'; import { fetchPoll, vote } from 'mastodon/actions/polls'; import Poll from 'mastodon/components/poll'; @@ -17,6 +18,17 @@ const mapDispatchToProps = (dispatch, { pollId }) => ({ onVote (choices) { dispatch(vote(pollId, choices)); }, + + onInteractionModal (type, status) { + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type, + accountId: status.getIn(['account', 'id']), + url: status.get('uri'), + }, + })); + } }); const mapStateToProps = (state, { pollId }) => ({ diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx index 723e27ae1c..446cc2586a 100644 --- a/app/javascript/mastodon/features/interaction_modal/index.jsx +++ b/app/javascript/mastodon/features/interaction_modal/index.jsx @@ -9,6 +9,7 @@ import { connect } from 'react-redux'; import { throttle, escapeRegExp } from 'lodash'; +import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react'; import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react'; import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; @@ -340,7 +341,7 @@ class InteractionModal extends React.PureComponent { static propTypes = { displayNameHtml: PropTypes.string, url: PropTypes.string, - type: PropTypes.oneOf(['reply', 'reblog', 'favourite', 'follow']), + type: PropTypes.oneOf(['reply', 'reblog', 'favourite', 'follow', 'vote']), onSignupClick: PropTypes.func.isRequired, signupUrl: PropTypes.string.isRequired, }; @@ -377,6 +378,11 @@ class InteractionModal extends React.PureComponent { title = ; actionDescription = ; break; + case 'vote': + icon = ; + title = ; + actionDescription = ; + break; } let signupButton; diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index f2d37e67a6..e91d6e52fc 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -386,6 +386,7 @@ "interaction_modal.description.follow": "With an account on Mastodon, you can follow {name} to receive their posts in your home feed.", "interaction_modal.description.reblog": "With an account on Mastodon, you can boost this post to share it with your own followers.", "interaction_modal.description.reply": "With an account on Mastodon, you can respond to this post.", + "interaction_modal.description.vote": "With an account on Mastodon, you can vote in this poll.", "interaction_modal.login.action": "Take me home", "interaction_modal.login.prompt": "Domain of your home server, e.g. mastodon.social", "interaction_modal.no_account_yet": "Not on Mastodon?", @@ -397,6 +398,7 @@ "interaction_modal.title.follow": "Follow {name}", "interaction_modal.title.reblog": "Boost {name}'s post", "interaction_modal.title.reply": "Reply to {name}'s post", + "interaction_modal.title.vote": "Vote in {name}'s poll", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}",