diff --git a/app/javascript/flavours/glitch/actions/interactions.js b/app/javascript/flavours/glitch/actions/interactions.js index 57f2459c01..6790d3313b 100644 --- a/app/javascript/flavours/glitch/actions/interactions.js +++ b/app/javascript/flavours/glitch/actions/interactions.js @@ -1,7 +1,11 @@ +import { boostModal, favouriteModal } from 'flavours/glitch/initial_state'; + import api, { getLinks } from '../api'; import { fetchRelationships } from './accounts'; import { importFetchedAccounts, importFetchedStatus } from './importer'; +import { unreblog, reblog } from './interactions_typed'; +import { openModal } from './modal'; export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST'; export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS'; @@ -432,3 +436,61 @@ export function unpinFail(status, error) { skipLoading: true, }; } + +function toggleReblogWithoutConfirmation(status, privacy) { + return (dispatch) => { + if (status.get('reblogged')) { + dispatch(unreblog({ statusId: status.get('id') })); + } else { + dispatch(reblog({ statusId: status.get('id'), privacy })); + } + }; +} + +export function toggleReblog(statusId, skipModal = false) { + return (dispatch, getState) => { + const state = getState(); + let status = state.statuses.get(statusId); + + if (!status) + return; + + // The reblog modal expects a pre-filled account in status + // TODO: fix this by having the reblog modal get a statusId and do the work itself + status = status.set('account', state.accounts.get(status.get('account'))); + + const missing_description_setting = state.getIn(['local_settings', 'confirm_boost_missing_media_description']); + const missing_description = status.get('media_attachments').some(item => !item.get('description')); + if (missing_description_setting && missing_description && !status.get('reblogged')) { + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation, missingMediaDescription: true } })); + } else if (boostModal && !skipModal) { + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + } else { + toggleReblogWithoutConfirmation(status); + } + }; +} + +export function toggleFavourite(statusId, skipModal = false) { + return (dispatch, getState) => { + const state = getState(); + let status = state.statuses.get(statusId); + + if (!status) + return; + + // The favourite modal expects a pre-filled account in status + // TODO: fix this by having the reblog modal get a statusId and do the work itself + status = status.set('account', state.accounts.get(status.get('account'))); + + if (status.get('favourited')) { + dispatch(unfavourite(status)); + } else { + if (favouriteModal && !skipModal) { + dispatch(openModal({ modalType: 'FAVOURITE', modalProps: { status, onFavourite: (status) => dispatch(favourite(status)) } })); + } else { + dispatch(favourite(status)); + } + } + }; +} diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index a05ed5fe4f..aac18eac0d 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -12,11 +12,9 @@ import { initAddFilter, } from 'flavours/glitch/actions/filters'; import { - reblog, - favourite, + toggleReblog, + toggleFavourite, bookmark, - unreblog, - unfavourite, unbookmark, pin, unpin, @@ -37,7 +35,7 @@ import { undoStatusTranslation, } from 'flavours/glitch/actions/statuses'; import Status from 'flavours/glitch/components/status'; -import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/initial_state'; +import { deleteModal } from 'flavours/glitch/initial_state'; import { makeGetStatus, makeGetPictureInPicture } from 'flavours/glitch/selectors'; import { showAlertForError } from '../actions/alerts'; @@ -113,25 +111,8 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }); }, - onModalReblog (status, privacy) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - } - }, - onReblog (status, e) { - dispatch((_, getState) => { - let state = getState(); - if (state.getIn(['local_settings', 'confirm_boost_missing_media_description']) && status.get('media_attachments').some(item => !item.get('description')) && !status.get('reblogged')) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog, missingMediaDescription: true } })); - } else if (e.shiftKey || !boostModal) { - this.onModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } - }); + dispatch(toggleReblog(status.get('id'), e.shiftKey)); }, onBookmark (status) { @@ -142,26 +123,8 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onModalFavourite (status) { - dispatch(favourite(status)); - }, - onFavourite (status, e) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - if (e.shiftKey || !favouriteModal) { - this.onModalFavourite(status); - } else { - dispatch(openModal({ - modalType: 'FAVOURITE', - modalProps: { - status, - onFavourite: this.onModalFavourite, - }, - })); - } - } + dispatch(toggleFavourite(status.get('id'), e.shiftKey)); }, onPin (status) { diff --git a/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js b/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js index b4df05b828..8ecea4bc73 100644 --- a/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js +++ b/app/javascript/flavours/glitch/features/notifications/containers/notification_container.js @@ -2,13 +2,9 @@ import { connect } from 'react-redux'; import { mentionCompose } from '../../../actions/compose'; import { - reblog, - favourite, - unreblog, - unfavourite, + toggleReblog, + toggleFavourite, } from '../../../actions/interactions'; -import { openModal } from '../../../actions/modal'; -import { boostModal } from '../../../initial_state'; import { makeGetNotification, makeGetStatus, makeGetReport } from '../../../selectors'; import Notification from '../components/notification'; @@ -35,28 +31,12 @@ const mapDispatchToProps = dispatch => ({ dispatch(mentionCompose(account)); }, - onModalReblog (status, privacy) { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }, - onReblog (status, e) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - if (e.shiftKey || !boostModal) { - this.onModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } - } + dispatch(toggleReblog(status.get('id'), e.shiftKey)); }, - onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + onFavourite (status, e) { + dispatch(toggleFavourite(status.get('id'), e.shiftKey)); }, }); diff --git a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx index 2b27070007..3e26d84069 100644 --- a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx @@ -15,11 +15,11 @@ import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react'; import StarIcon from '@/material-icons/400-24px/star.svg?react'; import { replyCompose } from 'flavours/glitch/actions/compose'; -import { reblog, favourite, unreblog, unfavourite } from 'flavours/glitch/actions/interactions'; +import { toggleReblog, toggleFavourite } from 'flavours/glitch/actions/interactions'; import { openModal } from 'flavours/glitch/actions/modal'; import { IconButton } from 'flavours/glitch/components/icon_button'; import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context'; -import { me, boostModal } from 'flavours/glitch/initial_state'; +import { me } from 'flavours/glitch/initial_state'; import { makeGetStatus } from 'flavours/glitch/selectors'; import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router'; @@ -101,16 +101,12 @@ class Footer extends ImmutablePureComponent { } }; - handleFavouriteClick = () => { + handleFavouriteClick = e => { const { dispatch, status } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -123,23 +119,12 @@ class Footer extends ImmutablePureComponent { } }; - _performReblog = (status, privacy) => { - const { dispatch } = this.props; - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }; - handleReblogClick = e => { const { dispatch, status } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else if ((e && e.shiftKey) || !boostModal) { - this._performReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this._performReblog } })); - } + dispatch(toggleReblog(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION', diff --git a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js index 9663f7ca4e..1c9e3ccce1 100644 --- a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js +++ b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js @@ -10,10 +10,8 @@ import { directCompose, } from '../../../actions/compose'; import { - reblog, - favourite, - unreblog, - unfavourite, + toggleReblog, + toggleFavourite, pin, unpin, } from '../../../actions/interactions'; @@ -25,7 +23,7 @@ import { unmuteStatus, deleteStatus, } from '../../../actions/statuses'; -import { boostModal, deleteModal } from '../../../initial_state'; +import { deleteModal } from '../../../initial_state'; import { makeGetStatus } from '../../../selectors'; import DetailedStatus from '../components/detailed_status'; @@ -70,28 +68,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }); }, - onModalReblog (status, privacy) { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }, - onReblog (status, e) { - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - if (e.shiftKey || !boostModal) { - this.onModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.onModalReblog } })); - } - } + dispatch(toggleReblog(status.get('id'), e.shiftKey)); }, - onFavourite (status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + onFavourite (status, e) { + dispatch(toggleFavourite(status.get('id'), e.shiftKey)); }, onPin (status) { diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index eb965046d1..2fca4b61b6 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -32,12 +32,10 @@ import { directCompose, } from '../../actions/compose'; import { - favourite, - unfavourite, + toggleFavourite, bookmark, unbookmark, - reblog, - unreblog, + toggleReblog, pin, unpin, } from '../../actions/interactions'; @@ -59,7 +57,7 @@ import { import ColumnHeader from '../../components/column_header'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; import StatusContainer from '../../containers/status_container'; -import { boostModal, favouriteModal, deleteModal } from '../../initial_state'; +import { deleteModal } from '../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../selectors'; import Column from '../ui/components/column'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; @@ -268,30 +266,13 @@ class Status extends ImmutablePureComponent { this.setState({ showMedia: !this.state.showMedia }); }; - handleModalFavourite = (status) => { - this.props.dispatch(favourite(status)); - }; handleFavouriteClick = (status, e) => { const { dispatch } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - if ((e && e.shiftKey) || !favouriteModal) { - this.handleModalFavourite(status); - } else { - dispatch(openModal({ - modalType: 'FAVOURITE', - modalProps: { - status, - onFavourite: this.handleModalFavourite, - }, - })); - } - } + dispatch(toggleFavourite(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -342,28 +323,12 @@ class Status extends ImmutablePureComponent { } }; - handleModalReblog = (status, privacy) => { - const { dispatch } = this.props; - - if (status.get('reblogged')) { - dispatch(unreblog({ statusId: status.get('id') })); - } else { - dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - } - }; - handleReblogClick = (status, e) => { - const { settings, dispatch } = this.props; + const { dispatch } = this.props; const { signedIn } = this.props.identity; if (signedIn) { - if (settings.get('confirm_boost_missing_media_description') && status.get('media_attachments').some(item => !item.get('description')) && !status.get('reblogged')) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.handleModalReblog, missingMediaDescription: true } })); - } else if ((e && e.shiftKey) || !boostModal) { - this.handleModalReblog(status); - } else { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: this.handleModalReblog } })); - } + dispatch(toggleReblog(status.get('id'), e && e.shiftKey)); } else { dispatch(openModal({ modalType: 'INTERACTION',