From 03dea64b794f3e6cd1e03df72578ed0004a4d84c Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 17:45:07 +0200 Subject: [PATCH 1/6] Refactor code for reblogging and favouriting (#31102) --- .../mastodon/actions/interactions.js | 50 +++++++++++++++++++ .../mastodon/containers/status_container.jsx | 28 ++--------- .../containers/notification_container.js | 28 ++--------- .../picture_in_picture/components/footer.jsx | 23 ++------- .../containers/detailed_status_container.js | 28 ++--------- .../mastodon/features/status/index.jsx | 28 ++--------- 6 files changed, 73 insertions(+), 112 deletions(-) diff --git a/app/javascript/mastodon/actions/interactions.js b/app/javascript/mastodon/actions/interactions.js index 57f2459c01..9d39b7a57f 100644 --- a/app/javascript/mastodon/actions/interactions.js +++ b/app/javascript/mastodon/actions/interactions.js @@ -1,7 +1,11 @@ +import { boostModal } from 'mastodon/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,49 @@ 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'))); + + if (boostModal && !skipModal) { + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + } else { + toggleReblogWithoutConfirmation(status); + } + }; +} + +export function toggleFavourite(statusId) { + return (dispatch, getState) => { + const state = getState(); + const status = state.statuses.get(statusId); + + if (!status) + return; + + if (status.get('favourited')) { + dispatch(unfavourite(status)); + } else { + dispatch(favourite(status)); + } + }; +} diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index e2c0af3533..8e34ace873 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -21,11 +21,9 @@ import { initAddFilter, } from '../actions/filters'; import { - reblog, - favourite, + toggleReblog, + toggleFavourite, bookmark, - unreblog, - unfavourite, unbookmark, pin, unpin, @@ -46,7 +44,7 @@ import { undoStatusTranslation, } from '../actions/statuses'; import Status from '../components/status'; -import { boostModal, deleteModal } from '../initial_state'; +import { deleteModal } from '../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../selectors'; const messages = defineMessages({ @@ -94,28 +92,12 @@ 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) { - if ((e && 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)); - } + dispatch(toggleFavourite(status.get('id'))); }, onBookmark (status) { diff --git a/app/javascript/mastodon/features/notifications/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 7b7e6e919c..98a3cf8b1e 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -2,17 +2,13 @@ import { connect } from 'react-redux'; import { mentionCompose } from '../../../actions/compose'; import { - reblog, - favourite, - unreblog, - unfavourite, + toggleFavourite, + toggleReblog, } from '../../../actions/interactions'; -import { openModal } from '../../../actions/modal'; import { hideStatus, revealStatus, } from '../../../actions/statuses'; -import { boostModal } from '../../../initial_state'; import { makeGetNotification, makeGetStatus, makeGetReport } from '../../../selectors'; import Notification from '../components/notification'; @@ -38,28 +34,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)); - } + dispatch(toggleFavourite(status.get('id'))); }, onToggleHidden (status) { diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx index 8404bf61b7..d5226eb346 100644 --- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/mastodon/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 'mastodon/actions/compose'; -import { reblog, favourite, unreblog, unfavourite } from 'mastodon/actions/interactions'; +import { toggleReblog, toggleFavourite } from 'mastodon/actions/interactions'; import { openModal } from 'mastodon/actions/modal'; import { IconButton } from 'mastodon/components/icon_button'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; -import { me, boostModal } from 'mastodon/initial_state'; +import { me } from 'mastodon/initial_state'; import { makeGetStatus } from 'mastodon/selectors'; import { WithRouterPropTypes } from 'mastodon/utils/react_router'; @@ -104,11 +104,7 @@ class Footer extends ImmutablePureComponent { const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -121,23 +117,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/mastodon/features/status/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index f85c3822d7..f37860d25c 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/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'; @@ -27,7 +25,7 @@ import { hideStatus, revealStatus, } from '../../../actions/statuses'; -import { boostModal, deleteModal } from '../../../initial_state'; +import { deleteModal } from '../../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../../selectors'; import DetailedStatus from '../components/detailed_status'; @@ -73,28 +71,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)); - } + dispatch(toggleFavourite(status.get('id'))); }, onPin (status) { diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index b0fbea9e22..e9df3697a2 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -38,12 +38,10 @@ import { unblockDomain, } from '../../actions/domain_blocks'; import { - favourite, - unfavourite, + toggleFavourite, bookmark, unbookmark, - reblog, - unreblog, + toggleReblog, pin, unpin, } from '../../actions/interactions'; @@ -64,7 +62,7 @@ import { import ColumnHeader from '../../components/column_header'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; import StatusContainer from '../../containers/status_container'; -import { boostModal, 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'; @@ -244,11 +242,7 @@ class Status extends ImmutablePureComponent { const { signedIn } = this.props.identity; if (signedIn) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } + dispatch(toggleFavourite(status.get('id'))); } else { dispatch(openModal({ modalType: 'INTERACTION', @@ -298,24 +292,12 @@ class Status extends ImmutablePureComponent { } }; - handleModalReblog = (status, privacy) => { - this.props.dispatch(reblog({ statusId: status.get('id'), visibility: privacy })); - }; - handleReblogClick = (status, e) => { const { dispatch } = 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.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', From 9cb94271333ccfe488fa84d49e3351f18594e480 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 18:03:58 +0200 Subject: [PATCH 2/6] Refactor CW handling in an action (#31103) --- app/javascript/mastodon/actions/statuses.js | 15 +++++++++++++++ .../mastodon/containers/status_container.jsx | 9 ++------- .../direct_timeline/components/conversation.jsx | 8 ++------ .../containers/notification_container.js | 9 ++------- .../containers/detailed_status_container.js | 9 ++------- 5 files changed, 23 insertions(+), 27 deletions(-) diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 1907d3aa91..26abaf1bcc 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -308,6 +308,21 @@ export function revealStatus(ids) { }; } +export function toggleStatusSpoilers(statusId) { + return (dispatch, getState) => { + const status = getState().statuses.get(statusId); + + if (!status) + return; + + if (status.get('hidden')) { + dispatch(revealStatus(statusId)); + } else { + dispatch(hideStatus(statusId)); + } + }; +} + export function toggleStatusCollapse(id, isCollapsed) { return { type: STATUS_COLLAPSE, diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index 8e34ace873..c803822dc0 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -36,8 +36,7 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, toggleStatusCollapse, editStatus, translateStatus, @@ -223,11 +222,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }, onToggleHidden (status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } + dispatch(toggleStatusSpoilers(status.get('id'))); }, onToggleCollapsed (status, isCollapsed) { diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx index 63dc705e40..326ea3e5ac 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx +++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx @@ -18,7 +18,7 @@ import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import { replyCompose } from 'mastodon/actions/compose'; import { markConversationRead, deleteConversation } from 'mastodon/actions/conversations'; import { openModal } from 'mastodon/actions/modal'; -import { muteStatus, unmuteStatus, revealStatus, hideStatus } from 'mastodon/actions/statuses'; +import { muteStatus, unmuteStatus, toggleStatusSpoilers } from 'mastodon/actions/statuses'; import AttachmentList from 'mastodon/components/attachment_list'; import AvatarComposite from 'mastodon/components/avatar_composite'; import { IconButton } from 'mastodon/components/icon_button'; @@ -138,11 +138,7 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown }) }, [dispatch, lastStatus]); const handleShowMore = useCallback(() => { - if (lastStatus.get('hidden')) { - dispatch(revealStatus(lastStatus.get('id'))); - } else { - dispatch(hideStatus(lastStatus.get('id'))); - } + dispatch(toggleStatusSpoilers(lastStatus.get('id'))); }, [dispatch, lastStatus]); if (!lastStatus) { diff --git a/app/javascript/mastodon/features/notifications/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 98a3cf8b1e..d64f2a679c 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -6,8 +6,7 @@ import { toggleReblog, } from '../../../actions/interactions'; import { - hideStatus, - revealStatus, + toggleStatusSpoilers, } from '../../../actions/statuses'; import { makeGetNotification, makeGetStatus, makeGetReport } from '../../../selectors'; import Notification from '../components/notification'; @@ -43,11 +42,7 @@ const mapDispatchToProps = dispatch => ({ }, onToggleHidden (status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } + dispatch(toggleStatusSpoilers(status.get('id'))); }, }); diff --git a/app/javascript/mastodon/features/status/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index f37860d25c..5ab1013700 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/features/status/containers/detailed_status_container.js @@ -22,8 +22,7 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, } from '../../../actions/statuses'; import { deleteModal } from '../../../initial_state'; import { makeGetStatus, makeGetPictureInPicture } from '../../../selectors'; @@ -156,11 +155,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onToggleHidden (status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } + dispatch(toggleStatusSpoilers(status.get('id'))); }, }); From 55705d8191f31c1089095956fb4124f7505b4bd7 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 21:30:06 +0200 Subject: [PATCH 3/6] Fix reblogging after refactor (#31105) --- app/javascript/mastodon/actions/interactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/actions/interactions.js b/app/javascript/mastodon/actions/interactions.js index 9d39b7a57f..b296a5006a 100644 --- a/app/javascript/mastodon/actions/interactions.js +++ b/app/javascript/mastodon/actions/interactions.js @@ -460,9 +460,9 @@ export function toggleReblog(statusId, skipModal = false) { status = status.set('account', state.accounts.get(status.get('account'))); if (boostModal && !skipModal) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: (status, privacy) => dispatch(toggleReblogWithoutConfirmation(status, privacy)) } })); } else { - toggleReblogWithoutConfirmation(status); + dispatch(toggleReblogWithoutConfirmation(status)); } }; } From f13a231b3980f76fc5b105ac8e430599df19e956 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 17:45:07 +0200 Subject: [PATCH 4/6] [Glitch] Refactor code for reblogging and favouriting Port 03dea64b794f3e6cd1e03df72578ed0004a4d84c to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/actions/interactions.js | 62 +++++++++++++++++++ .../glitch/containers/status_container.js | 47 ++------------ .../containers/notification_container.js | 30 ++------- .../picture_in_picture/components/footer.jsx | 25 ++------ .../containers/detailed_status_container.js | 30 ++------- .../flavours/glitch/features/status/index.jsx | 47 ++------------ 6 files changed, 89 insertions(+), 152 deletions(-) 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', From 643b1ef3e97684da49879f9ca7e8781b2f1b3b00 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 18:03:58 +0200 Subject: [PATCH 5/6] [Glitch] Refactor CW handling in an action Port 9cb94271333ccfe488fa84d49e3351f18594e480 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/actions/statuses.js | 15 +++++++++++++++ .../glitch/containers/status_container.js | 9 ++------- .../direct_timeline/components/conversation.jsx | 8 ++------ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/javascript/flavours/glitch/actions/statuses.js b/app/javascript/flavours/glitch/actions/statuses.js index 054626bda0..2ebe0bf96a 100644 --- a/app/javascript/flavours/glitch/actions/statuses.js +++ b/app/javascript/flavours/glitch/actions/statuses.js @@ -309,6 +309,21 @@ export function revealStatus(ids) { }; } +export function toggleStatusSpoilers(statusId) { + return (dispatch, getState) => { + const status = getState().statuses.get(statusId); + + if (!status) + return; + + if (status.get('hidden')) { + dispatch(revealStatus(statusId)); + } else { + dispatch(hideStatus(statusId)); + } + }; +} + export function toggleStatusCollapse(id, isCollapsed) { return { type: STATUS_COLLAPSE, diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index aac18eac0d..955adc5fa7 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -28,8 +28,7 @@ import { muteStatus, unmuteStatus, deleteStatus, - hideStatus, - revealStatus, + toggleStatusSpoilers, editStatus, translateStatus, undoStatusTranslation, @@ -234,11 +233,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }, onToggleHidden (status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } + dispatch(toggleStatusSpoilers(status.get('id'))); }, deployPictureInPicture (status, type, mediaProps) { diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx index 839de34dd4..2c70f48a37 100644 --- a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx +++ b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx @@ -18,7 +18,7 @@ import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import { replyCompose } from 'flavours/glitch/actions/compose'; import { markConversationRead, deleteConversation } from 'flavours/glitch/actions/conversations'; import { openModal } from 'flavours/glitch/actions/modal'; -import { muteStatus, unmuteStatus, revealStatus, hideStatus } from 'flavours/glitch/actions/statuses'; +import { muteStatus, unmuteStatus, toggleStatusSpoilers } from 'flavours/glitch/actions/statuses'; import AttachmentList from 'flavours/glitch/components/attachment_list'; import AvatarComposite from 'flavours/glitch/components/avatar_composite'; import { IconButton } from 'flavours/glitch/components/icon_button'; @@ -156,11 +156,7 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown }) }, [dispatch, lastStatus]); const handleShowMore = useCallback(() => { - if (lastStatus.get('hidden')) { - dispatch(revealStatus(lastStatus.get('id'))); - } else { - dispatch(hideStatus(lastStatus.get('id'))); - } + dispatch(toggleStatusSpoilers(lastStatus.get('id'))); if (lastStatus.get('spoiler_text')) { setExpanded(!expanded); From cbf25634a9144bb6420fb0350d7ea64bed4f763f Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 22 Jul 2024 21:30:06 +0200 Subject: [PATCH 6/6] [Glitch] Fix reblogging after refactor Port 55705d8191f31c1089095956fb4124f7505b4bd7 to glitch-soc Signed-off-by: Claire --- app/javascript/flavours/glitch/actions/interactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/javascript/flavours/glitch/actions/interactions.js b/app/javascript/flavours/glitch/actions/interactions.js index 6790d3313b..43673642f5 100644 --- a/app/javascript/flavours/glitch/actions/interactions.js +++ b/app/javascript/flavours/glitch/actions/interactions.js @@ -462,11 +462,11 @@ export function toggleReblog(statusId, skipModal = false) { 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 } })); + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: (status, privacy) => dispatch(toggleReblogWithoutConfirmation(status, privacy)), missingMediaDescription: true } })); } else if (boostModal && !skipModal) { - dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: toggleReblogWithoutConfirmation } })); + dispatch(openModal({ modalType: 'BOOST', modalProps: { status, onReblog: (status, privacy) => dispatch(toggleReblogWithoutConfirmation(status, privacy)) } })); } else { - toggleReblogWithoutConfirmation(status); + dispatch(toggleReblogWithoutConfirmation(status)); } }; }